日常居 AI、SEO与投放的一些笔记
AI 应用工程

用 JSON Schema 约束模型输出,边界在哪

2026-09-15 · AI 应用工程

让模型返回 JSON,然后 JSON.parse —— 这是最容易翻车的地方。模型会在 JSON 前后加解释,会在字符串里塞未转义的引号,会在数组末尾多一个逗号。

现在的模型大多支持结构化输出(response_format 或工具调用),能保证返回合法 JSON。但"合法"不等于"符合你的业务预期"。

它能保证什么

  • 返回一定能被解析成 JSON
  • 你定义的必填字段一定存在
  • 枚举字段一定是枚举里的值
  • 数字字段一定是数字类型,不是字符串

这四条已经解决了绝大部分解析崩溃。

它不能保证什么

一、内容质量

字段存在,但值是空的、是无意义的填充、或者跟原文不符。schema 管不了这个,只能靠提示词和评估。

二、长度限制

你写 description: 不超过 50 字,模型可能给你 120 字。schema 层面没有长度约束的强制力。工程上要在拿到结果后截断或重新请求。

三、嵌套深度

嵌套三层以上的 schema,模型出错率明显上升。我们试过五层嵌套的配置对象,字段错位的情况经常出现。现在的原则是最多两层,更深的拆成多次请求。

四、数组元素的一致性

要求返回 10 个对象,每个对象有相同的键。实际经常出现前 8 个有 reason 字段,后 2 个没有。这不是 schema 的问题,是模型在长输出后期"忘了"。

解决办法是把数组拆小:一次最多 5 个,分批请求。虽然多了几次调用,但稳定性提升明显。

一个实际的设计取舍

我们有个抽取任务,要从合同里抽出甲乙方、金额、期限、违约条款。最早设计成一个对象,一次抽完。

问题是一份合同十几页,模型经常漏字段。后来改成分三次请求:主体信息、金额与期限、条款摘要。每次只关注一小块,准确率从 72% 提到 91%。

代价是三次调用的成本,但比起人工返工,这笔账划算。

兜底还是要写

即使有结构化输出,解析失败也要有兜底。我们的做法是:解析失败 → 用更小的模型重试一次(小模型在简单 schema 上反而更稳)→ 还失败就转人工队列。

不要写"重试三次还失败就抛异常",用户看到的应该是"这条需要人工确认",不是 500 错误。

← 更新的一篇冷启动期别乱调价
更早的一篇 →更新老文章,比新写十篇更有效
← 返回首页