Pydantic AI Tutorial: Pagbuo ng LLM Agent gamit ang Type Safety, mula sa Unang Programa hanggang sa Production
Alam ng lahat ng gumawa na ng LLM apps na ang pinakamasakit ay hindi ang pag-connect sa API, kundi ang pagbabago ng format ng sagot ng modelo kada beses. Dinala ng Pydantic AI ang type validation ng Pydantic sa pagbuo ng Agent para maging may-istruktura ang output at ma-check nang static ang mga tool. Dadalhin ka ng gabay na ito mula sa installation hanggang sa advanced, kasama ang mga natutunan ko sa mga naging problema ko.
Panimula: Bakit Iba-iba Palagi ang Binu-buli ng Model?
Kung nakatrabaho ka na ng LLM API, malamang pamilyar ka sa senaryong ito: sinabihan mo ang modelo na "mag-return ng JSON na may name at score," at naging maayos naman ang unang siyam na beses, pero sa ika-sampung beses, naglagay ito ng "Sige, narito ang resulta:" bago ang JSON, kaya bumagsak agad ang iyong json.loads(). Tapos, magsisimula ka nang magsulat ng tambak na regular expressions para linisin ang string, at sunod-sunod na if statements para i-check kung nandoon ba ang mga field—sa huli, 70% ng code sa iyong "AI application" ay nakikipaglaban lang sa unstable output ng modelo.
Ako mismo ay nag-maintain ng isang internal classification service dati, at ang pag-handle lang sa paminsan-minsang pag-alis ng isang field ng modelo ay umabot sa tatlong araw ng overtime. Nang lumipat ako sa Pydantic AI, halos nawala lahat ng defensive code na iyon dahil direktang sinalo ng framework ang validation. Tatalakayin sa artikulong ito kung paano ito gamitin.
Ano ang Pydantic AI?
Ang Pydantic AI ay isang Python Agent framework na gawa ng Pydantic team. Malamang na nakita mo na ang pangalang Pydantic sa iba pang mga lugar—ang mga opisyal na SDK ng OpenAI, Anthropic, Google, pati na rin ang LangChain at LlamaIndex, ay umaasa rito para sa malaking bahagi ng kanilang data validation sa ilalim ng hood. Sa madaling salita, pagdating sa validation, sila ang may pinakamalaking kredibilidad sa ecosystem na ito.
Ang disenyo nitong pilosopiya ay kahawig ng FastAPI: gamitin ang katutubong type hints ng Python para malinaw na tukuyin ang mga gawi, at iwanan na ang iba sa framework. Mayroon lamang itong ilang pangunahing konsepto—Agent, Tools, Dependencies (dependency injection), at Structured Output. Hindi mo kailangang magsaulo ng tambak na sariling-imbentong abstract classes; ang pagsusulat nito ay parang normal na Python lamang, ngunit bibigyan ka ng iyong IDE ng auto-completion, at ang mga type checker (tulad ng Pyright at mypy) ay mahuhuli ang mga error bago mo pa man patakbuhin ang programa.
Ito ay model-agnostic, ibig sabihin ay hindi ito nakatali sa isang partikular na tagagawa ng modelo. Sinusuportahan nito ang mahigit sampung provider gaya ng OpenAI, Anthropic, Google, Groq, Cohere, Mistral, at Ollama, at ang pagpapalit ng modelo ay karaniwang nangangailangan lamang ng pagbabago ng isang string. Kung gusto mong maunawaan ang pagkakaiba ng Agent at ng karaniwang tawag sa API, maaari mong basahin muna ang Ano ang AI Agent.
Para saan ito magagamit?
Sa madaling salita, angkop ito sa anumang sitwasyon na "nangangailangan ng maaasahang resulta mula sa modelo":
- Structured Extraction: Magpasok ng liham ng reklamo ng customer at hilingin dito na ilabas ang tatlong field:
sentiment,category, aturgency, habang tinitiyak na tama ang mga uri ng data (types). - Klasipikasyon at Pag-label: Mag-label ng malaking dami ng dokumento, na may output na limitado sa mga Enum na tinukoy mo; ang anumang ligaw na sagot ng modelo ay haharangin.
- Tool-based Agent: Payagan ang modelo na tawagan ang iyong mga function—mag-query sa database, tumawag sa weather API, o mag-compute ng matematika. Ang framework ang bahalang mag-convert ng mga uri ng function sa mga paglalarawan ng tool na naiintindihan ng modelo.
- RAG Q&A: Ipares sa vector search upang lumikha ng isang sistema ng pagsagot sa tanong na may mga batayan. Para dito, maaari mong i-refer ang ating RAG Implementation Guide.
Kumpara sa malalaking framework na tulad ng LangChain na sumasaklaw sa lahat, sadyang ginawang magaan (thin) ang Pydantic AI. Kung gusto mo lang gawing maaasahan ang output ng modelo nang hindi kinakailangang magsaulo ng buong ecosystem para lamang sa isang maliit na feature, mas magiging madali ang learning curve nito.
Paano Gamitin: Unang Paggamit
1. Pag-install
bash
pip install pydantic-ai
Inirerekomenda na gumamit ng virtual environment. Mas ligtas ang bersyon ng Python na 3.9 pataas.
2. Pag-setup ng API Key
Gamit ang Anthropic bilang halimbawa, magtakda ng environment variable:
bash
export ANTHROPIC_API_KEY=iyong_api_key
Para sa OpenAI, itakda ang OPENAI_API_KEY, at iba pa.
3. Pagsulat ng Unang Agent
python
from pydantic_ai import Agent
agent = Agent('anthropic:claude-sonnet-4-6')
result = agent.run_sync('Ipaliwanag sa isang pangungusap kung ano ang vector database')
print(result.output)
Ang unang parameter ay ang pangalan ng modelo, na may format na provider:model. Upang lumipat sa OpenAI, palitan lamang ito ng 'openai:gpt-4o' o katulad nito, at ang natitirang code ay hindi na kailangang baguhin—ito ang benepisyo ng pagiging model-agnostic.
4. Pagbibigay ng Estruktura sa Output
Ito ang pinakamahalagang bahagi. Magtukoy ka ng isang Pydantic model bilang format ng output:
python
from pydantic import BaseModel
from pydantic_ai import Agent
class Review(BaseModel):
sentiment: str # positive / negative / neutral
score: int # 1 hanggang 5
summary: str
agent = Agent('anthropic:claude-sonnet-4-6', output_type=Review)
result = agent.run_sync('Masarap ang pagkain dito pero umabot sa halos isang oras ang hintay, medyo OA')
print(result.output.score) # Direktang nakukuha ang integer, hindi na kailangang i-parse nang mag-isa
print(result.output.sentiment) # Direktang nakukuha ang string
Kung ang ibinalik ng modelo ay hindi sumusunod sa uri ng data (type) ng Review, awtomatikong ibabalik ng framework ang mensahe ng error sa modelo upang hilingin dito na subuking muli. Kapag nakuha mo ang result.output, ito ay isa nang beripikadong Python object, at tutulungan ka pa ng iyong IDE na kumpletuhin ang mga field.
5. Pagbibigay ng Tool sa Agent
python
from pydantic_ai import Agent
agent = Agent('anthropic:claude-sonnet-4-6')
@agent.tool_plain
def get_weather(city: str) -> str:
"""Kunin ang kasalukuyang panahon sa tinukoy na lungsod"""
return f'Ang {city} ay nasa 28 degrees ngayon, maogma'
result = agent.run_sync('Kumusta ang panahon sa Taipei ngayon?')
print(result.output)
Ang docstring na iyon ay hindi lang basta nakalagay doon para sa palamuti—ito ay magiging paglalarawan ng tool na makikita ng modelo. Ang type hint ng function (city: str) ay mako-convert din sa spec ng parameter na naiintindihan ng modelo, at ang mga parameter ay bina-validate rin ng Pydantic.
Mga Advanced na Teknik
Ang Dependency Injection ang pinaka-underestimated nitong feature. Magagamit mo ang RunContext para ligtas na maipasa ang mga koneksyon sa database, pagkakakilanlan ng user (user identity), at mga API client papasok sa Agent at sa mga tool:
python
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext
@dataclass
class Deps:
user_id: int
db: object # Ang koneksyon mo sa database
agent = Agent('anthropic:claude-sonnet-4-6', deps_type=Deps)
@agent.tool
def get_orders(ctx: RunContext[Deps]) -> str:
return f'Kunin ang mga order para sa user {ctx.deps.user_id}'
Kapag nagsusulat ng mga pagsubok (tests), palitan lamang ang db ng isang mock object nang hindi na kinakailangang galawin ang tunay na database. Napakahalaga nito para sa pagsulat ng unit tests.
Streaming: Upang lumikha ng real-time typing effect, gamitin ang agent.run_stream(). Habang ginagawa nito ang structured output, bina-validate na rin ito nang paunti-unti, kaya mas maganda ang karanasan ng user.
Observability: Maayos na na-integrate ang Pydantic AI sa Logfire mula sa parehong koponan. Kapag naikonekta na ito, ang bawat tawag sa modelo, bawat pag-trigger ng tool, ang dami ng nagamit na tokens, at ang tagal sa segundo ay makikita lahat. Ang pinakamahirap i-debug sa mga LLM application ay kung "bakit ganoon mag-isip ang modelo." Dahil dito, hindi mo na kailangang manghula nang walang katiyakan. Kung gusto mong mas maging kumpleto ang pagpaplano ng iyong Agent, maaari mo itong basahin kasama ng ating Agent Development Guide.
Mga Karaniwang Pagkakamali at Pag-iingat
- Pag-aakalang 100% ligtas na ito dahil lang naglagay ka ng output_type: Susubukan ng framework na piliting ulitin ng modelo ang paggawa kapag nabigo ang validation, ngunit may limitasyon ang mga pagsubok na ito. Kapag patuloy itong nabigo, maglalabas ito ng exception, kaya kailangan mo pa rin ng try/except. Ang binabawasan ng type validation ay ang pagpasok ng "maruming data" sa sistema, hindi ang pagiging perpekto ng modelo.
- Pabigat-bigat na docstring sa mga tool: Umaasa nang lubusan ang modelo sa docstring para malaman kung kailan dapat tawagin ang tool. Kung malabo ang pagkakasulat, tatawagin ito ng modelo nang hindi tama o hindi na lang tatawagin. Ituring ito bilang isang manwal ng paggamit na isinulat para sa modelo.
- Paglalagay ng sobrang dami ng lohika sa tool nang walang pag-handle ng mga exception: Kung may maganap na error sa code sa loob ng tool, ibabalik ang mensahe sa modelo, at maaaring umikot nang paulit-ulit ang modelo sa error na iyon habang sinusunog ang napakaraming tokens. I-handle mo nang maayos ang mga exception na kailangang harangin.
- Pag-ignore sa gastusin: Ang pag-ulit sa structured output at ang maramihang pag-tawag sa tool ay mas mabilis kumain ng tokens kaysa sa iniisip mo. Siguraduhing ikonekta ang observability bago i-deploy upang malinaw na makita ang aktwal na gastos.
- Paggamit nito bilang isang malaking framework: Sadyang ginawa itong magaan. Kung kailangan mo ng komplikadong multi-step orchestration at tambak na ready-made connectors, malamang na mas madali ang LlamaIndex o iba pang solusyon, kaya huwag itong pilitin.
Puna ng TheAI Academy
Sa totoo lang, napakaraming framework ng Agent sa merkado kaya nakakalito kung alin ang pipiliin, ngunit ang solusyon ng Pydantic AI ay nakatutok sa isang napakaesipipikong sakit na naranasan na ng bawat LLM developer: ang hindi maaasahang output. Hindi nito sinusubukang maging ang "pinakamakapangyarihang framework sa sansinukob"—dinadala lamang nito nang malinis ang "type safety," isang bagay na pinahahalagahan na noon pa man ng komunidad ng Python, patungo sa pagbuo ng AI. Para sa mga sanay na sa istilo ng pagsulat ng FastAPI at Pydantic, halos walang learning curve ito.
Hindi nito gagawing mas matalino ang iyong modelo, ngunit gagawin nitong mas maaasahan ang iyong code—at ang huli ang talagang magliligtas sa iyo kapag naka-live na ito sa production.
Kung gagawa ka lang ng demo para subukan ito, maaaring hindi mo masyadong maramdaman ang halaga nito; ngunit hangga't ang iyong proyekto ay ilalagay sa totoong production, gagamitin ng mga tao, at kailangang i-maintain sa mahabang panahon, ang halaga ng type safety at observability ay magiging mas malinaw araw-araw.
Mga Pinagmulan ng Datos
Mga Madalas Itanong
Ano ang pagkakaiba ng Pydantic AI at LangChain, alin ang dapat piliin?
Ang pinakamalaking pagkakaiba ay ang "bigat". Ang LangChain ay isang malaking ecosystem na may maraming connectors, integrations, at abstraction layers, na angkop para sa mga malalaking proyektong nangangailangan ng komplikadong orchestration, ngunit matarik ang learning curve. Sadyang ginawang manipis ang Pydantic AI; ang core nito ay binubuo lamang ng Agent, tools, dependency injection, at structured output, at naka-focus sa type safety. Kung ang pangangailangan mo ay "gawing maaasahan ang output ng modelo at natural ang pagsulat sa Python", mas mabilis matutunan ang Pydantic AI; kung kailangan mo ng maraming ready-made integrations, mas madali ang LangChain. Hindi sila nagkakasalungatan, piliin mo lang depende sa laki ng proyekto.
Kailangan bang gumamit ng OpenAI model? Pwede bang gumamit ng local model?
Hindi. Model-agnostic ang Pydantic AI; sinusuportahan nito ang mahigit sampung provider gaya ng OpenAI, Anthropic, Google, Groq, Mistral, Cohere, at Ollama, at ang pagpapalit ng modelo ay karaniwang nangangailangan lang ng pag-edit ng string sa pagbuo ng Agent. Para mag-run ng local model, pwede mong gamitin ang Ollama sa pamamagitan ng pagturo ng model string sa local service, at hindi na kailangang baguhin ang iba pang bahagi ng code.
Talaga bang masisiguro ng structured output na hindi magkakamali ang modelo sa pagsagot?
Hindi nito masisiguro na hindi magkakamali ang modelo mismo, ngunit masisiguro nitong "ang data na hindi sumusunod sa tinukoy mong type ay hindi lulusot sa sistema". Kapag ang isinagot ng modelo ay hindi pumasa sa Pydantic validation, awtomatikong ibabalik ng framework ang error message para humingi ng retry. Gayunpaman, may limitasyon ang bilang ng retry, at ang patuloy na pagkabigo ay magdudulot ng exception, kaya kailangan mo pa ring gumamit ng try/except para sa pinakamasamang sitwasyon. Ang binabawasan nito ay ang panganib ng maruming data, hindi ang problema sa katalinuhan ng modelo.
Mahirap bang matuto nito para sa mga baguhan na hindi pa nakapagsulat ng Pydantic?
Kung alam mo ang basic Python at type hints, hindi mataas ang pinto ng pagpasok. Ang core ng Pydantic ay ang "pagtukoy kung ano ang hitsura ng data gamit ang class", at napaka-intuitive ng pagsulat. Inirerekomenda na gumugol ng sampung minuto para tingnan kung paano tukuyin ang BaseModel sa Pydantic bago bumalik sa pagsulat ng Agent, mas magiging madali ito. Ang tunay na hadlang sa konsepto ay ang paraan ng pagdidisenyo ng Agent at mga tool, na maaari mong pag-aralan kasama ang aming gabay sa pagbuo ng Agent.