📰 来源:Towards Data Science | 📅 翻译日期:2026年9月2日
🔗 原文:查看原文
🤖 翻译:DeepSeek AI · 仅供参考
背景:约束解码解决了语法问题,却带来了新的盲区
约束解码(Constrained Decoding)确实解决了一个实际问题。在基于语法的方法(如 Outlines 和 SGLang)出现之前,从语言模型获取有效 JSON 的过程就是一个重试循环:你提示、解析、捕获尾随逗号、再重新提示。约束解码终结了这一局面:通过有限状态机强制 token 选择,每个输出都能被解析。
团队迅速采用了这一技术,模式合规率接近 100%。然而,一个默认假设悄然潜入了生产代码库:如果 JSON 通过了模式验证,那么数据就是正确的。
BAML 的基准测试表明事实并非如此。在函数调用任务上,无约束生成配合事后解析的准确率为 93.63%,而同一模型在约束解码下的准确率仅为 91.37%。永远有效的 JSON 反而比偶尔出错的 JSON 准确率更低。
我在构建的一个分类管道开始在大约每 12 次运行中返回看似合理但伪造的值之后,开始追踪这个问题。JSON 总是能解析,Pydantic 从未报错。过了几周才注意到,因为所有下游检查都是结构性的。
五大失败模式:模式验证无法捕获的问题
以下五种失败模式反复出现,它们都产生模式有效但会静默破坏管道的输出:
- 枚举幻觉:枚举值有效,但含义错误。
- 自信伪造:在自由文本字段中返回看似合理的捏造数据。
- 跨字段矛盾:单个字段有效,但组合起来不可能。
- 分布坍缩:收敛到安全默认值。
- 数组幻觉:伪造条目而非返回空数组。
约束解码:它真正解决的问题
结构化输出过去意味着寄希望于模型表现得当。约束解码的构建初衷是解决这个问题,它也确实做到了,但并未解决全部问题。
这一进步是真实存在的。从“提示后祈祷式 JSON”(即在提示后添加“以 JSON 格式响应”并祈祷成功),到基于正则表达式的生成(LMQL),再到基于语法的约束解码。
XGrammar(现为 vLLM 和 TensorRT-LLM 的默认后端)每个 token 仅增加近零开销。语法问题已解决。
但解决语法问题反而制造了一个盲区。模式验证检查字段类型是否正确:字符串是字符串,数字是数字。但它无法说明该字符串或数字是否正确。
锁在文件柜上能让抽屉保持整齐,但无法说明里面的文件是否准确。模式验证也是同理。
为什么这很重要:格式强制消耗模型能力
强制模型遵循严格输出格式需要付出代价:模型必须将部分注意力用于保持格式合规,而非全部用于得出正确答案。
Lee 等人直接衡量了这种代价。在开源模型中,强制结构化输出格式导致准确率下降 3 到 9 个百分点。尤其是在数学推理任务中,当正确推理比格式更重要时,差距超过 15 个百分点。
Tam 等人从另一个角度发现了相同的模式:格式规则越严格,推理能力越差。格式并非免费,而大多数团队并未计算这一成本。
模式验证不会捕获的五大失败模式详解
模式验证会捕获类型错误,但不会捕获以下五种失败模式,因为每一种都会产生结构有效但实质上错误的结果。
枚举幻觉
模型选择了一个有效但语义错误的枚举值。例如,优先级枚举 ["low", "normal", "high", "urgent"]:语法保证了这四个值之一会被返回,但不会根据输入上下文加权。模型可能会在常规请求上返回 "urgent",或在关键请求上返回 "low",而模式均会接受。
自信伪造
自由文本字段返回看似合理但纯属虚构的数据。BAML 通过提交一张大象照片作为收据来证明这一点:约束解码返回了一份完整的、模式有效的费用报告,而不是拒绝。约束解码消除了模型拒绝或表达不确定性的能力。模式要求一个值,模型便会提供一个值,无论输入是否支持。
跨字段矛盾
模式验证会单独检查每个字段,但从不检查字段之间是否相互一致。情感提取器可以返回 {"sentiment": "positive", "score": 0.1}——一个积极标签,但分数接近零(应该意味着消极)。日期解析器可以返回 {"start": "2026-03-15", "end": "2026-03-10"}——结束日期早于开始日期。
这两种输出都通过了每个单独字段的验证。一旦将记录作为整体来看,两者都没有意义,而任何单字段验证器都无法捕获这种错误,因为约束存在于字段之间,而非任何一个字段内部。
分布坍缩
模型针对不同输入收敛到安全、通用的值。约束解码偏向有效集合中的高概率 token,而“安全”默认值(如 0.95, "medium", "general")比特定上下文的值具有更高的基础概率。
我是在分类管道中的置信分数连续三周停滞在 0.98 时才发现的。Collin Wilkins 记录了一个类似案例,其中每次输出(包括乱码)的置信度均为 0.99。每条记录都有有效的类型、正确的枚举和合理的数字。分布已经停止移动,但没有任何警报触发,因为每个单独的输出在结构上都是正确的。
数组幻觉
模型倾向于不返回空数组。在约束解码下,[] 是一个低概率 token 序列,因为语法将生成对象的路径加权得比空数组路径更高。当模式要求 items 字段为数组类型时,模型会捏造条目而不是返回空值。
在提取任务中,这会产生幻影结果:当正确答案为零时,你的管道报告“找到 3 个匹配项”。
失败模式总结表
| 失败模式 | 信号 | 根本原因 | 检测方法 |
|---|---|---|---|
| 枚举幻觉 | 值分布偏斜 | 语法选择了有效但上下文错误的 token | 按字段追踪值分布 |
| 自信伪造 | 自由文本与输入无关 | 模式强制要求值,模型被迫生成 | 语义相似度检查 |
| 跨字段矛盾 | 字段间逻辑冲突 | 单字段验证无法捕获跨字段约束 | 定义跨字段校验规则 |
| 分布坍缩 | 输出多样化退化 | 约束解码偏向高概率默认值 | 监控分布熵 |
| 数组幻觉 | 空数组被填充 | 语法中空数组路径概率低 | 检查空数组频率 |
参考资料
- BAML 基准测试与案例研究
- Lee 等人关于结构化输出代价的论文
- Tam 等人关于格式规则与推理能力的研究
- Collin Wilkins 关于置信度坍缩的案例分析
评论已关闭