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
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:
@@ -0,0 +1,116 @@
|
||||
---
|
||||
title: LLM Validation Basics with Instructor
|
||||
description: Master the fundamentals of validating LLM outputs to ensure reliable, business-compliant structured data from GPT-4, Claude, and other models.
|
||||
---
|
||||
|
||||
# LLM Validation Tutorial: Ensure Data Quality with Instructor
|
||||
|
||||
Master the fundamentals of validating LLM outputs in this comprehensive tutorial. Learn how to use Instructor's validation system to ensure GPT-4, Claude, and other language models produce reliable, business-compliant structured data.
|
||||
|
||||
## Why LLM Output Validation is Critical
|
||||
|
||||
When extracting structured data from LLMs, validation ensures:
|
||||
|
||||
1. **Data Integrity**: LLM outputs contain all required fields with correct formats
|
||||
2. **Business Compliance**: Extracted data adheres to your domain rules and constraints
|
||||
3. **Production Reliability**: LLM responses meet quality standards before entering your system
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
||||
│ LLM │ -> │ Instructor │ -> │ Validated │
|
||||
│ Generates │ │ Validates │ │ Structured │
|
||||
│ Response │ │ Structure │ │ Data │
|
||||
└─────────────┘ └──────────────┘ └─────────────┘
|
||||
│
|
||||
│ If validation fails
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ Retry with │
|
||||
│ Feedback │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## Basic LLM Validation Example
|
||||
|
||||
See how Instructor validates LLM outputs automatically:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, Field
|
||||
import instructor
|
||||
# Define validation rules for LLM extraction
|
||||
class UserProfile(BaseModel):
|
||||
name: str
|
||||
age: int = Field(ge=13, description="User's age in years")
|
||||
|
||||
# Extract and validate LLM output
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
response = client.create(
|
||||
model="gpt-5.4-mini", # Works with GPT-4, Claude, Gemini
|
||||
messages=[
|
||||
{"role": "user", "content": "My name is Jane Smith and I'm 25 years old."}
|
||||
],
|
||||
response_model=UserProfile # Automatic validation
|
||||
)
|
||||
|
||||
print(f"User: {response.name}, Age: {response.age}")
|
||||
```
|
||||
|
||||
Key validation features in this LLM tutorial:
|
||||
- **Constraint Validation**: Age must be ≥ 13 years
|
||||
- **Automatic Retry**: If LLM output fails validation, Instructor retries with error context
|
||||
- **Type Safety**: Ensures LLM returns proper data types
|
||||
|
||||
## Essential LLM Validation Patterns
|
||||
|
||||
Common validation rules for LLM outputs:
|
||||
|
||||
| Validation | Example | What It Does |
|
||||
|------------|---------|-------------|
|
||||
| Type checking | `age: int` | Ensures value is an integer |
|
||||
| Required fields | `name: str` | Field must be present |
|
||||
| Optional fields | `middle_name: Optional[str] = None` | Field can be missing |
|
||||
| Minimum value | `age: int = Field(ge=18)` | Value must be ≥ 18 |
|
||||
| Maximum value | `rating: float = Field(le=5.0)` | Value must be ≤ 5.0 |
|
||||
| String length | `username: str = Field(min_length=3)` | String must be at least 3 chars |
|
||||
|
||||
## How LLM Output Validation Works
|
||||
|
||||
The LLM validation pipeline in Instructor:
|
||||
|
||||
1. **LLM Generation**: Language model produces structured output
|
||||
2. **Schema Matching**: Instructor maps LLM response to your Pydantic model
|
||||
3. **Validation Check**: Pydantic validates against defined constraints
|
||||
4. **Smart Retry**: On failure, errors are sent back to the LLM with context
|
||||
5. **Success or Timeout**: Process continues until valid output or retry limit
|
||||
|
||||
## Enhance LLM Validation with Custom Messages
|
||||
|
||||
Guide LLMs with specific error messages for better corrections:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
class Product(BaseModel):
|
||||
name: str
|
||||
price: float = Field(
|
||||
gt=0,
|
||||
description="Product price in USD",
|
||||
json_schema_extra={"error_msg": "Price must be greater than zero"}
|
||||
)
|
||||
```
|
||||
|
||||
## Common LLM Validation Use Cases
|
||||
|
||||
- **Age Verification**: Ensure extracted ages meet minimum requirements
|
||||
- **Price Validation**: Verify LLM-extracted prices are positive numbers
|
||||
- **Email Format**: Validate email addresses from unstructured text
|
||||
- **Date Constraints**: Ensure dates are within valid ranges
|
||||
- **Business Rules**: Enforce domain-specific constraints on LLM outputs
|
||||
|
||||
## Continue Your LLM Validation Journey
|
||||
|
||||
- **[Custom Validators](custom_validators.md)** - Build complex validation logic for LLM outputs
|
||||
- **[Retry Mechanisms](retry_mechanisms.md)** - Configure how Instructor handles validation failures
|
||||
- **[Field-Level Validation](field_level_validation.md)** - Validate individual fields in LLM responses
|
||||
|
||||
Master validation to ensure your LLM applications produce reliable, production-ready data!
|
||||
@@ -0,0 +1,220 @@
|
||||
---
|
||||
title: Custom Validators for LLM Outputs
|
||||
description: Learn to build custom validators for LLM outputs using rule-based and semantic validation techniques with Instructor.
|
||||
---
|
||||
|
||||
# Custom LLM Validators Tutorial: Advanced Data Quality Control
|
||||
|
||||
Learn how to build custom validators for LLM outputs in this advanced tutorial. Master both rule-based and semantic validation techniques to ensure GPT-4, Claude, and other language models produce data that meets your exact requirements.
|
||||
|
||||
## Basic Custom Validator
|
||||
|
||||
Custom validators are functions that validate field values and can be applied using Pydantic's field validators.
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, field_validator
|
||||
import instructor
|
||||
|
||||
# Initialize the client
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
|
||||
class Person(BaseModel):
|
||||
name: str
|
||||
age: int
|
||||
|
||||
@field_validator('age')
|
||||
@classmethod
|
||||
def validate_age(cls, value):
|
||||
if value < 0 or value > 120:
|
||||
raise ValueError("Age must be between 0 and 120")
|
||||
return value
|
||||
|
||||
# Extract data with validation
|
||||
response = client.create(
|
||||
model="gpt-5.4-mini",
|
||||
messages=[
|
||||
{"role": "user", "content": "The person's name is John and they are 150 years old."}
|
||||
],
|
||||
response_model=Person
|
||||
)
|
||||
```
|
||||
|
||||
If the model returns an age outside the valid range, Instructor will retry the request with specific feedback about the validation failure.
|
||||
|
||||
For more information on how Instructor handles validation and retries, see [Validation Basics](../../concepts/validation.md) and the [Retrying](../../concepts/retrying.md) concepts page.
|
||||
|
||||
## Complex Validation
|
||||
|
||||
You can create more complex validators that check multiple fields or have conditional logic:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, field_validator, model_validator
|
||||
import instructor
|
||||
from typing import List, Optional
|
||||
from datetime import date
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
|
||||
class Employee(BaseModel):
|
||||
name: str
|
||||
hire_date: date
|
||||
termination_date: Optional[date] = None
|
||||
skills: List[str]
|
||||
|
||||
@field_validator('skills')
|
||||
@classmethod
|
||||
def validate_skills(cls, skills):
|
||||
if len(skills) < 1:
|
||||
raise ValueError("Employee must have at least one skill")
|
||||
return skills
|
||||
|
||||
@model_validator(mode='after')
|
||||
def validate_dates(self):
|
||||
if self.termination_date and self.termination_date < self.hire_date:
|
||||
raise ValueError("Termination date cannot be before hire date")
|
||||
return self
|
||||
```
|
||||
|
||||
For more advanced validation approaches, check out [Field-level Validation](../../concepts/fields.md) and the [Validators](../../concepts/reask_validation.md) concepts page.
|
||||
|
||||
## Handling Complex Data Types
|
||||
|
||||
Custom validators can also process more complex data types and perform transformations:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, field_validator
|
||||
import instructor
|
||||
import re
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
|
||||
class Contact(BaseModel):
|
||||
name: str
|
||||
email: str
|
||||
phone: str
|
||||
|
||||
@field_validator('email')
|
||||
@classmethod
|
||||
def validate_email(cls, value):
|
||||
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
||||
if not re.match(pattern, value):
|
||||
raise ValueError("Invalid email format")
|
||||
return value
|
||||
|
||||
@field_validator('phone')
|
||||
@classmethod
|
||||
def validate_phone(cls, value):
|
||||
# Remove non-digit characters and validate
|
||||
digits_only = re.sub(r'\D', '', value)
|
||||
if len(digits_only) < 10:
|
||||
raise ValueError("Phone number must have at least 10 digits")
|
||||
return digits_only # Return the cleaned version
|
||||
```
|
||||
|
||||
For a practical example of extraction with validation, see the [Contact Information Extraction](../../examples/extract_contact_info.md) example.
|
||||
|
||||
## Using External Services for Validation
|
||||
|
||||
You can also use external services or APIs for validation:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, field_validator
|
||||
import instructor
|
||||
import requests
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
|
||||
class Address(BaseModel):
|
||||
street: str
|
||||
city: str
|
||||
state: str
|
||||
zip_code: str
|
||||
|
||||
@field_validator('zip_code')
|
||||
@classmethod
|
||||
def validate_zip_code(cls, value):
|
||||
# Example of validation using an external service (simplified)
|
||||
# In a real app, you might use a postal code validation API
|
||||
if not (value.isdigit() and len(value) == 5):
|
||||
raise ValueError("Zip code must be 5 digits")
|
||||
return value
|
||||
```
|
||||
|
||||
## Semantic Validation with LLMs
|
||||
|
||||
For complex validation scenarios where rule-based validation is difficult, Instructor provides semantic validation capabilities using LLMs via the `llm_validator` function. For a comprehensive guide on this topic, see the dedicated [Semantic Validation](../../concepts/semantic_validation.md) page:
|
||||
|
||||
```python
|
||||
from typing import Annotated
|
||||
from pydantic import BaseModel, BeforeValidator
|
||||
import instructor
|
||||
from instructor import llm_validator
|
||||
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
|
||||
class ProductDescription(BaseModel):
|
||||
product_name: str
|
||||
description: Annotated[
|
||||
str,
|
||||
BeforeValidator(
|
||||
llm_validator(
|
||||
"The description must be professional, accurate, and free of hyperbole. "
|
||||
"It should not make unsubstantiated claims or use superlatives excessively.",
|
||||
client=client
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
# This would fail validation because it uses excessive hyperbole
|
||||
try:
|
||||
product = ProductDescription(
|
||||
product_name="SuperClean 3000",
|
||||
description="The absolute BEST cleaning product in the world! Will change your life FOREVER! Makes every other cleaning product completely OBSOLETE!"
|
||||
)
|
||||
except ValueError as e:
|
||||
print(e) # The validation error would explain the issue with the hyperbolic language
|
||||
```
|
||||
|
||||
Semantic validation is particularly useful for validating against criteria that are:
|
||||
|
||||
1. **Subjective** - Such as tone, style, or appropriateness
|
||||
2. **Contextual** - Requiring understanding of relationships between elements
|
||||
3. **Complex** - Where multiple interrelated factors need to be evaluated together
|
||||
4. **Hard to formalize** - When rules would be too numerous or complex to express programmatically
|
||||
|
||||
Unlike rule-based validators that check against predefined criteria, semantic validators leverage LLMs to evaluate content based on natural language instructions. They can understand nuance and context in ways that traditional validation cannot.
|
||||
|
||||
### When to Use Semantic Validation
|
||||
|
||||
Consider using semantic validation when:
|
||||
|
||||
- You need to enforce style guidelines or content policies
|
||||
- Validating natural language content against subjective criteria
|
||||
- Checking for consistency across multiple fields or complex relationships
|
||||
- Traditional validation would require hundreds of individual rules
|
||||
|
||||
Remember that semantic validation requires additional API calls, which adds cost and latency to your application. Use it strategically for high-value validation needs rather than for simple constraints that can be handled with standard validators.
|
||||
|
||||
## Handling Validation Failures
|
||||
|
||||
When validation fails, Instructor can handle it in different ways. Learn more about:
|
||||
|
||||
- [Retry Mechanisms](../../concepts/retrying.md) for automatic retries with feedback
|
||||
- [Self-Correction](../../examples/self_critique.md) for AI model self-correction techniques
|
||||
|
||||
## Best Practices for Custom Validators
|
||||
|
||||
1. **Be specific in error messages**: Provide clear error messages that explain exactly what went wrong
|
||||
2. **Validate early**: Apply validators to individual fields when possible before model-level validation
|
||||
3. **Keep validators focused**: Each validator should have a single responsibility
|
||||
4. **Use type hints**: Proper type hints help both Pydantic and Instructor understand your data better
|
||||
5. **Consider both validation and transformation**: Validators can both validate and transform data
|
||||
6. **Choose appropriate validation type**: Use rule-based validation for simple, objective criteria and semantic validation for complex, subjective, or context-dependent validation
|
||||
7. **Balance cost and benefits**: Consider the additional cost and latency of semantic validation against the value it provides
|
||||
|
||||
For more information on validation in general, check out the [Validation](../../concepts/validation.md) concepts page.
|
||||
|
||||
## Related Resources
|
||||
|
||||
- [Fields](../../concepts/fields.md) - Learn about field definitions and properties
|
||||
- [Models](../../concepts/models.md) - Understand model creation and configuration
|
||||
- [Types](../../concepts/types.md) - Explore the different data types you can use
|
||||
|
||||
Custom validators are a powerful way to ensure the data you extract meets your specific requirements, improving the reliability and quality of structured outputs from LLMs.
|
||||
@@ -0,0 +1,128 @@
|
||||
---
|
||||
title: Field-level Validation with Instructor
|
||||
description: Learn how to create specific validation rules for individual fields in your Pydantic models to ensure data quality.
|
||||
---
|
||||
|
||||
# Field-level Validation
|
||||
|
||||
Field-level validation lets you create specific rules for individual fields in your data models. This guide shows how to use field-level validation with Instructor.
|
||||
|
||||
## What is Field-level Validation?
|
||||
|
||||
Field-level validation in Instructor uses Pydantic's validation features to:
|
||||
|
||||
1. Check individual fields with custom rules
|
||||
2. Transform field values (like formatting or cleaning data)
|
||||
3. Apply business rules to specific fields
|
||||
4. Give clear feedback when values are invalid
|
||||
|
||||
Validation happens when your model is being processed, and if it fails, Instructor will retry with better instructions.
|
||||
|
||||
## Basic Field Validation
|
||||
|
||||
You can apply simple validation using Pydantic's Field constraints:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, Field
|
||||
import instructor
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
|
||||
class User(BaseModel):
|
||||
name: str = Field(..., min_length=2, description="User's full name")
|
||||
age: int = Field(..., ge=18, le=120, description="User's age in years")
|
||||
email: str = Field(
|
||||
...,
|
||||
pattern=r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
||||
description="Valid email address"
|
||||
)
|
||||
```
|
||||
|
||||
For more details, see the [Fields](../../concepts/fields.md) concepts page.
|
||||
|
||||
## Custom Field Validators
|
||||
|
||||
For more complex rules, use the `field_validator` decorator:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, field_validator
|
||||
import instructor
|
||||
import re
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
|
||||
class Product(BaseModel):
|
||||
name: str
|
||||
sku: str
|
||||
price: float
|
||||
|
||||
@field_validator('name')
|
||||
@classmethod
|
||||
def validate_name(cls, v):
|
||||
if len(v.strip()) < 3:
|
||||
raise ValueError("Product name must be at least 3 characters long")
|
||||
return v.strip().title() # Clean up and format
|
||||
|
||||
@field_validator('sku')
|
||||
@classmethod
|
||||
def validate_sku(cls, v):
|
||||
pattern = r'^[A-Z]{3}-\d{4}$'
|
||||
if not re.match(pattern, v):
|
||||
raise ValueError("SKU must be in format XXX-0000 (3 uppercase letters, dash, 4 digits)")
|
||||
return v
|
||||
```
|
||||
|
||||
## Validating Multiple Fields Together
|
||||
|
||||
Sometimes one field's validity depends on other fields. Use `model_validator` for this:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel, model_validator
|
||||
import instructor
|
||||
from datetime import date
|
||||
client = instructor.from_provider("openai/gpt-5-nano")
|
||||
|
||||
class Reservation(BaseModel):
|
||||
check_in: date
|
||||
check_out: date
|
||||
room_type: str
|
||||
guests: int
|
||||
|
||||
@model_validator(mode='after')
|
||||
def validate_dates(self):
|
||||
if self.check_out <= self.check_in:
|
||||
raise ValueError("Check-out date must be after check-in date")
|
||||
|
||||
if self.room_type == "Standard" and self.guests > 2:
|
||||
raise ValueError("Standard rooms can only fit 2 guests")
|
||||
|
||||
return self
|
||||
```
|
||||
|
||||
## How Validation Errors Are Handled
|
||||
|
||||
When validation fails, Instructor adds error details to help the AI fix the problem:
|
||||
|
||||
```
|
||||
The following errors occurred during validation:
|
||||
- product_sku: Product not found
|
||||
- quantity: Quantity must be at least 1
|
||||
|
||||
Please fix these errors and ensure the response is valid.
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Order matters**: Validators run in the order they're defined
|
||||
2. **Clear messages**: Write specific error messages
|
||||
3. **Clean first**: Handle data cleaning before validation
|
||||
4. **Validate early**: Check fields before model-level validation
|
||||
5. **Transform wisely**: Field validators can both check and change values
|
||||
|
||||
## Related Resources
|
||||
|
||||
- [Fields](../../concepts/fields.md) - Basic field properties
|
||||
- [Custom Validators](../../concepts/reask_validation.md) - Creating custom validation logic
|
||||
- [Validation Basics](../../concepts/validation.md) - Fundamental validation concepts
|
||||
- [Retry Mechanisms](../../concepts/retrying.md) - How validation retries work
|
||||
- [Fallback Strategies](../../concepts/error_handling.md) - Handling persistent validation failures
|
||||
- [Types](../../concepts/types.md) - Understanding data types in Pydantic models
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
# Retry Mechanisms
|
||||
|
||||
Retry mechanisms in Instructor handle validation failures by giving the LLM another chance to generate valid responses. This guide explains how retries work and how to customize them for your use case.
|
||||
|
||||
## How Retries Work
|
||||
|
||||
When validation fails, Instructor:
|
||||
|
||||
1. Captures the validation error(s)
|
||||
2. Formats them as feedback
|
||||
3. Adds the feedback to the prompt context
|
||||
4. Asks the LLM to try again with this new information
|
||||
|
||||
This creates a feedback loop that helps the LLM correct its output until it produces a valid response.
|
||||
|
||||
## Basic Retry Example
|
||||
|
||||
Here's a simple example showing retries in action:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
# Initialize the client with max_retries
|
||||
client = instructor.from_provider(
|
||||
"openai/gpt-4o",
|
||||
max_retries=2 # Will try up to 3 times (initial + 2 retries)
|
||||
)
|
||||
|
||||
class Product(BaseModel):
|
||||
name: str
|
||||
price: float = Field(..., gt=0)
|
||||
|
||||
@field_validator('name')
|
||||
@classmethod
|
||||
def validate_name(cls, v):
|
||||
if len(v) < 3:
|
||||
raise ValueError("Product name must be at least 3 characters")
|
||||
return v
|
||||
|
||||
# This will automatically retry if validation fails
|
||||
response = client.create(
|
||||
model="gpt-5.4-mini",
|
||||
messages=[
|
||||
{"role": "user", "content": "Product: Pen, Price: -5"}
|
||||
],
|
||||
response_model=Product
|
||||
)
|
||||
```
|
||||
|
||||
In this example, the initial response will likely fail validation because:
|
||||
- The price is negative (violating the `gt=0` constraint)
|
||||
- Instructor will automatically retry with feedback about these issues
|
||||
|
||||
For more details on max_retries configuration, see the [Retrying](../../concepts/retrying.md) concepts page.
|
||||
|
||||
## Customizing Retry Behavior
|
||||
|
||||
You can customize retry behavior when initializing the Instructor client:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
|
||||
# Customize retry behavior
|
||||
client = instructor.from_provider(
|
||||
"openai/gpt-4o",
|
||||
max_retries=3, # Maximum number of retries
|
||||
retry_if_parsing_fails=True, # Retry on JSON parsing failures
|
||||
throw_error=True # Throw an error if all retries fail
|
||||
)
|
||||
```
|
||||
|
||||
### Retry Configuration Options
|
||||
|
||||
| Option | Description | Default |
|
||||
|--------|-------------|---------|
|
||||
| `max_retries` | Maximum number of retry attempts | 0 |
|
||||
| `retry_if_parsing_fails` | Whether to retry if JSON parsing fails | True |
|
||||
| `throw_error` | Whether to throw an error if all retries fail | True |
|
||||
|
||||
## Handling Retry Failures
|
||||
|
||||
When all retries fail, Instructor raises an `InstructorRetryException` that contains comprehensive information about all failed attempts:
|
||||
|
||||
```python
|
||||
from instructor.core.exceptions import InstructorRetryException
|
||||
|
||||
try:
|
||||
response = client.create(
|
||||
model="gpt-5.4-mini",
|
||||
messages=[{"role": "user", "content": "Product: Invalid data"}],
|
||||
response_model=Product,
|
||||
max_retries=3
|
||||
)
|
||||
except InstructorRetryException as e:
|
||||
print(f"Failed after {e.n_attempts} attempts")
|
||||
print(f"Total usage: {e.total_usage}")
|
||||
|
||||
# New: Access detailed information about each failed attempt
|
||||
for attempt in e.failed_attempts:
|
||||
print(f"Attempt {attempt.attempt_number}: {attempt.exception}")
|
||||
if attempt.completion:
|
||||
# Analyze the raw completion that failed validation
|
||||
print(f"Raw response: {attempt.completion}")
|
||||
```
|
||||
|
||||
The `InstructorRetryException` now includes:
|
||||
|
||||
- `failed_attempts`: A list of `FailedAttempt` objects containing:
|
||||
- `attempt_number`: The retry attempt number
|
||||
- `exception`: The specific exception that occurred
|
||||
- `completion`: The raw LLM response (when available)
|
||||
- `n_attempts`: Total number of attempts made
|
||||
- `total_usage`: Total token usage across all attempts
|
||||
- `last_completion`: The final failed completion
|
||||
- `messages`: The conversation history
|
||||
|
||||
This comprehensive tracking enables better debugging and analysis of retry patterns.
|
||||
|
||||
For more on handling validation failures, see [Fallback Strategies](../../concepts/error_handling.md).
|
||||
|
||||
## Error Messages and Feedback
|
||||
|
||||
Instructor provides detailed error messages to the LLM during retries:
|
||||
|
||||
```
|
||||
The following errors occurred during validation:
|
||||
- price: ensure this value is greater than 0
|
||||
- name: Product name must be at least 3 characters
|
||||
|
||||
Please fix these errors and ensure the response is valid.
|
||||
```
|
||||
|
||||
This feedback helps the LLM understand exactly what needs to be fixed.
|
||||
|
||||
## Retry Limitations
|
||||
|
||||
While retries are powerful, they have some limitations:
|
||||
|
||||
1. **Retry Budget**: Each retry consumes tokens and time
|
||||
2. **Persistent Errors**: Some errors might not be fixable by the LLM
|
||||
3. **Model Limitations**: Some models may consistently struggle with certain validations
|
||||
|
||||
For complex validation scenarios, consider implementing [Custom Validators](custom_validators.md) or [Field-level Validation](field_level_validation.md).
|
||||
|
||||
## Advanced Retry Pattern: Progressive Validation
|
||||
|
||||
For complex schemas, you can implement a progressive validation pattern:
|
||||
|
||||
```python
|
||||
import instructor
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
# Initialize with moderate retries
|
||||
client = instructor.from_provider(
|
||||
"openai/gpt-4o",
|
||||
max_retries=2
|
||||
)
|
||||
|
||||
# Basic validation first
|
||||
class BasicProduct(BaseModel):
|
||||
name: str
|
||||
price: float = Field(..., gt=0)
|
||||
|
||||
# Advanced validation second
|
||||
class DetailedProduct(BasicProduct):
|
||||
description: str = Field(..., min_length=10)
|
||||
category: str
|
||||
in_stock: bool
|
||||
|
||||
# Two-step extraction with validation
|
||||
try:
|
||||
# First get basic fields
|
||||
basic = client.create(
|
||||
model="gpt-5.4-mini",
|
||||
messages=[
|
||||
{"role": "user", "content": "Product: Mini Pen, Price: $2.50"}
|
||||
],
|
||||
response_model=BasicProduct
|
||||
)
|
||||
|
||||
# Then get full details with context from the first step
|
||||
detailed = client.create(
|
||||
model="gpt-5.4-mini",
|
||||
messages=[
|
||||
{"role": "user", "content": f"Provide more details about {basic.name} which costs ${basic.price}"}
|
||||
],
|
||||
response_model=DetailedProduct
|
||||
)
|
||||
except Exception as e:
|
||||
# Handle validation failures
|
||||
print(f"Validation failed: {e}")
|
||||
```
|
||||
|
||||
## Related Resources
|
||||
|
||||
- [Retrying](../../concepts/retrying.md) - Core retry concepts
|
||||
- [Validation](../../concepts/validation.md) - Main validation documentation
|
||||
- [Custom Validators](../../concepts/reask_validation.md) - Creating custom validation logic
|
||||
- [Fallback Strategies](../../concepts/error_handling.md) - Handling persistent validation failures
|
||||
- [Self Critique](../../examples/self_critique.md) - Example of model self-correction
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Learn about [Field-level Validation](field_level_validation.md)
|
||||
- Implement [Custom Validators](custom_validators.md)
|
||||
Reference in New Issue
Block a user