Files
wehub-resource-sync 97e91a83f3
Ruff / Ruff (push) Waiting to run
Test / Core Tests (push) Waiting to run
Test / Offline Coverage Tests (Python 3.10) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.11) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.12) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.13) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.9) (push) Waiting to run
Test / Full Coverage (Python 3.11) (push) Waiting to run
Test / Core Provider Tests (OpenAI) (push) Blocked by required conditions
Test / Core Provider Tests (Anthropic) (push) Blocked by required conditions
Test / Core Provider Tests (Google) (push) Blocked by required conditions
Test / Core Provider Tests (Other) (push) Blocked by required conditions
Test / Anthropic Tests (push) Blocked by required conditions
Test / Gemini Tests (push) Blocked by required conditions
Test / Google GenAI Tests (push) Blocked by required conditions
Test / Vertex AI Tests (push) Blocked by required conditions
Test / OpenAI Tests (push) Blocked by required conditions
Test / Writer Tests (push) Blocked by required conditions
Test / Auto Client Tests (push) Blocked by required conditions
ty / type-check (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:38 +08:00

198 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Debugging Instructor Applications
description: Learn how to debug Instructor applications with hooks, logging, and exception handling. Practical techniques for inspecting inputs, outputs, and retries.
---
# Debugging
This guide shows how to quickly inspect inputs/outputs, capture retries, and reproduce failures when working with Instructor. It focuses on practical techniques using hooks, logging, and exception data.
## Enable Logs
### Quick Debug Mode (Recommended)
The fastest way to enable debug logging is with the `INSTRUCTOR_DEBUG` environment variable:
```bash
export INSTRUCTOR_DEBUG=1
python your_script.py
```
Or inline:
```bash
INSTRUCTOR_DEBUG=1 python your_script.py
```
This automatically enables debug logging with correlation IDs for request tracing.
### Manual Debug Configuration
You can also use the standard Python `logging` module for more control:
```python
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("instructor").setLevel(logging.DEBUG)
```
You will see messages for:
- Raw responses (provider-specific objects)
- Handler/mode selection
- Retry attempts and parse errors
- Reask adjustments to `messages`
- **Correlation IDs** for tracing requests (format: `[a1b2c3d4]`)
Tip: Set a handler/formatter to include timestamps and module names.
## Observe the Flow with Hooks
Hooks let you tap into key moments without modifying core code:
```python
from instructor.core.hooks import HookName
# Attach one or more handlers
client.on(HookName.COMPLETION_KWARGS, lambda **kw: print("KWARGS:", kw))
client.on(HookName.COMPLETION_RESPONSE, lambda resp: print("RESPONSE:", type(resp)))
client.on(HookName.PARSE_ERROR, lambda e: print("PARSE ERROR:", e))
client.on(HookName.COMPLETION_LAST_ATTEMPT, lambda e: print("LAST ATTEMPT:", e))
client.on(HookName.COMPLETION_ERROR, lambda e: print("COMPLETION ERROR:", e))
```
Common uses:
- Capture the final `kwargs` passed to the provider (including mode/tools/response_format).
- Record raw responses (e.g., to logs or a file) for offline analysis.
- Inspect parse errors and how reask modifies the next attempt.
Note: Handlers that accept `**kwargs` (or a parameter named `_instructor_meta`) receive a metadata dict with:
- `attempt_number`, `correlation_id`, `mode`, `response_model_name`.
Add `**kwargs` to your handler signature to access it:
```python
client.on(HookName.COMPLETION_KWARGS, lambda **kw: print(kw.get("_instructor_meta")))
```
## Inspect Raw Responses
Most parsed models returned by Instructor carry the original provider response for debugging:
```python
model = client.create(...)
raw = getattr(model, "_raw_response", None)
print(raw)
```
This is useful for checking provider metadata like token usage, model version, and provider-specific fields.
## Handling Failures & Retries
When all retries are exhausted, an `InstructorRetryException` is raised. It includes detailed context:
```python
from instructor.core.exceptions import InstructorRetryException
try:
client.create(...)
except InstructorRetryException as e:
print("Attempts:", e.n_attempts)
print("Last completion:", e.last_completion)
print("Create kwargs:", e.create_kwargs) # reproducible input
print("Failed attempts:", e.failed_attempts) # list of (attempt, exception, completion)
# If available, a compact trace packet to help debugging
if hasattr(e, "trace_packet") and e.trace_packet:
print("Trace packet:", e.trace_packet)
```
Use `e.create_kwargs` and `e.failed_attempts` to craft a minimal reproduction.
## Minimal Reproduction Template
```python
import openai
import instructor
from pydantic import BaseModel
class MyModel(BaseModel):
# fields...
pass
client = instructor.from_provider("openai/gpt-5-nano")
create_kwargs = {
# paste from InstructorRetryException.create_kwargs
}
try:
client.create(response_model=MyModel, **create_kwargs)
except Exception as err:
# Inspect and iterate
raise
```
This pattern captures the exact inputs that triggered a failure.
## Strict vs Non-Strict Parsing
- `strict=True` enforces exact schema matches and can surface schema drift early.
- If providers sometimes return extra fields or slightly different types (e.g., floats for ints), try `strict=False` to validate nonstrictly.
```python
client.create(..., response_model=MyModel, strict=True)
```
## Customizing Retries
You can pass an integer (attempt count) or a `tenacity` retrying object to control behavior:
```python
from tenacity import Retrying, stop_after_attempt, stop_after_delay
max_retries = Retrying(stop=stop_after_attempt(3) | stop_after_delay(10))
client.create(..., max_retries=max_retries)
```
This is helpful when balancing latency and robustness.
## Multimodal & Message Conversion
If you send images/audio/PDFs or text that may include media paths/URIs, Instructor can convert messages for provider formats.
- For supported modes, `processing.multimodal.convert_messages` runs automatically.
- If debugging content issues, log `messages` before and after conversion using the hooks above, and ensure media types/URIs are valid.
## Caching Considerations
If youre using a cache (`cache=...`), remember:
- Successful parsed responses are stored; retrieving from cache skips the provider call.
- If debugging live provider behavior, temporarily disable cache or change the cache key (e.g., tweak a message).
```python
model = client.create(..., cache=None)
```
## Common Troubleshooting Tips
- Validate the `response_model.model_json_schema()` matches what you expect the provider to return.
- Confirm `mode` is valid for your provider; mismatches can cause parsing failures.
- Check providerside limits (max tokens/response length); incomplete outputs raise specific exceptions.
- If using markdown JSON (`MD_JSON`), ensure the provider is actually returning a ```json code block.
If you need deeper visibility, add a custom handler to write kwargs/responses/errors to disk with a timestamp and correlation id.
## Example: Local Debug Run
You can run a minimal, nonetwork example that exercises hooks, logging, and parsing flow using a fake provider function:
- File: `examples/debugging/run.py`
- Run:
```bash
python examples/debugging/run.py
```
This script:
- Enables DEBUG logging for `instructor.*`
- Patches a fake provider `create` with `instructor.patch(mode=Mode.JSON)`
- Attaches hook handlers to print kwargs, response types, and parse errors
- Parses a simple JSON payload into a Pydantic model and prints the result