Pydantic AI:用类型安全与依赖注入构建生产级AI Agent
1. 项目概述当Pydantic遇见AI Agent如果你和我一样在过去一两年里折腾过各种AI Agent框架从LangChain到LlamaIndex再到CrewAI那你大概率经历过这样的场景为了接入一个模型你得写一堆胶水代码想给Agent加个工具得研究半天复杂的装饰器最头疼的是代码跑起来看着没问题但一上线就各种类型错误、运行时异常调试起来像在迷宫里找出口。我们总在期待一个框架能像FastAPI定义Web服务那样用清晰、直观、符合直觉的方式来定义AI Agent。现在这个期待可能被填上了——Pydantic AI来了。简单说Pydantic AI是一个用Python构建生产级GenAI应用和智能体工作流的框架。它的核心口号是“The Pydantic way”这可不是随便说说的。Pydantic团队在Python生态里是什么地位数据验证的绝对标杆。OpenAI SDK、Google AI SDK、Anthropic SDK、LangChain……这些你耳熟能详的库底层的数据验证层都是Pydantic。所以当这个团队决定亲自下场做AI Agent框架时他们带来的不是又一个“跟风者”而是一个从基因里就带着类型安全、开发者体验至上、生产就绪理念的解决方案。我花了一周时间深度试用了Pydantic AI从最简单的“Hello World”到构建一个具备工具调用、依赖注入、结构化输出的复杂客服Agent。我的整体感受是它确实把那种“FastAPI式”的愉悦感带到了AI开发中。你不用再和复杂的抽象层搏斗而是可以专注于定义“你的Agent是什么”、“它需要什么”、“它应该输出什么”。接下来我就结合自己的实操带你拆解这个框架的核心设计、上手步骤以及那些官方文档里不会明说但实际开发中能让你少踩80%坑的细节。2. 核心设计哲学为什么是“Pydantic Way”在深入代码之前我们必须先理解Pydantic AI的设计哲学。这决定了你用它时的思维模式也解释了它为什么在很多地方显得“不一样”。2.1 类型安全不是可选项是基础设施大多数AI框架把类型提示Type Hints当作“锦上添花”的文档。但在Pydantic AI里类型是框架运转的基石。你的Agent、它的依赖Dependencies、工具Tools的参数和返回值、以及最终的输出Output全部通过Pydantic模型和Python类型注解来定义。这意味着什么首先错误从运行时提前到了编写时。如果你的工具函数期望一个int类型的customer_id但你传了个字符串你的IDE比如VSCode或PyCharm会在你写代码的时候就用红色波浪线提醒你而不是等到程序运行到一半才抛出一个晦涩的ValidationError。这种体验有点像写Rust代码时的“如果编译通过基本就能运行”。其次它带来了无与伦比的开发体验和可维护性。当你定义一个返回SupportOutput模型的Agent时在整个代码链路中result.output的属性都是可被IDE自动补全和类型检查的。这对于构建复杂、多人协作的AI应用至关重要大大降低了心智负担。2.2 依赖注入让Agent变得可测试、可组合这是Pydantic AI让我拍案叫绝的设计。传统的Agent框架里工具函数经常需要访问数据库连接、用户会话、配置信息等“上下文”。常见的做法是使用全局变量、或者通过复杂闭包来传递导致代码耦合度高难以单独测试。Pydantic AI引入了明确的依赖注入Dependency Injection系统。你定义一个DepsType比如一个dataclass或Pydantic模型里面包含Agent运行所需的所有外部资源。然后在工具函数或动态指令中通过RunContext[DepsType]参数来安全地访问这些依赖。这样做有几个巨大优势关注点分离Agent的逻辑LLM交互、工具调用和外部资源管理数据库、API客户端被清晰地分开。易于测试你可以轻松地为测试创建一个DepsType的模拟Mock实例注入假数据或模拟服务从而对Agent的逻辑进行单元测试而不需要启动整个数据库或调用真实的外部API。可配置性根据运行环境开发、测试、生产你可以注入不同的依赖实例比如使用内存数据库还是云数据库。2.3 一切皆可组合Capability模式很多框架提供了丰富的功能但它们是“硬编码”进去的。Pydantic AI提出了“Capability”能力的概念。一个Capability是一个可复用的单元它打包了一组相关的工具Tools、钩子Hooks、指令Instructions和模型设置。例如框架内置了WebSearch和Thinking这两个Capability。你只需要在创建Agent时将capabilities[Thinking(), WebSearch()]作为参数传入你的Agent就立刻拥有了联网搜索和“链式思考”CoT的能力。这比手动去配置搜索API的密钥、设计提示词要优雅和高效得多。更重要的是这种设计是面向生态的。你可以构建自己的Capability比如一个专门与内部CRM系统交互的能力包或者安装社区发布的第三方Capability。这意味着功能的复用和共享变得极其简单避免了重复造轮子。3. 从零到一构建你的第一个生产级Agent理论说再多不如动手写一行代码。我们用一个贴近实际的场景来演示构建一个“智能天气旅行顾问”Agent。这个Agent能根据用户提供的城市和日期查询天气并结合一些简单的规则比如下雨天建议带伞高温天建议去室内场所给出旅行建议。我们会逐步加入工具、依赖注入和结构化输出。3.1 环境准备与安装首先确保你的Python版本在3.10以上。然后安装pydantic-ai。我强烈建议使用虚拟环境。# 创建并激活虚拟环境以venv为例 python -m venv .venv source .venv/bin/activate # Linux/macOS # .venv\Scripts\activate # Windows # 安装pydantic-ai pip install pydantic-ai注意安装过程可能会同时安装pydantic和httpx等依赖。由于Pydantic AI深度集成Pydantic请确保你安装的Pydantic版本是兼容的通常最新版即可。如果你项目中已有Pydantic注意版本冲突。接下来你需要一个LLM的API密钥。Pydantic AI是模型无关的这里我们以OpenAI为例。去OpenAI平台创建一个API Key。# 将你的API Key设置为环境变量更安全的方式 export OPENAI_API_KEYsk-... # Linux/macOS # set OPENAI_API_KEYsk-... # Windows CMD # $env:OPENAI_API_KEYsk-... # Windows PowerShell3.2 定义核心数据模型Pydantic的用武之地在Pydantic AI里先定义模型再写逻辑是一个好习惯。这能帮你理清思路。from pydantic import BaseModel, Field from datetime import date from enum import Enum # 定义一个枚举表示天气状况 class WeatherCondition(str, Enum): SUNNY sunny CLOUDY cloudy RAINY rainy SNOWY snowy STORMY stormy # 定义工具函数的返回模型天气查询结果 class WeatherData(BaseModel): city: str date: date condition: WeatherCondition temperature_high: float Field(description最高温度摄氏度) temperature_low: float Field(description最低温度摄氏度) humidity: int Field(description湿度百分比, ge0, le100) precipitation_prob: int Field(description降水概率百分比, ge0, le100) # 定义Agent的最终输出模型旅行建议 class TravelAdvice(BaseModel): summary: str Field(description对天气的简要总结和总体建议) clothing: str Field(description着装建议) activity_suggestion: str Field(description活动建议) risk_level: int Field(description出行风险等级1-10, ge1, le10) need_umbrella: bool Field(description是否需要带伞) need_sunscreen: bool Field(description是否需要涂防晒霜)为什么要把WeatherCondition定义成Enum因为枚举类型能为LLM提供清晰、有限的选项减少它“胡编乱造”的可能性。Field描述符不仅用于文档在有些模型如OpenAI的JSON模式下这些描述会传递给LLM帮助它更好地理解字段含义。ge和le是Pydantic的验证器确保数据在合理范围内。3.3 创建Agent并添加工具现在创建Agent并为其添加一个“查询天气”的工具。这里我们先模拟一个工具函数实际应用中你会在这里调用真实的天气API如OpenWeatherMap。from pydantic_ai import Agent, RunContext from typing import Any # 首先定义Agent的依赖类型。这里我们先留空用一个简单的字典后续再扩展。 from typing import Dict DepsType Dict[str, Any] # 临时使用后续会替换为更具体的类型 # 创建Agent实例 weather_agent Agent( modelopenai:gpt-4o, # 使用OpenAI的gpt-4o模型 deps_typeDepsType, output_typeTravelAdvice, # 指定Agent输出必须符合TravelAdvice模型 instructions( 你是一个专业的旅行天气顾问。根据用户提供的城市和日期查询天气信息并给出详细、贴心的旅行建议。 建议需考虑温度、湿度、降水概率和天气状况。请确保建议具体、实用。 风险等级根据极端天气暴雨、暴雪、高温等的可能性来评估。 ), ) # 注册一个工具模拟查询天气 weather_agent.tool async def get_weather(ctx: RunContext[DepsType], city: str, target_date: date) - WeatherData: 根据城市和日期查询天气信息。 Args: city: 要查询的城市名称例如“北京”、“New York”。 target_date: 要查询的日期。 Returns: 包含详细天气数据的WeatherData对象。 # 模拟数据 - 实际项目中这里应调用天气API # 注意为了演示我们根据城市名简单生成一些“假数据” print(f[工具调用] 模拟查询 {city} 在 {target_date} 的天气) # 一个简单的模拟逻辑 import random condition random.choice(list(WeatherCondition)) temp_high round(random.uniform(15, 35), 1) temp_low round(temp_high - random.uniform(5, 15), 1) humidity random.randint(30, 90) precip_prob 80 if condition in [WeatherCondition.RAINY, WeatherCondition.SNOWY, WeatherCondition.STORMY] else random.randint(0, 30) return WeatherData( citycity, datetarget_date, conditioncondition, temperature_hightemp_high, temperature_lowtemp_low, humidityhumidity, precipitation_probprecip_prob )几点关键解释agent.tool装饰器这是注册工具的标准方式。被装饰的异步函数会自动暴露给LLM。函数文档字符串Docstring极其重要LLM依靠函数的文档字符串来理解这个工具是做什么的、参数是什么意思。务必清晰、准确地描述。Pydantic AI会自动解析docstring将其作为工具描述和参数描述发送给LLM。参数类型city: str和target_date: date。Pydantic AI会利用这些类型信息为LLM生成一个JSON Schema指导LLM如何调用这个工具。date类型会被正确地处理。返回值类型- WeatherData。这确保了工具返回的数据结构是明确的也方便框架进行后续处理。3.4 运行Agent并查看结果现在让我们运行这个初步的Agent。import asyncio from datetime import date, timedelta async def main(): # 准备依赖目前是空字典 deps {} # 运行Agent tomorrow date.today() timedelta(days1) result await weather_agent.run( f我明天想去上海天气怎么样有什么建议吗今天是{tomorrow}。, depsdeps ) print( Agent运行结果 ) print(f最终输出: {result.output}) print(f使用的消息数: {len(result.all_messages())}) print(f工具调用历史:) for msg in result.all_messages(): if msg.kind tool-call or msg.kind tool-result: print(f - {msg.kind}: {msg.content}) # 运行异步主函数 if __name__ __main__: asyncio.run(main())运行这段代码你会看到类似以下的输出由于天气数据是随机的每次运行结果会不同[工具调用] 模拟查询 上海 在 2024-05-27 的天气 Agent运行结果 最终输出: summary上海明天天气晴朗最高气温28.5°C最低气温18.3°C湿度65%降水概率10%。 clothing建议穿着轻薄透气的衣物如短袖T恤、衬衫搭配薄外套或长裤早晚温差较大注意增减衣物。 activity_suggestion非常适合户外活动如城市观光、公园散步或滨江骑行。 risk_level2 need_umbrellaFalse need_sunscreenTrue 使用的消息数: 5 工具调用历史: - tool-call: {name: get_weather, arguments: {city: 上海, target_date: 2024-05-27}} - tool-result: {city: 上海, date: 2024-05-27, condition: sunny, temperature_high: 28.5, temperature_low: 18.3, humidity: 65, precipitation_prob: 10}发生了什么Agent收到了用户关于上海明天天气的询问。LLM识别出需要调用get_weather工具来获取信息。框架执行了工具函数获得了结构化的WeatherData。LLM根据工具返回的天气数据结合你的指令“给出详细、贴心的旅行建议”生成了最终的回复。最关键的一步框架将LLM的回复按照TravelAdvice模型的格式进行验证和解析。如果LLM返回的JSON不符合TravelAdvice的格式比如缺少字段、类型不对框架会自动要求LLM重试直到得到一个有效的输出。这就是结构化输出的威力。3.5 引入依赖注入让Agent更“智能”上面的Agent能工作但工具里的模拟数据太假了。让我们引入真实的依赖一个天气API客户端。同时我们可能还想根据用户的历史偏好来微调建议。from dataclasses import dataclass from pydantic_ai import Agent, RunContext import httpx from typing import Optional # 1. 定义更具体的依赖类型 dataclass class TravelDependencies: weather_client: httpx.AsyncClient # 用于调用真实天气API的HTTP客户端 user_preference: Optional[dict] None # 可选的用户偏好例如“讨厌下雨”、“喜欢户外” # 2. 更新Agent使用新的依赖类型 weather_agent_v2 Agent( modelopenai:gpt-4o, deps_typeTravelDependencies, # 关键变更指定依赖类型 output_typeTravelAdvice, instructions( 你是一个专业的旅行天气顾问。根据用户提供的城市和日期查询天气信息并给出详细、贴心的旅行建议。 建议需考虑温度、湿度、降水概率和天气状况。请确保建议具体、实用。 如果用户有已知偏好如讨厌下雨请在建议中予以考虑。 风险等级根据极端天气暴雨、暴雪、高温等的可能性来评估。 ), ) # 3. 更新工具函数使用注入的依赖 weather_agent_v2.tool async def get_weather_real(ctx: RunContext[TravelDependencies], city: str, target_date: date) - WeatherData: 根据城市和日期调用真实天气API查询天气信息。 Args: city: 要查询的城市名称。 target_date: 要查询的日期。 Returns: 包含详细天气数据的WeatherData对象。 # 注意这里使用了 ctx.deps.weather_client # 实际API调用代码这里以OpenWeatherMap为例需要注册获取API Key api_key YOUR_OPENWEATHER_API_KEY # 应从环境变量或配置中读取 # 构建请求URL (示例请参考OpenWeatherMap API文档) # url fhttps://api.openweathermap.org/data/2.5/forecast?q{city}appid{api_key}unitsmetric # 为了演示我们仍然模拟但展示了如何使用依赖 print(f[工具调用] 使用注入的client查询 {city} 的天气。用户偏好: {ctx.deps.user_preference}) # 模拟API调用延迟 import asyncio await asyncio.sleep(0.5) # 更“真实”的模拟可以考虑用户偏好来调整模拟结果仅演示逻辑 condition WeatherCondition.SUNNY if ctx.deps.user_preference and ctx.deps.user_preference.get(hates_rain): # 如果用户讨厌下雨我们“模拟”一个晴天结果实际API不会这样 print( - 检测到用户讨厌下雨模拟返回晴天数据。) import random return WeatherData( citycity, datetarget_date, conditioncondition, temperature_highround(random.uniform(20, 30), 1), temperature_lowround(random.uniform(10, 20), 1), humidityrandom.randint(40, 70), precipitation_prob10 if condition WeatherCondition.SUNNY else 60 ) # 4. 还可以添加动态指令根据依赖生成不同的系统提示 weather_agent_v2.instructions async def add_user_preference_context(ctx: RunContext[TravelDependencies]) - str: 根据用户偏好动态添加指令。 if not ctx.deps.user_preference: return prefs [] if ctx.deps.user_preference.get(hates_rain): prefs.append(该用户非常讨厌下雨天请在建议中强烈避免推荐雨天户外活动并强调防雨措施。) if ctx.deps.user_preference.get(likes_outdoor): prefs.append(该用户喜爱户外活动在天气允许的情况下优先推荐户外项目。) if prefs: return 用户已知偏好\n \n.join(prefs) return 现在运行这个升级版的Agentasync def main_v2(): # 创建真实的HTTP客户端这里仍用于模拟 async with httpx.AsyncClient() as client: # 构造依赖注入真实客户端和用户偏好 deps TravelDependencies( weather_clientclient, user_preference{hates_rain: True, likes_outdoor: True} ) result await weather_agent_v2.run( 我下周去杭州玩天气如何给点建议。, depsdeps ) print( 升级版Agent运行结果 ) print(result.output.json(indent2)) # 以格式化的JSON输出 asyncio.run(main_v2())依赖注入带来的好处可测试性在单元测试中你可以创建一个TravelDependencies的模拟对象其中weather_client是一个Mock对象返回预设的天气数据从而在不调用真实API的情况下测试Agent的逻辑。灵活性在生产环境和开发环境你可以注入不同的httpx.AsyncClient实例比如配置不同的超时、重试策略。上下文感知Agent现在能根据user_preference动态调整其行为这是通过agent.instructions装饰器实现的动态指令。这使得Agent的提示词不再是静态的而是可以根据运行时上下文进行定制。4. 高级特性与生产实践基础功能跑通后我们来看看Pydantic AI那些能让你的应用真正达到“生产级”的特性。4.1 可观测性Observability与Logfire集成AI应用的黑盒特性是生产部署的主要挑战之一。你不知道Agent内部做了什么决策、调用了哪些工具、花了多少钱、哪里出了错。Pydantic AI原生集成了Pydantic Logfire这是一个基于OpenTelemetry的可观测性平台。# 首先安装logfire # pip install logfire import logfire from pydantic_ai import Agent # 1. 配置Logfire需要从Logfire网站获取token logfire.configure(tokenyour-logfire-token) # 通常从环境变量读取 logfire.instrument_pydantic_ai() # 关键的一行自动注入遥测 # 2. 像往常一样创建和使用Agent agent Agent(openai:gpt-4o, instructions...) # ... 添加工具等 # 3. 运行Agent。所有交互LLM调用、工具调用、耗时、token消耗都会被自动记录。 result await agent.run(...)完成这些后打开Logfire控制台你会看到一个清晰的追踪Trace视图。它展示了整个Agent运行的流水线接收用户消息、LLM思考、工具调用包括输入参数和返回值、LLM再次思考、生成最终输出。每个步骤的耗时、Token使用量、成本如果配置了都一目了然。这对于调试复杂的工作流、监控性能、进行成本分析以及评估Evals至关重要。如果某个工具调用频繁失败或者某个提示词导致LLM陷入了长循环你都能快速定位。4.2 流式输出Streaming与实时体验对于需要长时间运行或希望提供实时反馈的Agent流式输出是必备功能。Pydantic AI的流式输出不仅支持文本流还支持结构化数据的流式验证。import asyncio from pydantic_ai import Agent from pydantic import BaseModel, Field class StreamedOutput(BaseModel): items: list[str] Field(description生成的条目列表) summary: str Field(description最终总结) agent Agent(openai:gpt-4o, output_typeStreamedOutput) async def main_stream(): prompt 列举5种适合在办公室养的盆栽植物并简要总结它们的共同优点。 # 使用 run_stream 而不是 run async with agent.run_stream(prompt) as result_stream: async for chunk in result_stream: # chunk 可以是多种类型 if chunk.kind output: # 结构化输出流output模型的部分字段可能已经生成并验证 print(f[结构化输出更新] {chunk.data}) elif chunk.kind content: # 原始文本内容流如果模型支持 print(f[文本流] {chunk.text}, end, flushTrue) elif chunk.kind tool-call: print(f[工具调用] {chunk.name}) elif chunk.kind tool-result: print(f[工具结果] {chunk.result}) # 流结束后可以获取完整的结果对象 final_result result_stream.result() print(f\n最终完整输出: {final_result.output}) asyncio.run(main_stream())run_stream返回一个异步上下文管理器它产生一个事件流。你可以在LLM生成内容的同时就收到部分输出content更重要的是一旦LLM开始生成结构化的JSON并满足StreamedOutput模型的部分验证output事件就会触发。这意味着你可以在最终结果完全生成之前就开始处理已验证的部分数据极大地提升了响应速度和应用体验。4.3 持久化执行Durable Execution与可靠性对于长时间运行、涉及多步工具调用或需要人工审批Human-in-the-loop的Agent进程崩溃或网络抖动会导致整个工作流失败需要重头再来。Pydantic AI的持久化执行功能就是为了解决这个问题。其核心思想是将Agent的运行状态对话历史、工具调用上下文、中间结果自动保存到外部存储如数据库、Redis。当执行中断后可以从断点恢复而不是重新开始。from pydantic_ai import Agent from pydantic_ai.durable_execution import DurableExecution, InMemoryDurableExecutionBackend # 1. 选择一个后端存储这里用内存后端演示生产环境需用数据库后端 backend InMemoryDurableExecutionBackend() durable_exec DurableExecution(backendbackend) # 2. 在创建Agent时启用持久化执行 agent Agent( openai:gpt-4o, instructions..., durable_executiondurable_exec, # 关键参数 ) # 3. 运行Agent时提供一个唯一的run_id run_id my_unique_travel_plan_123 try: result await agent.run(为我规划一个为期一周的日本关西旅行详细到每天。, run_idrun_id) except SomeTransientError: # 模拟一个临时错误如网络超时 print(执行中断...) # 一段时间后可以从同一个run_id恢复 recovered_result await agent.run(继续之前的规划。, run_idrun_id) # recovered_result 会从上次中断的地方继续对话历史都在。生产环境中你会使用PostgresDurableExecutionBackend或RedisDurableExecutionBackend。这确保了即使你的应用服务器重启那些运行到一半的、等待用户审批的Agent任务也不会丢失。4.4 评估Evals与性能监控如何知道你的Agent表现得好不好光靠人工测试不行。Pydantic AI内置了评估Evals框架允许你系统化地定义测试用例和评估标准。from pydantic_ai import Agent from pydantic_ai.evals import Eval, EvalResult, run_evals from pydantic import BaseModel class QAPair(BaseModel): question: str expected_keywords: list[str] # 期望回答中包含的关键词 # 定义评估集 eval_dataset [ QAPair(question北京明天天气如何, expected_keywords[北京, 天气, 温度]), QAPair(question下雨天去上海要带什么, expected_keywords[伞, 雨具, 防水]), # ... 更多测试用例 ] # 定义一个评估函数 def contains_keywords_eval(result, qa_pair: QAPair) - EvalResult: 评估Agent的回答是否包含预期关键词。 answer result.output if hasattr(result, output) else result.data score 0 found_keys [] for keyword in qa_pair.expected_keywords: if keyword in answer: score 1 found_keys.append(keyword) return EvalResult( scorescore / len(qa_pair.expected_keywords), # 得分比例 details{found_keywords: found_keys, question: qa_pair.question} ) # 创建要评估的Agent agent_to_eval Agent(openai:gpt-4o, instructions...) # 运行评估 eval_results await run_evals( agentagent_to_eval, dataseteval_dataset, eval_fncontains_keywords_eval, max_concurrency2 # 并发运行评估 ) for res in eval_results: print(f问题: {res.details[question]}) print(f 得分: {res.score:.2%}, 找到的关键词: {res.details[found_keywords]})你可以将评估结果与Logfire集成持续监控Agent在生产环境中的表现。如果某次代码更新导致评估分数下降你能立即收到警报。5. 避坑指南与最佳实践在实际使用Pydantic AI构建了几个项目后我总结了一些关键的经验和容易踩的坑。5.1 工具设计粒度、描述与错误处理1. 工具粒度要适中不要设计一个“巨无霸”工具比如plan_entire_trip(city, dates, budget, interests...)。这会让LLM难以正确使用且工具内部逻辑过于复杂。应该拆分成小工具get_attractions(city),check_weather(city, date),book_hotel(name, dates)。每个工具职责单一。2. 文档字符串是给LLM看的“API文档”务必详细、准确。使用Args:和Returns:部分。LLM对参数描述非常敏感。好的描述能极大提升工具调用的准确率。agent.tool async def search_flights( ctx: RunContext[DepsType], origin: str Field(description出发城市机场代码如PEK), destination: str Field(description到达城市机场代码如SHA), date: date Field(description出发日期格式YYYY-MM-DD), max_price: Optional[float] Field(None, description最高可接受价格人民币) ) - List[FlightInfo]: 根据条件搜索航班信息。 Args: origin: 出发地机场IATA三字码。 destination: 目的地机场IATA三字码。 date: 出发日期。 max_price: 可选价格过滤器。 Returns: 一个航班信息列表按价格从低到高排序。如果没有符合的航班返回空列表。 # ... 实现3. 工具内部必须有坚实的错误处理LLM调用工具时参数可能不合法比如不存在的城市代码。工具函数内部应该进行验证并抛出清晰的异常。Pydantic AI会捕获这些异常将其信息反馈给LLM让LLM有机会调整参数后重试。agent.tool async def get_city_code(ctx: RunContext[DepsType], city_name: str) - str: 根据城市名获取机场IATA代码。 code await ctx.deps.db.get_city_code(city_name) if not code: # 抛出清晰的错误LLM会看到这个信息 raise ValueError(f未找到城市 {city_name} 对应的机场代码。请提供更准确的城市名或检查拼写。) return code5.2 指令Instructions设计静态与动态结合静态指令创建Agent时传入的instructions参数用于定义Agent的固定角色和基础行为准则。动态指令通过agent.instructions装饰器用于注入运行时才能知道的信息比如用户信息、会话上下文、实时数据。这是实现个性化Agent的关键。agent.instructions async def inject_conversation_history(ctx: RunContext[DepsType]) - str: 将会话历史摘要注入指令。 history await ctx.deps.message_store.get_recent_messages(ctx.deps.user_id, limit5) if not history: return summary \n.join([fUser: {m.user} | Assistant: {m.assistant[:50]}... for m in history]) return f最近的对话历史摘要\n{summary}\n请参考以上历史进行回复保持连贯性。避免指令冲突静态指令和动态指令是合并的。确保它们不会互相矛盾。通常静态指令定义“是什么”角色动态指令定义“当前上下文”情境。5.3 模型选择与成本控制Pydantic AI支持众多模型但不同模型在工具调用、JSON模式遵循、成本方面差异巨大。复杂工具调用/结构化输出优先选择对工具调用和JSON模式支持最好的模型如OpenAI的gpt-4o/gpt-4-turbo、Anthropic的claude-3-5-sonnet。虽然贵但成功率高节省调试时间。简单任务/原型验证可以使用更便宜或开源的模型如gemini-flash、claude-haiku或者通过Ollama运行的本地模型如llama3.2。但需要测试其对工具调用的支持度。设置预算和超时在生产中务必在Agent或运行调用时设置max_messages最大交互轮次和timeout防止LLM陷入死循环或产生过高费用。from pydantic_ai.models.openai import OpenAIModel model OpenAIModel( gpt-4o, max_retries2, timeout30.0, ) agent Agent(modelmodel, ...) # 或者在运行时控制 result await agent.run( prompt, depsdeps, max_messages20, # 最多20轮消息交换包括工具调用 )5.4 调试与问题排查当Agent行为不符合预期时按以下步骤排查启用Logfire这是第一选择。查看Trace确认LLM收到了正确的消息、工具调用参数是否正确、工具返回了什么。检查工具描述LLM是否误解了工具功能简化描述确保每个参数的意义明确。简化测试用一个最简单的提示词和单一工具测试排除复杂指令的干扰。查看原始消息result.all_messages()提供了完整的对话历史包括所有LLM的原始请求和响应。这能帮你理解LLM的“思考过程”。结构化输出失败如果LLM始终无法生成符合output_type的JSON尝试在指令中更明确地要求输出格式“你必须返回一个JSON对象包含summary和risk_level字段...”使用更简单的输出模型或者将某些字段设为Optional。考虑使用支持JSON模式JSON Mode的模型并在模型设置中启用它。6. 总结Pydantic AI的定位与未来经过这一番深度探索Pydantic AI给我的感觉非常明确它不是一个试图囊括所有AI应用场景的“万能框架”而是一个为Python开发者打造的、专注于构建可靠、可维护、类型安全的生产级Agent的工具箱。它的优势在于其坚实的工程基础Pydantic、优秀的设计模式依赖注入、Capability、以及对生产环节的深度思考可观测性、持久化执行、评估。它可能不像一些框架那样有海量的预制“链”或“代理”但它提供了更优雅、更可靠的方式来构建属于你自己的、独一无二的智能体。如果你正在用Python构建需要与外部系统交互、有复杂逻辑、并且最终要部署上线的AI应用Pydantic AI值得你投入时间学习。它带来的类型安全和开发体验提升在项目复杂度增长时会变成巨大的生产力优势。从简单的天气顾问到复杂的多智能体协作系统Pydantic AI提供了一套一致且强大的抽象让你能更专注于业务逻辑而不是框架的复杂性。我个人在后续的项目中会继续深入使用它的Graph功能来编排复杂工作流并探索其与MCPModel Context Protocol的集成为Agent连接更丰富的外部工具和数据源。这个框架的生态还在早期但以其背后的团队和设计理念我相信它会成为Python AI工程化领域的一个重要选择。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2555901.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!