Skip to content
🔗 分享本题
查看我的学习进度 →

记忆点:JSON Mode 只管语法,Structured Outputs 管 Schema 字段,Constrained Decoding 管整个语言结构。

💡 答案要点

三者的本质区别在于「约束层级」不同:

┌───────────────────────────────────────────────────────┐
│ Layer 1: JSON Mode                                   │
│   → 只保证输出是合法 JSON                             │
│   → 不保证字段名、类型、必填项                        │
│   → 代价:最低                                        │
├───────────────────────────────────────────────────────┤
│ Layer 2: Structured Outputs (OpenAI)                  │
│   → JSON + 严格 Schema 校验                           │
│   → 模型训练时学习了 Schema 的结构                     │
│   → 代价:中等                                        │
├───────────────────────────────────────────────────────┤
│ Layer 3: Constrained Decoding                        │
│   → CFG(上下文无关文法)/ Regex 驱动 token-by-token  │
│   → 在采样阶段就禁止非法 token                         │
│   → 不依赖模型能力,纯解码器侧约束                      │
│   → 代价:最高(需要编译 Grammar)                     │
└───────────────────────────────────────────────────────┘

Constrained Decoding 的核心原理:

传统解码:
  候选词: ["价格", "价钱", "cost", "$", ...]
  softmax → 选 top-k → 可能选出 "$"

约束解码(CFG 语法: Number -> Int | Float | Dollar):
  候选词: ["价格", "价钱", "cost"] ← "$" 被直接排除!
  softmax + 掩码 → 只在合法词中选

主流实现方案:

python
# 方案1: Outlines - 基于 EBNF 语法的约束解码
import outlines
from outlines import generate

date_pattern = r"\d{4}-\d{2}-\d{2}"
regex_schema = f"""
    date: {date_pattern}
    status: "success" | "pending" | "failed"
    message: "[^""]*"
"""
response = outlines.generate.regex(llm, regex_schema)(prompt)

# 方案2: LMQL - Query Language for constrained generation
from lmql import query, args

@query(returns=f"{{int}}")
def answer(question: str) -> int:
    """强制返回整数"""
    """LMQL
    { response := random({question}) }
    return response >= 0
    """

# 方案3: Guidance (Microsoft)
import guidance

guide = """
{{#\system}}{{user}}Calculate the sum of 23+45.
{{#assistant}}The result is {{num|gen(regex=r'\d+', max_tokens=2)}}.
{{/assistant}}{{/user}}{{/system}}
"""
result = guidance.llm(guide, max_tokens=10)

选型决策树:

只需要合法 JSON? → JSON Mode
需要 Schema 字段校验?→ Structured Outputs
需要嵌套复杂格式/自定义语言?→ Constrained Decoding
需要确保数学/逻辑推理结果格式?→ Constrained Decoding
需要与传统 AI 系统集成(Java/C++ 等不支持新 API)?→ Constrained Decoding

面试加分点:

  • Constrained Decoding 的优势是不依赖模型能力——即使用很小的模型也能输出正确格式
  • 缺点是编译 Grammar 有成本,且某些复杂结构难以表达为 CFG
  • 工业实践中经常采用双层策略:先用 Structured Outputs 生成,再用 Post-parse 验证兜底

面试话术:

"JSON Mode 只管语法合法性,Structured Outputs 进一步做了 Schema 约束,而 Constrained Decoding 是在 token 级做语法约束。三层方案层层加码,约束力越来越强但延迟也越高。我在项目里用过 Outlines 处理复杂的嵌套 JSON,准确率接近 100%,但 Grammar 编写成本需要评估。生产上推荐 Structured Outputs 为主、Constrained Decoding 兜底的策略。"