一句话定义
结构化输出让模型的回答严格符合预定义的模式(JSON Schema 等),实现手段分为「提示约束」(要求并解析)与「约束解码」(在采样时屏蔽破坏语法的词元)两类——后者在数学上保证合法。
为什么重要
生产系统的下游不是人而是代码:没有合法 JSON,自动流水线就会中断。「解析失败重试」是 LLM 应用最常见的事故之一。理解结构化输出的两级实现,能让你把可靠性从「希望模型听话」升级为「机制上不可能不合法」。
前置知识
- kp-026(API 形状)
核心概念
- JSON 模式:API 参数级开关,保证输出是合法 JSON(不保证字段语义正确)。
- Schema 约束:进一步约束到指定 JSON Schema 的字段、类型与枚举。
- 约束解码(Constrained Decoding):每步采样前按语法/Schema 构建允许词元掩码,非法词元概率置零。
- 正则/语法引导:用上下文无关文法(CFG)或正则描述目标格式,驱动掩码生成。
- 解析校验回退:即便有约束,仍建议 schema 校验 + 失败重试兜底。
- 与工具调用的关系:工具参数即一种内置的结构化输出(见 kp-027)。
原理与机制
提示约束依赖模型行为(可能漏字段、包错引号),成功率非 100%;约束解码则把格式知识下沉到解码层:每生成一个词元前,用当前已生成串与目标 Schema/文法求「合法延续集」,对不允许的词元做掩码(logits 置 −∞)再采样——与 kp-025 的解码循环正交叠加。数学上,输出必然满足文法;语义层面(字段值是否合理)仍由模型能力决定,因此「语法保证合法 ≠ 内容保证正确」。开销方面,掩码构建有计算成本,主流框架已工程化优化。
公式或模型
约束解码的采样修改(与温度/top-p 叠加):
允许集 L(prefix) = { w : prefix + w 仍是合法前缀 }
P'(w) ∝ P(w) · 1[w ∈ L(prefix)]
P'(w) ∝ P(w) · 1[w ∈ L(prefix)]
图示
Schema: {name: string, age: integer}
已生成: {"name": "李雷", "age": → 合法延续只有 数字与 }
非法词元: 汉字、字母、引号等 → logits 全部置 −∞ → 永不输出
直观类比
像「只能往格子纸上写字」:提示约束是「请你写在格子里」(可能出格);约束解码是「纸本身就是格子,笔尖物理上出不了线」。但格子保证的是位置合法,不保证写的内容正确——内容对错仍取决于作者。
实例或案例
典型场景:信息抽取(合同字段 → JSON)、Agent 的工具参数(kp-027)、批量标注流水线。工程实践组合拳:JSON 模式开 + Schema 声明 + 应用层校验 + 失败重试(携带错误信息再生成);对枚举字段(如分类标签)约束解码可把「标签拼错」类错误降为零(Geng 等,2023 展示了文法约束在无微调下的有效性)。
常见误区
- 「JSON 模式保证内容正确」:只保证语法合法;字段值错误仍需业务校验。
- 「约束解码会大幅降低质量」:掩码只限制形式,模型在合法集内仍按自身分布选择;少数复杂 schema 下可能影响语义流畅度。
- 「有了约束就不需要重试」:外部服务异常、schema 本身设计不当仍会失败,兜底不可省。
与其他知识点的关系
自测题
- 提示约束与约束解码的本质区别?答案要点:前者靠模型行为(软约束、可违反),后者在采样层掩码(硬约束、语法上必然合法)。
- 约束解码保证什么、不保证什么?答案要点:保证输出符合 Schema/文法;不保证字段语义正确、内容高质量。
- 生产环境的结构化输出兜底组合?答案要点:Schema 校验 + 错误信息回填重试 + 监控失败率。
延伸阅读
- Grammar-Constrained Decoding for Structured NLP Tasks without Finetuning(Geng 等,2023)