참고소스 수정본

This commit is contained in:
LASTA_DEV01\lasta
2026-05-12 19:40:31 +09:00
parent 0f34a451fc
commit 2e9204243d
8708 changed files with 3259488 additions and 869 deletions

View File

@@ -0,0 +1,673 @@
---
title: "Anthropic Claude Tutorial: Structured Outputs with Instructor"
description: "Complete guide to using Anthropic's Claude models with Instructor for structured data extraction. Learn how to use Claude Haiku for type-safe outputs in Python."
---
## See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [from_provider Guide](../concepts/from_provider.md) - Detailed client configuration
- [Provider Examples](../index.md#provider-examples) - Quick examples for all providers
- [Mode Comparison](../modes-comparison.md) - Using Anthropic's tool calling
# Anthropic Claude Tutorial: Structured Outputs with Instructor
Learn how to use Anthropic's Claude Haiku models with Instructor to extract structured, validated data. This tutorial covers everything from basic setup to advanced patterns for production use.
## Quick Start: Install Instructor for Claude
Get started with Claude and Instructor for structured outputs:
```
pip install "instructor[anthropic]"
```
Once we've done so, getting started is as simple as using our `from_provider` method to patch the client up.
### Basic Usage
```python
# Standard library imports
import os
from typing import List
# Third-party imports
import anthropic
import instructor
from pydantic import BaseModel, Field
# Set up environment (typically handled before script execution)
# os.environ["ANTHROPIC_API_KEY"] = "your-api-key" # Uncomment and replace with your API key if not set
# Define your models with proper type annotations
class Properties(BaseModel):
"""Model representing a key-value property."""
name: str = Field(description="The name of the property")
value: str = Field(description="The value of the property")
class User(BaseModel):
"""Model representing a user with properties."""
name: str = Field(description="The user's full name")
age: int = Field(description="The user's age in years")
properties: List[Properties] = Field(description="List of user properties")
client = instructor.from_provider(
"anthropic/claude-4-5-haiku-latest",
mode=instructor.Mode.TOOLS
)
try:
# Extract structured data
user_response = client.create(
max_tokens=1024,
messages=[
{
"role": "system",
"content": "Extract structured information based on the user's request."
},
{
"role": "user",
"content": "Create a user for a model with a name, age, and properties.",
}
],
response_model=User,
)
# Print the result as formatted JSON
print(user_response.model_dump_json(indent=2))
# Expected output:
# {
# "name": "John Doe",
# "age": 35,
# "properties": [
# {
# "name": "City",
# "value": "New York"
# },
# {
# "name": "Occupation",
# "value": "Software Engineer"
# }
# ]
# }
except instructor.exceptions.InstructorError as e:
print(f"Validation error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
```
### Async Example
```python
import asyncio
async_client = instructor.from_provider(
"anthropic/claude-4-5-haiku-latest",
async_client=True,
mode=instructor.Mode.TOOLS,
)
async def extract_user():
return await async_client.create(
messages=[{"role": "user", "content": "Extract: Jason is 25 years old"}],
response_model=User,
)
user = asyncio.run(extract_user())
print(user)
```
### Parallel Tool Calling
Parallel tool mode is automatically detected when your response model is `Iterable[Union[Model1, Model2, ...]]`. Just use `Mode.TOOLS` (or let it default) and the handler will automatically:
- Set tool_choice to "auto" (required for parallel)
- Generate schemas for all union members
- Return a generator yielding each tool result
```python
from typing import Iterable, Literal
from pydantic import BaseModel
import instructor
class Weather(BaseModel):
location: str
units: Literal["imperial", "metric"]
class GoogleSearch(BaseModel):
query: str
# No need to specify Mode.PARALLEL_TOOLS - it's auto-detected!
client = instructor.from_provider(
"anthropic/claude-3-5-haiku-latest",
mode=instructor.Mode.TOOLS, # or just omit and use default
)
results = client.create(
messages=[
{"role": "system", "content": "You must always use tools"},
{
"role": "user",
"content": "What is the weather in toronto and dallas and who won the super bowl?",
},
],
response_model=Iterable[Weather | GoogleSearch], # Auto-detects parallel mode
)
for item in results:
print(item)
```
**How it works**: When Instructor detects `Iterable[Union[...]]`, it automatically:
1. Sets `tool_choice` to `"auto"` (allows model to call any tool)
2. Generates tool schemas from all union members
3. Returns a generator that yields each extracted tool call
4. Each yielded item is validated against its corresponding Pydantic model
## Multimodal
> We've provided a few different sample files for you to use to test out these new features. All examples below use these files.
>
> - (Image) : An image of some blueberry plants [image.jpg](https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/image.jpg)
> - (PDF) : A sample PDF file which contains a fake invoice [invoice.pdf](https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf)
Instructor provides a unified, provider-agnostic interface for working with multimodal inputs like images, PDFs, and audio files. With Instructor's multimodal objects, you can easily load media from URLs, local files, or base64 strings using a consistent API that works across different AI providers (OpenAI, Anthropic, Mistral, etc.).
Instructor handles all the provider-specific formatting requirements behind the scenes, ensuring your code remains clean and future-proof as provider APIs evolve.
Let's see how to use the Image and PDF classes.
### Image
> For a more in-depth walkthrough of the Image component, check out the [docs here](../concepts/multimodal.md)
Instructor makes it easy to analyse and extract semantic information from images using Anthropic's claude models. [Click here](https://docs.anthropic.com/en/docs/about-claude/models/all-models) to check if the model you'd like to use has vison capabilities.
Let's see an example below with the sample image above where we'll load it in using our `from_url` method.
Note that we support local files and base64 strings too with the `from_path` and the `from_base64` class methods.
```python
from instructor.processing.multimodal import Image
from pydantic import BaseModel, Field
import instructor
from anthropic import Anthropic
class ImageDescription(BaseModel):
objects: list[str] = Field(..., description="The objects in the image")
scene: str = Field(..., description="The scene of the image")
colors: list[str] = Field(..., description="The colors in the image")
client = instructor.from_provider("anthropic/claude-4-5-haiku-latest")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/image.jpg"
# Multiple ways to load an image:
response = client.create(
response_model=ImageDescription,
max_tokens=1000,
messages=[
{
"role": "user",
"content": [
"What is in this image?",
# Option 1: Direct URL with autodetection
Image.from_url(url),
# Option 2: Local file
# Image.from_path("path/to/local/image.jpg")
# Option 3: Base64 string
# Image.from_base64("base64_encoded_string_here")
# Option 4: Autodetect
# Image.autodetect(<url|path|base64>)
],
},
],
)
print(response)
# Example output:
# ImageDescription(
# objects=['blueberries', 'leaves'],
# scene='A blueberry bush with clusters of ripe blueberries and some unripe ones against a cloudy sky',
# colors=['green', 'blue', 'purple', 'white']
# )
```
### PDF
Instructor makes it easy to analyse and extract semantic information from PDFs using Anthropic's Claude line of models.
Let's see an example below with the sample PDF above where we'll load it in using our `from_url` method.
Note that we support local files and base64 strings too with the `from_path` and the `from_base64` class methods.
```python
from instructor.processing.multimodal import PDF
from pydantic import BaseModel, Field
import instructor
from anthropic import Anthropic
class Receipt(BaseModel):
total: int
items: list[str]
client = instructor.from_provider("anthropic/claude-4-5-haiku-latest")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf"
# Multiple ways to load an PDF:
response = client.create(
response_model=Receipt,
max_tokens=1000,
messages=[
{
"role": "user",
"content": [
"Extract out the total and line items from the invoice",
# Option 1: Direct URL
PDF.from_url(url),
# Option 2: Local file
# PDF.from_path("path/to/local/invoice.pdf"),
# Option 3: Base64 string
# PDF.from_base64("base64_encoded_string_here")
# Option 4: Autodetect
# PDF.autodetect(<url|path|base64>)
],
},
],
)
print(response)
# > Receipt(total=220, items=['English Tea', 'Tofu'])
```
If you'd like to cache the PDF and use it across multiple different requests, we support that with the `PdfWithCacheControl` class which we can see below.
```python
from instructor.processing.multimodal import PdfWithCacheControl
from pydantic import BaseModel
import instructor
from anthropic import Anthropic
class Receipt(BaseModel):
total: int
items: list[str]
client = instructor.from_provider("anthropic/claude-4-5-haiku-latest")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf"
# Multiple ways to load an PDF:
response, completion = client.create_with_completion(
response_model=Receipt,
max_tokens=1000,
messages=[
{
"role": "user",
"content": [
"Extract out the total and line items from the invoice",
# Option 1: Direct URL
PdfWithCacheControl.from_url(url),
# Option 2: Local file
# PDF.from_path("path/to/local/invoice.pdf"),
# Option 3: Base64 string
# PDF.from_base64("base64_encoded_string_here")
# Option 4: Autodetect
# PDF.autodetect(<url|path|base64>)
],
},
],
)
assert (
completion.usage.cache_creation_input_tokens > 0
or completion.usage.cache_read_input_tokens > 0
)
print(response)
# > Receipt(total=220, items=['English Tea', 'Tofu'])
```
## Streaming Support
Instructor has two main ways that you can use to stream responses out
1. **Iterables**: These are useful when you'd like to stream a list of objects of the same type (Eg. use structured outputs to extract multiple users)
2. **Partial Streaming**: This is useful when you'd like to stream a single object and you'd like to immediately start processing the response as it comes in.
### Partials
You can use our `create_partial` method to stream a single object. Note that validators should not be declared in the response model when streaming objects because it will break the streaming process.
```python
# Standard library imports
import os
# Third-party imports
import anthropic
import instructor
from pydantic import BaseModel, Field
# Set up environment (typically handled before script execution)
# os.environ["ANTHROPIC_API_KEY"] = "your-api-key" # Uncomment and replace with your API key if not set
# Initialize client with explicit mode
client = instructor.from_provider(
"anthropic/claude-4-5-haiku-latest",
mode=instructor.Mode.TOOLS,
)
# Define your model with proper annotations
class User(BaseModel):
"""Model representing a user profile."""
name: str = Field(description="The user's full name")
age: int = Field(description="The user's age in years")
bio: str = Field(description="A biographical description of the user")
try:
# Stream partial objects as they're generated
for partial_user in client.create_partial(
messages=[
{"role": "system", "content": "Create a detailed user profile based on the information provided."},
{"role": "user", "content": "Create a user profile for Jason, age 25"},
],
response_model=User,
max_tokens=4096,
):
print(f"Current state: {partial_user}")
# Expected output:
# > Current state: name='Jason' age=None bio=None
# > Current state: name='Jason' age=25 bio='Jason is a 25-year-old with an adventurous spirit and a love for technology. He is'
# > Current state: name='Jason' age=25 bio='Jason is a 25-year-old with an adventurous spirit and a love for technology. He is always on the lookout for new challenges and opportunities to grow both personally and professionally.'
except Exception as e:
print(f"Error during streaming: {e}")
```
### Iterable Example
You can also use our `create_iterable` method to stream a list of objects. This is helpful when you'd like to extract multiple instances of the same response model from a single prompt.
```python
# Standard library imports
import os
# Third-party imports
import anthropic
from instructor import from_provider
from pydantic import BaseModel, Field
# Set up environment (typically handled before script execution)
# os.environ["ANTHROPIC_API_KEY"] = "your-api-key" # Uncomment and replace with your API key if not set
# Initialize client with explicit mode
client = from_provider(
mode=instructor.Mode.TOOLS
)
# Define your model with proper annotations
class User(BaseModel):
"""Model representing a basic user."""
name: str = Field(description="The user's full name")
age: int = Field(description="The user's age in years")
try:
# Create an iterable of user objects
users = client.create_iterable(
messages=[
{
"role": "system",
"content": "Extract all users from the provided text into structured format."
},
{
"role": "user",
"content": """
Extract users:
1. Jason is 25 years old
2. Sarah is 30 years old
3. Mike is 28 years old
""",
},
],
max_tokens=4096,
response_model=User,
)
# Process each user as it's extracted
for user in users:
print(user)
# Expected output:
# > name='Jason' age=25
# > name='Sarah' age=30
# > name='Mike' age=28
except Exception as e:
print(f"Error during iteration: {e}")
```
## Instructor Modes
We provide several modes to make it easy to work with the different response models that Anthropic supports
1. `instructor.Mode.JSON` : This uses the text completion API from the Anthropic API and then extracts out the desired response model from the text completion model
2. `instructor.Mode.TOOLS` : This uses Anthropic's [tools calling API](https://docs.anthropic.com/en/docs/build-with-claude/tool-use) to return structured outputs. Automatically detects parallel tools from `Iterable[Union[...]]` response models.
3. `instructor.Mode.PARALLEL_TOOLS` : **Deprecated** - Use `Mode.TOOLS` with `Iterable[Union[Model1, Model2, ...]]` instead. Auto-detected automatically.
### Mode Auto-Detection
`Mode.TOOLS` now intelligently adapts based on your response model and parameters:
| Response Model | Parameters | Behavior |
|---|---|---|
| `Model` | Regular | Single tool (forced) |
| `Model` | `thinking={...}` | Single tool with extended thinking (auto) |
| `Iterable[Union[Model1, Model2]]` | Regular | Parallel tools (auto) |
| `Iterable[Union[Model1, Model2]]` | `thinking={...}` | Parallel with thinking |
In general, we recommend using `Mode.TOOLS` because it automatically handles all these cases and is the best way to ensure you have the desired response schema.
## Caching
If you'd like to use caching with the Anthropic Client, we also support it for images and text input.
### Caching Text Input
Here's how you can implement caching for text input ( assuming you have a giant `book.txt` file that you read in).
We've written a comprehensive walkthrough of how to use caching to implement Anthropic's new Contextual Retrieval method that gives a significant bump to retrieval accuracy.
```python
# Standard library imports
import os
# Third-party imports
import instructor
from anthropic import Anthropic
from pydantic import BaseModel, Field
# Set up environment (typically handled before script execution)
# os.environ["ANTHROPIC_API_KEY"] = "your-api-key" # Uncomment and replace with your API key if not set
# Define your Pydantic model with proper annotations
class Character(BaseModel):
"""Model representing a character extracted from text."""
name: str = Field(description="The character's full name")
description: str = Field(description="A description of the character")
# Initialize client with explicit mode and prompt caching
client = instructor.from_provider(
"anthropic/claude-4-5-haiku-latest",
mode=instructor.Mode.TOOLS,
)
try:
# Load your large context
with open("./book.txt", "r") as f:
book = f.read()
# Make multiple calls using the cached context
for _ in range(2):
# The first time processes the large text, subsequent calls use the cache
resp, completion = client.create_with_completion(
messages=[
{
"role": "system",
"content": "Extract character information from the provided text."
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "<book>" + book + "</book>",
"cache_control": {"type": "ephemeral"}, # Mark for caching
},
{
"type": "text",
"text": "Extract a character from the text given above",
},
],
},
],
response_model=Character,
max_tokens=1000,
)
# Process the result
print(f"Character: {resp.name}")
print(f"Description: {resp.description}")
# The completion contains the raw response
print(f"Raw completion length: {len(completion)}")
# Note: Second iteration should be faster due to cache hit
except Exception as e:
print(f"Error: {e}")
```
### Caching Images
We also support caching for images. This helps significantly, especially if you're using images repeatedly to save on costs. Read more about it [here](../concepts/caching.md)
```python
# Standard library imports
import os
# Third-party imports
import instructor
from anthropic import Anthropic
from pydantic import BaseModel, Field
# Set up environment (typically handled before script execution)
# os.environ["ANTHROPIC_API_KEY"] = "your-api-key" # Uncomment and replace with your API key if not set
# Define your model for image analysis
class ImageAnalyzer(BaseModel):
"""Model for analyzing image content."""
content_description: str = Field(description="Description of what appears in the images")
objects: list[str] = Field(description="List of objects visible in the images")
scene_type: str = Field(description="Type of scene shown in the images (indoor, outdoor, etc.)")
# Initialize client with explicit mode and image caching enabled
client = instructor.from_provider(
"anthropic/claude-4-5-haiku-latest",
mode=instructor.Mode.TOOLS,
)
try:
# Configure cache control for images
cache_control = {"type": "ephemeral"}
# Make a request with cached images
response = client.create(
response_model=ImageAnalyzer,
messages=[
{
"role": "system",
"content": "Analyze the content of the provided images in detail."
},
{
"role": "user",
"content": [
"What is in these two images?",
# Remote image with caching
{
"type": "image",
"source": "https://example.com/image.jpg",
"cache_control": cache_control
},
# Local image with caching
{
"type": "image",
"source": "path/to/image.jpg",
"cache_control": cache_control
},
]
}
],
autodetect_images=True # Automatically handle image content
)
# Process the results
print(f"Description: {response.content_description}")
print(f"Objects: {', '.join(response.objects)}")
print(f"Scene type: {response.scene_type}")
# Subsequent identical requests will use cached images
except Exception as e:
print(f"Error during image analysis: {e}")
```
## Thinking (Extended Thinking)
Anthropic supports extended thinking with their Claude models, enabling the model to think through complex problems before providing structured outputs. In Instructor, use `Mode.TOOLS` with the `thinking` parameter to enable this feature.
### Using Extended Thinking with TOOLS
```python
from anthropic import Anthropic
import instructor
from pydantic import BaseModel
class Answer(BaseModel):
answer: float
client = instructor.from_provider("anthropic/claude-3-5-haiku-latest")
response = client.create(
response_model=Answer,
messages=[
{
"role": "user",
"content": "Which is larger, 9.11 or 9.8?",
},
],
temperature=1,
max_tokens=2000,
thinking={"type": "enabled", "budget_tokens": 1024},
)
# Response is a validated Answer object
assert isinstance(response, Answer)
assert response.answer == 9.8
```
### How It Works
When you provide the `thinking` parameter with `type: "enabled"`:
1. **Automatic Mode Detection**: `Mode.TOOLS` automatically detects the thinking parameter and adjusts the tool choice strategy to `auto` (required by Anthropic's API when thinking is enabled)
2. **Model Reasoning**: Claude uses the allocated `budget_tokens` to reason about the problem
3. **Structured Output**: After reasoning, the model returns a valid tool call with your response model
4. **Validation**: The response is automatically validated against your Pydantic model
### Deprecation Notice
`Mode.ANTHROPIC_REASONING_TOOLS` is deprecated. Use `Mode.TOOLS` with the `thinking` parameter instead. Both modes now support thinking, but using the standard `TOOLS` mode is preferred and more flexible.

View File

@@ -0,0 +1,96 @@
---
title: Anyscale
description: Guide to using instructor with Anyscale
---
# Structured outputs with Anyscale, a complete guide w/ instructor
[Anyscale](https://www.anyscale.com/) is a platform that provides access to various open-source LLMs like Mistral and Llama models. This guide shows how to use instructor with Anyscale to get structured outputs from these models.
## Quick Start
First, install the required packages:
```bash
pip install instructor
```
You'll need an Anyscale API key which you can set as an environment variable:
```bash
export ANYSCALE_API_KEY=your_api_key_here
```
## Basic Example
Here's how to extract structured data from Anyscale models:
```python
import instructor
from pydantic import BaseModel
# Initialize the client with Anyscale base URL
client = instructor.from_provider(
"anyscale/Mixtral-8x7B-Instruct-v0.1",
mode=instructor.Mode.JSON_SCHEMA,
)
class UserExtract(BaseModel):
name: str
age: int
# Extract structured data
user = client.create(
response_model=UserExtract,
messages=[
{"role": "user", "content": "Extract jason is 25 years old"},
],
)
print(user)
# Output: UserExtract(name='Jason', age=25)
```
### Async Example
```python
import asyncio
import instructor
from pydantic import BaseModel
async_client = instructor.from_provider(
"anyscale/Mixtral-8x7B-Instruct-v0.1",
async_client=True,
mode=instructor.Mode.JSON_SCHEMA,
)
class UserExtract(BaseModel):
name: str
age: int
async def fetch_user():
return await async_client.create(
messages=[{"role": "user", "content": "Extract jason is 25 years old"}],
response_model=UserExtract,
)
user = asyncio.run(fetch_user())
print(user)
```
## Supported Modes
Anyscale supports the following instructor modes:
- `Mode.TOOLS`
- `Mode.JSON`
- `Mode.JSON_SCHEMA`
- `Mode.MD_JSON`
## Models
Anyscale provides access to various models, including:
- Mistral models (e.g., `mistralai/Mixtral-8x7B-Instruct-v0.1`)
- Llama models
- Other open-source LLMs available through their platform

View File

@@ -0,0 +1,320 @@
---
title: Structured outputs with Azure OpenAI, a complete guide w/ instructor
description: Learn how to use Azure OpenAI with instructor for structured outputs, including async/sync implementations, streaming, and validation.
---
# Structured Outputs with Azure OpenAI
This guide demonstrates how to use Azure OpenAI with instructor for structured outputs. Azure OpenAI provides the same powerful models as OpenAI but with enterprise-grade security and compliance features through Microsoft Azure.
## Installation
We can use the same installation as we do for OpenAI since the default `openai` client ships with an AzureOpenAI client.
First, install the required dependencies:
```bash
pip install instructor
```
Next, make sure that you've enabled Azure OpenAI in your Azure account and have a deployment for the model you'd like to use. [Here is a guide to get started](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource?pivots=web-portal)
Once you've done so, you'll have an endpoint and a API key to be used to configure the client.
```bash
instructor.exceptions.InstructorRetryException: Error code: 401 - {'statusCode': 401, 'message': 'Unauthorized. Access token is missing, invalid, audience is incorrect (https://cognitiveservices.azure.com), or have expired.'}
```
If you see an error like the one above, make sure you've set the correct endpoint and API key in the client.
## Authentication
To use Azure OpenAI, you'll need:
1. Azure OpenAI endpoint
2. API key
3. Deployment name
```python
import os
from openai import AzureOpenAI
import instructor
# Configure Azure OpenAI client
client = AzureOpenAI(
api_key=os.environ["AZURE_OPENAI_API_KEY"],
api_version="2024-02-01",
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"]
)
# Patch the client with instructor
client = instructor.from_provider("azure_openai/gpt-4o-mini")
```
## Using Auto Client (Recommended)
The easiest way to get started with Azure OpenAI is using the `from_provider` method:
```python
import instructor
import os
# Set your Azure OpenAI credentials
os.environ["AZURE_OPENAI_API_KEY"] = "your-api-key"
os.environ["AZURE_OPENAI_ENDPOINT"] = "https://your-resource.openai.azure.com/"
# Create client using the provider string
client = instructor.from_provider("azure_openai/gpt-4o-mini")
# Or async client
async_client = instructor.from_provider("azure_openai/gpt-4o-mini", async_client=True)
```
You can also pass credentials as parameters:
```python
import instructor
client = instructor.from_provider(
"azure_openai/gpt-4o-mini",
api_key="your-api-key",
azure_endpoint="https://your-resource.openai.azure.com/",
api_version="2024-02-01" # Optional, defaults to 2024-02-01
)
```
## Basic Usage
Here's a simple example using a Pydantic model:
```python
import os
import instructor
from openai import AzureOpenAI
from pydantic import BaseModel
client = AzureOpenAI(
api_key=os.environ["AZURE_OPENAI_API_KEY"],
api_version="2024-02-01",
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
)
client = instructor.from_provider("azure_openai/gpt-4o-mini")
class User(BaseModel):
name: str
age: int
# Synchronous usage
user = client.create(
messages=[{"role": "user", "content": "John is 30 years old"}],
response_model=User,
)
print(user)
# > name='John' age=30
```
## Async Implementation
Azure OpenAI supports async operations:
```python
import os
import instructor
import asyncio
from openai import AsyncAzureOpenAI
from pydantic import BaseModel
client = AsyncAzureOpenAI(
api_key=os.environ["AZURE_OPENAI_API_KEY"],
api_version="2024-02-15-preview",
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
)
client = instructor.from_provider("azure_openai/gpt-4o-mini")
class User(BaseModel):
name: str
age: int
async def get_user_async():
return await client.create(
messages=[{"role": "user", "content": "John is 30 years old"}],
response_model=User,
)
# Run async function
user = asyncio.run(get_user_async())
print(user)
# > name='John' age=30
```
## Nested Models
Azure OpenAI handles complex nested structures:
```python
import os
import instructor
from openai import AzureOpenAI
from pydantic import BaseModel
client = AzureOpenAI(
api_key=os.environ["AZURE_OPENAI_API_KEY"],
api_version="2024-02-01",
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
)
client = instructor.from_provider("azure_openai/gpt-4o-mini")
class Address(BaseModel):
street: str
city: str
country: str
class UserWithAddress(BaseModel):
name: str
age: int
addresses: list[Address]
resp = client.create(
messages=[
{
"role": "user",
"content": """
John is 30 years old and has two addresses:
1. 123 Main St, New York, USA
2. 456 High St, London, UK
""",
}
],
response_model=UserWithAddress,
)
print(resp)
# {
# 'name': 'John',
# 'age': 30,
# 'addresses': [
# {
# 'street': '123 Main St',
# 'city': 'New York',
# 'country': 'USA'
# },
# {
# 'street': '456 High St',
# 'city': 'London',
# 'country': 'UK'
# }
# ]
# }
```
## Streaming Support
Instructor has two main ways that you can use to stream responses out
1. **Iterables**: These are useful when you'd like to stream a list of objects of the same type (Eg. use structured outputs to extract multiple users)
2. **Partial Streaming**: This is useful when you'd like to stream a single object and you'd like to immediately start processing the response as it comes in.
### Partials
You can use our `create_partial` method to stream a single object. Note that validators should not be declared in the response model when streaming objects because it will break the streaming process.
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider("azure_openai/gpt-4o-mini")
class User(BaseModel):
name: str
age: int
bio: str
# Stream partial objects as they're generated
user = client.create_partial(
messages=[
{"role": "user", "content": "Create a user profile for Jason, age 25"},
],
response_model=User,
)
for user_partial in user:
print(user_partial)
# > name='Jason' age=None bio='None'
# > name='Jason' age=25 bio='A tech'
# > name='Jason' age=25 bio='A tech enthusiast'
# > name='Jason' age=25 bio='A tech enthusiast who loves coding, gaming, and exploring new'
# > name='Jason' age=25 bio='A tech enthusiast who loves coding, gaming, and exploring new technologies'
```
## Iterable Responses
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider("azure_openai/gpt-4o-mini")
class User(BaseModel):
name: str
age: int
# Extract multiple users from text
users = client.create_iterable(
messages=[
{
"role": "user",
"content": """
Extract users:
1. Jason is 25 years old
2. Sarah is 30 years old
3. Mike is 28 years old
""",
},
],
response_model=User,
)
for user in users:
print(user)
#> name='Jason' age=25
# > name='Sarah' age=30
# > name='Mike' age=28
```
## Instructor Modes
We provide several modes to make it easy to work with the different response models that OpenAI supports
1. `instructor.Mode.TOOLS` : This uses the [tool calling API](https://platform.openai.com/docs/guides/function-calling) to return structured outputs to the client
2. `instructor.Mode.JSON` : This forces the model to return JSON by using [OpenAI's JSON mode](https://platform.openai.com/docs/guides/structured-outputs#json-mode).
3. `instructor.Mode.FUNCTIONS` : This uses OpenAI's function calling API to return structured outputs and will be deprecated in the future.
4. `instructor.Mode.PARALLEL_TOOLS` : This uses the [parallel tool calling API](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) to return structured outputs to the client. This allows the model to generate multiple calls in a single response.
5. `instructor.Mode.MD_JSON` : This makes a simple call to the OpenAI chat completion API and parses the raw response as JSON.
6. `instructor.Mode.TOOLS_STRICT` : This uses the new Open AI structured outputs API to return structured outputs to the client using constrained grammar sampling. This restricts users to a subset of the JSON schema.
7. `instructor.Mode.JSON_O1` : This is a mode for the `O1` model. We created a new mode because `O1` doesn't support any system messages, tool calling or streaming so you need to use this mode to use Instructor with `O1`.
In general, we recommend using `Mode.Tools` because it's the most flexible and future-proof mode. It has the largest set of features that you can specify your schema in and makes things significantly easier to work with.
## Best Practices
## Additional Resources
- [Azure OpenAI Documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/)
- [Instructor Documentation](https://instructor-ai.github.io/instructor/)
- [Azure OpenAI Pricing](https://azure.microsoft.com/en-us/pricing/details/cognitive-services/openai-service/)

View File

@@ -0,0 +1,336 @@
---
title: Structured Outputs with AWS Bedrock and Pydantic
description: Learn how to use AWS Bedrock with Instructor for structured JSON outputs using Pydantic models. Create type-safe, validated responses from AWS Bedrock LLMs with Python.
---
# Structured Outputs with AWS Bedrock
This guide demonstrates how to use AWS Bedrock with Instructor to generate structured outputs. You'll learn how to use AWS Bedrock's LLM models with Pydantic to create type-safe, validated responses.
## Prerequisites
You'll need to have an AWS account with access to Bedrock and the appropriate permissions. You'll also need to set up your AWS credentials.
```bash
pip install "instructor[bedrock]"
```
### See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [from_provider Guide](../concepts/from_provider.md) - Detailed client configuration
- [Mode Migration Guide](../concepts/mode-migration.md) - Move to core modes
- [Provider Examples](../index.md#provider-examples) - Quick examples for all providers
- [AWS Integration Guide](../examples/index.md#aws-integration) - More AWS examples
# AWS Bedrock
AWS Bedrock is a fully managed service that offers a choice of high-performing foundation models (FMs) from leading AI companies like AI21 Labs, Anthropic, Cohere, Meta, Stability AI, and Amazon through a single API.
## Auto Client Setup
For simplified setup, you can use the auto client pattern:
```python
import instructor
# Auto client with model specification
client = instructor.from_provider("bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
# The auto client automatically handles:
# - AWS credential detection from environment
# - Region configuration (defaults to us-east-1)
# - Mode selection based on model (Claude models use TOOLS)
```
## Deprecation Notice
> **Deprecation Notice:**
>
> The `_async` argument to `instructor.from_bedrock` is deprecated. Please use `async_client=True` for async clients instead. Support for `_async` may be removed in a future release. All new code and examples should use `async_client`.
### Environment Configuration
Set your AWS credentials and region:
```bash
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export AWS_DEFAULT_REGION=us-east-1
```
Or configure using AWS CLI:
```bash
aws configure
```
## Sync Example
```python
import boto3
import instructor
from pydantic import BaseModel
bedrock_client = boto3.client('bedrock-runtime')
client = instructor.from_provider("bedrock/claude-3-5-sonnet-20241022")
class User(BaseModel):
name: str
age: int
user = client.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
print(user)
# > User(name='Jason', age=25)
```
## Async Example
> **Warning:**
> AWS Bedrock's official SDK (`boto3`) does not support async natively. If you need to call Bedrock from async code, you can use `asyncio.to_thread` to run synchronous Bedrock calls in a non-blocking way.
```python
import instructor
from pydantic import BaseModel
import asyncio
client = instructor.from_provider("bedrock/anthropic.claude-3-sonnet-20240229-v1:0")
class User(BaseModel):
name: str
age: int
def get_user():
return client.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[{"role": "user", "content": "Extract Jason is 25 years old"}],
response_model=User,
)
async def get_user_async():
return await asyncio.to_thread(get_user)
user = asyncio.run(get_user_async())
print(user)
```
## Supported Modes
AWS Bedrock supports the following **core** modes:
- `TOOLS`: Uses function calling for models that support it (like Claude models)
- `MD_JSON`: Direct JSON response generation (text extraction fallback)
> Legacy modes (`BEDROCK_TOOLS`, `BEDROCK_JSON`) are deprecated and map to `Mode.TOOLS` and `Mode.MD_JSON`.
> modes above. Use `TOOLS` or `MD_JSON` in new code.
```python
import boto3
import instructor
from instructor import Mode
from pydantic import BaseModel
# Use from_provider for simplified setup
client = instructor.from_provider("bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0", mode=Mode.TOOLS)
# Or if you need to use a custom boto3 client:
# bedrock_client = boto3.client('bedrock-runtime')
# client = instructor.from_provider("bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0", client=bedrock_client, mode=Mode.TOOLS)
class User(BaseModel):
name: str
age: int
```
## OpenAI Compatibility: Flexible Input Format and Model Parameter
Instructors Bedrock integration supports both OpenAI-style and Bedrock-native message formats, as well as any mix of the two. You can use either:
- **OpenAI-style**:
`{"role": "user", "content": "Extract: Jason is 25 years old"}`
- **Bedrock-native**:
`{"role": "user", "content": [{"text": "Extract: Jason is 25 years old"}]}`
- **Mixed**:
You can freely mix OpenAI-style and Bedrock-native messages in the same request. The integration will automatically convert OpenAI-style messages to the correct Bedrock format, while preserving any Bedrock-native fields you provide.
This flexibility also applies to other keyword arguments, such as the model name:
- You can use either `model` (OpenAI-style) or `modelId` (Bedrock-native) as a keyword argument.
- If you provide `model`, Instructor will automatically convert it to `modelId` for Bedrock.
- If you provide both, `modelId` takes precedence.
**Example:**
```python
import instructor
messages = [
{"role": "system", "content": "Extract the name and age."}, # OpenAI-style
{"role": "user", "content": [{"text": "Extract: Jason is 25 years old"}]}, # Bedrock-native
{"role": "assistant", "content": "Sure! Jason is 25."}, # OpenAI-style
]
# Both of these are valid:
user = client.create(
model="anthropic.claude-3-sonnet-20240229-v1:0", # OpenAI-style
messages=messages,
response_model=User,
)
user = client.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0", # Bedrock-native
messages=messages,
response_model=User,
)
```
All of the above will work seamlessly with Instructors Bedrock integration.
## Multimodal: Images and Documents
Instructor will convert OpenAI-style image parts into Bedrock image blocks automatically. For documents (PDFs), Bedrock expects a native `document` block, so you should either pass a Bedrock-native document dict directly or build one with the `PDF` helper.
```python
import instructor
from instructor.processing.multimodal import PDF
client = instructor.from_provider("bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
pdf = PDF.from_url("https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf")
response = client.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[
{
"role": "user",
"content": [
"Analyze this document",
pdf.to_bedrock(),
],
}
],
)
```
Bedrock document blocks also support S3 URIs (for example, `s3://bucket/key.pdf`) and local files; `PDF.to_bedrock()` will load the bytes and sanitize the document name for you.
## Nested Objects
```python
import boto3
import instructor
from pydantic import BaseModel
# Initialize the Bedrock client
bedrock_client = boto3.client('bedrock-runtime')
# Enable instructor patches for Bedrock client
client = instructor.from_provider("bedrock/claude-3-5-sonnet-20241022")
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
# Create structured output with nested objects
user = client.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
},
],
response_model=User,
)
print(user)
#> User(
#> name='Jason',
#> age=25,
#> addresses=[
#> Address(street='123 Main St', city='New York', country='USA'),
#> Address(street='456 Beach Rd', city='Miami', country='USA')
#> ]
#> )
```
## Modern Models and Features
### Latest Model Support
AWS Bedrock supports many modern foundation models:
```python
import instructor
# Claude 3.5 models (latest)
client = instructor.from_provider("bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
# or
client = instructor.from_provider("bedrock/anthropic.claude-3-5-haiku-20241022-v1:0")
# Amazon Nova models (multimodal)
client = instructor.from_provider("bedrock/amazon.nova-micro-v1:0")
# Meta Llama 3 models
client = instructor.from_provider("bedrock/meta.llama3-70b-instruct-v1:0")
# Mistral models
client = instructor.from_provider("bedrock/mistral.mistral-large-2402-v1:0")
```
### Advanced Configuration
```python
import boto3
import instructor
# Custom AWS configuration
bedrock_client = boto3.client(
'bedrock-runtime',
region_name='us-west-2',
aws_access_key_id='your_key',
aws_secret_access_key='your_secret'
)
# Use from_provider with custom client
client = instructor.from_provider(
"bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
client=bedrock_client,
mode=instructor.Mode.TOOLS
)
# Advanced inference configuration
user = client.create(
modelId="anthropic.claude-3-5-sonnet-20241022-v2:0",
messages=[{"role": "user", "content": "Extract user info"}],
response_model=User,
inferenceConfig={
"maxTokens": 2048,
"temperature": 0.1,
"topP": 0.9,
"stopSequences": ["STOP"]
}
)
```

View File

@@ -0,0 +1,242 @@
---
title: "Structured outputs with Cerebras, a complete guide w/ instructor"
description: "Complete guide to using Instructor with Cerebras's hardware-accelerated AI models. Learn how to generate structured, type-safe outputs with high-performance computing."
---
# Structured outputs with Cerebras, a complete guide w/ instructor
Cerebras provides hardware-accelerated AI models optimized for high-performance computing environments. This guide shows you how to use Instructor with Cerebras's models for type-safe, validated responses.
## Quick Start
Install Instructor with Cerebras support:
```bash
pip install "instructor[cerebras_cloud_sdk]"
```
## Simple User Example (Sync)
```python
import instructor
from cerebras.cloud.sdk import Cerebras
from pydantic import BaseModel
client = instructor.from_provider("cerebras/llama3.1-70b")
class User(BaseModel):
name: str
age: int
# Create structured output
resp = client.create(
messages=[
{
"role": "user",
"content": "Extract the name and age of the person in this sentence: John Smith is 29 years old.",
}
],
response_model=User,
)
print(resp)
#> User(name='John Smith', age=29)
```
## Simple User Example (Async)
```python
import instructor
from pydantic import BaseModel
import asyncio
client = instructor.from_provider(
"cerebras/llama3.1-70b",
async_client=True,
)
class User(BaseModel):
name: str
age: int
async def extract_user():
resp = await client.create(
messages=[
{
"role": "user",
"content": "Extract the name and age of the person in this sentence: John Smith is 29 years old.",
}
],
response_model=User,
)
return resp
# Run async function
resp = asyncio.run(extract_user())
print(resp)
#> User(name='John Smith', age=29)
```
## Nested Example
```python
from pydantic import BaseModel
import instructor
from cerebras.cloud.sdk import Cerebras
client = instructor.from_provider("cerebras/llama3.1-70b")
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
}
],
response_model=User,
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```
## Streaming Support
Instructor has two main ways that you can use to stream responses out
1. **Iterables**: These are useful when you'd like to stream a list of objects of the same type (Eg. use structured outputs to extract multiple users)
2. **Partial Streaming**: This is useful when you'd like to stream a single object and you'd like to immediately start processing the response as it comes in.
We currently support partial streaming for Cerebras by parsing the raw text completion. We have not implemented streaming for function calling at this point in time yet. Please make sure you have `mode=instructor.Mode.MD_JSON` set when using partial streaming.
```python
import instructor
from cerebras.cloud.sdk import Cerebras
from pydantic import BaseModel
from typing import Iterable
client = instructor.from_provider(
"cerebras/llama3.1-70b",
mode=instructor.Mode.MD_JSON,
)
class Person(BaseModel):
name: str
age: int
resp = client.create_partial(
messages=[
{
"role": "user",
"content": "Ivan is 27 and lives in Singapore",
}
],
response_model=Person,
stream=True,
)
for person in resp:
print(person)
# > name=None age=None
# > name='Ivan' age=None
# > name='Ivan' age=27
```
## Iterable Example
```python
import instructor
from cerebras.cloud.sdk import Cerebras
from pydantic import BaseModel
from typing import Iterable
client = instructor.from_provider(
"cerebras/llama3.1-70b",
mode=instructor.Mode.MD_JSON,
)
class Person(BaseModel):
name: str
age: int
resp = client.create_iterable(
messages=[
{
"role": "user",
"content": "Extract all users from this sentence : Chris is 27 and lives in San Francisco, John is 30 and lives in New York while their college roomate Jessica is 26 and lives in London",
}
],
response_model=Person,
stream=True,
)
for person in resp:
print(person)
# > Person(name='Chris', age=27)
# > Person(name='John', age=30)
# > Person(name='Jessica', age=26)
```
## Instructor Hooks
Instructor provides several hooks to customize behavior:
### Validation Hook
```python
from instructor import Instructor
def validation_hook(value, retry_count, exception):
print(f"Validation failed {retry_count} times: {exception}")
return retry_count < 3 # Retry up to 3 times
instructor.patch(client, validation_hook=validation_hook)
```
## Instructor Modes
We provide serveral modes to make it easy to work with the different response models that Cerebras Supports
1. `instructor.Mode.MD_JSON` : This parses the raw completions as a valid JSON object.
2. `instructor.Mode.TOOLS` : This uses Cerebras's tool calling mode to return structured outputs to the client.
In general, we recommend using `Mode.TOOLS` because it's the most flexible and future-proof mode. It has the largest set of features that you can specify your schema in and makes things significantly easier to work with.

View File

@@ -0,0 +1,163 @@
---
title: Structured outputs with Cohere, a complete guide w/ instructor
description: Learn how to leverage Cohere's command models with Python's instructor library for structured data outputs.
---
# Structured outputs with Cohere, a complete guide w/ instructor
This guide demonstrates how to use Cohere with Instructor to generate structured outputs. You'll learn how to use Cohere's command models to create type-safe responses.
You can now use any of the Cohere's [command models](https://docs.cohere.com/docs/models) with the `instructor` library to get structured outputs.
You'll need a cohere API key which can be obtained by signing up [here](https://dashboard.cohere.com/) and gives you [free](https://cohere.com/pricing), rate-limited usage for learning and prototyping.
### See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [from_provider Guide](../concepts/from_provider.md) - Detailed client configuration
- [Document Segmentation](../examples/document_segmentation.md) - Cohere example for document processing
- [Provider Examples](../index.md#provider-examples) - Quick examples for all providers
# Cohere V2 API Support
As of version 1.12.0, Instructor supports both Cohere V1 and V2 SDK clients. The V2 API provides an OpenAI-compatible interface with support for the latest Cohere models.
**Key differences:**
- **V2 API** (recommended): Uses `cohere.ClientV2` / `cohere.AsyncClientV2` with OpenAI-compatible message format
- **V1 API** (legacy): Uses `cohere.Client` / `cohere.AsyncClient` with Cohere-specific message format
The V2 API is recommended for new projects as it provides better compatibility with the OpenAI SDK interface and supports the latest models like `command-a-03-2025`.
## Setup
```
pip install "instructor[cohere]"
```
This installs `cohere>=5.1.8`, which includes both V1 and V2 client support.
Export your key:
```
export CO_API_KEY=<YOUR_COHERE_API_KEY>
```
## Example (V2 API - Recommended)
The easiest way to use Cohere with Instructor is through the `from_provider` factory, which automatically uses the V2 API:
```python
from pydantic import BaseModel, Field
from typing import List
import instructor
# Using from_provider automatically uses Cohere V2 API
client = instructor.from_provider(
"cohere/command-a-03-2025",
max_tokens=1000,
)
class Person(BaseModel):
name: str = Field(description="name of the person")
country_of_origin: str = Field(description="country of origin of the person")
class Group(BaseModel):
group_name: str = Field(description="name of the group")
members: List[Person] = Field(description="list of members in the group")
task = """\
Given the following text, create a Group object for 'The Beatles' band
Text:
The Beatles were an English rock band formed in Liverpool in 1960. With a line-up comprising John Lennon, Paul McCartney, George Harrison and Ringo Starr, they are regarded as the most influential band of all time. The group were integral to the development of 1960s counterculture and popular music's recognition as an art form.
"""
group = client.create(
response_model=Group,
messages=[{"role": "user", "content": task}],
temperature=0,
)
print(group.model_dump_json(indent=2))
"""
{
"group_name": "The Beatles",
"members": [
{
"name": "John Lennon",
"country_of_origin": "England"
},
{
"name": "Paul McCartney",
"country_of_origin": "England"
},
{
"name": "George Harrison",
"country_of_origin": "England"
},
{
"name": "Ringo Starr",
"country_of_origin": "England"
}
]
}
"""
```
### Async Example
```python
import instructor
async_client = instructor.from_provider(
"cohere/command-a-03-2025",
async_client=True,
max_tokens=1000,
)
```
## Using Cohere SDK Directly
You can also explicitly create a Cohere client and patch it with Instructor:
### V2 API (Recommended)
```python
import cohere
import instructor
# Use from_provider for simplified setup
client = instructor.from_provider("cohere/command-a-03-2025", mode=instructor.Mode.TOOLS)
# Now use it with structured outputs
response = client.create(
response_model=YourModel,
model="command-a-03-2025",
messages=[{"role": "user", "content": "Extract..."}],
)
```
### V1 API (Legacy Support)
The V1 API is still supported for backward compatibility:
```python
import cohere
import instructor
# Use from_provider for simplified setup (works with both V1 and V2)
client = instructor.from_provider("cohere/command-a-03-2025", mode=instructor.Mode.TOOLS)
# V1 uses different message format internally but instructor handles the conversion
response = client.create(
response_model=YourModel,
model="command-r-plus",
messages=[{"role": "user", "content": "Extract..."}],
)
```
**Note**: Instructor automatically detects whether you're using V1 or V2 client and handles message format conversion accordingly. The V2 API uses OpenAI-compatible message format (`messages`), while V1 uses Cohere's legacy format (`message` + `chat_history`).

View File

@@ -0,0 +1,169 @@
---
title: "Structured outputs with Cortex, a complete guide w/ instructor"
description: "Learn how to use Cortex with Instructor for structured outputs. Complete guide with examples and best practices."
---
# Structured outputs with Cortex
Cortex.cpp is a runtime that helps you run open source LLMs out of the box. It supports a wide variety of models and powers their [Jan](https://jan.ai) platform. This guide provides a quickstart on how to use Cortex with instructor for structured outputs.
## Quick Start
Instructor comes with support for the OpenAI client out of the box, so you don't need to install anything extra.
```bash
pip install "instructor"
```
Once you've done so, make sure to pull the model that you'd like to use. In this example, we'll be using a quantized llama3.2 model.
```bash
cortex run llama3.2:3b-gguf-q4-km
```
Let's start by initializing the client below - note that we need to provide a base URL and an API key here. The API key isn't important, it's just so the OpenAI client doesn't throw an error.
```python
import instructor
client = instructor.from_provider(
"cortex/llama3.2:3b-gguf-q4-km",
base_url="http://localhost:39281/v1",
api_key="this is a fake api key that doesn't matter",
)
```
## Simple User Example (Sync)
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider(
"cortex/llama3.2:3b-gguf-q4-km",
base_url="http://localhost:39281/v1",
api_key="this is a fake api key that doesn't matter",
)
class User(BaseModel):
name: str
age: int
resp = client.create(
messages=[{"role": "user", "content": "Ivan is 27 and lives in Singapore"}],
response_model=User,
)
print(resp)
# > name='Ivan', age=27
```
## Simple User Example (Async)
```python
import instructor
from pydantic import BaseModel
import asyncio
# Initialize with API key
client = instructor.from_provider(
"cortex/llama3.2:3b-gguf-q4-km",
async_client=True,
base_url="http://localhost:39281/v1",
api_key="this is a fake api key that doesn't matter",
)
class User(BaseModel):
name: str
age: int
async def extract_user():
user = await client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user)
#> User(name='Jason', age=25)
```
## Nested Example
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider(
"cortex/llama3.2:3b-gguf-q4-km",
base_url="http://localhost:39281/v1",
api_key="this is a fake api key that doesn't matter",
)
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
},
],
response_model=User,
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```
In this tutorial we've seen how we can run local models with Cortex while simplifying a lot of the logic around managing retries and function calling with our simple interface.
We'll be publishing a lot more content on Cortex and how to work with local models moving forward so do keep an eye out for that.
## Related Resources
- [Cortex Documentation](https://cortex.so/docs/)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
## Updates and Compatibility
Instructor maintains compatibility with the latest OpenAI API versions and models. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates.

View File

@@ -0,0 +1,89 @@
---
title: Databricks
description: Guide to using instructor with Databricks models
---
# Structured outputs with Databricks, a complete guide w/ instructor
[Databricks](https://www.databricks.com/) provides an AI platform with access to various models. This guide shows how to use instructor with Databricks to get structured outputs.
## Quick Start
First, install the required packages:
```bash
uv pip install instructor openai
```
Set your Databricks workspace URL and token as environment variables:
```bash
export DATABRICKS_TOKEN="your_personal_access_token"
export DATABRICKS_HOST="https://your-workspace.cloud.databricks.com"
```
`DATABRICKS_API_KEY` and `DATABRICKS_WORKSPACE_URL` are also supported if you prefer those names. The provider appends `/serving-endpoints` automatically, so the host only needs the base workspace URL.
## Basic Example
Here's how to extract structured data from Databricks models:
```python
import instructor
from pydantic import BaseModel
# Initialize the client; host and token are read from the environment
client = instructor.from_provider(
"databricks/dbrx-instruct",
mode=instructor.Mode.TOOLS,
)
# Define your data structure
class UserExtract(BaseModel):
name: str
age: int
# Extract structured data
user = client.create(
response_model=UserExtract,
messages=[
{"role": "user", "content": "Extract jason is 25 years old"},
],
)
print(user)
# Output: UserExtract(name='Jason', age=25)
```
If you need to point at a different workspace or testing endpoint, pass `base_url="https://alt-workspace.cloud.databricks.com/serving-endpoints"`. The helper will use that value as-is without adding another suffix.
### Async Example
```python
async_client = instructor.from_provider(
"databricks/dbrx-instruct",
async_client=True,
mode=instructor.Mode.TOOLS,
)
```
## Supported Modes
Databricks supports the same modes as OpenAI:
- `Mode.TOOLS`
- `Mode.JSON`
- `Mode.FUNCTIONS`
- `Mode.PARALLEL_TOOLS`
- `Mode.MD_JSON`
- `Mode.TOOLS_STRICT`
- `Mode.JSON_O1`
## Models
Databricks provides access to various models depending on your setup, including:
- Foundation models hosted on Databricks
- Custom fine-tuned models
- Open source models deployed on Databricks

View File

@@ -0,0 +1,323 @@
---
title: "Structured outputs with DeepSeek, a complete guide with instructor"
description: "Learn how to use Instructor with DeepSeek's models for type-safe, structured outputs."
---
# Structured outputs with DeepSeek, a complete guide with instructor
DeepSeek is a Chinese company that provides AI models and services. They're most notable for the deepseek coder and chat model and most recently, the R1 reasoning model.
This guide covers everything you need to know about using DeepSeek with Instructor for type-safe, validated responses.
## Quick Start
Instructor comes with support for the OpenAI Client out of the box, so you don't need to install anything extra.
```bash
pip install "instructor"
```
⚠️ **Important**: You must set your DeepSeek API key before using the client. You can do this in two ways:
1. Set the environment variable:
```bash
export DEEPSEEK_API_KEY='your-api-key-here'
```
2. Or provide it directly to the client:
```python
import os
from openai import OpenAI
client = OpenAI(api_key=os.getenv('DEEPSEEK_API_KEY'), base_url="https://api.deepseek.com")
```
## Simple User Example (Sync)
```python
import os
from openai import OpenAI
from pydantic import BaseModel
import instructor
client = instructor.from_provider(
"deepseek/deepseek-chat",
base_url="https://api.deepseek.com",
)
class User(BaseModel):
name: str
age: int
# Create structured output
user = client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
print(user)
# > name='Jason' age=25
```
## Simple User Example (Async)
```python
import os
import asyncio
from pydantic import BaseModel
import instructor
client = instructor.from_provider(
"deepseek/deepseek-chat",
async_client=True,
base_url="https://api.deepseek.com",
)
class User(BaseModel):
name: str
age: int
async def extract_user():
user = await client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user)
# > name='Jason' age=25
```
## Nested Example
```python
from pydantic import BaseModel
import os
from openai import OpenAI
import instructor
from pydantic import BaseModel
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
# Initialize with API key
client = instructor.from_provider(
"deepseek/deepseek-chat",
base_url="https://api.deepseek.com",
)
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
},
],
response_model=User,
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```
## Streaming Support
Instructor has two main ways that you can use to stream responses out
1. **Iterables**: These are useful when you'd like to stream a list of objects of the same type (Eg. use structured outputs to extract multiple users)
2. **Partial Streaming**: This is useful when you'd like to stream a single object and you'd like to immediately start processing the response as it comes in.
### Partials
```python
from pydantic import BaseModel
import os
from openai import OpenAI
import instructor
from pydantic import BaseModel
# Initialize with API key
client = instructor.from_provider(
"deepseek/deepseek-chat",
base_url="https://api.deepseek.com",
)
class User(BaseModel):
name: str
age: int
bio: str
user = client.create_partial(
messages=[
{
"role": "user",
"content": "Create a user profile for Jason and a one sentence bio, age 25",
},
],
response_model=User,
)
for user_partial in user:
print(user_partial)
# > name='Jason' age=None bio='None'
# > name='Jason' age=25 bio='A tech'
# > name='Jason' age=25 bio='A tech enthusiast'
# > name='Jason' age=25 bio='A tech enthusiast who loves coding, gaming, and exploring new'
# > name='Jason' age=25 bio='A tech enthusiast who loves coding, gaming, and exploring new technologies'
```
### Iterable Example
```python
from pydantic import BaseModel
import os
from openai import OpenAI
import instructor
from pydantic import BaseModel
# Initialize with API key
client = instructor.from_provider(
"deepseek/deepseek-chat",
base_url="https://api.deepseek.com",
)
class User(BaseModel):
name: str
age: int
# Extract multiple users from text
users = client.create_iterable(
messages=[
{
"role": "user",
"content": """
Extract users:
1. Jason is 25 years old
2. Sarah is 30 years old
3. Mike is 28 years old
""",
},
],
response_model=User,
)
for user in users:
print(user)
#> name='Jason' age=25
#> name='Sarah' age=30
#> name='Mike' age=28
```
## Reasoning Models
Because Instructor is built on top of the OpenAI API, we can get our reasoning traces from the `deepseek-reasoner` model. Make sure to configure the `MD_JSON` mode here to get the best experience.
```python
import os
from openai import OpenAI
from pydantic import BaseModel
import instructor
from rich import print
client = instructor.from_provider(
"deepseek/deepseek-chat",
base_url="https://api.deepseek.com",
mode=instructor.Mode.MD_JSON,
)
class User(BaseModel):
name: str
age: int
# Create structured output
completion, raw_completion = client.create_with_completion(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
print(completion)
# > User(name='Jason', age=25)
print(raw_completion.choices[0].message.reasoning_content)
# > Okay, let's see. The user wants me to extract information from the sentence "Jason is 25 years old" and format it into a JSON object that matches the given schema. The schema requires a "name" and an "age", both of which are required.
# >
# > First, I need to identify the name. The sentence starts with "Jason", so that's the name. Then the age is given as "25 years old". The age should be an integer, so I need to convert "25" from a string to a number.
# >
# > So putting that together, the JSON should have "name": "Jason" and "age": 25. Let me double-check the schema to make sure there are no other requirements. The properties are "name" (string) and "age" (integer), both required. Yep, that's all.
# >
# > I need to make sure the JSON is correctly formatted, with commas and braces. Also, the user specified to return it in a json codeblock, not the schema itself. So the final answer should be a JSON object with those key-value pairs.
```
## Instructor Modes
We suggest using the `Mode.Tools` mode for Deepseek which is the default when initializing via `from_provider`.
## Related Resources
- [DeepSeek Documentation](https://api-docs.deepseek.com/)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
## Updates and Compatibility
Instructor maintains compatibility with the latest OpenAI API versions and models. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates.

View File

@@ -0,0 +1,251 @@
---
title: "Structured outputs with Fireworks, a complete guide w/ instructor"
description: "Complete guide to using Instructor with Fireworks AI models. Learn how to generate structured, type-safe outputs with high-performance, cost-effective AI capabilities."
---
# Structured outputs with Fireworks, a complete guide w/ instructor
Fireworks provides efficient and cost-effective AI models with enterprise-grade reliability. This guide shows you how to use Instructor with Fireworks's models for type-safe, validated responses.
## Quick Start
Install Instructor with Fireworks support:
```bash
pip install "instructor[fireworks-ai]"
```
## Simple User Example (Sync)
```python
from fireworks.client import Fireworks
import instructor
from pydantic import BaseModel
# Initialize the client
client = Fireworks()
# Enable instructor patches
client = instructor.from_provider("fireworks/llama-v3-70b-instruct")
class User(BaseModel):
name: str
age: int
# Create structured output
user = client.create(
messages=[
{
"role": "user",
"content": "Extract: Jason is 25 years old",
}
],
response_model=User,
)
print(user)
# > User(name='Jason', age=25)
```
## Simple User Example (Async)
```python
import instructor
from pydantic import BaseModel
import asyncio
client = instructor.from_provider(
"fireworks/llama-v3-70b-instruct",
async_client=True,
)
class User(BaseModel):
name: str
age: int
async def extract_user():
user = await client.create(
messages=[
{
"role": "user",
"content": "Extract: Jason is 25 years old",
}
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user) # User(name='Jason', age=25)
```
## Nested Example
```python
from fireworks.client import Fireworks
import instructor
from pydantic import BaseModel
# Enable instructor patches
client = instructor.from_provider("fireworks/llama-v3-70b-instruct")
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
}
],
response_model=User,
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```
## Streaming Support
Instructor has two main ways that you can use to stream responses out
1. **Iterables**: These are useful when you'd like to stream a list of objects of the same type (Eg. use structured outputs to extract multiple users)
2. **Partial Streaming**: This is useful when you'd like to stream a single object and you'd like to immediately start processing the response as it comes in.
### Partial Streaming Example
```python
from fireworks.client import Fireworks
import instructor
from pydantic import BaseModel
# Enable instructor patches
client = instructor.from_provider("fireworks/llama-v3-70b-instruct")
class User(BaseModel):
name: str
age: int
bio: str
user = client.create_partial(
messages=[
{
"role": "user",
"content": "Create a user profile for Jason + 1 sentence bio, age 25",
},
],
response_model=User,
)
for user_partial in user:
print(user_partial)
# name=None age=None bio=None
# name='Jason' age=None bio=None
# name='Jason' age=25 bio="When he's"
# name='Jason' age=25 bio="When he's not working as a graphic designer, Jason can usually be found trying out new craft beers or attempting to cook something other than ramen noodles."
```
## Iterable Example
```python
from fireworks.client import Fireworks
import instructor
from pydantic import BaseModel
# Enable instructor patches
client = instructor.from_provider("fireworks/llama-v3-70b-instruct")
class User(BaseModel):
name: str
age: int
# Extract multiple users from text
users = client.create_iterable(
messages=[
{
"role": "user",
"content": """
Extract users:
1. Jason is 25 years old
2. Sarah is 30 years old
3. Mike is 28 years old
""",
},
],
response_model=User,
)
for user in users:
print(user)
# name='Jason' age=25
# name='Sarah' age=30
# name='Mike' age=28
```
## Instructor Modes
We provide several modes to make it easy to work with the different response models that Fireworks supports
1. `instructor.Mode.MD_JSON` : This parses the raw text completion into a pydantic object
2. `instructor.Mode.TOOLS` : This uses Fireworks's tool calling API to return structured outputs to the client
## Related Resources
- [Fireworks Documentation](https://docs.fireworks.ai/)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
## Updates and Compatibility
Instructor maintains compatibility with Fireworks's latest API versions. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates.
Note: Always verify model-specific features and limitations before implementing streaming functionality in production environments.

View File

@@ -0,0 +1,717 @@
---
draft: False
date: 2025-03-15
title: "Structured outputs with Google's genai SDK"
description: "Learn how to use Instructor with Google's Generative AI SDK to extract structured data from Gemini models."
slug: genai
tags:
- patching
authors:
- instructor
---
# Structured Outputs with Google's genai SDK
!!! info "Recommended SDK"
The `genai` SDK is Google's recommended Python client for working with Gemini models. It provides a unified interface for both the Gemini API and Vertex AI. For detailed setup instructions, including how to use it with Vertex AI, please refer to the [official Google AI documentation for the GenAI SDK](https://googleapis.github.io/python-genai/).
This guide demonstrates how to use Instructor with Google's `genai` SDK to extract structured data from Gemini models.
We currently have two modes for Gemini
- `Mode.TOOLS` : This leverages function calling under the hood and returns a structured response
- `Mode.JSON` : This provides Gemini with a JSON Schema that it will use to respond in a structured format with
!!! info "Gemini Thought Parts Filtering"
When using `Mode.TOOLS`, Instructor automatically filters out thought parts from Gemini responses. Gemini 2.5 models include internal reasoning parts with `thought: true` by default, which cannot be disabled. Instructor removes these thought parts before processing the structured output to prevent runtime errors.
This filtering happens automatically and requires no additional configuration. For more information about Gemini's thinking feature, see the [official documentation](https://ai.google.dev/gemini-api/docs/thinking).
!!! note "Backwards Compatibility"
The provider-specific modes (`Mode.TOOLS`, `Mode.JSON`, `Mode.JSON`) are still supported but emit deprecation warnings and map to the generic modes (`Mode.TOOLS`, `Mode.JSON`).
## Installation
```bash
pip install "instructor[google-genai]"
```
## Basic Usage
!!! warning "Unions and Optionals"
Gemini doesn't have support for Union and Optional types in the structured outputs and tool calling integrations. We currently throw an error when we detect these in your response model.
Getting started with Instructor and the genai SDK is straightforward. Just create a Pydantic model defining your output structure, patch the genai client, and make your request with a response_model parameter:
```python
from google import genai
import instructor
from pydantic import BaseModel
# Define your Pydantic model
class User(BaseModel):
name: str
age: int
# Initialize and patch the client
client = instructor.from_provider("google/gemini-2.5-flash")
# Extract structured data
response = client.create(
messages=[{"role": "user", "content": "Extract: Jason is 25 years old"}],
response_model=User,
)
print(response) # User(name='Jason', age=25)
```
## Alternative: Using the v2 GenAI client
!!! note "Recommended: Use `from_provider`"
The `from_provider` approach shown above is recommended for most use cases. The `from_genai` helper below is available if you need to work directly with the native `google.genai.Client` and keep the Google request format intact.
```python
from google.genai import Client
from instructor import Mode
from instructor.v2 import from_genai
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
raw_client = Client(api_key="YOUR_KEY")
client = from_genai(raw_client, mode=Mode.TOOLS)
result = client.chat.completions.create(
messages=[{"role": "user", "content": "Extract: Jason is 25 years old"}],
response_model=User,
)
print(result)
```
Behind the scenes the v2 client registers the correct mode handler, converts OpenAI-style messages to the GenAI `contents` format, and parses the response while filtering Gemini thought parts.
## Message Formatting
Genai supports multiple message formats, and Instructor seamlessly works with all of them. This flexibility allows you to use whichever format is most convenient for your application:
```python
from google import genai
import instructor
from pydantic import BaseModel
from google.genai import types
# Define your Pydantic model
class User(BaseModel):
name: str
age: int
# Initialize and patch the client
client = instructor.from_provider("google/gemini-2.5-flash")
# Single string (converted to user message)
response = client.create(
messages="Jason is 25 years old",
response_model=User,
)
print(response)
# > name='Jason' age=25
# Standard format
response = client.create(
messages=[
{"role": "user", "content": "Jason is 25 years old"}
],
response_model=User,
)
print(response)
# > name='Jason' age=25
# Using genai's Content type
response = client.create(
messages=[
genai.types.Content(
role="user",
parts=[genai.types.Part.from_text(text="Jason is 25 years old")]
)
],
response_model=User,
)
print(response)
# > name='Jason' age=25
```
### System Messages
System messages help set context and instructions for the model. With Gemini models, you can provide system messages in two different ways:
```python
from google import genai
import instructor
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
client = instructor.from_provider("google/gemini-2.5-flash")
# As a parameter
response = client.create(
system="Jason is 25 years old",
messages=[{"role": "user", "content": "You are a data extraction assistant"}],
response_model=User,
)
print(response)
# > name='Jason' age=25
# Or as a message with role "system"
response = client.create(
messages=[
{"role": "system", "content": "Jason is 25 years old"},
{"role": "user", "content": "You are a data extraction assistant"},
],
response_model=User,
)
print(response)
# > name='Jason' age=25
```
## Template Variables
Template variables make it easy to reuse prompts with different values. This is particularly useful for dynamic content or when testing different inputs:
```python
from google import genai
import instructor
from pydantic import BaseModel
from google.genai import types
# Define your Pydantic model
class User(BaseModel):
name: str
age: int
# Initialize and patch the client
client = instructor.from_provider("google/gemini-2.5-flash")
# Single string (converted to user message)
response = client.create(
messages=[{"role": "user", "content": "{{ name }} is {{ age }} years old"}],
response_model=User,
context={
"name": "Jason",
"age": 25,
},
)
print(response)
# > name='Jason' age=25
# Standard format
response = client.create(
messages=[{"role": "user", "content": "{{ name }} is {{ age }} years old"}],
response_model=User,
context={
"name": "Jason",
"age": 25,
},
)
print(response)
# > name='Jason' age=25
# Using genai's Content type
response = client.create(
messages=[
genai.types.Content(
role="user",
parts=[genai.types.Part.from_text(text="{{name}} is {{age}} years old")],
)
],
response_model=User,
context={
"name": "Jason",
"age": 25,
},
)
print(response)
# > name='Jason' age=25
```
## Validation and Retries
Instructor can automatically retry requests when validation fails, ensuring you get properly formatted data. This is especially helpful when enforcing specific data requirements:
```python
from typing import Annotated
from pydantic import AfterValidator, BaseModel
import instructor
from google import genai
def uppercase_validator(v: str) -> str:
if v.islower():
raise ValueError("Name must be ALL CAPS")
return v
class UserDetail(BaseModel):
name: Annotated[str, AfterValidator(uppercase_validator)]
age: int
client = instructor.from_provider("google/gemini-2.5-flash")
response = client.create(
messages=[{"role": "user", "content": "Extract: jason is 25 years old"}],
response_model=UserDetail,
max_retries=3,
)
print(response) # UserDetail(name='JASON', age=25)
```
## Multimodal Capabilities
> We've provided a few different sample files for you to use to test out these new features. All examples below use these files.
>
> - (Audio) : A Recording of the Original Gettysburg Address : [gettysburg.wav](https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/gettysburg.wav)
> - (Image) : An image of some blueberry plants [image.jpg](https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/image.jpg)
> - (PDF) : A sample PDF file which contains a fake invoice [invoice.pdf](https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf)
Instructor provides a unified, provider-agnostic interface for working with multimodal inputs like images, PDFs, and audio files. With Instructor's multimodal objects, you can easily load media from URLs, local files, or base64 strings using a consistent API that works across different AI providers (OpenAI, Anthropic, Mistral, etc.).
Instructor handles all the provider-specific formatting requirements behind the scenes, ensuring your code remains clean and future-proof as provider APIs evolve.
Let's see how to use the Image, Audio and PDF classes.
### Image Processing
!!! info "Autodetect Images"
For convenient handling of images, you can enable automatic image conversion using the `autodetect_images` parameter. When enabled, Instructor will automatically detect and convert file paths and HTTP URLs provided as strings into the appropriate format required by the Google GenAI SDK. This makes working with images seamless and straightforward. ( see examples below )
Instructor makes it easy to analyse and extract semantic information from images using the Gemini series of models. [Click here](https://ai.google.dev/gemini-api/docs/models) to check if the model you'd like to use has vison capabilities.
Let's see an example below with the sample image above where we'll load it in using our `from_url` method.
Note that we support local files and base64 strings too with the `from_path` and the `from_base64` class methods.
```python
from instructor.processing.multimodal import Image
from pydantic import BaseModel, Field
import instructor
from google.genai import Client
class ImageDescription(BaseModel):
objects: list[str] = Field(..., description="The objects in the image")
scene: str = Field(..., description="The scene of the image")
colors: list[str] = Field(..., description="The colors in the image")
client = instructor.from_provider("google/gemini-2.5-flash")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/image.jpg"
# Multiple ways to load an image:
response = client.create(
response_model=ImageDescription,
messages=[
{
"role": "user",
"content": [
"What is in this image?",
# Option 1: Direct URL with autodetection
Image.from_url(url),
# Option 2: Local file
# Image.from_path("path/to/local/image.jpg")
# Option 3: Base64 string
# Image.from_base64("base64_encoded_string_here")
# Option 4: Autodetect
# Image.autodetect(<url|path|base64>)
],
},
],
)
print(response)
# Example output:
# ImageDescription(
# objects=['blueberries', 'leaves'],
# scene='A blueberry bush with clusters of ripe blueberries and some unripe ones against a cloudy sky',
# colors=['green', 'blue', 'purple', 'white']
# )
```
### Audio Processing
Instructor makes it easy to analyse and extract semantic information from Audio files using the Gemini series of models. Let's see an example below with the sample Audio file above where we'll load it in using our `from_url` method.
Note that we support local files and base64 strings too with the `from_path`
```python
from instructor.processing.multimodal import Audio
from pydantic import BaseModel
import instructor
from google.genai import Client
class AudioDescription(BaseModel):
transcript: str
summary: str
speakers: list[str]
key_points: list[str]
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/gettysburg.wav"
client = instructor.from_provider("google/gemini-2.5-flash")
response = client.create(
response_model=AudioDescription,
messages=[
{
"role": "user",
"content": [
"Please transcribe and analyze this audio:",
# Multiple loading options:
Audio.from_url(url),
# Option 2: Local file
# Audio.from_path("path/to/local/audio.mp3")
],
},
],
)
print(response)
# > transcript='Four score and seven years ago our fathers..."]
```
### PDF
Instructor makes it easy to analyse and extract semantic information from PDFs using Gemini's new models.
Let's see an example below with the sample PDF above where we'll load it in using our `from_url` method. With this integration that we're passing in the raw bytes to gemini itself, we also support using the Files api with the `PDFWithGenaiFile` class.
Note that we support local files and base64 strings using this method too with the `from_path` and the `from_base64` class methods.
```python
from instructor.processing.multimodal import PDF
from pydantic import BaseModel
import instructor
from google.genai import Client
class Receipt(BaseModel):
total: int
items: list[str]
client = instructor.from_provider("google/gemini-2.5-flash")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf"
# Multiple ways to load an PDF:
response = client.create(
response_model=Receipt,
messages=[
{
"role": "user",
"content": [
"Extract out the total and line items from the invoice",
# Option 1: Direct URL
PDF.from_url(url),
# Option 2: Local file
# PDF.from_path("path/to/local/invoice.pdf"),
# Option 3: Base64 string
# PDF.from_base64("base64_encoded_string_here")
# Option 4: Autodetect
# PDF.autodetect(<url|path|base64>)
],
},
],
)
print(response)
# > Receipt(total=220, items=['English Tea', 'Tofu'])
```
We also support the use of PDFs with the Gemini `Files` api with the `PDFWithGenaiFile` that allows you to use existing uploaded files or local files.
Note that the `PdfWithGenaiFile.from_new_genai_file` operation is blocking and you can set the timeout and retry delay that we'll call while we await the upload to be registered as completed.
```python
PDFWithGenaiFile.from_new_genai_file(
"./invoice.pdf",
retry_delay=1, # Time to wait before checking if file is ready to use
max_retries=20 # Number of times to check before throwing an error
),
```
This makes it easier for you to work with the Gemini files API. You can use this in a normal chat completion as seen below
```python
from instructor.processing.multimodal import PDFWithGenaiFile
from pydantic import BaseModel
import instructor
from google.genai import Client
class Receipt(BaseModel):
total: int
items: list[str]
client = instructor.from_provider("google/gemini-2.5-flash")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf"
# Multiple ways to load an PDF:
response = client.create(
response_model=Receipt,
messages=[
{
"role": "user",
"content": [
"Extract out the total and line items from the invoice",
# Option 1: Direct URL
PDFWithGenaiFile.from_new_genai_file("./invoice.pdf"),
# Option 2 : Existing Genai File
# PDFWithGenaiFile.from_existing_genai_file("invoice.pdf"),
],
},
],
)
print(response)
```
If you'd like more fine-grained control over the files used, you can also use the `Files` api directly as seen below.
## Using Files
Our API integration also supports the use of files
```python
import instructor
from pydantic import BaseModel
class Summary(BaseModel):
summary: str
client = instructor.from_provider("google/gemini-2.5-flash")
file1 = client.files.upload(
file="./gettysburg.wav",
)
# As a parameter
response = client.create(
messages=[
{
"role": "user",
"content": [
"Summarise the audio file.",
file1,
]
}
],
response_model=Summary,
)
print(response)
# > summary="Abraham Lincoln's Gettysburg Address commences by stating that 87 years prior, the founding fathers created a new nation based on liberty and equality. It goes on to say that the Civil War is testing whether a nation so conceived can survive."
```
## Streaming Responses
!!! warning "Streaming Limitations"
**As of July 11, 2025, Google GenAI does not support streaming with tool/function calling or structured outputs for regular models.**
- `Mode.TOOLS` and `Mode.JSON` do not support streaming with regular models
- To use streaming, you must use `Partial[YourModel]` explicitly or switch to other modes like `Mode.JSON`
- Alternatively, set `stream=False` to disable streaming
Streaming allows you to process responses incrementally rather than waiting for the complete result. This is extremely useful for making UI changes feel instant and responsive.
### Partial Streaming
Receive a stream of complete, validated objects as they're generated:
```python
from pydantic import BaseModel
import instructor
client = instructor.from_provider(
"google/gemini-2.5-flash",
mode=instructor.Mode.JSON,
)
class Person(BaseModel):
name: str
age: int
class PersonList(BaseModel):
people: list[Person]
stream = client.create_partial(
model="gemini-2.5-flash",
response_model=PersonList,
stream=True,
messages=[
{
"role": "user",
"content": "Ivan is 20 years old, Jason is 25 years old, and John is 30 years old",
}
],
)
for extraction in stream:
print(extraction)
# > people=[PartialPerson(name='Ivan', age=None)]
# > people=[PartialPerson(name='Ivan', age=20), PartialPerson(name='Jason', age=25), PartialPerson(name='John', age=None)]
# > people=[PartialPerson(name='Ivan', age=20), PartialPerson(name='Jason', age=25), PartialPerson(name='John', age=30)]
```
### Iterable Streaming
For extracting multiple objects from a single response, use `create_iterable`:
```python
from pydantic import BaseModel
import instructor
client = instructor.from_provider("google/gemini-2.5-flash")
class User(BaseModel):
name: str
age: int
# Extract multiple users from a single response
stream = client.create_iterable(
model="gemini-2.5-flash",
response_model=User,
stream=True,
messages=[
{
"role": "user",
"content": "Jason is 25 years old, Sarah is 30 years old, and Mike is 28 years old",
}
],
)
for user in stream:
print(user)
# > User(name='Jason', age=25)
# > User(name='Sarah', age=30)
# > User(name='Mike', age=28)
```
### Async Streaming
Both partial and iterable streaming work with async clients:
```python
import asyncio
from pydantic import BaseModel
import instructor
class User(BaseModel):
name: str
age: int
async def async_partial_example():
client = instructor.from_provider("google/gemini-2.5-flash", async_client=True)
stream = client.create_partial(
model="gemini-2.5-flash",
response_model=User,
stream=True,
messages=[
{"role": "user", "content": "Jason is 25 years old"}
],
)
async for chunk in stream:
print(chunk)
async def async_iterable_example():
client = instructor.from_provider("google/gemini-2.5-flash", async_client=True)
stream = client.create_iterable(
model="gemini-2.5-flash",
response_model=User,
stream=True,
messages=[
{
"role": "user",
"content": "Jason is 25, Sarah is 30, Mike is 28"
}
],
)
async for user in stream:
print(user)
# Run async examples
asyncio.run(async_partial_example())
asyncio.run(async_iterable_example())
```
## Async Support
Instructor provides full async support for the genai SDK, allowing you to make non-blocking requests in async applications:
```python
import asyncio
import instructor
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
async def extract_user():
client = instructor.from_provider(
"google/gemini-2.5-flash",
async_client=True,
)
response = await client.create(
messages=[{"role": "user", "content": "Extract: Jason is 25 years old"}],
response_model=User,
)
return response
print(asyncio.run(extract_user()))
#> name = Jason age= 25
```

View File

@@ -0,0 +1,444 @@
---
title: "Google Gemini Tutorial: Structured Outputs with Instructor"
description: "Learn how to use Google's Gemini models (Pro, Flash, Ultra) with Instructor for structured data extraction. Complete tutorial with examples for multimodal AI and type-safe outputs."
---
## See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [from_provider Guide](../concepts/from_provider.md) - Detailed client configuration
- [Multi-Modal Examples](../examples/multi_modal_gemini.md) - Vision and multi-modal processing
- [Provider Examples](../index.md#provider-examples) - Quick examples for all providers
# Google Gemini Tutorial: Structured Outputs with Instructor
Master structured data extraction using Google's Gemini models with Instructor. This comprehensive tutorial covers Gemini Pro, Flash, and Ultra models, including multimodal capabilities for processing text, images, and more.
## Google GenAI SDK
Google's GenAI SDK is the recommended way to access Gemini models. It provides a unified interface for both the Gemini API and Vertex AI. This guide shows you how to use Instructor with Google's GenAI SDK for type-safe, validated responses.
```bash
pip install "instructor[google-genai]"
```
## Simple User Example (Sync)
```python
import instructor
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
# Using from_provider (recommended)
client = instructor.from_provider(
"google/gemini-3-flash",
)
resp = client.create(
response_model=User,
messages=[
{
"role": "user",
"content": "Extract Jason is 25 years old.",
}
],
)
print(resp) # User(name='Jason', age=25)
```
## Simple User Example (Async)
!!! info "Async Support"
Instructor supports async mode for the Google GenAI SDK. If you're using the async client, make sure that your client is declared within the same event loop as the function that calls it. If not you'll get a bunch of errors.
```python
import instructor
from pydantic import BaseModel
import asyncio
class User(BaseModel):
name: str
age: int
async def extract_user():
client = instructor.from_provider(
"google/gemini-3-flash",
async_client=True,
)
user = await client.create(
messages=[
{
"role": "user",
"content": "Extract Jason is 25 years old.",
}
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user) # User(name='Jason', age=25)
```
## Configuration Options
You can customize the model's behavior using generation configuration parameters. These parameters control aspects like temperature, token limits, and sampling methods. Pass these parameters as a dictionary to the `generation_config` parameter when creating the response.
The most common parameters include:
- `temperature`: Controls randomness in the output (0.0 to 1.0)
- `max_tokens`: Maximum number of tokens to generate
- `top_p`: Nucleus sampling parameter
- `top_k`: Number of highest probability tokens to consider
For more details on configuration options, see [Google's documentation on Gemini configuration parameters](https://cloud.google.com/vertex-ai/generative-ai/docs/samples/generativeaionvertexai-gemini-pro-config-example){target="_blank"}.
```python
import instructor
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"google/gemini-3-flash",
mode=instructor.Mode.JSON,
)
resp = client.create(
response_model=User,
messages=[
{
"role": "user",
"content": "Extract Jason is 25 years old.",
},
],
generation_config={
"temperature": 0.5,
"max_tokens": 1000,
"top_p": 1,
"top_k": 32,
},
)
print(resp)
```
## Safety settings with images
Google GenAI uses a different set of harm categories for image inputs (for example, `HARM_CATEGORY_IMAGE_HATE`).
When your request includes image content, Instructor will:
- Use the image-specific categories in the request config
- Map thresholds you pass for text categories (like `HARM_CATEGORY_HATE_SPEECH`) to the matching image category (like `HARM_CATEGORY_IMAGE_HATE`)
This avoids `400 INVALID_ARGUMENT` errors when you combine `safety_settings` with images.
```python
import instructor
from google.genai.types import HarmBlockThreshold, HarmCategory
from instructor.processing.multimodal import Image
from pydantic import BaseModel
class Result(BaseModel):
summary: str
client = instructor.from_provider("google/gemini-3-flash")
result = client.create(
response_model=Result,
messages=[
{
"role": "user",
"content": [
"Describe the image in one sentence.",
Image.autodetect("path/to/image.png"),
],
}
],
# You can still pass text categories. Instructor will map them for image inputs.
safety_settings={
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE,
},
)
print(result)
```
## Nested Example
```python
import instructor
from pydantic import BaseModel
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
client = instructor.from_provider(
"google/gemini-3-flash",
)
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
},
],
response_model=User,
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```
## Streaming Support
Instructor has two main ways that you can use to stream responses out
1. **Iterables**: These are useful when you'd like to stream a list of objects of the same type (Eg. use structured outputs to extract multiple users)
2. **Partial Streaming**: This is useful when you'd like to stream a single object and you'd like to immediately start processing the response as it comes in.
### Partials
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider(
"google/gemini-3-flash",
)
class User(BaseModel):
name: str
age: int
bio: str
user = client.create_partial(
messages=[
{
"role": "user",
"content": "Create a user profile for Jason and 1 sentence bio, age 25",
},
],
response_model=User,
)
for user_partial in user:
print(user_partial)
# > name=None age=None bio=None
# > name=None age=25 bio='Jason is a great guy'
# > name='Jason' age=25 bio='Jason is a great guy'
```
### Iterable Example
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider(
"google/gemini-3-flash",
)
class User(BaseModel):
name: str
age: int
# Extract multiple users from text
users = client.create_iterable(
messages=[
{
"role": "user",
"content": """
Extract users:
1. Jason is 25 years old
2. Sarah is 30 years old
3. Mike is 28 years old
""",
},
],
response_model=User,
)
for user in users:
print(user)
#> name='Jason' age=25
#> name='Sarah' age=30
#> name='Mike' age=28
```
## Known Limitations (as of Nov 12, 2024)
Google Gemini has the following known limitations when used with Instructor:
1. **Union Types**: Gemini does not support Union types (except for Optional). Use separate response models or Literal types instead.
2. **Enum Types**: Gemini returns string values instead of properly typed Enum instances. You may need to manually convert strings to enums after extraction.
3. **Union Streaming**: Streaming is not supported for Union types with Iterable.
These limitations are specific to Google Gemini and do not affect other providers like OpenAI or Anthropic. Tests automatically skip these features for Google to prevent failures.
## Instructor Modes
We provide several modes to make it easy to work with the different response models that Gemini supports:
1. `instructor.Mode.TOOLS` : This uses Gemini's tool calling API to return structured outputs (default)
2. `instructor.Mode.JSON` : This uses Gemini's JSON schema mode for structured outputs
!!! note "Backwards Compatibility"
Legacy provider-specific modes (for example `Mode.TOOLS`, `Mode.JSON`, `Mode.JSON`, `Mode.TOOLS`) are deprecated. They emit warnings and map to the generic modes.
!!! info "Mode Selection"
When using `from_provider`, the appropriate mode is automatically selected based on the provider and model capabilities.
## Available Models
Google offers several Gemini models:
- Gemini Flash (General purpose)
- Gemini Pro (Multimodal)
- Gemini Flash-8b (Coming soon)
## Using Gemini's Multimodal Capabilities
We've written an extensive list of guides on how to use gemini's multimodal capabilities with instructor.
- [Using Geminin To Extract Travel Video Recomendations](../blog/posts/multimodal-gemini.md)
- [Parsing PDFs with Gemini](../blog/posts/chat-with-your-pdf-with-gemini.md)
- [Generating Citations with Gemini](../blog/posts/generating-pdf-citations.md)
Stay tuned to the blog for more guides on using Gemini with instructor.
## Related Resources
- [Google AI Documentation](https://ai.google.dev/)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
## Migration from google-generativeai
If you're currently using the legacy `google-generativeai` package with Instructor, here's how to migrate:
### Old Way (Deprecated)
```python
import instructor
import google.generativeai as genai
client = instructor.from_provider(
"google/gemini-2.5-flash",
mode=instructor.Mode.JSON,
)
```
### New Way (Recommended)
```python
import instructor
# Option 1: Using from_provider (recommended)
client = instructor.from_provider("google/gemini-2.5-flash")
# Option 2: Using from_genai directly (legacy/advanced)
from google import genai
from instructor import from_genai
client = from_genai(genai.Client())
```
### Vertex AI Migration
For Vertex AI users, the migration is similar:
#### Old Way (Deprecated)
```python
import instructor
import vertexai
from vertexai.generative_models import GenerativeModel
vertexai.init(project="your-project", location="us-central1")
client = instructor.from_provider("google/gemini-2.5-flash", vertexai=True),
mode=instructor.Mode.TOOLS,
)
```
#### New Way (Recommended)
```python
import instructor
# Option 1: Using from_provider (recommended)
client = instructor.from_provider(
"vertexai/gemini-3-flash",
project="your-project",
location="us-central1"
)
# Option 2: Using from_genai with vertexai=True (legacy/advanced)
from google import genai
from instructor import from_genai
client = from_genai(
genai.Client(
vertexai=True,
project="your-project",
location="us-central1"
)
)
```
## Updates and Compatibility
Instructor maintains compatibility with Google's latest API versions. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates.

View File

@@ -0,0 +1,155 @@
---
title: Structured Outputs with Groq AI and Pydantic
description: Learn how to use Groq AI for structured outputs with Pydantic in Python and enhance API interactions.
---
# Structured Outputs with Groq AI
This guide demonstrates how to use Groq AI with Instructor to generate structured outputs. You'll learn how to use Groq's LLM models to create type-safe responses.
you'll need to sign up for an account and get an API key. You can do that [here](https://console.groq.com/docs/quickstart).
```bash
export GROQ_API_KEY=<your-api-key-here>
pip install "instructor[groq]"
```
### See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [Groq Examples](../examples/groq.md) - Practical Groq examples
- [from_provider Guide](../concepts/from_provider.md) - Detailed client configuration
- [Provider Examples](../index.md#provider-examples) - Quick examples for all providers
# Groq AI
Groq supports structured outputs with their new `llama-3-groq-70b-8192-tool-use-preview` model.
### Sync Example
```python
import os
from groq import Groq
import instructor
from pydantic import BaseModel
# Initialize with API key
client = Groq(api_key=os.getenv("GROQ_API_KEY"))
# Enable instructor patches for Groq client
client = instructor.from_provider("groq/llama3-8b-8192")
class User(BaseModel):
name: str
age: int
# Create structured output
user = client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
print(user)
# > User(name='Jason', age=25)
```
### Async Example
```python
import instructor
from pydantic import BaseModel
import asyncio
# Initialize async client using provider string
client = instructor.from_provider(
"groq/llama3-8b-8192",
async_client=True,
)
class User(BaseModel):
name: str
age: int
async def extract_user():
user = await client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user)
# > User(name='Jason', age=25)
```
### Nested Object
```python
import os
from groq import Groq
import instructor
from pydantic import BaseModel
# Initialize with API key
client = Groq(api_key=os.getenv("GROQ_API_KEY"))
# Enable instructor patches for Groq client
client = instructor.from_provider("groq/llama3-8b-8192")
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
},
],
response_model=User,
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```

View File

@@ -0,0 +1,181 @@
---
title: "LLM Provider Integration Tutorials - Instructor"
description: "Complete tutorials for integrating Instructor with 15+ LLM providers. Learn structured data extraction with OpenAI, Anthropic Claude, Google Gemini, local models with Ollama, and more."
---
# LLM Provider Integration Tutorials
Learn how to integrate Instructor with various AI model providers. These comprehensive tutorials cover everything from cloud-based services like OpenAI and Anthropic to local open-source models, helping you extract structured outputs from any LLM.
<div class="grid cards" markdown>
- :material-cloud: **Major Cloud Providers**
Leading AI providers with comprehensive features
[:octicons-arrow-right-16: OpenAI](./openai.md) ·
[:octicons-arrow-right-16: OpenAI Responses](./openai-responses.md) ·
[:octicons-arrow-right-16: Azure](./azure.md) ·
[:octicons-arrow-right-16: Anthropic](./anthropic.md) ·
[:octicons-arrow-right-16: Google.GenerativeAI](./google.md) ·
[:octicons-arrow-right-16: Vertex AI](./vertex.md) ·
[:octicons-arrow-right-16: AWS Bedrock](./bedrock.md) ·
[:octicons-arrow-right-16: Google.GenAI](./genai.md) ·
[:octicons-arrow-right-16: xAI](./xai.md)
- :material-cloud-outline: **Additional Cloud Providers**
Other commercial AI providers with specialized offerings
[:octicons-arrow-right-16: Cohere](./cohere.md) ·
[:octicons-arrow-right-16: Mistral](./mistral.md) ·
[:octicons-arrow-right-16: DeepSeek](./deepseek.md) ·
[:octicons-arrow-right-16: Together AI](./together.md) ·
[:octicons-arrow-right-16: Groq](./groq.md) ·
[:octicons-arrow-right-16: Fireworks](./fireworks.md) ·
[:octicons-arrow-right-16: Cerebras](./cerebras.md) ·
[:octicons-arrow-right-16: Writer](./writer.md) ·
[:octicons-arrow-right-16: Perplexity](./perplexity.md)
[:octicons-arrow-right-16: SambaNova](./sambanova.md)
- :material-open-source-initiative: **Open Source**
Run open-source models locally or in the cloud
[:octicons-arrow-right-16: Ollama](./ollama.md) ·
[:octicons-arrow-right-16: llama-cpp-python](./llama-cpp-python.md)
- :material-router-wireless: **Routing**
Unified interfaces for multiple providers
[:octicons-arrow-right-16: LiteLLM](./litellm.md)
[:octicons-arrow-right-16: OpenRouter](./openrouter.md)
</div>
## Common Features
All integrations support these core features:
| Feature | Description | Documentation |
|---------|-------------|---------------|
| **Model Patching** | Enhance provider clients with structured output capabilities | [Patching](../concepts/patching.md) |
| **Response Models** | Define expected response schema with Pydantic | [Models](../concepts/models.md) |
| **Validation** | Ensure responses match your schema definition | [Validation](../concepts/validation.md) |
| **Streaming** | Stream partial or iterative responses | [Partial](../concepts/partial.md), [Iterable](../concepts/iterable.md) |
| **Hooks** | Add callbacks for monitoring and debugging | [Hooks](../concepts/hooks.md) |
However, each provider has different capabilities and limitations. Refer to the specific provider documentation for details.
## Provider Modes
Providers support different methods for generating structured outputs:
| Mode | Description | Providers |
|------|-------------|-----------|
| `TOOLS` | Uses OpenAI-style tools/function calling | OpenAI, Anthropic, Mistral |
| `PARALLEL_TOOLS` | Multiple simultaneous tool calls | OpenAI |
| `JSON` | Direct JSON response generation | OpenAI, Gemini, Cohere, GenAI |
| `MD_JSON` | JSON embedded in markdown | Most providers |
See the [Modes Comparison](../modes-comparison.md) guide for details.
## Getting Started
There are two ways to use providers with Instructor:
### 1. Using Provider Initialization (Recommended)
The simplest way to get started is using the provider initialization:
```python
import instructor
from pydantic import BaseModel
class UserInfo(BaseModel):
name: str
age: int
# Initialize any provider with a simple string
client = instructor.from_provider("openai/gpt-4")
# Or use async client
async_client = instructor.from_provider("anthropic/claude-3-sonnet", async_client=True)
# Use the same interface for all providers
response = client.create(
response_model=UserInfo,
messages=[{"role": "user", "content": "Your prompt"}]
)
```
Supported provider strings:
- `openai/model-name`: OpenAI models
- `anthropic/model-name`: Anthropic models
- `google/model-name`: Google models
- `mistral/model-name`: Mistral models
- `cohere/model-name`: Cohere models
- `perplexity/model-name`: Perplexity models
- `groq/model-name`: Groq models
- `writer/model-name`: Writer models
- `bedrock/model-name`: AWS Bedrock models
- `cerebras/model-name`: Cerebras models
- `fireworks/model-name`: Fireworks models
- `vertexai/model-name`: Vertex AI models
- `genai/model-name`: Google GenAI models
- `ollama/model-name`: Ollama models
### Provider Checklist
Use these example strings with `from_provider` to quickly get started:
- [x] `instructor.from_provider("openai/gpt-5-nano")`
- [x] `instructor.from_provider("anthropic/claude-3-sonnet")`
- [x] `instructor.from_provider("google/gemini-2.5-flash")`
- [x] `instructor.from_provider("mistral/mistral-large-latest")`
- [x] `instructor.from_provider("cohere/command-r")`
- [x] `instructor.from_provider("perplexity/sonar-small")`
- [x] `instructor.from_provider("groq/llama3-8b-8192")`
- [x] `instructor.from_provider("writer/palmyra-x-004")`
- [x] `instructor.from_provider("bedrock/anthropic.claude-3-sonnet-20240229-v1:0")`
- [x] `instructor.from_provider("cerebras/llama3.1-70b")`
- [x] `instructor.from_provider("fireworks/llama-v3-70b-instruct")`
- [x] `instructor.from_provider("vertexai/gemini-3-flash")`
- [x] `instructor.from_provider("genai/gemini-3-flash")`
- [x] `instructor.from_provider("ollama/llama3")`
### 2. Manual Client Setup
Alternatively, you can manually set up the client:
1. Install the required dependencies:
```bash
pip install "instructor[provider]" # e.g., instructor[anthropic]
```
2. Import the provider client and patch it with Instructor:
```python
import instructor
from provider_package import Client
client = instructor.from_provider(Client())
```
3. Use the patched client with your Pydantic model:
```python
response = client.create(
response_model=YourModel,
messages=[{"role": "user", "content": "Your prompt"}]
)
```
For provider-specific setup and examples, visit each provider's documentation page.
## Need Help?
If you need assistance with a specific integration:
1. Check the provider-specific documentation
2. Browse the [examples](../examples/index.md) and [cookbooks](../examples/index.md)
3. Search existing [GitHub issues](https://github.com/jxnl/instructor/issues)
4. Join our [Discord community](https://discord.gg/bD9YE9JArw)

View File

@@ -0,0 +1,121 @@
---
title: "Structured outputs with LiteLLM, a complete guide w/ instructor"
description: "Complete guide to using Instructor with LiteLLM's unified interface. Learn how to generate structured, type-safe outputs across multiple LLM providers."
---
# Structured outputs with LiteLLM, a complete guide w/ instructor
LiteLLM provides a unified interface for multiple LLM providers, making it easy to switch between different models and providers. This guide shows you how to use Instructor with LiteLLM for type-safe, validated responses across various LLM providers.
## Quick Start
Install Instructor with LiteLLM support:
```bash
pip install "instructor[litellm]"
```
## Simple User Example (Sync)
```python
from litellm import completion
import instructor
from pydantic import BaseModel
# Enable instructor patches
client = instructor.from_provider("litellm/gpt-3.5-turbo")
class User(BaseModel):
name: str
age: int
# Create structured output
user = client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
print(user) # User(name='Jason', age=25)
```
## Simple User Example (Async)
```python
import instructor
from pydantic import BaseModel
import asyncio
client = instructor.from_provider(
"litellm/gpt-3.5-turbo",
async_client=True,
)
class User(BaseModel):
name: str
age: int
async def extract_user():
user = await client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user) # User(name='Jason', age=25)
```
## Cost Calculation
In order to calculate the cost of the response, LiteLLM provides a simple `response_cost` attribute on the response object's `_hidden_params` attribute. This is recorded in their documentation [here](https://docs.litellm.ai/docs/completion/token_usage#6-completion_cost).
Here is a code snippet using instructor to calculate the cost of the response:
```python
import instructor
from litellm import completion
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
client = instructor.from_provider("litellm/gpt-3.5-turbo")
instructor_resp, raw_completion = client.create_with_completion(
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Extract Jason is 25 years old.",
}
],
response_model=User,
)
print(raw_completion._hidden_params["response_cost"])
#> 0.00189
```
## Related Resources
- [LiteLLM Documentation](https://docs.litellm.ai/)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
## Updates and Compatibility
Instructor maintains compatibility with LiteLLM's latest releases. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates.
Note: Always verify provider-specific features and limitations in their respective documentation before implementation.

View File

@@ -0,0 +1,108 @@
---
draft: False
date: 2024-02-12
title: "Structured outputs with llama-cpp-python, a complete guide w/ instructor"
description: "Complete guide to using Instructor with llama-cpp-python. Learn how to generate structured, type-safe outputs with llama-cpp-python."
slug: llama-cpp-python
tags:
- patching
authors:
- jxnl
---
# Structured outputs with llama-cpp-python, a complete guide w/ instructor
This guide demonstrates how to use llama-cpp-python with Instructor to generate structured outputs. You'll learn how to use JSON schema mode and speculative decoding to create type-safe responses from local LLMs.
Open-source LLMS are gaining popularity, and llama-cpp-python has made the `llama-cpp` model available to obtain structured outputs using JSON schema via a mixture of [constrained sampling](https://llama-cpp-python.readthedocs.io/en/latest/#json-schema-mode) and [speculative decoding](https://llama-cpp-python.readthedocs.io/en/latest/#speculative-decoding).
They also support a [OpenAI compatible client](https://llama-cpp-python.readthedocs.io/en/latest/#openai-compatible-web-server), which can be used to obtain structured output as a in process mechanism to avoid any network dependency.
<!-- more -->
## Patching
Instructor's patch enhances an create call it with the following features:
- `response_model` in `create` calls that returns a pydantic model
- `max_retries` in `create` calls that retries the call if it fails by using a backoff strategy
!!! note "Learn More"
To learn more, please refer to the [docs](../index.md). To understand the benefits of using Pydantic with Instructor, visit the tips and tricks section of the [why use Pydantic](../why.md) page. If you want to check out examples of using Pydantic with Instructor, visit the [examples](../examples/index.md) page.
### See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [Ollama Integration](./ollama.md) - Alternative local model setup
- [Local Classification](../examples/local_classification.md) - Classification with local models
- [Open Source Models](../examples/open_source.md) - More open-source model examples
# llama-cpp-python
Recently llama-cpp-python added support for structured outputs via JSON schema mode. This is a time-saving alternative to extensive prompt engineering and can be used to obtain structured outputs.
In this example we'll cover a more advanced use case of JSON_SCHEMA mode to stream out partial models. To learn more [partial streaming](https://github.com/jxnl/instructor/concepts/partial.md) check out partial streaming.
## Quick Start with `from_provider`
If you run the `llama-cpp-python` server in OpenAI compatible mode, you can use the unified `from_provider` API to patch the client. Simply point the base URL at your local server:
```python
import instructor
# Sync client
client = instructor.from_provider(
"ollama/openhermes", base_url="http://localhost:8080/v1"
)
# Async client
async_client = instructor.from_provider(
"ollama/openhermes", async_client=True, base_url="http://localhost:8080/v1"
)
```
You can then call `chat.completions.create` just like with any other provider.
```python
import llama_cpp
import instructor
from llama_cpp.llama_speculative import LlamaPromptLookupDecoding
from pydantic import BaseModel
llama = llama_cpp.Llama(
model_path="../../models/OpenHermes-2.5-Mistral-7B-GGUF/openhermes-2.5-mistral-7b.Q4_K_M.gguf",
n_gpu_layers=-1,
chat_format="chatml",
n_ctx=2048,
draft_model=LlamaPromptLookupDecoding(num_pred_tokens=2),
logits_all=True,
verbose=False,
)
create = instructor.patch(
create=llama.create_chat_completion_openai_v1,
mode=instructor.Mode.JSON_SCHEMA,
)
class UserDetail(BaseModel):
name: str
age: int
user = create(
messages=[
{
"role": "user",
"content": "Extract `Jason is 30 years old`",
}
],
response_model=UserDetail,
)
print(user)
#> name='Jason' age=30
```

View File

@@ -0,0 +1,348 @@
---
draft: False
date: 2025-03-11
title: "Structured outputs with Mistral, a complete guide w/ instructor"
description: "Complete guide to using Instructor with Mistral. Learn how to generate structured, type-safe outputs with Mistral."
slug: mistral
tags:
- patching
authors:
- shanktt
- ivanleomk
---
# Structured outputs with Mistral, a complete guide w/ instructor
This guide demonstrates how to use Mistral with Instructor to generate structured outputs. You'll learn how to use function calling with Mistral Large to create type-safe responses.
Mistral Large is the flagship model from Mistral AI, supporting 32k context windows and functional calling abilities. Mistral Large's addition of [function calling](https://docs.mistral.ai/guides/function-calling/) makes it possible to obtain structured outputs using JSON schema.
## Quick Start
To get started with Instructor and Mistral, you'll need to install the required packages:
```bash
pip install "instructor[mistral]"
```
⚠️ **Important**: You must set your Mistral API key by setting it explicitly on the client
```python
import os
from mistralai import Mistral
client = Mistral(api_key='your-api-key-here')
```
## Available Modes
Instructor provides two modes for working with Mistral:
1. `instructor.Mode.TOOLS`: Uses Mistral's function calling API to return structured outputs (default)
2. `instructor.Mode.JSON_SCHEMA`: Uses Mistral's structured output capabilities
To set the mode for your mistral client, simply use the code snippet below
```python
import os
from pydantic import BaseModel
import instructor
# Initialize with API key
instructor_client = instructor.from_provider(
"mistral/mistral-large-latest",
mode=Mode.TOOLS,
)
```
## Simple User Example (Sync)
```python
import os
from pydantic import BaseModel
import instructor
from instructor import Mode
class UserDetails(BaseModel):
name: str
age: int
# Initialize the client
instructor_client = instructor.from_provider(
"mistral/mistral-large-latest",
mode=Mode.TOOLS,
)
# Extract a single user
user = instructor_client.create(
response_model=UserDetails,
messages=[{"role": "user", "content": "Jason is 25 years old"}],
temperature=0,
)
print(user)
# Output: UserDetails(name='Jason', age=25)
```
## Async Example
For asynchronous operations, you can use the `use_async=True` parameter when creating the client:
```python
import os
import asyncio
from pydantic import BaseModel
import instructor
from instructor import Mode
class User(BaseModel):
name: str
age: int
# Initialize the async client
instructor_client = instructor.from_provider(
"mistral/mistral-large-latest",
async_client=True,
mode=Mode.TOOLS,
)
async def extract_user():
user = await instructor_client.create(
response_model=User,
messages=[{"role": "user", "content": "Jack is 28 years old."}],
temperature=0,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user)
# Output: User(name='Jack', age=28)
```
## Nested Example
You can also work with nested models:
```python
from pydantic import BaseModel
from typing import List
import os
import instructor
from instructor import Mode
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: List[Address]
# Initialize the client
instructor_client = instructor.from_provider(
"mistral/mistral-large-latest",
mode=Mode.TOOLS,
)
# Create structured output with nested objects
user = instructor_client.create(
response_model=User,
messages=[
{"role": "user", "content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
"""}
],
temperature=0,
)
print(user)
# Output:
# User(
# name='Jason',
# age=25,
# addresses=[
# Address(street='123 Main St', city='New York', country='USA'),
# Address(street='456 Beach Rd', city='Miami', country='USA')
# ]
# )
```
## Streaming Support
Instructor now supports streaming capabilities with Mistral! You can use both `create_partial` for incremental model building and `create_iterable` for streaming collections.
### Streaming Partial Responses
```python
from pydantic import BaseModel
import instructor
from mistralai import Mistral
from instructor.dsl.partial import Partial
class UserExtract(BaseModel):
name: str
age: int
# Initialize with API key
client = Mistral(api_key=os.environ.get("MISTRAL_API_KEY"))
# Enable instructor patches for Mistral client
instructor_client = instructor.from_provider("mistral/mistral-small")
# Stream partial responses
model = instructor_client.create(
response_model=Partial[UserExtract],
stream=True,
messages=[
{"role": "user", "content": "Jason Liu is 25 years old"},
],
)
for partial_user in model:
print(f"Received update: {partial_user}")
# Output might show:
# Received update: UserExtract(name='Jason', age=None)
# Received update: UserExtract(name='Jason Liu', age=None)
# Received update: UserExtract(name='Jason Liu', age=25)
```
### Streaming Iterable Collections
```python
from pydantic import BaseModel
import instructor
from mistralai import Mistral
class UserExtract(BaseModel):
name: str
age: int
# Initialize with API key
client = Mistral(api_key=os.environ.get("MISTRAL_API_KEY"))
# Enable instructor patches for Mistral client
instructor_client = instructor.from_provider("mistral/mistral-small")
# Stream iterable responses
users = instructor_client.create_iterable(
response_model=UserExtract,
messages=[
{"role": "user", "content": "Make up two people"},
],
)
for user in users:
print(f"Generated user: {user}")
# Output:
# Generated user: UserExtract(name='Emily Johnson', age=32)
# Generated user: UserExtract(name='Michael Chen', age=28)
```
### Async Streaming
You can also use async versions of both streaming approaches:
```python
import asyncio
from pydantic import BaseModel
import instructor
from mistralai import Mistral
from instructor.dsl.partial import Partial
class UserExtract(BaseModel):
name: str
age: int
# Initialize client with async support
client = Mistral(api_key=os.environ.get("MISTRAL_API_KEY"))
instructor_client = instructor.from_provider("mistral/mistral-small")
async def stream_partial():
model = await instructor_client.create(
response_model=Partial[UserExtract],
stream=True,
messages=[
{"role": "user", "content": "Jason Liu is 25 years old"},
],
)
async for partial_user in model:
print(f"Received update: {partial_user}")
async def stream_iterable():
users = instructor_client.create_iterable(
response_model=UserExtract,
messages=[
{"role": "user", "content": "Make up two people"},
],
)
async for user in users:
print(f"Generated user: {user}")
# Run async functions
asyncio.run(stream_partial())
asyncio.run(stream_iterable())
```
## Related Resources
- [Mistral AI Documentation](https://docs.mistral.ai/)
- [Mistral Function Calling Guide](https://docs.mistral.ai/guides/function-calling/)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
## Updates and Compatibility
Instructor maintains compatibility with the latest Mistral API versions and models. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates on Mistral integration features.
## Multimodal
Instructor makes it easy to analyse and extract semantic information from PDFs using Mistral's models. Let's see an example below with the sample PDF above where we'll load it in using our `from_url` method. Note that for now Mistral only supports document URLs.
```
from instructor.processing.multimodal import PDF
from pydantic import BaseModel
import instructor
from mistralai import Mistral
import os
class Receipt(BaseModel):
total: int
items: list[str]
client = instructor.from_provider("mistral/mistral-small")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf"
response = client.create(
response_model=Receipt,
max_tokens=1000,
messages=[
{
"role": "user",
"content": [
"Extract out the total and line items from the invoice",
PDF.from_url(
url
), # Also supports PDF.from_path() and PDF.from_base64()
],
},
],
)
print(response)
# > Receipt(total=220, items=['English Tea', 'Tofu'])
```

View File

@@ -0,0 +1,214 @@
---
draft: False
date: 2024-02-08
title: "Structured outputs with Ollama, a complete guide w/ instructor"
description: "Complete guide to using Instructor with Ollama. Learn how to generate structured, type-safe outputs with Ollama."
slug: ollama
tags:
- patching
- open source
authors:
- jxnl
---
# Structured outputs with Ollama, a complete guide w/ instructor
This guide demonstrates how to use Ollama with Instructor to generate structured outputs. You'll learn how to use JSON schema mode with local LLMs to create type-safe responses.
Open-source LLMS are gaining popularity, and the release of Ollama's OpenAI compatibility later it has made it possible to obtain structured outputs using JSON schema.
By the end of this blog post, you will learn how to effectively utilize instructor with ollama. But before we proceed, let's first explore the concept of patching.
<!-- more -->
## Patching
Instructor's patch enhances a openai api it with the following features:
- `response_model` in `create` calls that returns a pydantic model
- `max_retries` in `create` calls that retries the call if it fails by using a backoff strategy
- `timeout` parameter for controlling total retry duration (especially important for Ollama)
!!! note "Learn More"
To learn more, please refer to the [docs](../index.md). To understand the benefits of using Pydantic with Instructor, visit the tips and tricks section of the [why use Pydantic](../why.md) page.
## Timeout Handling with Ollama
Ollama integration now properly supports timeout parameters to ensure reliable request handling:
```python
from pydantic import BaseModel
import instructor
class Character(BaseModel):
name: str
age: int
client = instructor.from_provider(
"ollama/llama2",
mode=instructor.Mode.JSON,
)
resp = client.create(
messages=[
{
"role": "user",
"content": "Tell me about Harry Potter",
}
],
response_model=Character,
max_retries=2,
timeout=10.0, # Total timeout across all retry attempts
)
```
The timeout parameter ensures that:
- **Total timeout control**: Limits the total time spent across all retry attempts, not per individual attempt
- **Ollama compatibility**: Prevents timeout issues where retries would multiply the total wait time
- **Predictable behavior**: A 3-second timeout stays 3 seconds total, not 9+ seconds when retrying
!!! tip "Timeout Best Practices"
When using Ollama, especially with larger models, set appropriate timeout values based on your model's response time. The timeout applies to the total retry duration, making response times more predictable.
### See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [Ollama Examples](../examples/ollama.md) - Practical Ollama examples
- [Open Source Models](../examples/open_source.md) - More open-source model examples
- [Local Deployment](../examples/index.md#local-deployment) - Local model deployment guide
# Ollama
Start by downloading [Ollama](https://ollama.ai/download), and then pull a model such as Llama 2 or Mistral.
!!! tip "Make sure you update your `ollama` to the latest version!"
```
ollama pull llama2
```
## Quick Start with Auto Client
You can use Ollama with Instructor's auto client for a simple setup:
```python
import instructor
from pydantic import BaseModel
class Character(BaseModel):
name: str
age: int
# Simple setup - automatically configured for Ollama
client = instructor.from_provider("ollama/llama2")
resp = client.create(
messages=[{"role": "user", "content": "Tell me about Harry Potter"}],
response_model=Character,
)
```
### Async Example
```python
import instructor
from pydantic import BaseModel
import asyncio
async_client = instructor.from_provider(
"ollama/llama2",
async_client=True,
)
class Character(BaseModel):
name: str
age: int
async def get_character():
return await async_client.create(
messages=[{"role": "user", "content": "Tell me about Harry Potter"}],
response_model=Character,
)
print(asyncio.run(get_character()))
```
### Intelligent Mode Selection
The auto client automatically selects the best mode based on your model:
- **Function Calling Models** (llama3.1, llama3.2, llama4, mistral-nemo, qwen2.5, etc.): Uses `TOOLS` mode for enhanced function calling support
- **Other Models**: Uses `JSON` mode for structured output
```python
# These models automatically use TOOLS mode
client = instructor.from_provider("ollama/llama3.1")
client = instructor.from_provider("ollama/qwen2.5")
# Other models use JSON mode
client = instructor.from_provider("ollama/llama2")
```
You can also override the mode manually:
```python
import instructor
# Force JSON mode
client = instructor.from_provider("ollama/llama3.1", mode=instructor.Mode.JSON)
# Force TOOLS mode
client = instructor.from_provider("ollama/llama2", mode=instructor.Mode.TOOLS)
```
## Manual Setup
```python
from openai import OpenAI
from pydantic import BaseModel, Field
from typing import List
import instructor
class Character(BaseModel):
name: str
age: int
fact: List[str] = Field(..., description="A list of facts about the character")
# enables `response_model` in create call
client = instructor.from_provider(
"ollama/llama2",
mode=instructor.Mode.JSON,
)
resp = client.create(
messages=[
{
"role": "user",
"content": "Tell me about the Harry Potter",
}
],
response_model=Character,
)
print(resp.model_dump_json(indent=2))
"""
{
"name": "Harry James Potter",
"age": 37,
"fact": [
"He is the chosen one.",
"He has a lightning-shaped scar on his forehead.",
"He is the son of James and Lily Potter.",
"He attended Hogwarts School of Witchcraft and Wizardry.",
"He is a skilled wizard and sorcerer.",
"He fought against Lord Voldemort and his followers.",
"He has a pet owl named Snowy."
]
}
"""
```

View File

@@ -0,0 +1,469 @@
---
title: "OpenAI Responses API Guide"
description: "Learn how to use Instructor's new Responses API with OpenAI models for structured outputs. Complete guide with examples and best practices."
---
# OpenAI Responses API Guide
The Responses API provides a more streamlined way to work with OpenAI models through Instructor. This guide covers everything you need to know about using the new Responses API for type-safe, validated outputs.
## Quick Start
```python
import instructor
from pydantic import BaseModel
# Initialize the client
client = instructor.from_provider(
"openai/gpt-4.1-mini", mode=instructor.Mode.RESPONSES_TOOLS
)
# Define your response model
class User(BaseModel):
name: str
age: int
# Create structured output
profile = client.responses.create(
input="Extract out Ivan is 28 years old",
response_model=User,
)
print(profile)
#> name='Ivan' age=28
```
## Response Modes
The Responses API supports two main modes:
1. `instructor.Mode.RESPONSES_TOOLS`: Standard mode for structured outputs
2. `instructor.Mode.RESPONSES_TOOLS_WITH_INBUILT_TOOLS`: Enhanced mode that includes built-in tools like web search and file search
```python
# Initialize the client
client = instructor.from_provider(
"openai/gpt-4.1-mini", mode=instructor.Mode.RESPONSES_TOOLS
)
```
## Core Methods
The Responses API provides several methods for creating structured outputs. Here's how to use each one:
### Basic Creation
The `create` method is the simplest way to get a structured output:
=== "Sync"
```python
from pydantic import BaseModel
import instructor
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS
)
profile = client.responses.create(
input="Extract: Jason is 25 years old",
response_model=User,
)
print(profile) # User(name='Jason', age=25)
```
=== "Async"
```python
from pydantic import BaseModel
import instructor
import asyncio
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS,
async_client=True
)
async def main():
profile = await client.responses.create(
input="Extract: Jason is 25 years old",
response_model=User,
)
print(profile) # User(name='Jason', age=25)
asyncio.run(main())
```
### Create with Completion
If you need the original completion object from OpenAI, you can do so with the `create_with_completion` method. This is useful when you have specific methods and data that you need to work from.
=== "Sync"
```python
from pydantic import BaseModel
import instructor
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS
)
response, completion = client.responses.create_with_completion(
input="Extract: Jason is 25 years old",
response_model=User,
)
print(response) # User(name='Jason', age=25)
print(completion) # Raw completion object
```
=== "Async"
```python
from pydantic import BaseModel
import instructor
import asyncio
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS,
async_client=True
)
async def main():
response, completion = await client.responses.create_with_completion(
input="Extract: Jason is 25 years old",
response_model=User,
)
print(response) # User(name='Jason', age=25)
print(completion) # Raw completion object
asyncio.run(main())
```
### Iterable Creation
If you're interested in extracting multiple instances of the same object, we provide a convinient wrapper to be able to do so.
=== "Sync"
```python
from pydantic import BaseModel
from typing import Iterable
import instructor
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS
)
profiles = client.responses.create(
input="Generate three fake profiles",
response_model=Iterable[User],
)
for profile in profiles:
print(profile)
```
=== "Async"
```python
from pydantic import BaseModel
from typing import Iterable
import instructor
import asyncio
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS,
async_client=True
)
async def main():
profiles = await client.responses.create_iterable(
input="Generate three fake profiles",
response_model=User,
)
async for profile in profiles:
print(profile)
asyncio.run(main())
```
### Partial Creation
We also provide validated outputs that you can stream in real time. This is incredibly useful for working with dynamic generative UI.
=== "Sync"
```python
from pydantic import BaseModel
import instructor
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS
)
resp = client.responses.create_partial(
input="Generate a fake profile",
response_model=User,
)
for user in resp:
print(user) # Will show partial updates as they come in
```
=== "Async"
```python
from pydantic import BaseModel
import instructor
import asyncio
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS,
async_client=True
)
async def main():
resp = client.responses.create_partial(
input="Generate a fake profile",
response_model=User,
)
async for user in resp:
print(user) # Will show partial updates as they come in
asyncio.run(main())
```
## Built-In Tools
The Responses API comes with powerful built-in tools that enhance the model's capabilities. These tools are managed by OpenAI, so you don't need to implement any additional code to use them.
For the most up-to-date documentation on how to use these tools, please refer to the [OpenAI Documentation](https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses)
### Web Search
The web search tool allows models to search the internet for real-time information. This is particularly useful for getting up-to-date information or verifying facts.
Model responses that use the web search tool will include two parts:
- A web_search_call output item with the ID of the search call.
- A message output item containing:
1. The text result in message.content[0].text
2. Annotations message.content[0].annotations for the cited URLs
By default, the model's response will include inline citations for URLs found in the web search results.
In addition to this, the url_citation annotation object will contain the URL, title and location of the cited source. You can extract this information using the `create_with_completion` method.
=== "Sync"
```python
from pydantic import BaseModel
import instructor
class Citation(BaseModel):
id: int
url: str
class Summary(BaseModel):
citations: list[Citation]
summary: str
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS_WITH_INBUILT_TOOLS,
async_client=False,
)
response, completion = client.responses.create_with_completion(
input="What are some of the best places to visit in New York for Latin American food?",
tools=[{"type": "web_search_preview"}],
response_model=Summary,
)
print(response)
# > citations=[Citation(id=1,url=....)]
# > summary = New York City offers a rich variety of ...
```
=== "Async"
```python
from pydantic import BaseModel
import instructor
import asyncio
class Citation(BaseModel):
id: int
url: str
class Summary(BaseModel):
citations: list[Citation]
summary: str
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS_WITH_INBUILT_TOOLS,
async_client=True,
)
async def main():
response = await client.responses.create(
input="What are some of the best places to visit in New York for Latin American food?",
tools=[{"type": "web_search_preview"}],
response_model=Summary,
)
print(response)
asyncio.run(main())
# > citations=[Citation(id=1,url=....)]
# > summary = New York City offers a rich variety of ...
```
You can customize the web search behavior with additional parameters:
```python
response = client.responses.create(
input="What are the best restaurants around Granary Square?",
tools=[{
"type": "web_search_preview",
"user_location": {
"type": "approximate",
"country": "GB",
"city": "London",
"region": "London",
}
}],
response_model=Summary,
)
```
### File Search
The file search tool enables models to retrieve information from your knowledge base through semantic and keyword search. This is useful for augmenting the model's knowledge with your own documents.
This makes it easy to build RAG applications out of the box
=== "Sync"
```python
from pydantic import BaseModel
import instructor
class Citation(BaseModel):
file_id: int
file_name: str
excerpt: str
class Response(BaseModel):
citations: list[Citation]
response: str
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS_WITH_INBUILT_TOOLS
)
response = client.responses.create(
input="How much does the Kyoto itinerary cost?",
tools=[{
"type": "file_search",
"vector_store_ids": ["your_vector_store_id"],
"max_num_results": 2,
}],
response_model=Response,
)
```
=== "Async"
```python
from pydantic import BaseModel
import instructor
import asyncio
class Citation(BaseModel):
file_id: int
file_name: str
excerpt: str
class Response(BaseModel):
citations: list[Citation]
response: str
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS_WITH_INBUILT_TOOLS,
async_client=True
)
async def main():
response = await client.responses.create(
input="How much does the Kyoto itinerary cost?",
tools=[{
"type": "file_search",
"vector_store_ids": ["your_vector_store_id"],
"max_num_results": 2,
}],
response_model=Response,
)
asyncio.run(main())
```
## Related Resources
- [OpenAI Documentation](https://platform.openai.com/docs)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)

View File

@@ -0,0 +1,466 @@
---
title: "Structured outputs with OpenAI, a complete guide with instructor"
description: "Learn how to use Instructor with OpenAI's models for type-safe, structured outputs. Complete guide with examples and best practices for GPT-4 and other OpenAI models."
---
# Structured outputs with OpenAI, a complete guide with instructor
OpenAI is the primary integration for Instructor, offering robust support for structured outputs with GPT-3.5, GPT-4, and future models. This guide covers everything you need to know about using OpenAI with Instructor for type-safe, validated responses.
## Quick Start
Instructor comes with support for OpenAI out of the box, so you don't need to install anything extra.
```bash
pip install "instructor"
```
⚠️ **Important**: You must set your OpenAI API key before using the client. You can do this in two ways:
1. Set the environment variable:
```bash
export OPENAI_API_KEY='your-api-key-here'
```
2. Or provide it directly to the client:
```python
import instructor
client = instructor.from_provider(
"openai/gpt-5-nano",
api_key='your-api-key-here',
)
```
## Simple User Example (Sync)
```python
import instructor
from pydantic import BaseModel
# Initialize client using provider string
client = instructor.from_provider("openai/gpt-5-nano")
class User(BaseModel):
name: str
age: int
# Create structured output
user = client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
print(user)
#> User(name='Jason', age=25)
```
## Simple User Example (Async)
```python
import instructor
from pydantic import BaseModel
import asyncio
# Initialize async client using provider string
client = instructor.from_provider("openai/gpt-5-nano", async_client=True)
class User(BaseModel):
name: str
age: int
async def extract_user():
user = await client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user)
#> User(name='Jason', age=25)
```
## Responses API Mode
OpenAI now recommends the Responses API for new builds. Instructor exposes this API through two modes so you can keep the same interface while gaining better caching, stateful context, and optional built-in tools. Pass `mode=instructor.Mode.RESPONSES_TOOLS` when you want Instructor to call the Responses API instead of Chat Completions. Use `instructor.Mode.RESPONSES_TOOLS_WITH_INBUILT_TOOLS` if you plan to use OpenAI-managed tools like web search or file search.
```python
import asyncio
from pydantic import BaseModel
import instructor
class SupportTicket(BaseModel):
issue: str
priority: str
client = instructor.from_provider(
"openai/gpt-4.1-mini",
mode=instructor.Mode.RESPONSES_TOOLS,
async_client=True,
)
async def create_ticket() -> SupportTicket:
return await client.create(
messages=[
{
"role": "user",
"content": "Log a high priority bug about failed password resets.",
}
],
response_model=SupportTicket,
)
ticket = asyncio.run(create_ticket())
print(ticket)
```
See the [OpenAI Responses API guide](./openai-responses.md) for a deeper walkthrough that includes built-in tool usage, streaming, and best practices.
## Nested Example
```python
from pydantic import BaseModel
from typing import List
import os
from openai import OpenAI
import instructor
from pydantic import BaseModel
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: List[Address]
# Initialize client
client = instructor.from_provider(
"openai/gpt-5-nano",
api_key=os.getenv('OPENAI_API_KEY'),
)
# Create structured output with nested objects
user = client.create(
messages=[
{"role": "user", "content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
"""},
],
response_model=User,
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```
## Multimodal
> We've provided a few different sample files for you to use to test out these new features. All examples below use these files.
>
> - (Audio) : A Recording of the Original Gettysburg Address : [gettysburg.wav](https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/gettysburg.wav)
> - (Image) : An image of some blueberry plants [image.jpg](https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/image.jpg)
> - (PDF) : A sample PDF file which contains a fake invoice [invoice.pdf](https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf)
Instructor provides a unified, provider-agnostic interface for working with multimodal inputs like images, PDFs, and audio files. With Instructor's multimodal objects, you can easily load media from URLs, local files, or base64 strings using a consistent API that works across different AI providers (OpenAI, Anthropic, Mistral, etc.).
Instructor handles all the provider-specific formatting requirements behind the scenes, ensuring your code remains clean and future-proof as provider APIs evolve.
Let's see how to use the Image, Audio and PDF classes.
### Image
> For a more in-depth walkthrough of the Image component, check out the [docs here](../concepts/multimodal.md)
Instructor makes it easy to analyse and extract semantic information from images using OpenAI's GPT-4o models. [Click here](https://platform.openai.com/docs/models) to check if the model you'd like to use has vision capabilities.
Let's see an example below with the sample image above where we'll load it in using our `from_url` method.
Note that we support local files and base64 strings too with the `from_path` and the `from_base64` class methods.
```python
from instructor.processing.multimodal import Image
from pydantic import BaseModel, Field
import instructor
from openai import OpenAI
class ImageDescription(BaseModel):
objects: list[str] = Field(..., description="The objects in the image")
scene: str = Field(..., description="The scene of the image")
colors: list[str] = Field(..., description="The colors in the image")
client = instructor.from_provider("openai/gpt-5-nano")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/image.jpg"
# Multiple ways to load an image:
response = client.create(
response_model=ImageDescription,
messages=[
{
"role": "user",
"content": [
"What is in this image?",
# Option 1: Direct URL with autodetection
Image.from_url(url),
# Option 2: Local file
# Image.from_path("path/to/local/image.jpg")
# Option 3: Base64 string
# Image.from_base64("base64_encoded_string_here")
# Option 4: Autodetect
# Image.autodetect(<url|path|base64>)
],
},
],
)
print(response)
# Example output:
# ImageDescription(
# objects=['blueberries', 'leaves'],
# scene='A blueberry bush with clusters of ripe blueberries and some unripe ones against a cloudy sky',
# colors=['green', 'blue', 'purple', 'white']
# )
```
### PDF
Instructor makes it easy to analyse and extract semantic information from PDFs using OpenAI's GPT-4o models.
Let's see an example below with the sample PDF above where we'll load it in using our `from_url` method.
Note that we support local files and base64 strings too with the `from_path` and the `from_base64` class methods.
```python
from instructor.processing.multimodal import PDF
from pydantic import BaseModel, Field
import instructor
from openai import OpenAI
class Receipt(BaseModel):
total: int
items: list[str]
client = instructor.from_provider("openai/gpt-5-nano")
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/invoice.pdf"
# Multiple ways to load an PDF:
response = client.create(
response_model=Receipt,
messages=[
{
"role": "user",
"content": [
"Extract out the total and line items from the invoice",
# Option 1: Direct URL
PDF.from_url(url),
# Option 2: Local file
# PDF.from_path("path/to/local/invoice.pdf"),
# Option 3: Base64 string
# PDF.from_base64("base64_encoded_string_here")
# Option 4: Autodetect
# PDF.autodetect(<url|path|base64>)
],
},
],
)
print(response)
# > Receipt(total=220, items=['English Tea', 'Tofu'])
```
### Audio
Instructor makes it easy to analyse and extract semantic information from Audio files using OpenAI's GPT-4o models. Let's see an example below with the sample Audio file above where we'll load it in using our `from_url` method.
Note that we support local files and base64 strings too with the `from_path`
```python
from instructor.processing.multimodal import Audio
from pydantic import BaseModel
import instructor
from openai import OpenAI
class AudioDescription(BaseModel):
transcript: str
summary: str
speakers: list[str]
key_points: list[str]
url = "https://raw.githubusercontent.com/instructor-ai/instructor/main/tests/assets/gettysburg.wav"
client = instructor.from_provider("openai/gpt-5-nano")
response = client.create(
response_model=AudioDescription,
modalities=["text"],
audio={"voice": "alloy", "format": "wav"},
messages=[
{
"role": "user",
"content": [
"Please transcribe and analyze this audio:",
# Multiple loading options:
Audio.from_url(url),
# Option 2: Local file
# Audio.from_path("path/to/local/audio.mp3")
],
},
],
)
print(response)
# > transcript='Four score and seven years ago our fathers..."]
```
## Streaming Support
Instructor has two main ways that you can use to stream responses out
1. **Iterables**: These are useful when you'd like to stream a list of objects of the same type (Eg. use structured outputs to extract multiple users)
2. **Partial Streaming**: This is useful when you'd like to stream a single object and you'd like to immediately start processing the response as it comes in.
### Partials
```python
from pydantic import BaseModel
client = instructor.from_provider("openai/gpt-5-nano")
class User(BaseModel):
name: str
age: int
bio: str
user = client.create_partial(
messages=[
{"role": "user", "content": "Create a user profile for Jason, age 25"},
],
response_model=User,
)
for user_partial in user:
print(user_partial)
# > name='Jason' age=None bio='None'
# > name='Jason' age=25 bio='A tech'
# > name='Jason' age=25 bio='A tech enthusiast'
# > name='Jason' age=25 bio='A tech enthusiast who loves coding, gaming, and exploring new'
# > name='Jason' age=25 bio='A tech enthusiast who loves coding, gaming, and exploring new technologies'
```
### Iterable Example
```python
import os
from openai import OpenAI
import instructor
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
# Extract multiple users from text
users = client.create_iterable(
messages=[
{"role": "user", "content": """
Extract users:
1. Jason is 25 years old
2. Sarah is 30 years old
3. Mike is 28 years old
"""},
],
response_model=User,
)
for user in users:
print(user)
#> name='Jason' age=25
#> name='Sarah' age=30
#> name='Mike' age=28
```
## Instructor Modes
We provide several modes to make it easy to work with the different response models that OpenAI supports
1. `instructor.Mode.RESPONSES_TOOLS` : Calls the OpenAI Responses API while keeping Instructor's familiar API. Best for new builds that want lower latency, better caching, and the new stateful context features.
2. `instructor.Mode.RESPONSES_TOOLS_WITH_INBUILT_TOOLS` : Same as above, but automatically enables OpenAI's built-in tools (web search, file search, etc.) inside the Responses API.
3. `instructor.Mode.TOOLS` : This uses the [tool calling API](https://platform.openai.com/docs/guides/function-calling) to return structured outputs to the client.
4. `instructor.Mode.JSON` : This forces the model to return JSON by using [OpenAI's JSON mode](https://platform.openai.com/docs/guides/structured-outputs#json-mode).
5. `instructor.Mode.FUNCTIONS` : This uses OpenAI's function calling API to return structured outputs and will be deprecated in the future.
6. `instructor.Mode.PARALLEL_TOOLS` : This uses the [parallel tool calling API](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) to return structured outputs to the client. This allows the model to generate multiple calls in a single response.
7. `instructor.Mode.MD_JSON` : This makes a simple call to the OpenAI chat completion API and parses the raw response as JSON.
8. `instructor.Mode.TOOLS_STRICT` : This uses the new Open AI structured outputs API to return structured outputs to the client using constrained grammar sampling. This restricts users to a subset of the JSON schema.
9. `instructor.Mode.JSON_O1` : This is a mode for the `O1` model. We created a new mode because `O1` doesn't support any system messages, tool calling or streaming so you need to use this mode to use Instructor with `O1`.
In general, choose `Mode.RESPONSES_TOOLS` (or the built-in tools variant) when you're targeting the Responses API, and stick with `Mode.TOOLS` for classic Chat Completions integrations. Both modes keep schema handling identical, so switching between them is a single-line change.
## Batch API
We also support batching requests using the `create_batch` method. This is helpful if your request is not time sensitive because you'll get a 50% discount on the token cost.
Read more about how to use it [here](../examples/batch_job_oai.md)
## Best Practices
1. **Model Selection** : We recommend using gpt-4o-mini for simpler use cases because it's cheap and works well with a clearly defined objective for structured outputs. When the task is more ambigious, consider upgrading to `4o` or even `O1` depending on your needs
2. **Performance Optimization** : Streaming a response model is faster and should be done from the get-go. This is especially true if you're using a simple response model.
## Common Use Cases
- Data Extraction
- Form Parsing
- API Response Structuring
- Document Analysis
- Configuration Generation
## Related Resources
- [OpenAI Documentation](https://platform.openai.com/docs)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
- [OpenAI Responses API Guide](./openai-responses.md)
## Updates and Compatibility
Instructor maintains compatibility with the latest OpenAI API versions and models. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates.

View File

@@ -0,0 +1,270 @@
---
title: "Structured outputs with OpenRouter, a complete guide with instructor"
description: "Learn how to use Instructor with OpenRouter to access multiple LLM providers through a unified API. Get type-safe, structured outputs from various models including Qwen, Gemini, Mistral, and Cohere."
---
# Structured outputs with OpenRouter, a complete guide with instructor
OpenRouter provides a unified API to access multiple LLM providers, allowing you to easily switch between different models. This guide shows you how to use Instructor with OpenRouter for type-safe, validated responses across various LLM providers.
To set Provider specific configuration on the `openai` client, make sure to use the `extra_body` kwarg.
## Quick Start
⚠️ **Important**: Make sure that the model you're using has support for `Tool Calling` and/or `Structured Outputs` in the [OpenRouter models listing](https://openrouter.ai/models)
Instructor works with OpenRouter through the OpenAI client, so you don't need to install anything extra beyond the base package.
## Simple User Example (Sync)
We support simple tool calling with this
```python
from openai import OpenAI
import instructor
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openrouter/google/gemini-2.0-flash-lite-001",
base_url="https://openrouter.ai/api/v1",
async_client=False
)
resp = client.create(
messages=[
{
"role": "user",
"content": "Ivan is 28 years old",
},
],
response_model=User,
extra_body={"provider": {"require_parameters": True}},
)
print(resp)
#> name='Ivan' age=20
```
## Simple User Example ( Async )
```python
import instructor
from pydantic import BaseModel
import asyncio
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"openrouter/google/gemini-2.0-flash-lite-001",
async_client=True,
)
async def extract_user():
user = await client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
extra_body={"provider": {"require_parameters": True}},
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user)
```
## Nested Object Example ( Sync )
```python
from pydantic import BaseModel
from openai import OpenAI
import instructor
from pydantic import BaseModel
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
# Initialize with API key
# Initialize client with base URL
client = instructor.from_provider(
"openrouter/google/gemini-2.0-flash-lite-001",
base_url="https://openrouter.ai/api/v1",
async_client=False
)
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
},
],
extra_body={"provider": {"require_parameters": True}},
response_model=User,
)
print(user)
#> name='Jason' age=25 addresses=[Address(street='123 Main St', city='New York', country='USA'), Address(street='456 Beach Rd', city='Miami', country='USA')]
```
## Structured Outputs (Sync)
⚠️ **Important**: Check that your chosen model supports `Structured Outputs` in the [OpenRouter models listing](https://openrouter.ai/models). Structured Outputs is a subset of Tool Calling that constrains the model's output to match your schema in order to produce valid JSON Schema.
Instructor also supports Structured Outputs with OpenRouter as documented in their API [here](https://openrouter.ai/docs/features/structured-outputs). Note that the following User model will throw an error if we use the OpenAI GPT-4o model like `openai/gpt-4o-2024-11-20` because OpenAI does not support using a regex pattern as part of their structured output schema.
```python
from pydantic import BaseModel, Field
from openai import OpenAI
import instructor
class User(BaseModel):
name: str
age: int
phone_number: str = Field(
pattern=r"^\+?1?\s*\(?(\d{3})\)?[-.\s]*(\d{3})[-.\s]*(\d{4})$"
)
# Initialize with API key
# Initialize client with base URL
client = instructor.from_provider(
"openrouter/google/gemini-2.0-flash-lite-001",
base_url="https://openrouter.ai/api/v1",
async_client=False
)
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old and his number is 1-212-456-7890
""",
},
],
response_model=User,
extra_body={"provider": {"require_parameters": True}},
)
print(user)
# > name='Jason' age=25 phone_number='+1 (212) 456-7890'
```
## JSON Mode
In the event that your model doesn't support tool calling, you will see the following error when you try to use `mode.TOOLS`
> instructor.exceptions.InstructorRetryException: Error code: 404 - {'error': {'message': 'No endpoints found that support tool use. To learn more about provider routing, visit: https://openrouter.ai/docs/provider-routing', 'code': 404}}
In this case, we recommend using the `JSON` mode instead as seen below.
```python
from pydantic import BaseModel, Field
from openai import OpenAI
import instructor
class User(BaseModel):
name: str
age: int
phone_number: str = Field(
pattern=r"^\+?1?\s*\(?(\d{3})\)?[-.\s]*(\d{3})[-.\s]*(\d{4})$"
)
# Initialize with API key
# Initialize client with base URL
client = instructor.from_provider(
"openrouter/google/gemini-2.0-flash-lite-001",
base_url="https://openrouter.ai/api/v1",
async_client=False
)
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old and his number is 1-212-456-7890
""",
},
],
response_model=User,
)
print(user)
```
## Streaming
You can also use streaming with as seen below using the `create_partial` method. While we're using JSON mode here, this should work with tool calling and structured outputs too.
```python
from pydantic import BaseModel, Field
from openai import OpenAI
import instructor
class User(BaseModel):
name: str
age: int
# Initialize with API key
# Initialize client with base URL
client = instructor.from_provider(
"openrouter/google/gemini-2.0-flash-lite-001",
base_url="https://openrouter.ai/api/v1",
)
# Create structured output with nested objects
user = client.create_partial(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old and his number is 1-212-456-7890
""",
},
],
response_model=User,
)
for chunk in user:
print(chunk)
# > name=None age=None
# > name='Jason' age=None
# > name='Jason' age=25
```

View File

@@ -0,0 +1,189 @@
---
title: Structured Outputs with Perplexity AI and Pydantic
description: Learn how to use Perplexity AI with Instructor for structured JSON outputs using Pydantic models. Create type-safe, validated responses from Perplexity's Sonar models with Python.
---
# Structured Outputs with Perplexity AI
This guide demonstrates how to use Perplexity AI with Instructor to generate structured outputs. You'll learn how to use Perplexity's Sonar models with Pydantic to create type-safe, validated responses.
## Prerequisites
You'll need to sign up for a Perplexity account and get an API key. You can do that [here](https://www.perplexity.ai/).
```bash
export PERPLEXITY_API_KEY=<your-api-key-here>
pip install "instructor[perplexity]"
```
### See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [from_provider Guide](../concepts/from_provider.md) - Detailed client configuration
- [Provider Examples](../index.md#provider-examples) - Quick examples for all providers
- [Search Examples](../examples/search.md) - Search query processing examples
# Perplexity AI
Perplexity AI provides access to powerful language models through their API. Instructor supports structured outputs with Perplexity's models using the OpenAI-compatible API.
### Sync Example
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider(
"perplexity/sonar-small-online",
api_key=os.getenv("PERPLEXITY_API_KEY"),
base_url="https://api.perplexity.ai",
)
class User(BaseModel):
name: str
age: int
# Create structured output
user = client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
print(user)
# > User(name='Jason', age=25)
```
### Async Example
```python
import instructor
from pydantic import BaseModel
import asyncio
async_client = instructor.from_provider(
"perplexity/sonar-small-online",
async_client=True,
)
class User(BaseModel):
name: str
age: int
async def extract_user():
user = await client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user)
# > User(name='Jason', age=25)
```
### Nested Objects
```python
import os
from openai import OpenAI
import instructor
from pydantic import BaseModel
# Initialize with API key
client = instructor.from_provider(
"perplexity/sonar-small-online",
api_key=os.getenv("PERPLEXITY_API_KEY"),
base_url="https://api.perplexity.ai",
)
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
},
],
response_model=User,
)
print(user)
#> User(
#> name='Jason',
#> age=25,
#> addresses=[
#> Address(street='123 Main St', city='New York', country='USA'),
#> Address(street='456 Beach Rd', city='Miami', country='USA')
#> ]
#> )
```
## Supported Modes
Perplexity AI currently supports the following mode with Instructor:
- `PERPLEXITY_JSON`: Direct JSON response generation
```python
import os
from openai import OpenAI
import instructor
from instructor import Mode
from pydantic import BaseModel
# Initialize client with base URL
client = instructor.from_provider(
"perplexity/sonar-small-online",
api_key=os.getenv("PERPLEXITY_API_KEY"),
base_url="https://api.perplexity.ai",
)
class User(BaseModel):
name: str
age: int
# Create structured output
user = client.create(
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
print(user)
# > User(name='Jason', age=25)
```
## Additional Resources
- [Perplexity API Documentation](https://docs.perplexity.ai/)
- [Perplexity API Reference](https://docs.perplexity.ai/reference/post_chat_completions)

View File

@@ -0,0 +1,79 @@
---
title: SambaNova
description: Use Instructor with SambaNova's LLM API for structured outputs.
---
## See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [from_provider Guide](../concepts/from_provider.md) - Detailed client configuration
- [Provider Examples](../index.md#provider-examples) - Quick examples for all providers
- [Enterprise Integration](../examples/index.md#enterprise-integration) - More enterprise examples
# SambaNova Integration
Instructor supports SambaNova's LLM API, allowing you to use structured outputs with their models.
## Installation
```bash
pip install "instructor[openai]"
```
## Basic Usage
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider("sambanova/Meta-Llama-3.1-405B-Instruct")
class User(BaseModel):
name: str
age: int
user = client.create(
messages=[
{"role": "user", "content": "Ivan is 28"},
],
response_model=User,
)
print(user)
# > User(name='Ivan', age=28)
```
## Async Usage
```python
import instructor
from pydantic import BaseModel
client = instructor.from_provider(
"sambanova/Meta-Llama-3.1-405B-Instruct",
async_client=True,
)
class User(BaseModel):
name: str
age: int
async def get_user():
user = await client.create(
messages=[
{"role": "user", "content": "Ivan is 28"},
],
response_model=User,
)
return user
# Run with asyncio
import asyncio
user = asyncio.run(get_user())
print(user)
# > User(name='Ivan', age=28)
```
## Available Models
Check the [SambaNova documentation](https://docs.sambanova.ai/cloud/docs/get-started/supported-models) for the latest model offerings and capabilities.

View File

@@ -0,0 +1,127 @@
---
draft: False
date: 2024-01-27
slug: together
title: "Structured outputs with Together AI, a complete guide w/ instructor"
description: "Complete guide to using Instructor with Together AI. Learn how to generate structured, type-safe outputs with Together AI."
tags:
- patching
- open source
authors:
- jxnl
---
# Structured outputs with Together AI, a complete guide with instructor
This guide demonstrates how to use Together AI with Instructor to generate structured outputs. You'll learn how to use function calling with Together's models to create type-safe responses.
Open-source LLMS are gaining popularity, and with the release of Together's Function calling models, its been easier than ever to get structured outputs.
By the end of this blog post, you will learn how to effectively utilize instructor with Together AI. But before we proceed, let's first explore the concept of patching.
!!! note "Other Languages"
This blog post is written in Python, but the concepts are applicable to other languages as well, as we currently have support for [Javascript](https://instructor-ai.github.io/instructor-js), [Elixir](https://hexdocs.pm/instructor/Instructor.html) and [PHP](https://github.com/cognesy/instructor-php/).
<!-- more -->
## Patching
Instructor's patch enhances the openai api it with the following features:
- `response_model` in `create` calls that returns a pydantic model
- `max_retries` in `create` calls that retries the call if it fails by using a backoff strategy
!!! note "Learn More"
To learn more, please refer to the [docs](../index.md). To understand the benefits of using Pydantic with Instructor, visit the tips and tricks section of the [why use Pydantic](../why.md) page.
### See Also
- [Getting Started](../getting-started.md) - Quick start guide
- [from_provider Guide](../concepts/from_provider.md) - Detailed client configuration
- [Provider Examples](../index.md#provider-examples) - Quick examples for all providers
- [Open Source Models](../examples/open_source.md) - More open-source model examples
# Together AI
The good news is that Together employs the same OpenAI client, and its models support some of these output modes too!
!!! note "Getting access"
If you want to try this out for yourself check out the [Together AI](https://www.together.ai/) website. You can get started [here](http://api.together.ai/).
```python
import os
from pydantic import BaseModel
import instructor
client = instructor.from_provider(
"together/Mixtral-8x7B-Instruct-v0.1",
api_key=os.environ["TOGETHER_API_KEY"],
base_url="https://api.together.xyz/v1",
)
# By default, the patch function will patch the ChatCompletion.create and ChatCompletion.create methods to support the response_model parameter
# Now, we can use the response_model parameter using only a base model
# rather than having to use the OpenAISchema class
class UserExtract(BaseModel):
name: str
age: int
user: UserExtract = client.create(
response_model=UserExtract,
messages=[
{"role": "user", "content": "Extract jason is 25 years old"},
],
)
assert isinstance(user, UserExtract), "Should be instance of UserExtract"
assert user.name.lower() == "jason"
assert user.age == 25
print(user.model_dump_json(indent=2))
"""
{
"name": "jason",
"age": 25
}
"""
{
"name": "Jason",
"age": 25,
}
```
### Async Example
```python
import instructor
from pydantic import BaseModel
import os
import asyncio
async_client = instructor.from_provider(
"together/Mixtral-8x7B-Instruct-v0.1",
async_client=True,
api_key=os.environ["TOGETHER_API_KEY"],
base_url="https://api.together.xyz/v1",
)
class UserExtract(BaseModel):
name: str
age: int
async def extract_user():
return await async_client.create(
response_model=UserExtract,
messages=[{"role": "user", "content": "Extract jason is 25 years old"}],
)
print(asyncio.run(extract_user()))
```
You can find more information about Together's function calling support [here](https://docs.together.ai/docs/function-calling).

View File

@@ -0,0 +1,162 @@
---
title: "TrueFoundry"
---
This guide provides instructions for integrating Instructor with the [TrueFoundry AI Gateway](https://www.truefoundry.com/ai-gateway) for structured data extraction from LLMs.
## What is TrueFoundry?
TrueFoundry provides an enterprise-ready [AI Gateway](https://www.truefoundry.com/ai-gateway) and integrates seamlessly with libraries like instructor, providing enterprise-grade AI features including cost tracking, security guardrails, and access controls.
## Prerequisites
Before integrating Instructor with TrueFoundry, ensure you have:
1. **TrueFoundry Account**: Create a [TrueFoundry account](https://www.truefoundry.com/register) with at least one model provider and generate a Personal Access Token by following the instructions in [Generating Tokens](https://docs.truefoundry.com/gateway/authentication). For a quick setup guide, see our [Gateway Quick Start](https://docs.truefoundry.com/gateway/quick-start)
2. **Instructor Installation**: Install Instructor using pip: `pip install instructor`
3. **OpenAI Library**: Install the OpenAI Python library: `pip install openai`
4. **Pydantic**: Install Pydantic for data validation: `pip install pydantic`
## Setup Process
### Step 1: Install Dependencies
```bash
pip install instructor openai pydantic
```
### Step 2: Configure Instructor with TrueFoundry Gateway
Get your TrueFoundry Gateway API key, base URL, and model name from the unified code snippet in your TrueFoundry playground:
<Frame>
<img src="../img/new-code-snippet.png" />
</Frame>
Here's how to configure Instructor to use TrueFoundry's AI Gateway:
```python
import instructor
from pydantic import BaseModel
from openai import OpenAI
# Configure OpenAI client to use TrueFoundry Gateway
client = OpenAI(
api_key="your-truefoundry-api-key", # Your TrueFoundry Personal Access Token
base_url="your-truefoundry-base-url", # Your TrueFoundry Gateway URL
)
# Patch the client with Instructor
instructor_client = instructor.from_provider("openai/gpt-4o")
# Define your Pydantic model for structured output
class User(BaseModel):
name: str
age: int
email: str
# Extract structured data
user_info = instructor_client.create(
model="openai-main/gpt-4o", # Your TrueFoundry model ID
response_model=User,
messages=[
{"role": "user", "content": "Extract user information: John Doe is 30 years old and his email is john@example.com"}
],
)
print(f"Name: {user_info.name}")
print(f"Age: {user_info.age}")
print(f"Email: {user_info.email}")
```
## Usage Examples
### Basic Structured Data Extraction
```python
import instructor
from pydantic import BaseModel
from openai import OpenAI
# Configure TrueFoundry Gateway
client = OpenAI(
api_key="your-truefoundry-api-key",
base_url="your-truefoundry-base-url",
)
instructor_client = instructor.from_provider("openai/gpt-4o")
# Define response structure
class ProductInfo(BaseModel):
name: str
price: float
category: str
in_stock: bool
# Extract product information
product = instructor_client.create(
model="openai-main/gpt-4o",
response_model=ProductInfo,
messages=[
{"role": "user", "content": "Extract product details: The iPhone 15 Pro costs $999, it's in the Electronics category and is currently available in stock."}
],
)
print(f"Product: {product.name}")
print(f"Price: ${product.price}")
print(f"Category: {product.category}")
print(f"In Stock: {product.in_stock}")
```
### Complex Data Structures with Lists
```python
import instructor
from pydantic import BaseModel
from typing import List
from openai import OpenAI
# Configure TrueFoundry Gateway
client = OpenAI(
api_key="your-truefoundry-api-key",
base_url="your-truefoundry-base-url",
)
instructor_client = instructor.from_provider("openai/gpt-4o")
class Task(BaseModel):
title: str
description: str
priority: str
estimated_hours: int
class ProjectPlan(BaseModel):
project_name: str
total_duration_weeks: int
tasks: List[Task]
# Extract complex project structure
project = instructor_client.create(
model="openai-main/gpt-4o",
response_model=ProjectPlan,
messages=[
{"role": "user", "content": """
Create a project plan for building a mobile app:
Project: Food Delivery App (8 weeks total)
Tasks:
1. UI/UX Design - Create user interface mockups and wireframes - High priority - 2 weeks
2. Backend Development - Build API and database - High priority - 3 weeks
3. Frontend Development - Build mobile app frontend - Medium priority - 2 weeks
4. Testing & QA - Test all features and fix bugs - Medium priority - 1 week
"""}
],
)
print(f"Project: {project.project_name}")
print(f"Duration: {project.total_duration_weeks} weeks")
print("\nTasks:")
for task in project.tasks:
print(f"- {task.title}: {task.description} ({task.priority} priority, {task.estimated_hours} weeks)")
```
That's it! You're now ready to use Instructor with TrueFoundry Gateway for robust, production-ready structured data extraction from LLMs.

View File

@@ -0,0 +1,287 @@
---
title: "Structured outputs with Vertex AI, a complete guide w/ instructor"
description: "Complete guide to using Instructor with Google Cloud's Vertex AI. Learn how to generate structured, type-safe outputs with enterprise-grade AI capabilities."
---
# Structured outputs with Vertex AI, a complete guide w/ instructor
Google Cloud's Vertex AI provides enterprise-grade AI capabilities with robust scaling and security features. This guide shows you how to use Instructor with Vertex AI for type-safe, validated responses.
!!! warning "Migration Notice"
The direct `from_vertexai` integration is being deprecated in favor of the unified `google-genai` SDK.
Please use `from_provider` or `from_genai` with `vertexai=True` for new projects.
See the [migration guide](#migration-to-google-genai) below.
## Quick Start
Install Instructor with Google GenAI support (which includes Vertex AI):
```bash
pip install "instructor[google-genai]"
```
## Simple User Example (Sync)
```python
import instructor
from pydantic import BaseModel
import os
# Set your project ID and location
os.environ["GOOGLE_CLOUD_PROJECT"] = "your-project-id"
os.environ["GOOGLE_CLOUD_LOCATION"] = "us-central1"
class User(BaseModel):
name: str
age: int
# Using from_provider (recommended)
client = instructor.from_provider(
"vertexai/gemini-3-flash",
)
resp = client.create(
response_model=User,
messages=[
{
"role": "user",
"content": "Extract Jason is 25 years old.",
}
],
)
print(resp)
#> User(name='Jason', age=25)
```
## Simple User Example (Async)
```python
import asyncio
import instructor
import vertexai # type: ignore
from vertexai.generative_models import GenerativeModel # type: ignore
from pydantic import BaseModel
vertexai.init()
class User(BaseModel):
name: str
age: int
client = instructor.from_provider(
"vertex_ai/gemini-1.5-pro-preview-0409",
async_client=True,
mode=instructor.Mode.TOOLS,
)
async def extract_user():
user = await client.create(
messages=[
{
"role": "user",
"content": "Extract Jason is 25 years old.",
}
],
response_model=User,
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user) # User(name='Jason', age=25)
```
## Streaming Support
Instructor now supports streaming capabilities with Vertex AI! You can use both `create_partial` for incremental model building and `create_iterable` for streaming collections.
### Streaming Partial Responses
```python
import vertexai # type: ignore
from vertexai.generative_models import GenerativeModel # type: ignore
import instructor
from pydantic import BaseModel
from instructor.dsl.partial import Partial
vertexai.init()
class UserExtract(BaseModel):
name: str
age: int
client = instructor.from_provider(
"vertex_ai/gemini-1.5-pro-preview-0409",
mode=instructor.Mode.TOOLS,
)
# Stream partial responses
response_stream = client.create(
response_model=Partial[UserExtract],
stream=True,
messages=[
{"role": "user", "content": "Anibal is 23 years old"},
],
)
for partial_user in response_stream:
print(f"Received update: {partial_user}")
# Output might show:
# Received update: UserExtract(name='Anibal', age=None)
# Received update: UserExtract(name='Anibal', age=23)
```
### Streaming Iterable Collections
```python
import vertexai # type: ignore
from vertexai.generative_models import GenerativeModel # type: ignore
import instructor
from pydantic import BaseModel
vertexai.init()
class UserExtract(BaseModel):
name: str
age: int
client = instructor.from_provider(
"vertex_ai/gemini-1.5-pro-preview-0409",
mode=instructor.Mode.TOOLS,
)
# Stream iterable responses
response_stream = client.create_iterable(
response_model=UserExtract,
messages=[
{"role": "user", "content": "Make up two people"},
],
)
for user in response_stream:
print(f"Generated user: {user}")
# Output:
# Generated user: UserExtract(name='Sarah Johnson', age=32)
# Generated user: UserExtract(name='David Chen', age=27)
```
### Async Streaming
You can also use async versions of both streaming approaches:
```python
import asyncio
import vertexai # type: ignore
from vertexai.generative_models import GenerativeModel # type: ignore
import instructor
from pydantic import BaseModel
from instructor.dsl.partial import Partial
vertexai.init()
class UserExtract(BaseModel):
name: str
age: int
client = instructor.from_provider(
"vertex_ai/gemini-1.5-pro-preview-0409",
async_client=True,
mode=instructor.Mode.TOOLS,
)
async def stream_partial():
response_stream = await client.create(
response_model=Partial[UserExtract],
stream=True,
messages=[
{"role": "user", "content": "Anibal is 23 years old"},
],
)
async for partial_user in response_stream:
print(f"Received update: {partial_user}")
async def stream_iterable():
response_stream = client.create_iterable(
response_model=UserExtract,
messages=[
{"role": "user", "content": "Make up two people"},
],
)
async for user in response_stream:
print(f"Generated user: {user}")
# Run async functions
asyncio.run(stream_partial())
asyncio.run(stream_iterable())
```
## Related Resources
- [Vertex AI Documentation](https://cloud.google.com/vertex-ai/docs)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
## Migration to Google GenAI
The legacy `from_vertexai` method is being deprecated in favor of the unified Google GenAI SDK. Here's how to migrate:
### Old Way (Deprecated)
```python
import instructor
import vertexai
from vertexai.generative_models import GenerativeModel
vertexai.init(project="your-project", location="us-central1")
client = instructor.from_provider("google/gemini-2.5-flash", vertexai=True),
mode=instructor.Mode.TOOLS,
)
```
### New Way (Recommended)
```python
import instructor
# Option 1: Using from_provider (simplest)
client = instructor.from_provider(
"vertexai/gemini-3-flash",
project="your-project", # Optional if set in environment
location="us-central1" # Optional, defaults to us-central1
)
# Option 2: Using from_genai with Google GenAI SDK
from google import genai
from instructor import from_genai
client = from_genai(
genai.Client(
vertexai=True,
project="your-project",
location="us-central1",
model="gemini-3-flash"
)
)
```
### Environment Variables
You can also set these environment variables to avoid passing project/location each time:
```bash
export GOOGLE_CLOUD_PROJECT="your-project-id"
export GOOGLE_CLOUD_LOCATION="us-central1"
```
## Updates and Compatibility
Instructor maintains compatibility with Vertex AI's latest API versions. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates.
Streaming support has been added for both partial responses and iterable collections, with both synchronous and asynchronous interfaces.

View File

@@ -0,0 +1,179 @@
---
title: Structured Outputs with Writer, a complete guide with instructor
description: Learn how to use Writer for structured outputs using their latest Palmyra-X-004 model for more reliable system outputs
---
# Structured Outputs with Writer, a complete guide with instructor
This guide demonstrates how to use Writer for structured outputs using their latest Palmyra-X-004 model for more reliable system outputs.
You'll need to sign up for an account and get an API key. You can do that [here](https://writer.com).
```bash
export WRITER_API_KEY=<your-api-key-here>
pip install "instructor[writer]"
```
## Palmyra-X-004
Writer supports structured outputs with their latest Palmyra-X-004 model that introduces tool calling functionality
### Sync Example
```python
import instructor
from writerai import Writer
from pydantic import BaseModel
# Initialize Writer client
client = instructor.from_provider("writer/palmyra-x-004")
class User(BaseModel):
name: str
age: int
# Extract structured data
user = client.create(
messages=[{"role": "user", "content": "Extract: John is 30 years old"}],
response_model=User,
)
print(user)
#> name='John' age=30
```
### Async Example
```python
import instructor
from pydantic import BaseModel
import asyncio
client = instructor.from_provider(
"writer/palmyra-x-004",
async_client=True,
)
class User(BaseModel):
name: str
age: int
async def extract_user():
# Extract structured data
user = await client.create(
messages=[{"role": "user", "content": "Extract: John is 30 years old"}],
response_model=User,
)
print(user)
# > name='John' age=30
if __name__ == "__main__":
import asyncio
asyncio.run(extract_user())
```
## Nested Objects
Writer also supports nested objects, which is useful for extracting data from more complex responses.
```python
import instructor
from writerai import Writer
from pydantic import BaseModel
# Initialize Writer client
client = instructor.from_provider("writer/palmyra-x-004")
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: list[Address]
# Create structured output with nested objects
user = client.create(
messages=[
{
"role": "user",
"content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
""",
},
],
response_model=User,
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```
## Streaming Support
Instructor has two main ways that you can use to stream responses out
1. **Iterables**: These are useful when you'd like to stream a list of objects of the same type (Eg. use structured outputs to extract multiple users)
2. **Partial Streaming**: This is useful when you'd like to stream a single object and you'd like to immediately start processing the response as it comes in.
We currently support streaming for Writer with native tool for both methods listed above.
### Partial Streaming
```python
import instructor
from writerai import Writer
from pydantic import BaseModel
client = instructor.from_provider("writer/palmyra-x-004")
class Person(BaseModel):
name: str
age: int
resp = client.create_partial(
messages=[
{
"role": "user",
"content": "Ivan is 27 and lives in Singapore",
}
],
response_model=Person,
)
for person in resp:
print(person)
# > name=None age=None
# > name='Ivan' age=None
# > name='Ivan' age=27
```

View File

@@ -0,0 +1,227 @@
---
title: "Structured outputs with xAI, a complete guide with instructor"
description: "Learn how to use Instructor with xAI's Grok models for type-safe, structured outputs. Complete guide with examples and best practices."
---
# Structured outputs with xAI, a complete guide with instructor
xAI provides access to Grok models through the `xai-sdk` package, enabling structured outputs with Instructor. This guide covers everything you need to know about using xAI's Grok models with Instructor for type-safe, validated responses.
## Quick Start
Instructor is distributed without xAI dependencies by default. Install xAI support with the optional `xai` extra:
```bash
pip install "instructor[xai]"
```
Or using uv:
```bash
uv pip install "instructor[xai]"
```
⚠️ **Important**: You must set your xAI API key before using the client. You can do this in two ways:
1. Set the environment variable:
```bash
export XAI_API_KEY='your-api-key-here'
```
2. The xAI SDK will use this environment variable automatically.
## Simple User Example (Sync)
```python
import instructor
from pydantic import BaseModel
# Auto-configure xAI client
client = instructor.from_provider("xai/grok-3-mini")
class User(BaseModel):
name: str
age: int
# Create structured output
user = client.create(
response_model=User,
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
)
print(user)
#> User(name='Jason', age=25)
```
## Simple User Example (Async)
```python
import instructor
from pydantic import BaseModel
import asyncio
# Auto-configure async xAI client
client = instructor.from_provider("xai/grok-3-mini", async_client=True)
class User(BaseModel):
name: str
age: int
async def extract_user():
user = await client.create(
response_model=User,
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
)
return user
# Run async function
user = asyncio.run(extract_user())
print(user)
#> User(name='Jason', age=25)
```
## Nested Example
```python
from pydantic import BaseModel
from typing import List
import instructor
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: List[Address]
# Auto-configure xAI client
client = instructor.from_provider("xai/grok-3-mini")
# Create structured output with nested objects
user = client.create(
response_model=User,
messages=[
{"role": "user", "content": """
Extract: Jason is 25 years old.
He lives at 123 Main St, New York, USA
and has a summer house at 456 Beach Rd, Miami, USA
"""},
],
)
print(user)
#> {
#> 'name': 'Jason',
#> 'age': 25,
#> 'addresses': [
#> {
#> 'street': '123 Main St',
#> 'city': 'New York',
#> 'country': 'USA'
#> },
#> {
#> 'street': '456 Beach Rd',
#> 'city': 'Miami',
#> 'country': 'USA'
#> }
#> ]
#> }
```
## Instructor Modes
xAI supports the following modes:
1. `instructor.Mode.JSON` : Forces the model to return JSON output (default)
2. `instructor.Mode.TOOLS` : Uses function calling for structured outputs
```python
import instructor
from instructor import Mode
# Using JSON mode (default)
client = instructor.from_provider("xai/grok-3-mini", mode=Mode.JSON)
# Using TOOLS mode
client = instructor.from_provider("xai/grok-3-mini", mode=Mode.TOOLS)
```
## Available Models
xAI provides access to the following models:
- **grok-3** - The most capable Grok model for complex reasoning tasks
- **grok-3-mini** - A smaller, faster version optimized for speed and cost
## Limitations
### Streaming Support
⚠️ **Note**: Streaming responses (`create_iterable` and `create_partial`) are not yet supported due to differences in xAI's streaming API. See [issue #1663](https://github.com/567-labs/instructor/issues/1663) for updates.
### Python Version
⚠️ **Requires Python 3.10+**: The xAI SDK requires Python 3.10 or higher.
## Best Practices
### 1. API Key Management
Store your xAI API key securely using environment variables:
```bash
export XAI_API_KEY="your-api-key-here"
```
### 2. Model Selection
- Use `grok-3-mini` for:
- Simple extraction tasks
- High-volume processing
- Cost-sensitive applications
- Use `grok-3` for:
- Complex reasoning tasks
- Multi-step analysis
- Higher accuracy requirements
### 3. Error Handling
Always handle potential API errors gracefully:
```python
try:
user = client.create(
response_model=User,
messages=[{"role": "user", "content": "Extract user data"}],
)
except Exception as e:
print(f"Error: {e}")
```
## Common Use Cases
- Data Extraction from unstructured text
- Form parsing and validation
- Content classification
- Entity recognition
- Structured data generation
## Related Resources
- [xAI Documentation](https://docs.x.ai/)
- [Instructor Core Concepts](../concepts/index.md)
- [Type Validation Guide](../concepts/validation.md)
- [Advanced Usage Examples](../examples/index.md)
## Updates and Compatibility
Instructor maintains compatibility with the latest xAI SDK versions. Check the [changelog](https://github.com/jxnl/instructor/blob/main/CHANGELOG.md) for updates.