marp | theme | paginate | class | ||
---|---|---|---|---|---|
true |
default |
true |
|
Code : 2VFIT5ZXIGPLZGWK1TI5HZFXNUEJ
"If FastAPI is the framework that makes creating APIs fun, PydanticAI is the tool that makes building AI Agents just as enjoyable."
PydanticAI is a framework for building AI Agents in Python, designed to help developers create production-grade Generative AI applications quickly, correctly, and with a good structure.
- Built by the Pydantic Team: Developed by the same team that created Pydantic.
- Model-agnostic: Connects with OpenAI, Anthropic, Gemini, Ollama, and more.
- Integrates with Pydantic Logfire: Monitor Agent performance in real-time.
- Safe with Type Checking: Agents and outputs are type-safe.
- Easy to write in a Pythonic style: Familiar Control Flow, Composition, Dependency Injection.
- Manages results with a defined structure: Ensures consistent responses.
- Supports streaming results: Ideal for applications requiring real-time responses.
- Write graph-based code with Pydantic Graph: Manage complex flows with Type Hints.
Building an AI Agent starts with Structured Data Extraction.
PydanticAI acts as a bridge between:
- The world of Unstructured Text from LLMs
- The world of Structured Data in Pydantic
- Python 3.9 or higher
pydantic-ai
andopenai
libraries- OpenAI API Key
uv add "pydantic-ai-slim[openai]"
Linux / macOS
export OPENAI_API_KEY="sk-..."
Windows (Powershell)
$env:OPENAI_API_KEY="sk-..."
Create a "blueprint" for the data with Pydantic.
# extract_user.py
from pydantic import BaseModel, Field
class User(BaseModel):
"""
A model for storing user data extracted from text
The text in this docstring will be passed to LLM for understanding
"""
name: str = Field(description="Full name and surname of the user")
age: int = Field(description="Age of the user in years")
Specifying
docstring
anddescription
helps the LLM understand the meaning of each field.
Create an Agent to extract data from text according to the User
model.
# extract_user.py (continued)
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
llm = OpenAIModel('gpt-4o')
agent = Agent(llm)
prompt = "My name is John Doe and I will be 30 years old on my next birthday."
agent_run_result = agent.run_sync(prompt, output_type=User)
result: User = agent_run_result.output
print(result)
Run the file with the command:
python extract_user.py
Expected output:
Input Prompt: 'My name is John Doe and I will be 30 years old on my next birthday.'
--- Extracted Data ---
Name: John Doe
Age: 29
Type of result: <class '__main__.User'>
Object: User(name='John Doe', age=29)
----------------------
- Data Accuracy: The Agent understands that "will be 30" means the current age is 29.
- Result is a Pydantic Object:
result
is an instance of theUser
class, allowing direct access toresult.name
andresult.age
with automatic data validation.
- Convert Model to Schema: PydanticAI converts the
User
model into a schema that the LLM understands (similar to Function Calling). - Create Prompt: Creates a prompt containing the schema and instructions for the LLM to respond in a structured format.
- Process and Validate: Receives JSON from the LLM, creates a
User
instance, and validates it.
PydanticAI allows us to "declare what kind of data we want" and lets the Agent handle the complex parts of communicating with the LLM for us.
If you are looking for a tool that helps make working with LLMs more systematic, reusable, testable, and scalable in the long run, PydanticAI is the answer you shouldn't overlook.
The essential foundation for building flexible, efficient, and scalable AI applications.
- Agent: The "brain" or main controller of the system.
- LLM Models: The connector to Large Language Model providers.
- Messages and Chat History: The mechanism for managing conversation context.
The main class that acts as the processing center.
- Receives input from the user (Prompt)
- Coordinates with the LLM
- Decides when to use tools
- Returns results in a structured format (Pydantic Model)
Designed to work with various LLMs through the Model
class, which acts as an intermediary to communicate with each provider's API, making it easy to switch models.
- OpenAI (
gpt-4o
,gpt-4.1-mini
) - Google (
gemini-2.5-flash
) - Anthropic (
claude-3-5-sonnet-latest
)
Install: uv add "pydantic-ai-slim[openai]"
Setup: export OPENAI_API_KEY='sk-...'
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
# Method 1: Use the model name directly
agent = Agent('openai:gpt-4o')
# Method 2: Create a Model instance
model = OpenAIModel('gpt-4o')
agent = Agent(model)
Install: uv add "pydantic-ai-slim[google]"
Setup: export GOOGLE_API_KEY='your-api-key'
from pydantic_ai import Agent
from pydantic_ai.models.google import GoogleModel
model = GoogleModel('gemini-2.5-flash')
agent = Agent(model)
For Vertex AI, set
GoogleProvider(vertexai=True)
Install: uv add "pydantic-ai-slim[anthropic]"
Setup: export ANTHROPIC_API_KEY='your-api-key'
from pydantic_ai import Agent
from pydantic_ai.models.anthropic import AnthropicModel
# Method 1
agent = Agent('anthropic:claude-3-5-sonnet-latest')
# Method 2
model = AnthropicModel('claude-3-5-sonnet-latest')
agent = Agent(model)
The heart of creating a chatbot that can remember conversational context (Multi-turn conversation).
Message
object: Manages messages in each turn.message_history
: A list ofMessage
objects sent with new prompts to help the AI understand the context.
from pydantic_ai import Agent
agent = Agent('openai:gpt-4o')
conversation_history = []
while True:
prompt = input("You: ")
if prompt.lower() == "exit":
break
# 1. Send prompt with history
response = agent.run_sync(
prompt,
message_history=conversation_history
)
# 2. Update history with new messages
conversation_history = response.new_messages()
print(f"Bot: {response.output}")
You can define a personality or role for the Agent from the start using system_prompt
.
persona = "You are a pirate named Captain Jack, you are gruff and brash."
agent = Agent(
'openai:gpt-4o',
system_prompt=persona
)
response = agent.run_sync("Introduce yourself.")
print(response.output)
Result: "I am Captain Jack! The greatest pirate of the seven seas. What can I do for you?"
Agent
: The main controller.LLM Models
: Choose the desired model.message_history
: Used inrun_sync()
to send context.response.new_messages()
: Used to update the conversation history.system_prompt
: Used to define the Agent's personality.
Once you understand these components, you are ready to build more complex AI!
Transforming the Agent from an "answer provider" to a "doer".
They are Python functions that we give to the Agent, enabling it to:
- Call Python functions that we create.
- Access external APIs.
- Interact with various systems.
This allows the Agent to perform real tasks, not just answer questions.
LLMs are not good at math, so we create a new Tool.
# math_tools.py
def add(a: int, b: int) -> int:
"""Use this function to add two numbers."""
return a + b
def subtract(a: int, b: int) -> int:
"""Use this function to subtract two numbers."""
return a - b
Important:
Type Hints
anddocstrings
help the LLM understand what the Tool does.
# math_agent.py
from pydantic_ai import Agent
from math_tools import add, subtract
# Bind Tools via a list when creating the Agent
agent = Agent("openai:gpt-4o-mini", tools=[add, subtract])
result = agent.run_sync("What is 125 plus 349?")
print(result.output)
# Result: 125 plus 349 equals 474.
PydanticAI will automatically select and run the
add
tool.
Create a Tool to check the weather from OpenWeatherMap.
# weather_tool.py
import requests
def get_current_weather(location: str) -> str:
"""Get the current weather in a given location."""
# ... (API call code) ...
return response.json()
# Bind the Tool to the Agent
weather_agent = Agent('openai:gpt-4o', tools=[get_current_weather])
response = weather_agent.run_sync("What's the weather like in Bangkok?")
print(response.output)
The Agent will call the API, receive the JSON data, and then summarize it in an easy-to-understand language.
- PydanticAI converts the Tool (Python code) into a schema and sends it to the LLM.
- LLM analyzes the question and decides which Tool to use.
- PydanticAI receives the command from the LLM and calls the actual Python function.
- The result from the function is sent back to the LLM.
- LLM generates the final answer from that result.
PydanticAI can connect to other Tool Ecosystems:
- MCP (Model Context Protocol): A standard for AI Agents.
- LangChain Tools: Access LangChain's large library of tools.
- ACI.dev Tools: Connect to business applications like Zendesk, Slack.
Create a Chatbot that remembers and has a personality.
To enable the Chatbot to understand context and have a continuous conversation, we must use Chat History.
conversation_history
: is a list of messages that have already been exchanged.- We send this
history
with every new question. - The LLM uses the
history
to understand the context.
from pydantic_ai import Agent
agent = Agent('openai:gpt-4o')
conversation_history = [] # Start with an empty history
while True:
prompt = input("You: ")
if prompt.lower() == "exit": break
# Send the prompt and history together
response = agent.run_sync(prompt, message_history=conversation_history)
# Update the history with the latest messages
conversation_history = response.new_messages()
print(f"Bot: {response.output}")
Use system_prompt
to define the Agent's role and personality traits.
# Define Persona
persona = "You are a pirate named Captain Jack, you are gruff and always end your sentences with 'Ahoy!'"
# Create Agent with System Prompt
agent = Agent('openai:gpt-4o', system_prompt=persona)
# Test conversation
response = agent.run_sync("What is PydanticAI?")
print(response.output)
Bot: PydanticAI? Never heard of it. If you mean Pydantic, that's a Python library... Ahoy!
Retrieval-Augmented Generation
LLMs have general knowledge, but they don't know about:
- Internal company documents
- The latest product information
- Customer databases
RAG is the solution!
It's like giving the LLM a "cheat sheet" or "reference document" before it answers a question.
Process:
- Retrieval: Search for relevant information from our "knowledge base" (Vector Store).
- Augmentation: Combine the found information with the original question.
- Generation: Send the augmented prompt to the LLM to generate an answer based on that information.
We will convert our documents (e.g., .txt, .pdf) into a Vector Store.
- Prepare Documents: Create a
pydanticai_info.txt
file. - Install Libraries:
uv add langchain-community langchain-openai faiss-cpu
- Write a script to create the Vector Store:
- Load documents
- Split them into small pieces (Chunks)
- Convert them into numbers (Embeddings)
- Save to
faiss_index_pydanticai
# create_vector_store.py
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
# 1. Load and split documents
loader = TextLoader("./pydanticai_info.txt")
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)
# 2. Create Embeddings and Vector Store
embeddings = OpenAIEmbeddings()
vector_store = FAISS.from_documents(chunks, embeddings)
# 3. Save
vector_store.save_local("faiss_index_pydanticai")
Create an Agent with a Tool for searching the Vector Store.
# rag_agent.py
from pydantic_ai import Agent
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
# 1. Load the previously created Vector Store
embeddings = OpenAIEmbeddings()
vector_store = FAISS.load_local("faiss_index_pydanticai", embeddings, ...)
retriever = vector_store.as_retriever()
# 2. Create a Tool for searching
def retrieve_pydanticai_info(query: str) -> str:
"""Find information about PydanticAI in the knowledge base."""
docs = retriever.invoke(query)
return "\n\n".join([doc.page_content for doc in docs])
# 3. Create the Agent with the Tool
rag_agent = Agent("openai:gpt-4o", tools=[retrieve_pydanticai_info])
# Ask a question that requires knowledge from the document
prompt = "What is the core philosophy of PydanticAI?"
response = rag_agent.run_sync(prompt)
print(response.output)
Result:
The core philosophy of PydanticAI is to combine the power of Pydantic for defining clear data structures with the reasoning capabilities of LLMs...
The Agent will call retrieve_pydanticai_info
to search for information before answering, making the answer accurate and based on our document.