约束解码的生成:从逐 token 采样,到“知道下一步是什么”
生成一段 JSON 时,模型其实有 95% 的时间都在做“确定的重复”:{、"、字段名、:、}。真正需要模型“想”的,可能只有每个字段的值。那能不能告诉解码器:这些位置不用采样,直接填?如果再把“猜下一步”交给一个更快的草稿模型,生成会不会快好几倍? 本文是围绕这个问题的技术分享,面向已经接触过 LLM 推理、想理解约束解码来龙去脉的读者。主线是:约束解码解决什么问题 → 方法如何一步步演进 → 关键证据支持哪些结论 → 实践中的经验与边界。 核心猜想:约束解码里大量内容是确定性重复(固定字段、括号、键名),能否把“确定的部分直接跳过采样、交给更快的前向”做成加速?这条主线贯穿全文,也是约束解码与投机解码(speculative decoding)能走到一起的原因。 问题与背景 约束解码要解决的核心问题:输出必须满足结构约束(正则、JSON Schema、CFG),且正确性要有保证,而不是“运气好碰对格式”。 约束解码与普通解码的差别在于,每一步都要回答“哪些 token 合法”。这个查询与 mask 本身有成本,于是出现两条演进方向: 约束怎么表达:从“必须包含指定词”(集合级约束),到“必须匹配某种语法”(FSM 可判定的约束)。 约束怎么不花钱:从逐 token 串行查表,到预计算、跳确定部分、与 GPU 前向重叠、最后与投机解码并行验证。 下文按“问题 → 方法 → 证据”展开,论文链接直接列在对应方法处。 一、早期约束解码:约束做进搜索过程 约束解码最早解决的问题是“输出必须包含某些指定内容”——不是格式合法,而是句子里必须出现某个词或短语。早期方法把约束做进 beam search 的搜索过程。 Grid Beam Search(Hokamp & Liu, ACL 2017) 论文:Lexically Constrained Decoding for Sequence Generation Using Grid Beam Search 链接:https://aclanthology.org/P17-1141/ 、 arXiv:1704.07138 方法 约束定义为“输出必须包含一组指定的短语/词”。 模型在 beam 上扩展时,额外维护一个“已覆盖约束”的状态,beam 排序优先覆盖更多约束的候选。 约束是集合级的“必须包含”,不要求前缀匹配,可以出现在输出任意位置。 判断:这一代方法把约束做进搜索,正确,但只覆盖“必须包含词”这一种约束,且 beam 扩展成本随约束数量上升。它的意义是确立了“约束进解码过程”的范式,而不是进训练或后处理。 ...