chore: import upstream snapshot with attribution
Ruff / Ruff (push) Has been cancelled
Test / Core Tests (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.10) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.11) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.12) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.13) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.9) (push) Has been cancelled
Test / Full Coverage (Python 3.11) (push) Has been cancelled
Test / Core Provider Tests (OpenAI) (push) Has been cancelled
Test / Core Provider Tests (Anthropic) (push) Has been cancelled
Test / Core Provider Tests (Google) (push) Has been cancelled
Test / Core Provider Tests (Other) (push) Has been cancelled
Test / Anthropic Tests (push) Has been cancelled
Test / Gemini Tests (push) Has been cancelled
Test / Google GenAI Tests (push) Has been cancelled
Test / Vertex AI Tests (push) Has been cancelled
Test / OpenAI Tests (push) Has been cancelled
Test / Writer Tests (push) Has been cancelled
Test / Auto Client Tests (push) Has been cancelled
ty / type-check (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:36:38 +08:00
commit 97e91a83f3
978 changed files with 159975 additions and 0 deletions
+197
View File
@@ -0,0 +1,197 @@
---
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