14. Structured Output / 结构化输出在 Agent 中为什么重要?怎么保证输出格式?
整理结构化输出在 Agent 中的作用、约束方式与常见问题。
简单回答
结构化输出在 Agent 中至关重要,因为 Agent 的输出不是给人看的自然语言,而是要被代码解析和执行的——工具调用的函数名和参数、任务规划的步骤列表、决策的分类标签等,都需要严格的格式才能被下游系统正确处理。保证输出格式的方法包括:API 层面的 JSON Mode / Structured Output 约束、Prompt 中明确指定格式和示例、输出后解析+校验+重试、以及使用 Pydantic 等 schema 验证工具。
详细解释
为什么 Agent 比普通对话更需要结构化输出
普通对话场景下,LLM 输出自然语言文本直接展示给用户,格式不太重要——多个换行、少个标点都无所谓。但在 Agent 场景中,LLM 的输出是要被程序解析的——它必须是合法的 JSON、符合预定义的 schema、包含必要的字段。
比如 Agent 决定调用工具时,需要输出类似这样的结构:
如果 LLM 输出了 search("最新AI论文") 这样的自由文本格式,或者 JSON 中漏了一个引号导致解析失败,整个 Agent 的执行流程就中断了。在多步任务中,一个格式错误就可能导致整个任务失败。
保证输出格式的方法
API 层面的约束是最可靠的。OpenAI 的 Structured Outputs 功能允许你传入一个 JSON Schema,API 保证模型的输出严格符合这个 schema——不会有格式错误、不会缺少必要字段。底层实现是通过受限解码(Constrained Decoding)——在 token 生成时,只允许模型选择符合当前 schema 约束的 token。这是最硬的保证。
Anthropic 的 Claude 也支持 Tool Use 格式约束,模型生成的工具调用参数会是合法的 JSON。
Prompt Engineering。 在 Prompt 中明确指定输出格式,包括 JSON 的结构、字段名称和类型、以及一两个完整的示例。好的 Prompt 格式说明应该包括:输出格式的严格定义("只输出 JSON,不要包含任何其他文本")、字段说明、以及正反例。
但 Prompt 约束不是硬保证——LLM 有时候会"忘记"格式要求(特别是在长上下文或复杂任务中),或者在某些边界情况下输出不合规的格式。所以不能只靠 Prompt。
输出解析 + 校验 + 重试。 在应用层对 LLM 的输出做解析和校验。如果解析失败(不是合法 JSON)或校验不通过(缺少必要字段、类型不对),把错误信息反馈给 LLM 让它重新生成。通常设 2~3 次重试上限。
LangChain 中的 OutputParser、Pydantic 的 BaseModel 验证、以及 Guardrails AI 的 output validation 都是做这件事的工具。
使用 Function Calling / Tool Use 接口。 如果场景是工具调用,直接用 LLM 平台提供的 Function Calling 接口,而不是自己让 LLM 输出 JSON 再解析。Function Calling 接口在 API 层面保证了输出的结构化——模型要么输出文本回复,要么输出工具调用,工具调用的格式由 API 保证。
结构化输出的 trade-off
过度严格的格式约束可能限制模型的表达能力。比如要求模型的所有输出都是固定 schema 的 JSON,模型可能在某些需要自由文本解释的场景下表现不好。好的设计是:该结构化的部分(工具调用、决策标签)用严格的 schema 约束,该自由表达的部分(给用户的回答、推理过程)保持自然语言。
受限解码在性能上也有一定开销——模型在每个 token 位置需要检查 schema 约束,可能略微增加推理延迟。不过这个开销通常很小,几乎可以忽略。
面试时可以这样答
结构化输出在 Agent 中至关重要,因为 Agent 的输出是要被代码解析和执行的。工具调用的函数名和参数、规划的步骤列表,一个格式错误就可能导致整个流程中断。
保证格式有几个层次。最可靠的是 API 层面的约束——OpenAI 的 Structured Outputs 通过受限解码保证输出严格符合 JSON Schema,这是硬保证。其次是 Function Calling 接口,API 层面保证工具调用的格式。再次是 Prompt 中明确指定格式和示例,但 Prompt 约束是"软"的,不能完全保证。最后在应用层做解析校验,解析失败就带着错误信息重试。
实际项目中通常多层结合——用 Function Calling 或 Structured Outputs 做基础保障,Prompt 中加格式说明做辅助,应用层做兜底校验。工具调用这类关键输出一定要用硬约束,不能只靠 Prompt。
常见追问
- Structured Outputs 底层的受限解码是怎么实现的?
- 如果 LLM 的输出校验失败了,重试时 Prompt 怎么设计效果最好?
- 结构化输出和 Chain of Thought 有矛盾吗?怎么处理?