结构化输出的意义
LLM 是输出不可控的概率模型,而结构化输出则增强输出的可控性。
有了这种可控性,LLM 就具备了一个程序的交互 interface 可以稳定地接入上下游程序,比如调用工具
结构化输出的原理及实现方式
实现格式化输出通常有以下几种手段,
- 提示词工程
通过指令 “只输出JSON”,few-shot 示例等提示词技巧引导模型进行格式化输出 - 后处理
instruct 等库对模型输出进行后处理,进行提取或修复等。包括解析后反馈错误重新生成等。 - 约束解码
在选择 token 时用 mask 机制直接排除不符合输出格式的候选 token,在有限输出空间内选择 token。{"key": value},从仅让模型预测格式串中的value部分,到约束value的格式/类型,约束解码都可以保证可靠的格式化输出。
再进一步,通过等价的状态机进行约束解码,可以进行任意的格式化输出。约束解码是结构化输出的主要工程手段。 - SFT / RL
通过后训练手段形成输出偏好,使模型遵循一定模式。可靠性高,是结构化输出的理论保障、能力来源。
当前许多模型厂商从 SFT/RL 的角度增强模型的格式化输出能力,并从推理端实现约束解码(例如Ollama),从而提供可靠的结构化输出 API。
工具调用与结构化输出,先有鸡还是先有蛋
依靠结构化输出的结果,我们才能稳定地处理工具调用
然而,如果模型能调用给定的工具,那么任意输出格式都可以包装成工具,通过 LLM 填写调用参数,也就实现了指定格式的输出
看起来两者相互成就,已经变成了鸡生蛋,蛋生鸡的问题
许多厂商都强调模型有tool use/ function call能力,却不强调模型支持结构化输出,可能工具使用能力是结构化输出的内核吧,结构化输出结合了众多工程手段来提供可靠性
本地模型在 langchain 中的结构化输出
本文在 langchain 以下生态中进行讨论(2026-02-02)
1 | langchain-core 1.2.7 |
以 YesNoJudge 类的 JSON 格式,搭配不同 with_structured_output() 的格式化输出方式(即method参数)测试结构化输出表现method 参数可选项有 json_schema, function_calling 和 json_mode,其中json_mode因无法给出确定格式的 JSON ,需要后处理,不推荐使用。(来源:https://platform.openai.com/docs/guides/structured-outputs#json-mode)
1 | class YesNoJudge(BaseModel): |
图:指定`json_schema` 方式,在 prompt 中提示按JSON格式输出后,gpt-oss:20b 仍调用不存在的工具进行格式化输出
图:指定 `function_calling` 方式,在 prompt 中提示按JSON格式输出后,qwen3:4b 会在内容中输出 json,不调用工具
图:指定 `function_calling` 方式,去除json prompt,qwen3:4b 仍倾向于遵循指令在内容中输出结果,不调用工具
图:指定 `function_calling` 方式,去除指令式prompt,qwen3:4b 有概率调用工具返回结果可见 Qwen 模型更重视指令遵循,而 GPT 偏向于使用工具
langchain 中 with_structured_output() 的实现简析
不同 backend 生态包的 with_structured_output() 实现不同,
对于langchan-openai:
- function_calling 把 JSON schema 作为 tool 传入,并填充 tool_choice 参数,强制 LLM 使用工具输出工具调用的 schema
相当于把工具调用能力转化为结构化输出能力 - json_schema 方式则是对输出内容进行解析,该参数
- json_mode 建议配合 prompt 使用,全靠模型发挥
而 create_agnet API 中 response_format 也是直接调用 LLM 后端的结构化输出能力
langchain + langchain-openai + Ollama 后端结构化输出踩的坑
为什么用 langchain-openai 不用 langchain-ollama,因为想着兼容 OpenAI API 会好一些
甚至用 langchain-ollama + Ollama 还一直出现 502 报错。。openai / curl 均正常
看似兼容,实则不兼容
如 langchain[openai, ollama] 中 chat_models 的 with_structured_output() 实现不一致
且将 Ollama 作为后端使用 langchain-openai 时 with_structured_output 的表现和模型高度相关,需根据模型调优 method 参数
实际支持多个后端仍需要进行适配多处实现,效果不一
如langchain[openai, ollama]中chat_models的with_structured_output()与from langchain.agents import create_agent的response_format都用于结构化输出,然而可靠性不同过度封装
源码里到处是消除警告的类型不匹配 # type: ignore
MessageState 的消息 messages 传入 AgentState 的 messages 提示类型不匹配,有点搞笑