
Pydantic AI: Ghidul de producție (Dincolo de Hello World)
Output-urile brute ale LLM-urilor strică aplicațiile. Ceri JSON, primești markdown. Ceri un număr între 1 și 10, primești „Sigur! Iată un număr: șapte.” Dacă ai construit ceva real cu API-uri LLM, ai scris cod defensiv de parsare care te face să îți pui la îndoială alegerile de carieră. Pydantic AI rezolvă această problemă; este framework-ul de agenți type-safe creat de aceeași echipă din spatele Pydantic și FastAPI. Gândește-te la el ca la „FastAPI pentru agenți AI”: definești ceea ce dorești folosind hint-uri de tip Python, iar framework-ul se ocupă de validare, reîncercări și apelarea tool-urilor.
Acest ghid Pydantic AI este destinat dezvoltatorilor care și-au rulat deja primul apel LLM și doresc modele de producție: output-uri structurate care nu se strică, injectare de dependențe pentru agenți testabili și tool-uri din lumea reală, dincolo de API-urile meteo. La final, vei avea agenți funcționali cu tool-uri, DI, streaming și teste.
<!-- IMAGE: Arhitectura agentului Pydantic AI, Agentul primește promptul, apelează tool-uri prin RunContext, validează output-ul prin modelul Pydantic -->Pydantic AI în linii mari
| Atribut | Detalii |
|---|---|
| Ce este | Framework de agenți AI type-safe pentru Python |
| Creat de | Echipa Pydantic (Samuel Colvin și alții) |
| Filosofie | „FastAPI pentru agenți AI”, hint-urile de tip conduc totul |
| Licență | MIT (open-source) |
| Versiunea curentă | v1.74.0 (martie 2026) |
| Versiune Python | 3.9+ |
| Modele suportate | OpenAI, Anthropic, Google Gemini, Groq, Mistral, Ollama și altele |
| Funcționalități cheie | Output-uri structurate, apelare tool-uri, injectare dependențe, streaming, TestModel |
| Stele GitHub | 16.000+ |
| Pregătit pentru producție | Da, v1.0 lansat în septembrie 2025 |
| Observabilitate | Integrare nativă Logfire (bazată pe OpenTelemetry) |
| Curba de învățare | Mică dacă cunoști Pydantic/FastAPI; moderată în caz contrar |
Funcționalitățile remarcabile sunt output-urile structurate (validate cu modele Pydantic), injectarea dependențelor (similar cu Depends din FastAPI) și TestModel (LLM mock pentru testare fără apeluri API). Dacă vii din zona LangChain și te întrebi „există ceva mai curat?”, probabil că acesta este răspunsul.
Instalare și primul agent
# Install with OpenAI support (swap openai for anthropic, google, etc.)
pip install "pydantic-ai[openai]"
# Set your API key
export OPENAI_API_KEY="sk-..."Primul tău agent în 5 linii:
from pydantic_ai import Agent
agent = Agent("openai:gpt-4o", system_prompt="You are a helpful assistant.")
result = agent.run_sync("What's the capital of France?")
print(result.output) # "Paris"Asta e tot. Agent împachetează modelul, run_sync trimite un prompt și returnează un rezultat. result.output este aici un simplu șir de caractere, dar acest lucru urmează să se schimbe.
Output-uri structurate, motivul existenței Pydantic AI
Aceasta este funcționalitatea de bază. În loc să primești un șir de caractere de la LLM și să sperii că este un JSON valid, definești un model Pydantic, iar agentul returnează un obiect Python validat.
Înainte: Output brut LLM
# The old way -- hope for the best
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Review the movie Inception. Return JSON with title, rating (1-10), summary."}]
)
# response.choices[0].message.content is a string
# Maybe it's JSON. Maybe it has markdown code fences. Maybe rating is "eight".
# You're on your own.După: Structurat cu Pydantic AI
from pydantic import BaseModel
from pydantic_ai import Agent
class MovieReview(BaseModel):
title: str
rating: int # Guaranteed to be an int, not "eight"
summary: str
recommended: bool
agent = Agent("openai:gpt-4o", result_type=MovieReview)
result = agent.run_sync("Review the movie Inception")
review = result.output # This is a MovieReview instance, not a string
print(f"{review.title}: {review.rating}/10")
print(f"Recommended: {review.recommended}")
print(review.summary)Diferența este ca de la cer la pământ. result.output este un obiect real MovieReview. Dacă LLM-ul returnează rating: "eight" în loc de rating: 8, validarea Pydantic va detecta eroarea. Pentru o privire mai detaliată asupra modului în care funcționează acest lucru la diferiți provideri, consultă ghidul nostru despre output-uri structurate across LLM providers.
Ce se întâmplă când validarea eșuează
Iată partea pe care niciun alt tutorial nu o arată: ce se întâmplă când LLM-ul greșește?
from pydantic import BaseModel, Field
from pydantic_ai import Agent
class StrictReview(BaseModel):
title: str
rating: int = Field(ge=1, le=10) # Must be 1-10
pros: list[str] = Field(min_length=2) # At least 2 pros
agent = Agent("openai:gpt-4o", result_type=StrictReview)
# If the LLM returns rating=15 or only 1 pro:
# 1. Pydantic validation fails
# 2. The error message is sent BACK to the LLM
# 3. The LLM tries again with the corrected output
# 4. This repeats up to the retry limit
result = agent.run_sync("Review the movie Inception")Această buclă de reîncercare cu feedback este funcționalitatea killer a Pydantic AI. LLM-ul învață din propriile erori de validare. Nu scrii logică de reîncercare, framework-ul se ocupă de ea.
Verdict: Output-urile structurate sunt cel mai bun motiv pentru a utiliza Pydantic AI în locul apelurilor API brute. Dacă parsezi manual JSON-ul LLM, oprește-te.
Tool-uri și apelarea funcțiilor
Tool-urile permit agentului tău să apeleze funcții Python pentru a obține date reale. În loc ca LLM-ul să halucineze fapte, acesta poate interoga baza ta de date, poate căuta în documentația ta sau poate apela un API.
Înregistrarea unui tool
from pydantic_ai import Agent
agent = Agent("openai:gpt-4o")
@agent.tool
async def search_docs(query: str) -> str:
"""Search the documentation for relevant articles."""
# Your actual search logic here
results = await doc_search_engine.search(query, limit=5)
return "\n".join(r.title + ": " + r.snippet for r in results)Decoratorul @agent.tool înregistrează funcția. Pydantic AI citește hint-urile de tip și docstring-ul funcției pentru a-i spune LLM-ului ce face tool-ul, ce argumente primește și ce returnează. Fără scrierea manuală a schemei, hint-urile tale de tip SUNT schema. Pentru contexte despre cum funcționează apelarea funcțiilor LLM sub capotă, avem un ghid dedicat.
RunContext: Transmiterea datelor către tool-uri
Aici Pydantic AI se distanțează de alte framework-uri. RunContext îți permite să transmiți date de runtime (conexiuni la baza de date, informații despre utilizator, clienți API) către tool-urile tale fără stare globală.
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext
@dataclass
class SupportDeps:
customer_id: str
db_connection: DatabaseConnection
agent = Agent("openai:gpt-4o", deps_type=SupportDeps)
@agent.tool
async def get_order_history(ctx: RunContext[SupportDeps], limit: int = 5) -> str:
"""Fetch recent orders for the current customer."""
orders = await ctx.deps.db_connection.query(
"SELECT * FROM orders WHERE customer_id = $1 ORDER BY date DESC LIMIT $2",
ctx.deps.customer_id, limit
)
return format_orders(orders)ctx.deps oferă tool-ului acces la orice ai transmis la runtime. Tool-ul nu importă o conexiune globală la baza de date, ci o primește. Aceasta este injectarea dependențelor, iar ea este ceea ce face agenții tăi testabili.
Un exemplu de tool din lumea reală
@agent.tool
async def run_sql_query(ctx: RunContext[SupportDeps], sql: str) -> str:
"""Run a read-only SQL query against the analytics database.
Only SELECT queries are allowed."""
if not sql.strip().upper().startswith("SELECT"):
return "Error: only SELECT queries are allowed"
results = await ctx.deps.db_connection.fetch(sql)
return json.dumps(results, default=str)Verdict: Apelarea tool-urilor în Pydantic AI este mai curată decât în orice alt framework, mulțumită hint-urilor de tip care fac munca grea. Scrii funcții Python normale cu adnotări de tip. Framework-ul se ocupă de restul.
Injectarea dependențelor, funcționalitatea pe care LangGraph și-ar fi dorit-o
Dacă ai folosit Depends din FastAPI, înțelegi deja sistemul DI al Pydantic AI. Dacă nu, iată versiunea scurtă: în loc ca agentul tău să se întindă să ia ceea ce are nevoie (conexiuni globale la baza de date, clienți API, configurare), îi oferi totul la runtime.
Definirea dependențelor
from dataclasses import dataclass
from pydantic_ai import Agent
@dataclass
class AppDeps:
db: AsyncDatabasePool
search_client: SearchAPIClient
current_user: User
agent = Agent(
"openai:gpt-4o",
deps_type=AppDeps,
system_prompt="You are a customer support agent."
)Utilizarea dependențelor în tool-uri
@agent.tool
async def lookup_account(ctx: RunContext[AppDeps]) -> str:
"""Look up the current user's account details."""
account = await ctx.deps.db.fetchrow(
"SELECT * FROM accounts WHERE user_id = $1",
ctx.deps.current_user.id
)
return json.dumps(account, default=str)
# Run with real dependencies
result = await agent.run(
"What's my account status?",
deps=AppDeps(db=real_db, search_client=real_search, current_user=user)
)De ce DI face agenții tăi testabili
Acesta este adevăratul beneficiu. În LangChain, ai transmite contextul prin kwargs de chain sau closure-uri, neexistând un model standard. În Pydantic AI, înlocuirea dependențelor reale cu dubluri de test este trivială:
# In your test file
from pydantic_ai import Agent
from your_app import agent, AppDeps
async def test_account_lookup():
mock_deps = AppDeps(
db=MockDatabase({"user_123": {"status": "active", "plan": "pro"}}),
search_client=MockSearch(),
current_user=User(id="user_123")
)
result = await agent.run("What's my account status?", deps=mock_deps)
assert "active" in result.output
assert "pro" in result.outputFără monkey-patching. Fără mocking al importurilor globale. Transmiți pur și simplu deps diferite.
Verdict: Injectarea dependențelor este motivul pentru care dezvoltatorii Python experimentați preferă Pydantic AI. Este influența FastAPI care se manifestă.
Provideri de modele, OpenAI, Anthropic, Gemini, Ollama
Pydantic AI este agnostica față de model. Schimbarea providerilor este o modificare de o singură linie:
# OpenAI
agent = Agent("openai:gpt-4o")
# Anthropic
agent = Agent("anthropic:claude-sonnet-4-20250514")
# Google Gemini
agent = Agent("google-gla:gemini-2.0-flash")
# Local Ollama
agent = Agent("ollama:llama3.1")Tot restul, tool-urile, output-urile structurate, DI, rămân identice. Logica ta de business nu se schimbă atunci când schimbi modelele.
| Provider | Modele | Nivel gratuit | Complexitate configurare |
|---|---|---|---|
| OpenAI | GPT-4o, GPT-4o mini, o1 | Credit $5 (conturi noi) | Scăzută, doar cheie API |
| Anthropic | Claude Sonnet, Haiku, Opus | Fără nivel gratuit | Scăzută, doar cheie API |
| Google Gemini | Gemini 2.0 Flash, Pro | Nivel gratuit generos | Medie, configurare proiect |
| Groq | Llama, Mixtral | Nivel gratuit disponibil | Scăzută, doar cheie API |
| Ollama (local) | Llama, Mistral, Phi etc. | Complet gratuit | Medie, instalare Ollama |
Verdict: Designul agnostic față de model înseamnă că nu ești niciodată blocat într-un singur provider. Începe cu OpenAI pentru comoditate, fă benchmarking cu Anthropic și folosește Ollama pentru dezvoltarea locală.
Streaming de răspunsuri
Pentru interfețele chat și aplicațiile în timp real, streaming-ul este esențial. Pydantic AI îl suportă menținând în același timp type-safety:
from pydantic_ai import Agent
from pydantic import BaseModel
class AnalysisResult(BaseModel):
summary: str
sentiment: str
confidence: float
agent = Agent("openai:gpt-4o", result_type=AnalysisResult)
async def stream_analysis(text: str):
async with agent.run_stream(f"Analyze this text: {text}") as stream:
async for partial in stream.stream_structured():
# partial is a partially-validated AnalysisResult
print(f"Streaming: {partial}")
# Final result is fully validated
result = await stream.get_output()
print(f"Final: {result.summary} ({result.confidence:.0%} confident)")Acest lucru funcționează perfect cu StreamingResponse din FastAPI, același ecosistem, aceleași modele. Documentația agenților Pydantic AI acoperă opțiuni avansate de streaming, inclusiv streaming doar text cu stream_text().
Pydantic AI vs LangGraph vs OpenAI Agents SDK
Ești aici, deci probabil te întrebi: „ar trebui să folosesc Pydantic AI sau LangGraph?” Răspuns onest: rezolvă probleme diferite și s-ar putea să le folosești pe ambele.
Tabel comparativ de funcționalități
| Funcționalitate | Pydantic AI | LangGraph | OpenAI Agents SDK |
|---|---|---|---|
| Type Safety | Complet (modele Pydantic) | Parțial (TypedDict) | Minimal |
| Injectare dependențe | Integrat (stil FastAPI) | Niciuna | Niciuna |
| Output-uri structurate | Nativen cu reîncercare | Prin parser-e de output | Prin modul JSON |
| Apelare tool-uri | Decorator @agent.tool | Decorator @tool | Definiții de funcții |
| Multi-Agent | Handoff-uri de bază | Avansat (mașini de stare) | Handoff-uri + guardrails |
| Streaming | Streaming tipizat | Evenimente de streaming | Streaming |
| Suport modele | 10+ provideri | În principal modele LangChain | Doar OpenAI |
| Testare | TestModel integrat | Fără testare integrată | Fără testare integrată |
| Curba de învățare | Scăzută (dacă știi Pydantic) | Ridicată (concepte graf) | Scăzută (API simplu) |
| Dimensiunea comunității | În creștere (16K stele) | Mare (ecosistem LangChain) | În creștere (suport OpenAI) |
| Cel mai potrivit pentru | Agenți curati, testabili | Fluxuri de lucru complexe de stare | Proiecte doar OpenAI |
Când să folosești fiecare
Alege Pydantic AI când dorești cod de agenți curat și type-safe. Este ideal pentru sarcini cu un singur agent care implică tool-uri (boți de suport clienți, extragere de date, agenți de review cod) și situații în care testabilitatea contează. Dacă echipa ta folosește deja FastAPI și Pydantic, curba de învățare este aproape nulă.
Alege LangGraph când ai nevoie de fluxuri de lucru complexe, cu mai mulți pași, cu ramificări condiționale, aprobare human-in-the-loop și gestionare sofisticată a stării. LangGraph excelsă la orchestrarea mai multor pași, nu la calitatea individuală a agentului. Pentru o analiză aprofundată, vezi comparația noastră completă LangGraph vs CrewAI vs OpenAI Agents SDK.
Alege OpenAI Agents SDK când ești 100% pe OpenAI, dorești cea mai simplă configurare posibilă și nu ai nevoie de suport multi-provider sau DI.
Modelul de combinație
Iată ce fac echipele experimentate de fapt: folosesc Pydantic AI pentru agenți individuali (cod curat, testabil, output-uri tipizate) și LangGraph pentru orchestrarea între agenți (rutare, mașini de stare, logică condițională). Nu concurează, sunt straturi complementare.
# Pydantic AI agent -- clean, testable, type-safe
support_agent = Agent("openai:gpt-4o", result_type=SupportResponse, deps_type=SupportDeps)
# LangGraph graph -- orchestrates when to call which agent
graph = StateGraph(SupportState)
graph.add_node("classify", classify_intent)
graph.add_node("support", lambda state: support_agent.run_sync(state["query"]))
graph.add_node("escalate", escalate_to_human)Verdict: Alege Pydantic AI pentru cod de agenți curat și testabil. Alege LangGraph pentru fluxuri de lucru complexe cu mai mulți pași. Nu se exclud reciproc.
Testarea agenților tăi cu TestModel
Aceasta este secțiunea care separă un ghid pentru începători de unul de producție. Orice codebase real are nevoie de teste, iar testarea agenților este notoriu de dificilă; apelurile LLM sunt lente, scumpe și non-deterministe. Pydantic AI oferă o soluție: TestModel.
from pydantic_ai import Agent
from pydantic_ai.models.test import TestModel
from pydantic import BaseModel
class SupportResponse(BaseModel):
answer: str
confidence: float
escalate: bool
agent = Agent("openai:gpt-4o", result_type=SupportResponse)
# In tests: swap the real model for TestModel
def test_support_agent():
with agent.override(model=TestModel()):
result = agent.run_sync("I need help with billing")
# TestModel returns valid structured data matching your result_type
assert isinstance(result.output, SupportResponse)
assert isinstance(result.output.confidence, float)
assert isinstance(result.output.escalate, bool)TestModel generează date valide care corespund cu result_type fără a face niciun apel API. Cost zero, determinist, rapid. Documentația de testare Pydantic AI acoperă modele avansate precum FunctionModel pentru răspunsuri personalizate și capture_run_messages pentru inspectarea apelurilor de tool-uri.
Testarea tool-urilor și DI împreună
def test_order_lookup_tool():
# Mock dependencies
mock_deps = SupportDeps(
customer_id="test-123",
db_connection=MockDB(orders=[{"id": "ord-1", "status": "shipped"}])
)
with agent.override(model=TestModel()):
result = agent.run_sync(
"Where is my order?",
deps=mock_deps
)
assert isinstance(result.output, SupportResponse)Fără apeluri API. Fără teste instabile. Fără costuri. Rulează acest lucru în CI/CD alături de restul suitei tale de teste.
Aceasta este cea mai mare lacună de conținut de pe întregul SERP. Niciun alt ghid Pydantic AI acoperă testarea. Dacă construiești agenți pentru producție, asta ai nevoie.
Observabilitate, integrare Logfire în 5 minute
Agenții de producție au nevoie de observabilitate AI. Vrei să vezi fiecare apel LLM, invocare de tool, latență, număr de tokeni și cost. Pydantic AI se integrează nativ cu Logfire, platforma de observabilitate a echipei Pydantic (construită pe OpenTelemetry).
import logfire
from pydantic_ai import Agent
logfire.configure() # Uses LOGFIRE_TOKEN env var
logfire.instrument_pydantic_ai()
agent = Agent("openai:gpt-4o", result_type=MovieReview)
# Every run is now traced automatically
result = agent.run_sync("Review Inception")Trei linii. Obții trace-uri complete care arată: promptul trimis, răspunsul modelului, apelurile de tool-uri (dacă există), validările reușite/eșuate, reîncercările, latența și costul estimat. Dacă Logfire nu este pe gustul tău, Langfuse este o alternativă open-source solidă cu suport pentru context engineering pentru trasarea evoluției prompturilor tale.
Întrebări frecvente
Ce este Pydantic AI și cum diferă de LangChain?
Pydantic AI este un framework de agenți type-safe în care hint-urile de tip Python conduc validarea, schemele de tool-uri și injectarea dependențelor. LangChain este un framework mai mare, concentrat pe înlănțuirea apelurilor LLM. Diferența cheie: Pydantic AI validează output-urile la nivel de framework și oferă injectare de dependențe integrată pentru testabilitate, LangChain nu face niciuna dintre acestea implicit.
Cum construiesc un agent AI type-safe cu Pydantic AI?
Definește un BaseModel Pydantic pentru output-ul tău, transmite-l ca result_type către Agent și apelează run_sync() sau run(). Agentul returnează o instanță validată a modelului tău, nu un șir brut. Vezi secțiunea Output-uri structurate pentru exemple complete.
Ar trebui să folosesc Pydantic AI sau LangGraph pentru agenții de producție?
Folosește Pydantic AI pentru agenți individuali unde contează type-safety, testabilitatea și codul curat. Folosește LangGraph pentru orchestrarea fluxurilor de lucru complexe cu mai mulți pași și rutare condițională. Multe echipe folosesc ambele, agenți Pydantic AI într-un strat de orchestrare LangGraph.
Cum gestionează Pydantic AI apelarea tool-urilor și injectarea dependențelor?
Decorează o funcție cu @agent.tool, iar Pydantic AI citește hint-urile sale de tip pentru a genera schema tool-ului. Pentru DI, setează deps_type pe Agent și acceptă RunContext[YourDeps] în tool-uri. Dependențele de runtime (conexiuni DB, clienți API) circulă fără stare globală.
Cum adaug streaming unui agent Pydantic AI?
Folosește agent.run_stream() în loc de agent.run(). Returnează un manager de context async care yield-uiește rezultate parțiale prin stream_structured() sau stream_text(). Rezultatul final este în continuare fully validated împotriva result_type.
Este Pydantic AI pregătit pentru producție în 2026?
Da. Versiunea 1.0 a fost lansată în septembrie 2025 cu un angajament de stabilitate API. Este susținut de echipa Pydantic (cea mai descărcată librărie Python pentru validarea datelor) și se află actualmente la v1.74.0 cu actualizări regulate.
Pot folosi Pydantic AI cu Ollama și modele locale?
Da. Folosește Agent("ollama:llama3.1") și asigură-te că Ollama rulează local. Instalează extra-ul providerului ollama: pip install "pydantic-ai[ollama]". Output-urile structurate și tool-urile funcționează la fel ca și cu providerii cloud.
Cum testez agenții Pydantic AI?
Folosește TestModel, un model mock care generează date structurate valide corespunzătoare cu result_type fără apeluri API. Împachetează testul în agent.override(model=TestModel()) și rulează aserțiuni pe output. Vezi secțiunea Testare pentru exemple complete pytest.
Funcționează Pydantic AI cu FastAPI?
Perfect. Partajează aceeași filosofie de injectare a dependențelor și sunt construite de aceeași echipă. Poți folosi agenți Pydantic AI în endpoint-urile FastAPI, poți partaja tipuri de dependențe între ele și poți stream-ui răspunsurile agenților prin StreamingResponse.
Care este diferența dintre Pydantic AI și OpenAI Agents SDK?
Pydantic AI este agnostic față de model (funcționează cu OpenAI, Anthropic, Gemini, Ollama etc.), are injectare de dependențe, TestModel pentru testare și validare Pydantic. OpenAI Agents SDK este mai simplu, dar blocat pe modele OpenAI și îi lipsesc DI și testarea integrată. Alege Pydantic AI pentru flexibilitate; alege OpenAI Agents SDK pentru cea mai simplă configurare posibilă doar pentru OpenAI.
Concluzii cheie și pași următori
| Concept | Insight cheie | Pas următor |
|---|---|---|
| Output-uri structurate | result_type este validat și reîncercat automat | Definește modele Pydantic pentru toate output-urile agenților |
| Tool-uri | Hint-urile de tip SUNT schema, fără definiții manuale | Construiește tool-uri cu @agent.tool și RunContext |
| Injectare dependențe | Transmite deps de runtime explicit pentru testabilitate | Definește o dataclass deps_type pentru fiecare agent |
| Testare | TestModel elimină costurile API în CI/CD | Adaugă agent.override(model=TestModel()) în suita de teste |
| Provideri modele | Schimbare model dintr-o linie, fără modificări de cod | Începe cu OpenAI, benchmarking alternative mai târziu |
| Observabilitate | Configurare Logfire în 3 linii pentru trace-uri complete | Adaugă logfire.instrument_pydantic_ai() în producție |
Începe cu un agent mic care are output-uri structurate. Adaugă un tool. Adaugă dependențe. Scrie un test cu TestModel. Aceasta este calea spre producție, iar acum ai tot ce îți trebuie pentru a o parcurge.
Documentația oficială Pydantic AI și repository-ul GitHub sunt excelente pentru a aprofunda. Framework-ul evoluează rapid, așa că adaugă changelog-ul la bookmark-uri.