Guide · 使用教程
PydanticAI 教程:结构化输出与工具人工审批
从类型化工单建议到待审批写入工具,逐步验证输出、权限、故障恢复与费用。
这篇教程做一个可审计的客服工单 Agent:模型先返回经过 Pydantic 校验的结构化建议,只读工具可以自动查询,任何写入或退款动作必须等待人批准。示例以虚构数据为基础,目标是验收边界,不是让模型直接处理真实订单。
1. 安装并隔离密钥
官方安装文档要求 Python 3.10 及以上。可用 pip install pydantic-ai,或仅安装所需供应商 extra 的 pydantic-ai-slim。在开发环境设置所选模型供应商的 API Key,不把它放进源代码、日志或截图。模型名、支持的工具调用和结构化输出方式,应按该供应商当前文档核对。
2. 定义业务上可检查的输出
先定义一个工单建议对象,限制类别、严重度和说明长度。示意代码如下,实际模型名请换成已开通的型号:
from typing import Literal
from pydantic import BaseModel, Field
from pydantic_ai import Agent
class TicketAdvice(BaseModel):
category: Literal['billing', 'technical', 'other']
priority: int = Field(ge=1, le=5)
summary: str = Field(min_length=8, max_length=300)
needs_human: bool
agent = Agent('openai:YOUR_MODEL', output_type=TicketAdvice)
result = agent.run_sync('客户说:本月被扣了两次费用,请给出工单建议。')
print(result.output)
检查 result.output 是否为 TicketAdvice,并用一组固定样本统计字段验证失败率、重试次数和事实错误。Pydantic 只知道类型和你写的校验规则,不知道客户是否真的被重复扣款;账单事实必须由只读订单服务提供。
3. 把查询与写入工具分开
只读查询工具只接收经过认证的用户和订单标识,服务端再次校验租户归属。退款、发邮件等写入工具必须单独定义,并给高影响操作添加 requires_approval=True 或按参数触发 ApprovalRequired。官方的延迟工具流程会返回 DeferredToolRequests,其中有待执行工具的名称、参数和 call ID。界面要把真实操作内容展示给有权限的人,禁止用一句“批准所有”替代具体审核。
from pydantic_ai import Agent, DeferredToolRequests
approval_agent = Agent(
'openai:YOUR_MODEL',
output_type=[TicketAdvice, DeferredToolRequests],
)
@approval_agent.tool_plain(requires_approval=True)
def issue_refund(order_id: str, amount_cents: int) -> str:
# 实际业务中必须在这里再次校验身份、租户、金额、订单状态和幂等键。
return f'模拟退款申请:{order_id},{amount_cents} 分'
示例函数只返回文本,没有真实退款。若运行结果包含 DeferredToolRequests,保存完整消息历史,向有权限的操作员展示每个 tool_call_id 与参数;收到明确决定后,将对应批准/拒绝写进 DeferredToolResults.approvals,并把原消息历史与结果传给下一次 agent.run_sync(..., message_history=..., deferred_tool_results=...)。不要把前端传回的批准布尔值当作最终授权:官方文档明确提醒适配器端点可能接受客户端提交的批准,工具函数内部仍要执行服务端权限检查。完整官方示例。
4. 做四组失败测试
第一组让模型输出不合 schema,检查重试和最终错误;第二组让用户拒绝退款,确认工具没有执行;第三组伪造别的用户或租户的订单,确认服务端拒绝;第四组让写入成功但回执丢失,确认稳定幂等键阻止重复副作用。再模拟模型 429、审批等待和进程重启。需要跨进程恢复时按官方持久化与 durable execution 文档配置后端,不能只依赖当前 Python 进程里的对象。
5. 记录成本和隐私
统计每个成功工单的模型请求数、校验重试、人工处理时间和运行环境费用。核心框架采用 MIT 许可,但模型 API 费用另算;若启用 Logfire,还要检查日志是否包含客户原话、订单标识、工具参数,以及所选套餐的记录量和保留期。先用虚构数据验收脱敏,再导入真实业务流量。
资料:安装、结构化输出、延迟工具与审批、持久化、Logfire 定价。
常见问题
- PydanticAI 的 output_type 做什么?
- 它让最终结果进入定义好的 Pydantic 类型验证;字段通过不代表事实正确。
- 为什么写入工具要设置 requires_approval=True?
- 这会让工具调用先进入待批准流程,方便人看到操作及参数后决定是否执行。
- 前端传回的批准是否足够安全?
- 不够。官方文档强调适配器端点可能接受客户端提交的批准,工具函数内部仍要做服务端身份和权限检查。
- 审批被拒绝后如何继续?
- 把对应 tool_call_id 的拒绝结果写入 DeferredToolResults,并连同原消息历史传给下一次 agent.run。
- 能把真实退款 API 直接放进示例吗?
- 应先用无副作用模拟工具验收;正式写入还需租户、金额、订单状态、幂等和审计控制。
- PydanticAI 框架免费是否意味着整个流程免费?
- 不是。模型 token、部署环境、数据库和可选的 Logfire/网关服务均可能产生费用。