来自一次近期对比的简短笔记。我们需要让 LLM 产出结构化输出(符合一个带嵌套对象与条件必填字段的非平凡 JSON 架构)。我们在同一模型与同一输入集上对四种受约束生成方案做了基准测试。

所讨论的架构(节选):

{
  "type": "object",
  "required": ["finding", "evidence", "confidence"],
  "properties": {
    "finding":    { "type": "string", "minLength": 20 },
    "evidence":   {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["source_id", "tier"],
        "properties": {
          "source_id": { "type": "string", "pattern": "^SRC\\.[0-9]+\\.[0-9]+$" },
          "tier":      { "enum": ["A", "B", "C", "D", "E"] },
          "page":      { "type": "integer", "minimum": 1 }
        }
      },
      "minItems": 1
    },
    "confidence": { "enum": ["HIGH", "MED", "LOW", "UNVERIFIED"] },
    "open_questions": { "type": "array", "items": { "type": "string" } }
  },
  "if":   { "properties": { "confidence": { "const": "UNVERIFIED" } } },
  "then": { "required": ["open_questions"] }
}

设置

  • 1,000 条输入提示,每条要求输出匹配一个含 14 个字段、3 个嵌套对象、4 条条件必填规则的架构。
  • 四个后端使用相同基础模型。
  • 测量:架构符合率(输出能否按架构通过校验)、语义正确率(在符合架构的前提下是否给出正确答案)、完成所需令牌数(效率指标)。

结果

后端符合率语义正确率完成所需令牌
1. 原生函数调用(厂商特性)99.6%91.2%基线
2. 语法受约束解码(开源)100.0%90.4%+18%
3. 通过 JSON 架构受约束采样99.8%91.0%+6%
4. 仅提示词("按此架构以 JSON 回应")86.4%89.7%-2%

我们的读法

  • 在这个架构上,前三种可互换。厂商原生函数调用最快——无需额外解码遍。语法受约束在校验上最彻底但最慢。架构受约束采样是不错的中间档。
  • 在此规模与场景下,仅提示词方案不可行。13.6% 的不符合率即便在语义质量尚可的情况下,也意味着大约每 7 条输出就有 1 条校验失败需要重试——这会抵消其延迟优势。
  • 语义正确率与约束后端基本无关。无论架构如何强制,模型在做的事都是同一件事。

这对我们的工作意味着什么

对于交付物为结构化生成管道的客户委托,我们现在默认推荐:在可获得的情况下使用厂商原生函数调用,开源回退方案为语法受约束解码。我们不推荐为任何下游消费者依赖符合性的场景使用仅提示词架构强制——而绝大多数场景都属此类。

注意事项

  • 单一模型、单一架构。我们尚未测试这一符合率排序是否在跨模型家族或更深嵌套架构上仍然成立。早期工作的经验性结果表明,随着架构嵌套加深,语法受约束方案优势会进一步拉开,但我们未做严格基准测试。
  • 完成所需令牌只是粗略的效率代理;真实延迟取决于不在我们测量范围内的厂商实现选择。