Files
wehub-resource-sync 97e91a83f3
Ruff / Ruff (push) Has been cancelled
Test / Core Tests (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.10) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.11) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.12) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.13) (push) Has been cancelled
Test / Offline Coverage Tests (Python 3.9) (push) Has been cancelled
Test / Full Coverage (Python 3.11) (push) Has been cancelled
Test / Core Provider Tests (OpenAI) (push) Has been cancelled
Test / Core Provider Tests (Anthropic) (push) Has been cancelled
Test / Core Provider Tests (Google) (push) Has been cancelled
Test / Core Provider Tests (Other) (push) Has been cancelled
Test / Anthropic Tests (push) Has been cancelled
Test / Gemini Tests (push) Has been cancelled
Test / Google GenAI Tests (push) Has been cancelled
Test / Vertex AI Tests (push) Has been cancelled
Test / OpenAI Tests (push) Has been cancelled
Test / Writer Tests (push) Has been cancelled
Test / Auto Client Tests (push) Has been cancelled
ty / type-check (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:36:38 +08:00

224 lines
5.2 KiB
Markdown

---
authors:
- jxnl
categories:
- Pydantic
comments: true
date: 2023-09-11
description: Learn how Pydantic simplifies working with LLMs and structured JSON outputs
in Python, enhancing developer experience and code organization.
draft: false
tags:
- Pydantic
- LLMs
- Python
- OpenAI
- JSON
---
# Generating Structured Output / JSON from LLMs
Language models have seen significant growth. Using them effectively often requires complex frameworks. This post discusses how Instructor simplifies this process using Pydantic.
<!-- more -->
## The Problem with Existing LLM Frameworks
Current frameworks for Language Learning Models (LLMs) have complex setups. Developers find it hard to control interactions with language models. Some frameworks require complex JSON Schema setups.
## The OpenAI Function Calling Game-Changer
OpenAI's Function Calling feature provides a constrained interaction model. However, it has its own complexities, mostly around JSON Schema.
## Why Pydantic?
Instructor uses Pydantic to simplify the interaction between the programmer and the language model.
- **Widespread Adoption**: Pydantic is a popular tool among Python developers.
- **Simplicity**: Pydantic allows model definition in Python.
- **Framework Compatibility**: Many Python frameworks already use Pydantic.
```python
import pydantic
import instructor
# Enables the response_model
client = instructor.from_provider("openai/gpt-5-nano")
class UserDetail(pydantic.BaseModel):
name: str
age: int
def introduce(self):
return f"Hello I'm {self.name} and I'm {self.age} years old"
user: UserDetail = client.create(
model="gpt-5.4-mini",
response_model=UserDetail,
messages=[
{"role": "user", "content": "Extract Jason is 25 years old"},
],
)
```
## Simplifying Validation Flow with Pydantic
Pydantic validators simplify features like re-asking or self-critique. This makes these tasks less complex compared to other frameworks.
```python
from typing_extensions import Annotated
from pydantic import BaseModel, BeforeValidator
from instructor import llm_validator
class QuestionAnswerNoEvil(BaseModel):
question: str
answer: Annotated[
str,
BeforeValidator(llm_validator("don't say objectionable things")),
]
```
## The Modular Approach
Pydantic allows for modular output schemas. This leads to more organized code.
### Composition of Schemas
```python
class UserDetails(BaseModel):
name: str
age: int
class UserWithAddress(UserDetails):
address: str
```
### Defining Relationships
```python
class UserDetail(BaseModel):
id: int
age: int
name: str
friends: List[int]
class UserRelationships(BaseModel):
users: List[UserDetail]
```
### Using Enums
```python
from enum import Enum, auto
class Role(Enum):
PRINCIPAL = auto()
TEACHER = auto()
STUDENT = auto()
OTHER = auto()
class UserDetail(BaseModel):
age: int
name: str
role: Role
```
### Flexible Schemas
```python
from typing import List
class Property(BaseModel):
key: str
value: str
class UserDetail(BaseModel):
age: int
name: str
properties: List[Property]
```
### Chain of Thought
```python
class TimeRange(BaseModel):
chain_of_thought: str
start_time: int
end_time: int
class UserDetail(BaseModel):
id: int
age: int
name: str
work_time: TimeRange
leisure_time: TimeRange
```
## Language Models as Microservices
The architecture resembles FastAPI. Most code can be written as Python functions that use Pydantic objects. This eliminates the need for prompt chains.
### FastAPI Stub
```python
import fastapi
from pydantic import BaseModel
class UserDetails(BaseModel):
name: str
age: int
app = fastapi.FastAPI()
@app.get("/user/{user_id}", response_model=UserDetails)
async def get_user(user_id: int) -> UserDetails:
return ...
```
### Using Instructor as a Function
```python
def extract_user(str) -> UserDetails:
return client.chat.completions(
response_model=UserDetails,
messages=[]
)
```
### Response Modeling
```python
class MaybeUser(BaseModel):
result: Optional[UserDetail]
error: bool
message: Optional[str]
```
## Conclusion
Instructor, with Pydantic, simplifies interaction with language models. It is usable for both experienced and new developers.
## Related Concepts
- [Getting Started Guide](../../index.md) - Learn how to install and use Instructor
- [Model Providers](../../integrations/index.md) - Explore supported LLM providers
- [Validation Context](../../concepts/reask_validation.md) - Understand how to validate LLM outputs
- [Response Models](../../concepts/models.md) - Deep dive into defining structured outputs
## See Also
- [Why Instructor is the Best Library](best_framework.md) - Learn about Instructor's philosophy and advantages
- [Structured Outputs and Prompt Caching with Anthropic](structured-output-anthropic.md) - See how Instructor works with Claude
- [Chain of Density Tutorial](../../tutorials/6-chain-of-density.ipynb) - Learn advanced prompting techniques
If you enjoy the content or want to try out `instructor` please check out the [github](https://github.com/jxnl/instructor) and give us a star!