结构化输出实战:为什么你的 AI 总返回非法 JSON

📅 2026/9/18 ✍️ 小文 📖 约 1 分钟

调用 AI 拿结构化数据,最烦的就是偶发的非法 JSON。本文讲清约束解码、JSON Schema、重试与校验的完整方案,附可直接用的模板。

一个让人抓狂的日常

你用 AI 提取数据,提示词里明明写了”只返回 JSON”,但总有一两次它给你加一句”好的,这是结果:“,或者少个逗号、多个注释。解析一失败,整条流水线就崩。

很多人的做法是”再包一层 try/except,失败重试”。这是治标不治本——重试成本高,还会掩盖真正的问题。

第一步:搞清三种可靠性等级

结构化输出有三档,可靠性天差地别:

  • 第一档:提示词约束。只在提示里写”返回 JSON”。最不可靠,模型有概率违反。
  • 第二档:JSON 模式(JSON Mode)。API 保证输出是合法 JSON,但不保证字段符合你的 schema。
  • 第三档:约束解码(Structured Outputs / Schema 约束)。API 保证输出严格符合你给的 JSON Schema。最可靠。

核心认知:只要能用第三档,就别用第一档。 现在主流厂商的旗舰模型都支持 schema 级约束,这是根治方案。

第二步:把 Schema 设计对

即便有约束解码,schema 设计不好照样出事。几个铁律:

1. 必填字段要少而稳

把所有字段都设成 required,模型没把握时只会硬编。让模型能说”我不知道”——加一个 uncertain 布尔字段或 null 类型。

2. 用 enum 替代自由文本

如果需要模型输出”高/中/低”这种有限取值,用 enum 而不是 string。约束解码会把输出限制在枚举里,从根上杜绝”比较高”这类越界值。

3. 拒绝深层嵌套

schema 越深,模型越容易在中间层出错。能拍平就拍平,用扁平结构 + 引用 ID 代替深层嵌套。

4. 数值加边界

minimum / maximum 参数,防止模型返回负价格、超过 100 的百分比。

第三步:校验层不能省

即使有约束解码,服务端必须再校验一遍。原因:

  • 约束解码保证”符合 schema”,但不保证符合业务规则
  • 比如格式对但逻辑错:数量为 0、日期为未来、ID 不存在

用 Zod、Pydantic 这类库做语义校验,把 format 之上的业务规则兜住。schema 管形状,校验管对错。

第四步:重试要”带上错误”

如果确实要重试,别傻重试。把校验失败的报错原文塞回下一轮提示:

上一次输出校验失败:字段 price 必须大于 0,你返回了 -5。请修正后重新输出。

这叫错误反馈重试,成功率比无脑重试高得多。同时设上限(比如 2 次),避免死循环烧钱。

一个完整的容错流程

  1. 用约束解码请求,schema 明确、字段精简
  2. 服务端用 Pydantic/Zod 做形状 + 业务双重校验
  3. 失败则带错误信息重试,最多 2 次
  4. 仍失败则降级:落日志、转人工、返回默认值
  5. 所有失败进监控,看是偶发还是系统性问题

常见坑

  • 把 JSON Mode 当 Structured Outputs:前者只保证合法,不保证 schema,别搞混
  • schema 太复杂:字段超过 20 个就要考虑拆分任务
  • 忽略降级路径:没有兜底,一次失败就炸穿
  • 不做失败监控:失败率悄悄涨到 5% 你都发现不了

一句话总结

结构化输出要可靠,靠四层防线:约束解码保形状、schema 设计防越界、服务端校验保业务、错误反馈重试做兜底。别再用提示词求模型”乖一点”了——把可靠性交给机制,而不是祈祷。

📤 分享到