Structured outputs for LLMs with type safety, validation, and automatic retries
—
The instructor package provides a comprehensive mode system for configuring how structured extraction works across different LLM providers. Each mode optimizes for specific provider capabilities and use cases.
The Mode enum defines extraction strategies for different providers and scenarios.
from instructor import Mode
class Mode(Enum):
"""
LLM interaction modes for structured extraction.
Defines how the instructor client should interact with different
LLM providers to achieve structured output extraction.
"""
# OpenAI Modes
TOOLS = "tools"
TOOLS_STRICT = "tools_strict"
JSON = "json"
JSON_O1 = "json_o1"
JSON_SCHEMA = "json_schema"
MD_JSON = "markdown_json"
PARALLEL_TOOLS = "parallel_tools"
FUNCTIONS = "functions" # Deprecated
# Response API Modes
RESPONSES_TOOLS = "responses_tools"
RESPONSES_TOOLS_WITH_INBUILT_TOOLS = "responses_tools_with_inbuilt_tools"
# XAI Modes
XAI_JSON = "xai_json"
XAI_TOOLS = "xai_tools"
# Anthropic Modes
ANTHROPIC_TOOLS = "anthropic_tools"
ANTHROPIC_JSON = "anthropic_json"
ANTHROPIC_REASONING_TOOLS = "anthropic_reasoning_tools"
ANTHROPIC_PARALLEL_TOOLS = "anthropic_parallel_tools"
# Provider-Specific Modes
MISTRAL_TOOLS = "mistral_tools"
VERTEXAI_TOOLS = "vertexai_tools"
GEMINI_TOOLS = "gemini_tools"
COHERE_TOOLS = "cohere_tools"
GROQ_TOOLS = "groq_tools"
FIREWORKS_TOOLS = "fireworks_tools"
CEREBRAS_TOOLS = "cerebras_tools"
WRITER_TOOLS = "writer_tools"
BEDROCK_TOOLS = "bedrock_tools"
@classmethod
def tool_modes(cls) -> List['Mode']:
"""
Get all tool-based modes.
Returns:
List of modes that use function/tool calling
"""
@classmethod
def json_modes(cls) -> List['Mode']:
"""
Get all JSON-based modes.
Returns:
List of modes that use JSON schema extraction
"""
@classmethod
def warn_mode_functions_deprecation(cls) -> None:
"""Warn about deprecated FUNCTIONS mode."""Default and recommended mode for OpenAI models with function calling support.
import instructor
from openai import OpenAI
# Standard tools mode
client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.TOOLS
)
# Usage
result = client.create(
model="gpt-4",
messages=[{"role": "user", "content": "Extract user: John, 25, engineer"}],
response_model=UserProfile
)Strict mode with enhanced schema validation and enforcement.
# Strict tools mode for maximum reliability
client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.TOOLS_STRICT
)
# Enhanced validation and schema enforcement
result = client.create(
model="gpt-4",
messages=[{"role": "user", "content": "Extract data..."}],
response_model=StrictModel,
strict=True # Enforces strict schema adherence
)Direct JSON schema extraction without function calling.
# JSON mode for models without function calling
client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.JSON
)
# Forces JSON response format
result = client.create(
model="gpt-3.5-turbo-1106",
messages=[{"role": "user", "content": "Return JSON: user data..."}],
response_model=UserProfile,
response_format={"type": "json_object"}
)Specialized JSON mode optimized for OpenAI O1 models.
# Optimized for O1 models
client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.JSON_O1
)
result = client.create(
model="o1-preview",
messages=[{"role": "user", "content": "Analyze and extract..."}],
response_model=AnalysisResult
)Parallel function calling for multiple simultaneous extractions.
# Parallel extraction mode
client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.PARALLEL_TOOLS
)
# Can extract multiple entities in one call
results = client.create(
model="gpt-4",
messages=[{"role": "user", "content": "Extract all users and products..."}],
response_model=List[Union[UserProfile, ProductInfo]]
)Primary mode for Anthropic models using their tool calling system.
import instructor
from anthropic import Anthropic
# Standard Anthropic tools
client = instructor.from_anthropic(
Anthropic(),
mode=instructor.Mode.ANTHROPIC_TOOLS
)
result = client.create(
model="claude-3-sonnet-20240229",
messages=[{"role": "user", "content": "Extract information..."}],
response_model=DataModel
)JSON-based extraction for Anthropic models.
# JSON mode for Anthropic
client = instructor.from_anthropic(
Anthropic(),
mode=instructor.Mode.ANTHROPIC_JSON
)
result = client.create(
model="claude-3-haiku-20240307",
messages=[{"role": "user", "content": "Return structured data..."}],
response_model=SimpleModel
)Enhanced mode with reasoning capabilities (beta feature).
# Reasoning tools mode (beta)
client = instructor.from_anthropic(
Anthropic(),
mode=instructor.Mode.ANTHROPIC_REASONING_TOOLS,
beta=True
)
result = client.create(
model="claude-3-opus-20240229",
messages=[{"role": "user", "content": "Analyze and extract insights..."}],
response_model=ReasoningResult,
reasoning=True
)Parallel tool calling for Anthropic models.
# Parallel tools for Anthropic
client = instructor.from_anthropic(
Anthropic(),
mode=instructor.Mode.ANTHROPIC_PARALLEL_TOOLS
)
results = client.create(
model="claude-3-sonnet-20240229",
messages=[{"role": "user", "content": "Extract multiple entities..."}],
response_model=List[EntityType]
)Optimized for Mistral AI models with tool calling.
import instructor
from mistralai.client import MistralClient
client = instructor.from_mistral(
MistralClient(),
mode=instructor.Mode.MISTRAL_TOOLS
)
result = client.create(
model="mistral-large-latest",
messages=[{"role": "user", "content": "Extract data..."}],
response_model=DataModel
)Google Vertex AI integration with function calling.
import instructor
from vertexai.preview.generative_models import GenerativeModel
client = instructor.from_vertexai(
GenerativeModel("gemini-pro"),
mode=instructor.Mode.VERTEXAI_TOOLS
)Google Gemini models with function calling support.
import instructor
import google.generativeai as genai
client = instructor.from_genai(
genai.GenerativeModel("gemini-pro"),
mode=instructor.Mode.GEMINI_TOOLS
)def select_optimal_mode(provider: str, model: str) -> instructor.Mode:
"""
Select optimal mode based on provider and model capabilities.
Args:
provider: LLM provider name
model: Specific model identifier
Returns:
Recommended mode for the provider/model combination
"""
if provider == "openai":
if model.startswith("gpt-4"):
return instructor.Mode.TOOLS_STRICT
elif model.startswith("gpt-3.5-turbo"):
return instructor.Mode.TOOLS
elif model.startswith("o1"):
return instructor.Mode.JSON_O1
else:
return instructor.Mode.JSON
elif provider == "anthropic":
if "opus" in model or "sonnet" in model:
return instructor.Mode.ANTHROPIC_TOOLS
else:
return instructor.Mode.ANTHROPIC_JSON
elif provider == "mistral":
return instructor.Mode.MISTRAL_TOOLS
elif provider == "google":
if "gemini" in model:
return instructor.Mode.GEMINI_TOOLS
else:
return instructor.Mode.VERTEXAI_TOOLS
# Default fallback
return instructor.Mode.JSON
# Usage
optimal_mode = select_optimal_mode("openai", "gpt-4-turbo")
client = instructor.from_openai(OpenAI(), mode=optimal_mode)# Production reliability - use strict modes
production_client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.TOOLS_STRICT
)
# Cost optimization - use JSON modes
cost_optimized_client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.JSON
)
# High throughput - use parallel modes
parallel_client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.PARALLEL_TOOLS
)
# Complex reasoning - use reasoning modes
reasoning_client = instructor.from_anthropic(
Anthropic(),
mode=instructor.Mode.ANTHROPIC_REASONING_TOOLS,
beta=True
)# Comprehensive client configuration
client = instructor.from_openai(
OpenAI(
api_key="your-key",
base_url="https://custom-endpoint.com",
timeout=30.0,
max_retries=3
),
mode=instructor.Mode.TOOLS_STRICT,
# Instructor-specific configuration
hooks=my_hooks,
max_validation_retries=2,
strict_mode=True,
enable_caching=True
)# Tools mode with custom settings
tools_config = {
"strict": True,
"parallel_tool_calls": False,
"tool_choice": "auto"
}
client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.TOOLS_STRICT,
**tools_config
)
# JSON mode with custom settings
json_config = {
"response_format": {"type": "json_object"},
"temperature": 0.1,
"max_tokens": 1000
}
client = instructor.from_openai(
OpenAI(),
mode=instructor.Mode.JSON,
**json_config
)class AdaptiveClient:
"""Client that adapts mode based on context."""
def __init__(self, base_client):
self.base_client = base_client
self.openai_client = instructor.from_openai(base_client)
def create_adaptive(
self,
model: str,
messages: List[Dict],
response_model: Type[BaseModel],
prefer_reliability: bool = True,
**kwargs
):
"""Create with adaptive mode selection."""
# Select mode based on context
if prefer_reliability:
if "gpt-4" in model:
mode = instructor.Mode.TOOLS_STRICT
else:
mode = instructor.Mode.TOOLS
else:
mode = instructor.Mode.JSON
# Recreate client with selected mode
adaptive_client = instructor.from_openai(
self.base_client,
mode=mode
)
return adaptive_client.create(
model=model,
messages=messages,
response_model=response_model,
**kwargs
)
# Usage
adaptive = AdaptiveClient(OpenAI())
# High reliability extraction
result = adaptive.create_adaptive(
model="gpt-4",
messages=[{"role": "user", "content": "Critical data..."}],
response_model=CriticalModel,
prefer_reliability=True
)
# Cost-optimized extraction
result = adaptive.create_adaptive(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Simple data..."}],
response_model=SimpleModel,
prefer_reliability=False
)| Mode | Reliability | Speed | Cost | Streaming | Parallel |
|---|---|---|---|---|---|
| TOOLS | High | Fast | Medium | Yes | No |
| TOOLS_STRICT | Highest | Fast | Medium | Yes | No |
| JSON | Medium | Fastest | Low | Limited | No |
| JSON_O1 | High | Medium | High | No | No |
| PARALLEL_TOOLS | High | Medium | Medium | Yes | Yes |
| ANTHROPIC_TOOLS | High | Fast | Medium | Yes | No |
| ANTHROPIC_REASONING_TOOLS | Highest | Slow | High | Limited | No |
def robust_extraction(
client,
model: str,
messages: List[Dict],
response_model: Type[BaseModel],
fallback_modes: List[instructor.Mode] = None
):
"""Extraction with mode fallback on errors."""
if fallback_modes is None:
fallback_modes = [
instructor.Mode.TOOLS_STRICT,
instructor.Mode.TOOLS,
instructor.Mode.JSON
]
last_error = None
for mode in fallback_modes:
try:
# Recreate client with current mode
mode_client = instructor.from_openai(
client.client, # Access underlying OpenAI client
mode=mode
)
result = mode_client.create(
model=model,
messages=messages,
response_model=response_model
)
return result, mode
except Exception as e:
last_error = e
print(f"Mode {mode} failed: {e}")
continue
raise RuntimeError(f"All modes failed. Last error: {last_error}")
# Usage with fallback
try:
result, used_mode = robust_extraction(
client,
model="gpt-4",
messages=[{"role": "user", "content": "Extract..."}],
response_model=MyModel
)
print(f"Success with mode: {used_mode}")
except RuntimeError as e:
print(f"All extraction attempts failed: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-instructor