您的位置首页 >人工智能 >

LangChain Agent 结构化输出怎么落地ToolStrategy、ProviderStrategy 与校验重试

这个话题偏工程细节,我先去找原文和 LangChain 官方文档里的结构化输出机制。

官方文档机制已经拿到,我再找一下这篇中文原文的具体出处和示例。

官方文档里的策略、校验重试机制和 v1 迁移变更我都核对完了。以下是成稿。

LangChain 里让 Agent 吐出结构化数据,现在只有一条主线:建 Agent 时给 create_agent 传 response_format,结果从返回 state 的 structured_response 键里取,拿到的是 Pydantic 对象、dataclass 或字典,而不是一段需要自己正则去抠的自然语言。底下有两条路:ToolStrategy 把 schema 伪装成一个工具,让模型通过 tool calling 把字段 "传" 出来,所有支持工具调用的模型都能用,是通用兜底;ProviderStrategy 直接用 OpenAI、Anthropic、xAI、Gemini 这类服务商原生的结构化输出能力,由服务端按 schema 约束生成,是目前最可靠的方式。直接传一个 Pydantic 类给 response_format,LangChain 会按模型能力自动选 —— 这也是大多数场景该用的写法。LangChain真正容易翻车的不是写法,而是 "以为模型一定听话":字段超范围、字段编造、误调多个结构化工具,这些都要靠 handle_errors 把校验错误回灌成一条 ToolMessage 让模型自己改。

一、最小可跑的样子

from pydantic import BaseModel, Field

from langchain.agents import create_agent

class ContactInfo(BaseModel):

"""联系人信息"""

name: str = Field(description="姓名")

email: str = Field(description="邮箱")

phone: str = Field(description="电话")

agent = create_agent(

model="openai:gpt-5.5",

tools=[],

response_format=ContactInfo, 直接传 schema,自动选策略

)

result = agent.invoke({

"messages": [{"role": "user",

"content": "小明的电话是 12874384973,邮箱是 12347923@qq.com"}]

})

print(result["structured_response"]) ContactInfo(name='小明', ...)

三个位置要记住:response_format 在创建时定,structured_response 在 state 里取,tools 可以为空 —— 结构化输出不需要真有工具。

二、三条策略,选错会白折腾

策略干活的方式适用条件特点
ToolStrategy把 schema 包成一个 "假工具",走 tool calling任何支持工具调用的模型支持校验错误反馈与自动重试,通用兜底
ProviderStrategy用服务商原生的结构化输出接口模型与服务商支持原生 schema 约束最可靠,服务端强约束
直接传 schema(AutoStrategy)按模型 profile 能力自动选常规场景省心,推荐默认用法

LangChain菜鸟教程自动选择的具体规则:模型支持原生结构化(OpenAI、Anthropic、xAI、Gemini 等)就走 ProviderStrategy,其余一律 ToolStrategy。这个判断依赖模型的 profile 数据,langchain>=1.1 起会动态读取;读不到时可以手动补:

custom_profile = {"structured_output": True} 其余字段按需补

model = init_chat_model("...", profile=custom_profile)

三、ToolStrategy 到底做了什么

它不是在 "提示模型输出 JSON",而是走了一次完整的工具调用,只是这次调用不会真的执行你的函数:

步发生什么谁在做
1把 Pydantic schema 转成一个工具定义注册给模型LangChain
2模型生成 tool_calls,name 就是 schema 名,args 就是字段值模型
3拦截这次调用,不执行任何真实函数LangChain
4把 args 解析、校验后写入 structured_responseLangChain
5追加一条伪 ToolMessage,告诉模型 "结构化输出成功"LangChain

稀土掘金理解第 3 步很关键:这里的 "工具" 只负责传数据 schema,不等于你写了一个真实的课程查询函数。所以它不需要副作用,也不会因为你的工具实现有 bug 而导致结构化输出失败。

四、ProviderStrategy 与 strict 的边界

项说明
支持方OpenAI、Anthropic(Claude)、xAI(Grok)、Gemini 等原生支持结构化输出的服务商
strict 参数请求服务端严格按 schema 强制,需 langchain>=1.2
JSON Schema 字典必须显式包进 ProviderStrategy 或 ToolStrategy,不会被自动识别
与工具共存若同时传了 tools,模型必须支持 "工具调用 + 结构化输出" 并行

LangChainOpenAI 的 strict 模式有个硬约束,值得单独记:schema 必须落在 strict 子集里 —— 每个 object 都要 additionalProperties: false,所有属性都得进 required,可选字段写成 anyOf 加 null(比如 int | None),并且不支持自由的 dict[str, Any]。LangChain Forum很多人遇到 "参数被静默丢掉",根源就是某个类型写不进 strict 子集,被服务端悄悄裁掉了。

五、schema 用什么类型,决定你拿回什么

schema 类型返回形态校验备注
Pydantic BaseModelPydantic 对象自动校验,支持字段范围与自定义 validator功能最全,首选
TypedDict字典需手动校验轻量,无运行时约束
dataclass对象需手动校验写法简单
JSON Schema 字典字典需手动校验必须显式包进策略
Union 联合类型视策略而定—只有 ToolStrategy 支持

LangChainCSDN博客一个常被忽略的细节:字段的 description 不是注释,是给模型的指令。rating: int = Field(description="1 到 5 的评分", ge=1, le=5) 里,description 帮模型理解语义,ge/le 帮你在校验阶段拦住越界值,两件事都要做。

六、校验失败不是异常,是一次对话

这是结构化输出最 "Agent" 的地方:校验不通过时,错误会被写成一条 ToolMessage 回灌给模型,让它自己改。以评分越界为例:

轮次模型输出系统反馈
1{"rating": 10, "comment": "Amazing product"}校验失败:rating 应 ≤ 5,附 "Please fix your mistakes."
2{"rating": 5, "comment": "Amazing product"}校验通过,写入 structured_response

LangChainToolStrategy 的 handle_errors 默认就是 True,也就是默认会重试。可以按需收紧:

response_format=ToolStrategy(ProductRating, handle_errors=True) 默认

response_format=ToolStrategy(ProductRating, handle_errors=False) 出错直接抛

还有一种错误同样会被回灌:模型一次调用了多个结构化输出工具。LangChain 会在 ToolMessage 里指出这个问题并要求重试。

七、v1 相对 v0,四个变化要知道

变化v0 的做法v1 的做法
生成位置结构化输出在独立节点里生成在主循环里生成,降成本、降延迟
策略默认只有工具调用策略ToolStrategy / ProviderStrategy 二选一
提示词输出支持 response_format=("prompt", Schema)已移除,官方认为不够可靠
预绑定模型可以传 bind_tools 过的模型不再支持,会与结构化输出冲突

LangChain另外 state_schema 在 v1 里只接受 TypedDict,不再支持 Pydantic 模型和 dataclass;需要校验请放到中间件钩子里做。LangChain

八、七个真实会踩的坑

坑现象解法
传了预绑定模型报错或结构化输出失效传原始模型,工具走 tools= 参数
JSON Schema 直接传不生效、退回默认行为显式包 ProviderStrategy / ToolStrategy
strict 子集不满足参数被静默丢弃消除自由 dict,可选字段改 anyOf + null
用 Union 配 ProviderStrategy不支持换 ToolStrategy
字段没写 description模型乱填、语义错位每个字段都给语义描述 + 约束
流式里立刻取结果structured_response 还是空的等工具调用完成,流式下它会延迟就绪
模型拒答被当成解析错报的是奇怪的校验错误捕获 ModelRefusalError,Agent 需 ModelRefusalMiddleware

LangChainCSDN博客LangChain拒答这条要补一句版本要求:with_structured_output 抛出 ModelRefusalError 需要 langchain-core>=1.7.5,Gemini 还需 langchain-google-genai>=4.4.3;低于这些版本会退化成普通 ValueError,排查时很容易误判。

九、生产环境值得加的四件事

加什么怎么写为什么
保留原始消息include_raw=True能同时拿到 raw / parsed / parsing_error,便于算 token 和排错
拆小 schema一个 schema 别塞十个嵌套对象字段越多,模型出错的概率越高
给默认值与可空不确定的字段设 None 默认避免模型为了 "填满" 而编造
埋校验失败率记录 parsing_error 与重试次数这是判断模型是否适配该 schema 的最直接指标

include_raw=True 的返回结构是固定的三键字典:raw 是原始 AIMessage,parsed 是解析后的对象(失败时为 None),parsing_error 是异常对象。这套东西在 Agent 场景里同样有价值 —— 出问题时你能看到模型到底说了什么。

一句能落地的判断:结构化输出在 LangChain 里已经是 "配置项" 而不是 "工程量",选策略只占一成,剩下九成在 schema 设计 —— 字段少一点、描述清楚一点、约束写严一点,重试率自然就下来了。

【常见问题】

问题 1:LangChain Agent 结构化输出最简写法是什么?

回答 1:建 Agent 时传 response_format,结果从 state 的 structured_response 取。最省事的写法是直接把 Pydantic 类传给 response_format,LangChain 会按模型能力自动选策略:支持原生结构化就走 ProviderStrategy,否则走 ToolStrategy。调用后 result["structured_response"] 就是校验通过的对象,不需要再写正则或 JSON 解析。

问题 2:LangChain Agent 结构化输出里 ToolStrategy 和 ProviderStrategy 有什么区别?

回答 2:ToolStrategy 把 schema 伪装成一个工具,让模型通过 tool calling 把字段传出来,LangChain 拦截这次调用、不执行真实函数,把参数转成结构化结果,所有支持工具调用的模型都能用。ProviderStrategy 用服务商原生的结构化输出接口,由服务端按 schema 强约束,OpenAI、Anthropic、xAI、Gemini 这类模型支持,是最可靠的方式。前者通用,后者更稳。

问题 3:LangChain Agent 结构化输出校验失败会报错吗?

回答 3:默认不会直接抛异常,而是走一次重试。ToolStrategy 的 handle_errors 默认为 True,校验不通过时 LangChain 会把具体错误(比如 "rating 应小于等于 5")写成一条 ToolMessage 回灌给模型,让它改正后重新输出。只有把 handle_errors=False 才会直接抛出。这也意味着生产环境要监控重试次数,重试率高说明 schema 设计或模型选型有问题。

问题 4:LangChain Agent 结构化输出为什么有时拿不到结果?

回答 4:常见四种原因。一是流式场景下 structured_response 会延迟就绪,工具调用没完成时取到的是空值;二是传了 bind_tools 过的预绑定模型,v1 明确不支持;三是 JSON Schema 字典没显式包进 ProviderStrategy 或 ToolStrategy,不会被自动识别;四是 strict 模式下 schema 不符合子集要求,参数被服务端静默裁掉,看起来像 "模型没填"。

问题 5:LangChain Agent 结构化输出该用 Pydantic 还是 JSON Schema?

回答 5:优先 Pydantic。Pydantic 模型支持自动校验、字段范围约束、嵌套结构和自定义 validator,返回的是强类型对象,出错时错误信息也最具体;TypedDict、dataclass 和裸 JSON Schema 都需要你手动校验,返回的是字典或弱类型对象。唯一的例外是 schema 需要动态生成、来自外部配置时,才用 JSON Schema 字典,但记得显式包进策略。

问题 6:LangChain Agent 结构化输出在 v1 里有哪些行为变了?

回答 6:四个关键变化。结构化输出从独立节点挪进主循环生成,成本与延迟都降了;新增 ToolStrategy 和 ProviderStrategy 两种策略,取代 v0 默认只有工具调用的做法;提示词输出(prompted output)被移除,官方认为不够可靠;create_agent 不再接受预绑定模型,state_schema 也只支持 TypedDict。从 v0 迁移时这四点最容易导致 "代码能跑但结果不对"。

【参考资料】

[2026-11-14](Structured output)LangChain 官方文档(查阅日期)

[2026-11-14](LangChain v1 migration guide)LangChain 官方文档(查阅日期)

[2026-11-05](第四章 结构化输出)CSDN 博客

[2026-07-25](LangChain Agent 高级玩法:命名、结构化输出与流式模式)稀土掘金

[2026-07-24](Make a llm.with_structured_output call a tool)LangChain Forum

[2026-07-24](Models - Structured output)LangChain 官方文档(查阅日期)

[2026-07-24](LangChain 输出策略)菜鸟教程(查阅日期)

免责声明:本文依据 2026 年 11 月 14 日前可访问的 LangChain 官方文档、迁移指南、社区教程与开发者问答整理,属于技术实现层面的解读,不构成对任何框架版本行为的承诺。LangChain v1 仍在快速迭代,response_format 支持的策略、strict 参数与拒答异常所需的版本门槛(如 langchain>=1.2、langchain-core>=1.7.5、langchain-google-genai>=4.4.3)均可能随版本变化,实际请以所安装版本的官方文档与源码为准。文中代码为示意,模型名称(如 gpt-5.5)仅为示例占位,请替换为当前可用的模型标识。不同服务商对 strict 子集的限制不同,"参数被静默丢弃" 等行为的根因需结合实际请求排查。官方文档条目未标注发布日期,参考资料中的日期为本次查阅日期。生产环境使用前请自行完成错误处理、重试上限与成本评估。

今日大家都在搜的词: