Synth Daily

结构化输出容易制造虚假信心

强制模型输出结构化数据(如 JSON)虽然能保证格式正确,但会牺牲内容的准确性和灵活性。这种方法通过“约束解码”实现,它限制了模型的选择,使其优先满足格式要求而非提供最优质的答案。实践表明,这会导致数据提取错误、无法妥善处理异常情况(如输入一张大象图片而非收据),并削弱了“链式思考”等高级推理技巧。因此,更好的方法是让模型自由生成文本,然后再用代码解析所需信息,这样既能获得更高质量的结果,也能更有效地处理错误和意外情况。

结构化输出的虚假信心

尽管看起来很方便,但直接使用语言模型(LLM)的结构化输出功能,会比让它自由生成文本得到更差的结果。这会带来几个严重问题:

  • 更容易出错: 即使在简单的数据提取任务中,也更容易出现错误。
  • 错误处理不当: 模型无法灵活地报告输入数据的问题。
  • 推理能力下降: 会削弱像“链式思考”(Chain-of-Thought)这类提升模型表现的关键技术。
  • 潜在安全风险: 在极端情况下,更容易受到提示注入攻击。

以从收据图片中提取数据为例,当使用 OpenAI 的结构化输出 API 时,模型可能会错误地将 0.46 公斤的香蕉识别为数量 1。然而,如果使用相同的模型,但让它自由生成文本并附上 JSON,它就能正确识别出 0.46 这个数值。

异常情况处理的难题

当你强制模型必须输出一个符合预定格式的对象时,你也剥夺了它处理异常情况的能力。

如果你让模型解析一张收据,但给它的是一张大象的图片,你希望它能告诉你:“这是一张大象,不是收据。”

强制结构化输出会让模型陷入困境,它不得不生成一个毫无意义但格式正确的对象。这就像填写一份有5个必填项的错误报告,但这些选项都与你的问题无关,你只能随便填一些无用的信息才能提交。

有人可能会说:“我可以设计一个包含错误类型的更好格式!” 但这也很难做到。你需要预见所有可能的错误:总金额缺失、部分项目无法识别、甚至是有人上传大象图片。当你把太多关于错误的描述放进提示词里,反而会诱导模型更容易返回错误。

削弱模型的推理能力

“一步一步地解释你的推理过程”是提升模型智能表现的常用技巧,但在结构化输出模式下,这个技巧的效果会大打折扣。

直观地理解,可以把模型的智能想象成一份“预算”。如果你强迫它按照非常特定的格式进行推理和输出,就等于在让模型把宝贵的智能点数浪费在无用的格式整理工作上,比如在 JSON 字符串中处理换行符和引号的转义。

在自由文本模式下,模型可以先进行推理,然后给出最终的 JSON 答案:

逐步分析可得:
1. 这封邮件来自亚马逊,确认了订单状态。
2. 主题行显示订单已发货。
...
综合以上几点,输出的 JSON 如下:
{ "order_status": "SHIPPED", ... }

这个完整的回答本身不是一个有效的 JSON,但它包含了高质量的推理和准确的 JSON 数据。而结构化输出则无法兼容这种自然的推理过程。

技术根源:约束解码

结构化输出的实现依赖于一种叫做 约束解码(constrained decoding) 的技术。它在模型生成每一个词(token)时进行干预,只允许模型选择那些符合预设格式的词。

例如,如果模型已经生成了 {"quantity": 51,并且格式要求 quantity 是一个整数:

  • 模型想生成 {"quantity": 51.2,但 . 这个符号会被禁止,因为它不符合整数格式。
  • 模型只能被迫选择 ,} 等能构成有效 JSON 的符号。

这种约束确保了输出格式的合规性,但代价是牺牲了内容的质量。你强迫模型优先遵守你的格式,而不是返回它认为最准确的答案。

最佳实践:解析自由文本

解决方案其实很简单:让模型做它最擅长的事——生成自然语言。

允许模型以自由形式回应,这样它就可以:

  • 拒绝执行不合理的任务。
  • 在你提供矛盾信息时发出警告。
  • 在你无意中要求它使用错误方法时,告诉你正确的方法。

使用约束解码的结构化输出会让模型很难做到以上任何一点。虽然你得到了一个格式完美的保证,但这个保证是以牺牲回答质量为代价的。这就是为什么说结构化输出会制造一种 “虚假信心”:你为了格式的规整,在不知不觉中放弃了内容的准确性。

相比之下,解析模型的自由文本输出,才能让你保留最高的输出质量,这也是提升 LLM 应用可靠性的有效途径。