跳到主要内容

Markdown 优于 JSON:你正在支付却未察觉的输出格式税

· 阅读需 12 分钟
Tian Pan
Software Engineer

大多数团队在上线当天开启 JSON 模式,却从未衡量这背后的代价。这种假设合情合理:结构化输出能保证正确性,为什么不选它呢?答案是,严格的 JSON 模式约束解码通常会使数学、符号和多步分析任务的推理准确度降低 5–15%,而由于评估是在开启格式标志之前运行的,或者评估衡量的是可解析性而非质量,因此没人注意到这一点。

输出格式是一种解码时的约束,正如所有约束一样,它会扭曲模型的概率分布。当你查看日志时,这种扭曲是不可见的:JSON 有效,Schema 匹配,字段类型也对得上。你在日志中看不到的是模型本可以用散文形式产出的推理过程,但由于无法塞进你给定的语法中而消失了。“格式税”是真实存在的,在文献中已有详尽记录,但在生产环境中几乎普遍未被衡量。

这篇文章将探讨何时该支付这笔费用,如何在不必支付时及时止损,以及对于既想要结构化输出又想要准确性的工程师来说,格式选择的决策树究竟是什么样的。

机制:为什么约束解码会损害质量

在每个解码步骤中,语言模型都会在其词表上生成一个概率分布。约束解码应用了一个 Logit 掩码:任何违反目标语法的 Token 其概率都会被清零,剩余的 Token 会进行重新归一化。从结构上讲,这很整洁——输出保证可以解析。从统计学上讲,这是模型对自己分布撒的一个谎,而且这个谎言会产生复利效应。

实践中出现了两种特定的失效模式。第一种是 Token 切分接缝(tokenization seam)。模型是针对常见字符串的特定 Token 切分方式进行训练的——“because”一词在散文中有一种切分方式,在 JSON 左引号后则是另一种,模型在训练期间学到的概率质量集中在第一种切分方式上,而非第二种。当语法强制执行第二种切分路径时,模型是在处理一个预训练期间极少见的序列。输出质量会微妙地下降——语法正确,但语义变薄了。

第二种是字段顺序陷阱。像 {"answer": string, "reasoning": string} 这样的 JSON Schema 看起来无害,实则是灾难性的:模型被迫在生成任何推理 Token 之前先输出答案 Token。模型原本用于检查工作的思维链(Chain-of-thought)现在要么缺失了(如果模型将答案字段视为终止),要么是事后为了匹配已做出的决定而伪造出来的。《Let Me Speak Freely?》论文 (arxiv 2408.02442) 记录了在更严格的格式约束下,GSM8K、Last Letter 和 Shuffled Objects 任务的准确率大幅下降,原因正在于此。

不同格式间的经验差距

格式选择在不同任务中并不是中性的。在选择默认格式之前,有几个 2024–2026 年间的衡量结果值得深入理解:

  • 推理任务在严格 JSON 模式下表现下降。 《Let Me Speak Freely?》研究表明,从自然语言提示转向格式受限的 JSON 指令会导致推理基准测试的准确度显著下降。采用“自然语言转格式”(NL-to-Format)的二阶段方案——即先生成散文,再进行转换——可以将性能恢复到接近无限制的水平。
  • 分类和提取任务在 JSON 模式下可能会提升。 同一篇论文发现,在 DDXPlus 和类似的分类数据集上,JSON 模式表现出色,有时甚至更好,因为约束以任务所需的方式压缩了输出空间。
  • 格式偏好取决于模型。 针对提示格式的研究 (arxiv 2411.10541) 发现,GPT-3.5-turbo 在不同模板的代码翻译任务中表现差异高达 40%,且偏好 JSON;而 GPT-4 更偏好 Markdown,且对格式变化的鲁棒性更强。大型模型能更好地吸收“格式税”;小型模型则会将其弊端暴露无遗。
  • Token 成本并非旗鼓相当。 对于相同的嵌套内容,Markdown 使用的 Token 比 JSON 少约 34–38%,而 XML 需要的 Token 比 Markdown 多约 80%。在输出端,你会在每次请求中支付两次这笔税——一次是金钱成本,一次是延迟。
  • 约束解码并非百害而无一利。 JSONSchemaBench 显示,在像 GSM8K 这样结构极简的任务中,约束解码实际上可以通过让模型保持在轨道上,将下游性能提升高达 4%,并使生成速度提高约 50%。情况非常微妙:损害特定于那些语法阻断了模型原本会采取的推理路径的任务。

如果你只能记住一个校准点,那就是:模型越小,推理任务越重,且 Schema 中答案早于推理时,格式税就越沉重。而在提取任务中、在大型前沿模型上,以及当 Schema 与任务契合时,格式税最轻。

三种格式:按其实际用途排名

Markdown:适用于推理和散文

当模型需要思考时,Markdown 是目前摩擦力最低的输出格式。它不强加任何语法,没有 logit 掩码,也没有模型在预训练中没见过千万次的 token 分词边界。列表符号、标题和代码块都是训练分布中原生存在的。对于任何以推理的正确性或完整性为主要质量指标的任务——如 Agent 规划、多步调试、以及需要权衡上下文的客户支持——Markdown 应该作为默认选择。

Markdown 的弱点在于机器解析。将 Markdown 解析为下游的类型化字段是非常脆弱的。如果你的工作流中下一步是人类阅读输出,Markdown 胜出;如果下一步是需要 {city: string, temperature: number} 的函数,Markdown 则会落败。

XML 标签:用于提取和边界设定

XML 标签占据了一个非常有用的中间地带。它们具有足够的结构来可靠地界定字段——例如 <quote>...</quote><answer>...</answer><reasoning>...</reasoning>——但又足够轻量,不会强制进行受限解码。模型是在编写带有标记的散文,而不是在语法中穿行。

Anthropic 专门训练了 Claude 来识别 XML 标签作为提示词组织机制,这种模式在两个方向上都有效:作为输入结构和作为输出结构。对于提取任务(“提取文档中提到的所有日期”)以及混合了散文和结构化内容(推理块后跟结构化摘要)的任务,XML 标签能为你提供 90% JSON 的可解析性,同时保持接近 Markdown 的生成质量。

其缺点是冗余。在三种格式中,XML 是最消耗 Token 的。如果你是按输出 Token 付费,包含大量 XML 的响应是最昂贵的选择——成本大约是同等 Markdown 内容的两倍。

严格 JSON(强制 Schema):用于机器间的交付

严格 JSON 模式——无论是 OpenAI 的结构化输出、Anthropic 的工具调用,还是像 Outlines 这样基于 FSM 的库——当输出必须在没有人工干预的情况下直接进入代码时,是正确的选择。API 响应、工具参数、数据库写入、服务间消息。下游消费者是一个解析器,一个格式错误字段的代价要高于损失几个百分点的推理质量。

诀窍是不要过早地使用严格 JSON。一个仅写着“以 JSON 响应”并给出一个松散示例的系统提示词,与带有 logit 掩码的严格 Schema 强制解码完全是两回事。松散版本付出了大部分格式税(模型仍倾向于生成 JSON 形状的输出),却几乎没有任何保证。严格版本付出了全部税,并得到了全部保证。中间地带——没有 Schema 的 “JSON 模式”——通常是两头不讨好。

双重传递模式:兼而有之

“自然语言转格式”模式是大多数团队尚未尝试过的、投资回报率(ROI)最高的提示工程技巧。它通过两次调用完成:

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates