참고소스 수정본
This commit is contained in:
309
참고/instructor-main/docs/concepts/error_handling.md
Normal file
309
참고/instructor-main/docs/concepts/error_handling.md
Normal file
@@ -0,0 +1,309 @@
|
||||
---
|
||||
title: Error Handling
|
||||
description: Learn how to handle errors and exceptions when using Instructor for structured outputs.
|
||||
---
|
||||
|
||||
# Error Handling
|
||||
|
||||
Instructor provides a comprehensive exception hierarchy to help you handle errors gracefully. All Instructor exceptions inherit from `InstructorError`.
|
||||
|
||||
## Exception Reference
|
||||
|
||||
| Exception | Description | Key Attributes |
|
||||
|-----------|-------------|----------------|
|
||||
| `InstructorError` | Base exception for all Instructor errors | - |
|
||||
| `IncompleteOutputException` | Output truncated due to token limit | `last_completion` |
|
||||
| `InstructorRetryException` | All retry attempts exhausted | `n_attempts`, `failed_attempts`, `total_usage` |
|
||||
| `ValidationError` | Response validation failed | - |
|
||||
| `ResponseParsingError` | Cannot parse LLM response | `mode`, `raw_response` |
|
||||
| `ProviderError` | Provider-specific error | `provider` |
|
||||
| `ConfigurationError` | Invalid configuration | - |
|
||||
| `ModeError` | Invalid mode for provider | `mode`, `provider`, `valid_modes` |
|
||||
| `ClientError` | Client initialization failed | - |
|
||||
| `MultimodalError` | Processing image/audio/PDF failed | `content_type`, `file_path` |
|
||||
| `AsyncValidationError` | Async validation failed | `errors` |
|
||||
|
||||
## Common Exceptions
|
||||
|
||||
### Incomplete Output
|
||||
|
||||
Raised when the LLM output is truncated due to reaching the token limit:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from pydantic import BaseModel
|
||||
from instructor.core.exceptions import IncompleteOutputException, InstructorRetryException
|
||||
|
||||
|
||||
class Report(BaseModel):
|
||||
content: str
|
||||
|
||||
|
||||
client = instructor.from_provider("openai/gpt-4.1-mini", mode=instructor.Mode.JSON)
|
||||
|
||||
try:
|
||||
response = client.create(
|
||||
response_model=Report,
|
||||
messages=[{"role": "user", "content": "Write a long report..."}],
|
||||
max_tokens=50,
|
||||
max_retries=0,
|
||||
)
|
||||
except (IncompleteOutputException, InstructorRetryException) as e:
|
||||
print(f"Output truncated: {e}")
|
||||
print(f"Last completion: {e.last_completion}")
|
||||
```
|
||||
|
||||
### Retry Exhausted
|
||||
|
||||
Raised when all retry attempts fail:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from pydantic import BaseModel
|
||||
from instructor.core.exceptions import InstructorRetryException
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
name: str
|
||||
age: int
|
||||
|
||||
|
||||
client = instructor.from_provider("openai/gpt-4.1-mini")
|
||||
|
||||
try:
|
||||
response = client.create(
|
||||
response_model=User,
|
||||
messages=[{"role": "user", "content": "Extract user info..."}],
|
||||
max_retries=3,
|
||||
)
|
||||
except InstructorRetryException as e:
|
||||
print(f"Failed after {e.n_attempts} attempts")
|
||||
for attempt in e.failed_attempts:
|
||||
print(f" Attempt {attempt.attempt_number}: {attempt.exception}")
|
||||
```
|
||||
|
||||
### Validation Error
|
||||
|
||||
Raised when the response fails validation:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from pydantic import BaseModel, field_validator
|
||||
from instructor.core.exceptions import ValidationError
|
||||
|
||||
|
||||
class StrictModel(BaseModel):
|
||||
value: int
|
||||
|
||||
@field_validator("value")
|
||||
@classmethod
|
||||
def validate_value(cls, v: int) -> int:
|
||||
if v < 0:
|
||||
raise ValueError("Value must be positive")
|
||||
return v
|
||||
|
||||
|
||||
client = instructor.from_provider("openai/gpt-4.1-mini")
|
||||
|
||||
try:
|
||||
response = client.create(
|
||||
response_model=StrictModel,
|
||||
messages=[{"role": "user", "content": "Extract data..."}],
|
||||
)
|
||||
except ValidationError as e:
|
||||
print(f"Validation failed: {e}")
|
||||
```
|
||||
|
||||
### Provider and Configuration Errors
|
||||
|
||||
Raised for provider-specific issues or invalid configuration:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from instructor.core.exceptions import ConfigurationError, ModeError
|
||||
|
||||
# Invalid provider format
|
||||
try:
|
||||
client = instructor.from_provider("invalid-format")
|
||||
except ConfigurationError as e:
|
||||
print(f"Configuration error: {e}")
|
||||
|
||||
# Wrong mode for provider
|
||||
try:
|
||||
client = instructor.from_provider(
|
||||
"openai/gpt-4.1-mini",
|
||||
mode=instructor.Mode.TOOLS,
|
||||
)
|
||||
except ModeError as e:
|
||||
print(f"Invalid mode. Valid modes: {e.valid_modes}")
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Catch Specific Exceptions
|
||||
|
||||
```python
|
||||
import logging
|
||||
import instructor
|
||||
from pydantic import BaseModel
|
||||
from instructor.core.exceptions import (
|
||||
IncompleteOutputException,
|
||||
InstructorRetryException,
|
||||
ValidationError,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
name: str
|
||||
age: int
|
||||
|
||||
|
||||
client = instructor.from_provider("openai/gpt-4.1-mini")
|
||||
|
||||
try:
|
||||
response = client.create(
|
||||
response_model=User,
|
||||
messages=[{"role": "user", "content": "Extract: Sam is 34"}],
|
||||
)
|
||||
except IncompleteOutputException:
|
||||
logger.warning("Output truncated, retrying with more tokens")
|
||||
response = client.create(
|
||||
response_model=User,
|
||||
messages=[{"role": "user", "content": "Extract: Sam is 34"}],
|
||||
max_tokens=2000,
|
||||
)
|
||||
except InstructorRetryException as e:
|
||||
logger.error(f"Failed after {e.n_attempts} attempts")
|
||||
response = None
|
||||
except ValidationError as e:
|
||||
logger.error(f"Validation failed: {e}")
|
||||
raise
|
||||
```
|
||||
|
||||
### Use Base Exception for General Handling
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from pydantic import BaseModel
|
||||
from instructor.core.exceptions import InstructorError
|
||||
|
||||
|
||||
class Data(BaseModel):
|
||||
value: str
|
||||
|
||||
|
||||
client = instructor.from_provider("openai/gpt-4.1-mini")
|
||||
|
||||
try:
|
||||
response = client.create(
|
||||
response_model=Data,
|
||||
messages=[{"role": "user", "content": "Extract data"}],
|
||||
)
|
||||
except InstructorError as e:
|
||||
# Catches any Instructor-specific error
|
||||
print(f"Instructor error: {type(e).__name__}: {e}")
|
||||
```
|
||||
|
||||
### Graceful Degradation
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from pydantic import BaseModel, field_validator
|
||||
from instructor.core.exceptions import ValidationError, InstructorRetryException
|
||||
|
||||
|
||||
class StrictData(BaseModel):
|
||||
value: int
|
||||
|
||||
@field_validator("value")
|
||||
@classmethod
|
||||
def validate_value(cls, v: int) -> int:
|
||||
if v < 0:
|
||||
raise ValueError("Value must be positive")
|
||||
return v
|
||||
|
||||
|
||||
class RelaxedData(BaseModel):
|
||||
value: str
|
||||
|
||||
|
||||
client = instructor.from_provider("openai/gpt-4.1-mini")
|
||||
|
||||
|
||||
def extract_with_fallback(content: str):
|
||||
try:
|
||||
return client.create(
|
||||
response_model=StrictData,
|
||||
messages=[{"role": "user", "content": content}],
|
||||
)
|
||||
except ValidationError:
|
||||
# Fall back to less strict model
|
||||
return client.create(
|
||||
response_model=RelaxedData,
|
||||
messages=[{"role": "user", "content": content}],
|
||||
)
|
||||
except InstructorRetryException:
|
||||
return None
|
||||
```
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
New exceptions inherit from both `ValueError` and `InstructorError`, so existing code continues to work:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from pydantic import BaseModel
|
||||
from instructor.core.exceptions import ResponseParsingError
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
name: str
|
||||
age: int
|
||||
|
||||
|
||||
client = instructor.from_provider("openai/gpt-4.1-mini")
|
||||
|
||||
# Old code still works
|
||||
try:
|
||||
response = client.create(
|
||||
response_model=User,
|
||||
messages=[{"role": "user", "content": "Extract: Kai is 41"}],
|
||||
)
|
||||
except ValueError as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
# New code can access additional context
|
||||
try:
|
||||
response = client.create(
|
||||
response_model=User,
|
||||
messages=[{"role": "user", "content": "Extract: Kai is 41"}],
|
||||
)
|
||||
except ResponseParsingError as e:
|
||||
print(f"Mode: {e.mode}, Raw: {e.raw_response}")
|
||||
```
|
||||
|
||||
## Integration with Hooks
|
||||
|
||||
Monitor errors using the hooks system:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from instructor.core.exceptions import ValidationError
|
||||
|
||||
|
||||
def on_parse_error(error: Exception):
|
||||
if isinstance(error, ValidationError):
|
||||
print(f"Validation error: {error}")
|
||||
|
||||
|
||||
client = instructor.from_provider("openai/gpt-4.1-mini")
|
||||
client.hooks.on("parse:error", on_parse_error)
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [Retrying](./retrying.md) - Retry strategies with Tenacity
|
||||
- [Validation](./validation.md) - Validation patterns
|
||||
- [Hooks](./hooks.md) - Error monitoring with hooks
|
||||
Reference in New Issue
Block a user