如何保证大模型输出符合指定 JSON 格式?
未标记
询问 AI
考查重点:结构约束与解析反馈。Schema 定字段与类型,优先结构化输出/约束解码,收到后解析并校业务语义;失败给具体错误有限重试
本题目录
参考答案
核心回答
要稳定拿到指定 JSON,需要把约束放在输出协议、生成过程和接收校验三个位置,不能只在 Prompt 里写一句“请输出 JSON”。
先用 JSON Schema 明确字段名、类型、必填项、枚举、嵌套结构和未知值的表示方式。模型和接口支持时,优先使用严格的结构化输出;JSON Object 模式主要约束 JSON 语法,不能据此保证字段齐全。Prompt 再解释字段含义、提供与协议一致的例子,并要求不输出额外说明。
接收端检查请求是否正常结束,再解析完整响应、校验结构,最后检查业务规则。格式失败时,把具体错误反馈给模型,在次数和耗时预算内修复;信息不足则返回约定的未知状态或向用户补问。JSON 能解析、符合 Schema、业务内容正确是三个不同层次:即使结构合法,也不能直接把模型生成的订单号当成真实且有权访问的订单。
先把“指定格式”定义成可验证的协议
以订单意图提取为例,约定 intent 只能是 query_order 或 unknown,order 必须是对象,内部必须出现 id;提取不到订单号时,id 为 null。
{ "intent": "unknown", "order": { "id": null } }
这里有几个容易遗漏的细节:
- 必填和非空不同。
id可以为null,并不意味着可以省略id。把未知值纳入协议,能减少模型为凑字段而编造内容。 - 列出字段不等于要求字段出现。 JSON Schema 的
properties描述字段规则,required才规定必填项。嵌套对象也要分别定义。 - 多余字段需要单独约束。 若协议不允许自由扩展,在相应对象上设置
additionalProperties: false,而不只限制最外层。 - 业务规则要另行表达。
intent=query_order但id=null时,系统应补问订单号;有订单号后,还要查订单是否存在以及当前用户是否有权读取。
可以从同一份类型定义生成请求使用的 Schema,并复用它做接收校验,减少两端规则漂移。生成的 Schema 仍要适配服务端支持的子集,例如对引用、联合类型或复杂约束的限制。
生成时,原生约束和 Prompt 各做什么
支持严格 Schema 的接口可以在生成阶段限制输出结构。以 XGrammar 这类约束解码实现为例,解码器根据当前语法状态,屏蔽下一步不合法的 token,使采样继续沿合法结构前进。它比生成完再修补括号更直接,但约束的是结构,无法保证字符串里的事实正确;不同服务也不一定使用相同实现。
JSON Object 模式通常只承诺输出可解析的 JSON,对必填字段、枚举和嵌套层级的保证应另查接口约定。例如 DeepSeek 的 JSON Output 文档要求 Prompt 包含 JSON 指示并给出格式示例,同时提示空内容、输出长度等情况;阿里云百炼则区分 JSON Object 和严格 JSON Schema 模式,并规定不同的模型、模式支持条件。接入时应核对实际调用的模型和接口,而不是只看参数名称。
Function Calling 也可以把目标数据放进工具参数,由应用提取并校验。不过,是否严格遵守参数 Schema,取决于提供方及其严格模式支持;“支持工具调用”本身不等于支持所有 Schema 约束。若这里只需要结构化结果,接收工具参数也不意味着要执行一个有业务副作用的函数。
Prompt 负责讲清语义,例如:“从用户输入提取订单查询意图;只输出约定的 JSON 对象;无法提取的订单号填 null;不增加字段、Markdown 围栏或说明文字。”再附一个与 Schema 一致的合法示例。低 temperature 可以减少输出变化,但不提供格式保证。业务输入应作为待提取的数据传入,避免其中的指令覆盖输出要求。
接收端怎样校验
下面是一个接收端示例,使用 Pydantic v2;只做文本解析和结构校验,不调用模型或查询订单:
import json
from typing import Literal
from pydantic import BaseModel, ConfigDict
class OrderInfo(BaseModel):
model_config = ConfigDict(strict=True, extra="forbid")
id: str | None
class Extraction(BaseModel):
model_config = ConfigDict(strict=True, extra="forbid")
intent: Literal["query_order", "unknown"]
order: OrderInfo
def unique_object(pairs):
result = {}
for key, value in pairs:
if key in result:
raise ValueError(f"重复字段: {key}")
result[key] = value
return result
def reject_constant(value):
raise ValueError(f"非标准 JSON 数值: {value}")
def parse_output(text: str) -> Extraction:
obj = json.loads(text, object_pairs_hook=unique_object,
parse_constant=reject_constant)
return Extraction.model_validate(obj)
strict=True 避免把错误类型悄悄转换成正确类型,两个对象的 extra="forbid" 分别拒绝顶层和嵌套的多余字段。id 没有默认值,因此必须出现,但可以是 null。需要向接口传递结构定义时,可从 Extraction.model_json_schema() 获取 JSON Schema,再按接口支持范围适配。
Python 的默认 JSON 解码允许 NaN 等扩展值,并会对重复键保留最后一个值。示例拒绝非标准数值,也明确选择拒绝重复键,避免上下游对同一响应产生不同解释;重复键处理属于这里的协议策略。实际接收层还应控制响应大小与嵌套深度。
解析之前,先处理 API 错误、拒答、空内容和达到输出上限等结束状态。流式响应中的半个字符串或尚未闭合的对象,只是中间片段;需要完整对象的业务逻辑,应等响应结束并通过校验后再运行。展示增量内容与执行业务操作可以采用不同的时机。
格式失败后,怎样恢复而不过度重试
按失败原因处理,比统一“再问一次”有效:
- Schema 或接口配置不受支持。 修改配置或简化协议;原样重试通常不会解决问题。
- 语法或结构错误。 返回精确到字段路径的错误,例如
order.id缺失或类型错误,要求按原协议重新输出。重试仍经过完整校验,并限制总次数、耗时和 token 开销。 - 内容被截断。 结合任务需要调整输出预算、缩小单次抽取范围,或拆分任务;补一个右括号不能恢复丢失的信息。
- 业务信息不足。 使用协议中的未知值、补问用户或交给约定的兜底流程,不用默认订单号或金额填平错误。
如果结果会触发写操作,修复和重试应停留在生成、校验阶段;真正执行时另做权限和幂等控制,避免一次格式修复重复创建订单。
验证效果时,分别统计首次 JSON 解析通过率、首次 Schema 通过率和业务正确率,再看修复后的最终成功率、重试次数与延迟。测试集应包含引号与转义、嵌套字段、缺失值、多余说明、截断和输入中夹带指令等情况,才能知道问题发生在哪一层。
常见追问
为什么不能用正则截取第一个大括号到最后一个大括号?
字符串本身可能包含大括号、转义引号,响应也可能包含多个对象或不完整结构。通用嵌套 JSON 应由解析器处理;若允许从包装文本提取 JSON,也要明确提取规则并继续校验,不能把“截出一段”当作正确。
严格 Schema 模式还需要接收端校验吗?
需要处理接口失败、拒答、截断与版本配置等状态,并验证业务规则。接收端的结构检查还能及时发现集成配置或协议变更问题;原生约束与接收校验承担不同位置的责任。
模型少输出一个字段,补成 null 可以吗?
只有协议明确该字段允许 null,且缺失信息的业务含义与之相符时,才能按约定处理。否则应视为结构错误;缺字段、明确为空和提取失败可能是不同状态,不能无条件合并。
对应教程
- 《从零开始学 AI Agent》第14章:输出解析器:先看 Schema、输出解析器与结构化输出的职责区别,再看 Pydantic 的运行时校验。本文进一步展开原生模式的适用条件、嵌套协议与失败恢复。
参考资料
- 国内:JavaGuide:结构化输出与 Function Calling:参考 JSON Mode、Schema 与工具调用的约束差异及错误反馈,组织正文中协议、生成和接收校验的三层保证。
- 国内:DeepSeek:JSON Output:依据 JSON Object 的参数、Prompt 示例和输出限制,说明正文中 DeepSeek 模式的语法保证、空内容与截断处理。
- 国内:阿里云百炼:结构化输出:参考 JSON Object 与严格 JSON Schema 模式的区别,交代正文中百炼的字段约束与模型、调用模式支持条件。
- 国外:LangChain:Structured output:借鉴原生输出与工具参数两条路径及校验恢复,说明正文中结构化结果的接收方式和失败修复职责。
- 国外:JSON Schema:Object:依据 properties、required、additionalProperties 与 null 的语义,解释正文中嵌套对象必填、可空及额外字段的区别。
相关面经
5 篇恒生电子
AI 应用开发工程师让大模型稳定输出结构化数据,如JSON是ai应用开发常见需求,但模型有时会输出多余的解释文字或格式不合法,你会用哪些手段提升结构化输出的稳定性和可解析性。
恒生电子
AI 开发工程师大模型稳定输出结构化 JSON,经常出现多余文字、格式非法,你会用哪些手段提升结构化输出稳定性与可解析性?
蚂蚁集团
去哪儿
AI 全栈开发工程师LLM如何通过手段保证输出的内容符合规定的JSON格式?
去哪儿
AI 全栈开发工程师生成格式化例如JSON内容,如何确保AI生成的可靠性(键的准确性,嵌套层级)
