十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

pydantic-ai output 模块深度解析:从 ToolOutput 到 NativeOutput 的 Agent 输出类型体系

pydantic-ai output 模块深度解析:从 ToolOutput 到 NativeOutput 的 Agent 输出类型体系 pydantic-ai output 模块深度解析从 ToolOutput 到 NativeOutput 的 Agent 输出类型体系【免费下载链接】pydantic-aiHow Python does AI. Agents, realtime voice, image generation, embeddings. Every model, every interface, typed end to end.项目地址: https://gitcode.com/GitHub_Trending/py/pydantic-aipydantic_ai.output是 pydantic-ai 中定义 Agent 输出契约的核心模块它决定了一次 Agent 运行run的最终返回内容——是纯文本、结构化数据、图片还是由模型提供参数后调用某个函数的返回值。本篇指南以pydantic_ai.output模块的公开 APIOutputDataT、ToolOutput、NativeOutput、PromptedOutput、TextOutput、StructuredDict、DeferredToolRequests、OutputObjectDefinition为主线结合模块源码与官方使用文档系统讲解每种输出类型的适用场景、参数含义、底层原理与代码示例帮助你在实际项目中精准选择并配置 Agent 的输出方式。阅读本文前建议先了解 Agent 的运行方式 与 结构化输出总览。一、模块总览output_type 与 OutputSpec在 pydantic-ai 中所有输出配置都汇聚到Agent构造函数的output_type参数上其类型为OutputSpec。根据 pydantic_ai_slim/pydantic_ai/output.py 中的定义OutputSpec可以是单个类型如MyModel、int、str单个输出函数或绑定方法类型/函数的序列list用于表达多个候选输出上述内容的任意嵌套组合或上述四种输出模式标记类Marker Class之一的实例ToolOutput、NativeOutput、PromptedOutput、TextOutput。模块还导出了两个辅助类型OutputDataT一个默认值为str的协变 TypeVar描述一次运行输出数据的类型Agent、AgentRunResult与StreamedRunResult均以它为泛型参数从而保证类型信息在结果对象上传递。OutputMode全部输出模式的字面量联合text | tool | native | prompted | tool_or_text | image | auto。其中tool_or_text已废弃不再使用auto表示由模型根据ModelProfile.default_structured_output_mode自动选择结构化输出模式。结构化输出可用的模式是StructuredOutputMode Literal[tool, native, prompted]。输出数据被包裹在运行结果中无论哪种输出类型输出数据都会被包裹在AgentRunResult或StreamedRunResult中以便访问运行的 usage 用量与消息历史。两者都以其包裹的数据为泛型参数因此类型检查器能保留输出数据的类型信息。一次运行在模型返回下列内容之一时结束某个输出类型对应的结构化数据、输出函数调用结果、纯文本当未指定输出类型或str在允许范围内时、图片或DeferredToolRequests当模型调用了延迟工具时。若超出了 Usage Limits 运行也会被取消。最基本的用法——用 Pydantic 模型作为output_type强制模型返回符合规范的字段from pydantic import BaseModel from pydantic_ai import Agent class CityLocation(BaseModel): city: str country: str agent Agent(google:gemini-3-flash-preview, output_typeCityLocation) result agent.run_sync(Where were the olympics held in 2012?) print(result.output) # cityLondon countryUnited Kingdom二、ToolOutput默认的工具调用输出模式ToolOutput是一个标记类用于使用一个工具来产出输出并可选地定制该工具。它是 pydantic-ai 的默认结构化输出方式每个输出类型或函数的 JSON Schema 被提供给模型作为某个特殊输出工具的参数 Schema模型通过发起一次工具调用来提交最终结果。这种模式被几乎所有模型支持并被验证在广泛的模型上表现良好。其字段定义如下见 output.py字段类型含义outputOutputTypeOrFunction输出类型或输出函数必填namestr \| None传给模型的工具名。若未指定且只有一个输出使用final_result若有多个输出会在类型/函数名基础上拼接生成工具名descriptionstr \| None传给模型的工具描述。默认取类型或函数的 docstringmax_retriesint \| None该输出工具的单工具重试上限会覆盖 Agent 输出侧重试预算未设置时使用 Agent 级默认值必须 0否则抛出UserErrorstrictbool \| None是否对该工具启用严格模式sequentialbool该输出工具是否必须作为屏障串行执行默认False。仅在end_strategyexhaustive下有意义此时工具本可并行sequentialTrue的输出工具会单独运行等模型先前发出的函数工具执行完毕后它才执行底层实现中见 pydantic_ai_slim/pydantic_ai/_output.pyOutputToolset.build()会为每个输出工具构造ToolDefinition默认工具名为常量DEFAULT_OUTPUT_TOOL_NAME final_result默认描述为The final response which ends this conversation。当存在多个输出且未指定名称时工具名会被清洗后追加类型名如final_result_Fruit重复名称自动加序号去重描述则取object_def.description缺失时使用默认描述。from pydantic import BaseModel from pydantic_ai import Agent, ToolOutput class Fruit(BaseModel): name: str color: str class Vehicle(BaseModel): name: str wheels: int agent Agent( openai:gpt-5.2, output_type[ ToolOutput(Fruit, namereturn_fruit), ToolOutput(Vehicle, namereturn_vehicle), ], ) result agent.run_sync(What is a banana?) print(repr(result.output)) # Fruit(namebanana, coloryellow)注意由于ToolOutput是对象而非类型多个输出必须用 list 传递不能写成Fruit | Vehicle联合。输出工具的重试与动态过滤使用输出工具时每个工具拥有独立的重试计数器Agent 输出侧的重试预算通过Agent(retries{output: N})或agent.run(retries{output: N})设置是所有输出工具的默认单工具上限若想覆盖某个工具可在ToolOutput上直接传max_retries例如ToolOutput(Fruit, max_retries2)。若需要在运行过程中动态修改或过滤可用输出工具可以定义 Agent 级的prepare_output_tools函数类型为ToolsPrepareFunc它在运行的每一步之前被调用接收RunContext与ToolDefinition列表返回该步要暴露的输出工具定义返回[]表示不暴露任何输出工具。这与普通工具的prepare_tools机制类似。三、NativeOutput模型原生的结构化输出NativeOutput标记类用于启用模型的原生 Structured OutputsJSON Schema response format能力模型被强制只输出符合给定 JSON Schema 的文本。注意并非所有模型都支持该能力部分模型还有使用限制例如部分 Gemini 模型不能将 Native Output 与函数工具同时使用因此选择前需确认目标模型的ModelProfile.default_structured_output_mode。from pydantic_ai import Agent, NativeOutput from tool_output import Fruit, Vehicle agent Agent( openai:gpt-5.2, output_typeNativeOutput( [Fruit, Vehicle], nameFruit or vehicle, descriptionReturn a fruit or vehicle. ), ) result agent.run_sync(What is a Ford Explorer?) print(repr(result.output)) # Vehicle(nameFord Explorer, wheels4)字段说明字段类型含义outputs单个输出类型/函数 或 其序列要输出的类型或函数namestr \| None传给模型的结构化输出名默认取类型/函数名descriptionstr \| None描述默认取 docstringstrictbool \| None是否使用严格模式若模型支持templatestr \| Literal[False] \| None传给模型的提示词模板。{schema}占位符会被替换为输出 JSON Schema未指定但模型 profile 表明需要把 Schema 作为提示词发送时使用 profile 上的默认模板设为False则完全禁用 Schema 提示词从源码看NativeOutputSchema继承自StructuredTextOutputSchema其mode属性返回native。StructuredTextOutputSchema.build_instructions()会复制object_def.json_schema注入title/description若模板中没有{schema}占位符则自动追加\n\n{schema}最终用json.dumps(schema)填充模板——这解释了模板的可定制机制。四、PromptedOutput通过指令提示的输出PromptedOutput标记类通过模型的 instructions指令提示模型输出符合 JSON Schema 的文本并尝试解析模型的纯文本响应。它适用于所有模型但通常是最不可靠的方式因为模型并不被强制匹配 Schema。虽然一般建议优先使用 Tool 或 Native 输出但某些场景下该模式可能产出更高质量的结果对于不支持原生工具调用或结构化输出的模型它是产生结构化输出的唯一选择。若模型 API 支持 JSON Mode强制输出合法 JSON该能力会被启用但模型仍需自行遵循 SchemaPydantic AI 会验证返回的结构化数据验证失败时要求模型重试。from pydantic import BaseModel from pydantic_ai import Agent, PromptedOutput from tool_output import Vehicle class Device(BaseModel): name: str kind: str agent Agent( openai:gpt-5.2, output_typePromptedOutput( [Vehicle, Device], nameVehicle or device, descriptionReturn a vehicle or device. ), ) result agent.run_sync(What is a MacBook?) print(repr(result.output)) # Device(nameMacBook, kindlaptop) agent Agent( openai:gpt-5.2, output_typePromptedOutput( [Vehicle, Device], templateGimme some JSON: {schema} ), ) result agent.run_sync(What is a Ford Explorer?) print(repr(result.output)) # Vehicle(nameFord Explorer, wheels4)字段与NativeOutput基本一致outputs、name、description、template区别在于其mode为prompted且template未指定时使用模型 profile 上的prompted_output_template默认模板。五、TextOutput让文本经过一个函数处理TextOutput标记类将输出函数与纯文本输出结合模型以纯文本而非输出工具调用提供字符串该字符串被作为唯一参数传入你提供的函数函数的返回值成为 Agent 运行的最终输出。如果不加TextOutput包装Pydantic AI 默认会为任何输出函数包括接收字符串的创建一个输出工具包装后则改为纯文本路径。from pydantic_ai import Agent, TextOutput def split_into_words(text: str) - list[str]: return text.split() agent Agent( openai:gpt-5.2, output_typeTextOutput(split_into_words), ) result agent.run_sync(Who was Albert Einstein?) print(result.output) # [Albert, Einstein, was, a, German-born, theoretical, physicist.]TextOutput可与一个或多个ToolOutput或未标记的类型/函数同时出现在output_type列表中。与其他输出函数一样文本输出函数可选的第一个参数可以是RunContext并可通过抛出ModelRetry请求模型用修正后的参数或换一种输出类型重试。输出函数的一般规则输出函数与函数工具类似但有三个关键区别模型被强制调用其中之一该调用会结束本次运行函数返回值不会回传给模型。函数参数由 Pydantic 校验可带 validation context支持RunContext作为第一个参数可抛出ModelRetry请求重试。输出函数不支持ToolFailed那是函数工具失败的专用异常在这里ToolFailed被当作普通异常处理可由on_output_process_errorhook 恢复否则中止运行。一个典型的路由 交接示例完整示例见 docs/output.md外层路由 Agent 的输出类型为[hand_off_to_sql_agent, RouterFailure]其中hand_off_to_sql_agent是一个接收RunContext与查询字符串的异步函数它内部把查询转成 SQL 并调用另一个 SQL Agent成功则返回list[Row]失败则抛出ModelRetry让外层模型换一种方式处理。流式场景下的部分输出处理使用run_stream()/run_stream_sync()流式运行时输出函数会被调用多次——每次模型产生部分输出时调用一次最终完整输出时再调用一次。若输出函数有副作用发送通知、写日志、更新数据库等应检查RunContext.partial_output标志流式时部分输出为True、最终输出为False其他运行方法中该标志恒为False。from pydantic import BaseModel from pydantic_ai import Agent, RunContext class DatabaseRecord(BaseModel): name: str value: int | None None # Make optional to allow partial output def save_to_database(ctx: RunContext, record: DatabaseRecord) - DatabaseRecord: Output function with side effect - only save final output to database. if ctx.partial_output: # Skip side effects for partial outputs return record # Only execute side effect for the final output print(fSaving to database: {record.name} {record.value}) return record agent Agent(openai:gpt-5.2, output_typesave_to_database)流式文本与 TextOutput 的注意事项使用stream_text()时不会应用TextOutput包装的函数deltaFalse时它对每个累积文本快照应用输出验证器deltaTrue时直接产出原始文本增量并跳过验证器。要流式获取TextOutput函数产生的结果应改用stream_output()。另外使用.stream_text(deltaTrue)时最终输出消息不会加入结果消息历史。六、StructuredDict附加自定义 JSON Schema 的字典输出当使用BaseModel、dataclass 或TypedDict定义结构化输出不可行时——例如从外部来源拿到 JSON Schema或 Schema 需要动态生成——可以用StructuredDict(json_schema, name, description)函数生成一个带有 JSON Schema 附件的dict[str, Any]子类Pydantic AI 会把这个 Schema 传给模型。from pydantic_ai import Agent, StructuredDict schema { type: object, properties: { name: {type: string}, age: {type: integer} }, required: [name, age] } agent Agent(openai:gpt-5.2, output_typeStructuredDict(schema)) result agent.run_sync(Create a person) print(result.output) # {name: John Doe, age: 30}参数说明json_schema必须是type: object的 JSON Schema用于定义字典内容的结构name结构化输出的名称未提供时使用 Schema 中的title字段如有description描述未提供时使用 Schema 中的description字段如有。实现细节见 output.py 中StructuredDict定义该函数首先调用_utils.check_object_json_schema校验 Schema 类型若 Schema 含$defs会用InlineDefsJsonSchemaTransformer将其内联因为 Pydantic 的TypeAdapter在__get_pydantic_json_schema__返回$defs时会失败若内联后仍有$defs则抛出UserError——即当前StructuredDict不支持递归$ref/$defs随后把name/description写入 Schema 的title/description字段最后返回一个实现了__get_pydantic_core_schema__dict[str, Any]的dict_schema与__get_pydantic_json_schema__返回附着的 Schema的_StructuredDict类。需要明确的是Pydantic AI不会对收到的 JSON 对象做任何校验是否正确解释 Schema 中的约束必填字段、整数范围等完全取决于模型。输出类型是dict[str, Any]你的代码应防御性地读取内容可以配合输出验证器把校验错误反馈给模型并让它重试。七、DeferredToolRequests把延迟工具请求作为输出DeferredToolRequests是一个 dataclass源码位于 pydantic_ai_slim/pydantic_ai/_deferred.py可作为output_type使用当模型在本次运行中调用了延迟工具deferred tools时该对象成为运行的输出。它有三个字段callslist[ToolCallPart]需要外部执行的工具调用approvalslist[ToolCallPart]需要人工审批human-in-the-loop的工具调用metadatadict[str, dict[str, Any]]以tool_call_id为键的工具调用元数据。结果可以通过build_results()方法构造DeferredToolResults传给下一次 Agent 运行tool_call_id必须匹配approvals键对应审批类调用calls键对应外部执行类调用metadata为逐调用元数据approve_allTrue时未显式列出的审批调用默认以ToolApproved()通过。remaining()方法返回应用结果后仍未解决的请求全部解决则返回None。# 使用 DeferredToolRequests 作为输出类型的示例 from pydantic_ai import Agent, DeferredToolRequests agent Agent( openai:gpt-5.2, output_type[DeferredToolRequests, ...], # 与其他输出类型并列 )在OutputSchema.build()中见 pydantic_ai_slim/pydantic_ai/_output.pyDeferredToolRequests会被识别并设置allows_deferred_toolsTrue且要求至少再提供一个其他输出类型。更详细的用法参见 deferred-tools 文档。八、OutputObjectDefinition 与输出上下文/钩子OutputObjectDefinition是结构化输出生成的输出对象定义一个 dataclass包含四个字段json_schemaObjectJsonSchema输出对象的 JSON Schemaname输出对象名称description输出对象描述strict是否启用严格模式。它在模块内部由ObjectOutputProcessor.__init__构造名称优先取显式传入的name否则取 JSON Schema 的title或输出对象自身的__name__描述优先取显式传入的description否则取 docstring 生成的描述两者都有时拼接。与之配套的还有OutputContext虽然未在__all__中列出但在模块内定义它描述正在处理的输出的上下文信息传给输出钩子使用mode配置的模式注意它反映的是配置而非本次响应的实际格式例如混合模式下ToolOutputSchema报告tool需结合tool_call判断、output_type、object_def、has_function、function_name、tool_call、tool_def、allows_text、allows_image、allows_deferred_tools。输出钩子hooks的编排在_output.py的run_output_validate_hooks/run_output_process_hooks中实现validate 钩子before_output_validate、wrap_output_validate、on_output_validate_error、after_output_validate只对需要解析的结构化输出触发process 钩子before_output_process、wrap_output_process、on_output_process_error、after_output_process对所有输出类型文本、结构化、图片都触发包括工具输出模式。任一钩子抛出的ValidationError或ModelRetry在wrap_validation_errorsTrue时会被转换为ToolRetryError构造RetryPromptPart回传给模型重试流式场景wrap_validation_errorsFalse则原样传播。agent.output_validator装饰器注册的输出验证器运行在 process 钩子内部因此会被wrap_output_process完整包裹。九、Optional Output允许None作为输出有些 Agent 完全通过工具调用完成工作不需要最终输出。默认情况下output_type含str模型被要求以文本结束最后一轮若它认为工作已结束且无话可说会返回空响应或仅含 thinking 内容的响应Pydantic AI 仍会要求它产出文本。把None加入output_type即可接受无最终消息作为合法结局from pydantic_ai import Agent agent Agent(anthropic:claude-opus-4-6, output_typestr | None) agent.tool_plain def mark_task_done(task_id: int) - str: Mark the task as done. return fTask {task_id} marked done. result agent.run_sync(Mark task 1 as done, then stop without saying anything.) print(result.output) # Nonestr | None是最典型的情况模型只能通过无文本输出的响应空响应、文本部分全为空串、或仅含 thinking 内容来表态None没有输出工具或结构化 Schema 参与。None也支持其他输出模式工具模式的裸联合如output_typeint | None、output_type[int, float, None]会额外暴露一个final_result_NoneType输出工具让模型通过工具调用提交None空响应仍同样被视为None。显式模式标记如ToolOutput(int | None)、NativeOutput([int, None])None作为包装器生成的判别式 Schema 的一个分支存在ToolOutput以null提交NativeOutput/PromptedOutput选择NoneType分支此时空响应不被接受模型必须通过 Schema 提交。约束output_typeNone单独使用不合法必须至少再提供一个其他输出类型。输出验证器仍会以None为参数运行因此可通过抛ModelRetry拒绝None。流式场景下stream_output()对空响应会产出空迭代器应改用get_output()获取最终的None。十、输出模式的选择与 end_strategy三种结构化输出模式可概括为模式机制适用性Tool Output默认输出 Schema 作为特殊输出工具的参数 Schema模型通过工具调用提交结果几乎所有模型稳定性好Native Output使用模型原生 Structured Outputs强制输出符合 JSON Schema 的文本需模型支持部分模型有功能限制Prompted Output把 JSON Schema 注入 instructions 提示模型按 Schema 输出文本所有模型可用可靠性最低当模型在同一响应中既产出最终结果又发出其他工具调用时end_strategy决定这些调用的命运默认gracefulgraceful默认输出工具按发出顺序执行首个成功者即为最终结果后续输出工具跳过同时请求的函数工具仍会执行副作用发生、结果在运行继续时对模型可用。early输出工具一旦成功立即结束运行同响应请求的函数工具完全跳过——最快适合拿到结果就不再需要函数工具的场景。exhaustive所有工具包括结果不会被使用的额外输出工具都执行并并行化首个按发出顺序通过校验的结果胜出。当所有输出工具都失败时三种策略下函数工具都会执行且运行继续没有结果可结束输出失败会作为重试回传给模型函数工具结果让模型在下一轮同时做出反应。在exhaustive策略下可用ToolOutput(sequentialTrue)把某个输出工具变成屏障确保响应中的函数工具全部先执行完——这是函数工具sequentialTrue标志在输出工具上的对应物。十一、源码视角OutputSchema.build 的分发逻辑理解整个输出体系最直观的方式是看 pydantic_ai_slim/pydantic_ai/_output.py 中OutputSchema.build()的分发流程_flatten_output_spec()递归展平output_spec序列会被展开PEP 604 联合通过get_union_args拆开得到扁平的项目列表检测特殊类型NoneType/None→allows_noneDeferredToolRequests→allows_deferred_toolsBinaryImage→allows_image各要求至少再提供一个其他类型若存在NativeOutput标记 → 返回NativeOutputSchema要求它必须是唯一输出类型内部再展平其outputs构建处理器若存在PromptedOutput标记 → 返回PromptedOutputSchema同样要求唯一否则按成员分类str/TextOutput归入文本输出最多一个ToolOutput归入工具输出其余归入普通类型/函数文本与工具并存 →ToolOutputSchema混合模式可同时接受文本与工具输出纯文本 →TextOutputSchema有ToolOutput→ToolOutputSchema有其他类型/函数 →AutoOutputSchemamodeauto最终由模型 profile 决定具体结构化模式仅图片 →ImageOutputSchema否则抛出UserError(At least one output type must be provided.)。单输出类型由ObjectOutputProcessor处理多个输出由UnionOutputProcessor处理——后者为每个成员注册一个kind判别键构造包含kind/data的判别式 JSON Schemaresult.anyOf并约束kind必须命中已注册键未知值会以普通ValidationError失败。非对象 Schema如int、list[int]会被包装进单元素对象{response: value}保证所有注册给模型的工具都是对象 Schema——这一点解释了 docs/output.md 中的说明。十二、输出验证器Output Validatorsagent.output_validator装饰器注册的验证函数用于补充 Pydantic 校验器难以/无法完成的验证尤其是涉及异步 IO 的场景。验证器可带可不带RunContext参数同步异步皆可OutputValidator会通过inspect.signature判断是否接收上下文通过is_async_callable判断是否异步。每次验证器抛出ModelRetry会消耗 1 单位运行输出重试预算默认 1可通过Agent(retries{output: N})、agent.run(retries{output: N})或ToolOutput(max_retriesN)调整。验证器内部ctx.max_retries反映实际限制你的上限文本路径的全局预算或工具路径的单工具上限ctx.retry是全局重试计数器在单次运行内切换输出工具时保持一致。验证器不支持ToolFailed——请用ModelRetry请求模型重新输出。若要对不同输出类型实现不同的验证逻辑推荐改用输出函数避免在验证器里做isinstance分支。流式场景下验证器同样会被多次调用应检查ctx.partial_output以只校验完整结果from pydantic_ai import Agent, ModelRetry, RunContext agent Agent(openai:gpt-5.2) agent.output_validator def validate_output(ctx: RunContext, output: str) - str: if ctx.partial_output: return output if len(output) 50: raise ModelRetry(Output is too short.) return output结语pydantic_ai.output模块以output_type为唯一入口通过ToolOutput、NativeOutput、PromptedOutput、TextOutput四个标记类 StructuredDict助手函数 DeferredToolRequests/BinaryImage/None等特殊类型覆盖了从纯文本、结构化数据、函数调用结果到图片、延迟工具请求的全部输出形态。理解OutputSpec的展平与分发逻辑、OutputObjectDefinition的构造规则、输出钩子与验证器的执行时机以及end_strategy对并发工具调用的影响是写出健壮、可预测的 pydantic-ai Agent 的关键。更多配套内容可参考 结构化输出总览、StreamedRunResult 流式结果 与 Agent 运行文档。【免费下载链接】pydantic-aiHow Python does AI. Agents, realtime voice, image generation, embeddings. Every model, every interface, typed end to end.项目地址: https://gitcode.com/GitHub_Trending/py/pydantic-ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表