怎么让模型稳定输出合法 JSON?结构化输出的几种实现与兜底策略?
谁在问:一二面·工程向;平台组必问
口语化问法
- 你怎么保证模型返回的 JSON 一定能解析?
- 约束解码和在提示词里写『只返回 JSON』有什么区别?
- 都用上结构化输出了,你还写校验吗?
考察意图
第一层考你知不知道有约束解码这条路(现在还答「让它返回 JSON 然后正则提取」的,说明技术栈停在 2023)。
第二层才是重点:你知不知道它保证的只是语法。 很多团队上了结构化输出之后反而放松了校验,把一个格式契约当成了业务保证——而这个误解造成的事故,通常比 parse 失败贵得多。
参考答案
60 分答案(及格线)
有几种做法,可靠性递增:
- 在提示词里要求只返回 JSON,配合失败重试和容错解析——最不可靠;
- JSON mode:保证输出是合法 JSON,但不保证符合我的 schema;
- 结构化输出 / 约束解码:把 JSON Schema 编译成语法,在生成每个 token 时屏蔽掉会违反结构的候选,从机制上保证输出符合 schema;工具调用侧有对应的严格模式约束参数。
兜底上会做 schema 校验、失败重试、以及解析失败时的降级处理。
90 分答案(有生产经验的回答)
补三层:
第一,机制上的区别是「请求」和「封路」。 提示词是叮嘱模型尽量别越界,约束解码是把所有违规的岔路都封死——模型不是更听话了,是物理上吐不出违反结构的 token。
第二,它保证的只有语法,而且 schema 只支持 JSON Schema 的一个子集。 截至 2026-08,官方明确不支持递归 schema、外部 $ref、minimum/maximum、minLength/maxLength 等数值与长度约束,additionalProperties 只能是 false;同时有整体复杂度上限,可选参数是复杂度大户。所以数值范围、字符串长度、日期是否真实存在、金额是否在权限内——这些语法层根本表达不了,必须活在代码里。
我们线上是三层校验:语法层交给约束解码;值域层用代码校验枚举越界、数值范围、日期真实性、格式正则;业务层用代码校验权限、与来源一致性、审批阈值。原则是:能用 schema 表达的交给 schema,不能表达的必须写代码,绝不写进提示词指望模型自觉。
第三,一个反直觉的副作用:结构化输出不降低幻觉率,只是把幻觉变成格式合法的幻觉。以前 parse 报错还能当一道天然告警,现在这道告警没了,所以第 2、3 层校验只会更重要,不会更不重要。
顺带一提:预填 { 逼模型直接吐 JSON 这个流传很广的老技巧,截至 2026-08 在 Claude Opus 4.7 及以后已经返回 400,官方要求改用结构化输出。
追问链
约束解码和「在提示词里要求返回 JSON」有什么本质区别?
期望前者在采样阶段屏蔽非法 token,是机制保证;后者只是概率上的倾向,模型可能加寒暄、缺字段、类型飘。加分项:说得出 schema 被编译成语法、编译产物会被缓存,因此首次调用有额外延迟、高频可忽略信号说得出「在 token 采样层面封死」 → 理解了机制;只说「结构化输出更可靠」 → 知道结论不知道原因有了约束解码,还需要校验吗?为什么?
期望需要 —— 它管形状不管内容。举得出具体例子最好:"2026-02-30"是合法字符串但这个日期不存在;金额字段是合法整数但数值离谱信号本题最重要的分水岭:答「不用了,schema 已经保证了」 → 直接掉档schema 能表达的和不能表达的分别是什么?
期望能表达结构 —— 字段有无、类型、嵌套形状、枚举取值;表达不了数值范围、字符串长度、正则、递归结构、跨字段一致性。所以枚举是特别值钱的设计:唯一一类「语法层能顺便管住语义」的字段,能枚举就别让模型自由发挥信号主动点出「枚举优先于自由文本」这条设计原则 → 真设计过 schemaschema 越来越复杂,编译直接报错了,你怎么办?
期望按官方给的顺序改:只给关键工具加严格模式 → 可选参数改必填(它显著放大语法状态空间、是复杂度大户,可用一个显式「未知」枚举值替代字段缺失)→ 拍平嵌套 → 实在不行拆到多个请求。加分项:限制是所有严格 schema 合起来算的,单个看着简单也可能超信号知道「可选参数是复杂度大户」 → 一定亲手撞过这个报错返回的 JSON 全部合法,但一批订单退款金额明显不合理、下游已打款,复盘一下
期望① 先止血:关自动执行改待审队列、已打款分档对账、加硬阈值 → ② 锅在架构不在模型:拿语法保证当业务保证,maximum本就不归约束解码管 → ③ 补值域层与业务层:上下限、原价、权限、审批 → ④ 能代码判的用代码判 → 能可逆的变可逆 → 剩下人工 → ⑤ 高危动作授权检查独立于模型输出 → ⑥ 关键字段建异常值监控,补回 parse 不报错丢的告警信号说「不是模型的锅是架构的锅」、把退款金额归到「本就该代码判」 → 优秀;答「加强提示词」或「schema 里加 maximum」 → 没读过限制清单
"2026-02-30" 是合法字符串」就把「用过」和「设计过」切开了。第 2 层是最重的分水岭 —— 语法不等于语义;第 5 层看你把锅归给架构还是归给模型。评分要点
- 知道约束解码及其机制(编译成语法、采样层屏蔽)
- 能区分 JSON mode 与 schema 约束
- 明确它保证语法、不保证语义
- 说得出 schema 至少两条表达不了的约束
- 有分层校验的设计(语法 / 值域 / 业务)
- 知道枚举优先于自由文本
- 知道 schema 复杂度上限与优化顺序
- 高危动作的判断权收回代码,不依赖模型输出
常见错误
maximum 就能管住数值。{ 这个已失效的技巧。