跳到正文
docai.cc

DOCAI · 课程 · L2 · 30 分钟

让模型稳定输出 JSON

从「求它输出 JSON」换成「约束它只能输出 JSON」:一条 schema、两次校验、一个失败兜底,构成能上生产的三件套。

你将学会

  • 用 schema 而不是靠提示词约束输出格式
  • 在代码里做两层校验:格式校验与业务校验
  • 给解析失败设计一个能继续跑的兜底

第一步:别靠提示词

在提示里写「请只输出 JSON」,能用的概率不低,但不是保证。 模型可能加解释、加代码块、把字段改成中文名。这些都会让解析失败。

正确做法是让服务在解码层约束:

  • 有原生结构化输出的,直接给 schema;
  • 没有的,用工具调用:把 schema 定义成一个工具的参数。

两种方式都比提示可靠,因为它们不让模型生成不合法的东西。

第二步:写一份克制的 schema

{
  "type": "object",
  "properties": {
    "title":    { "type": "string" },
    "category": { "type": "string", "enum": ["bug", "feature", "question"] },
    "summary":  { "type": "string" },
    "confidence": { "type": "string", "enum": ["high", "low"] }
  },
  "required": ["title", "category", "summary"]
}

四条经验:

  1. 字段控制在 5–6 个;
  2. 能枚举就别用自由文本;
  3. 必填字段要少而准;
  4. 留一个 confidence 或 notes,让模型把不确定写出来。

第三步:两层校验

第一层:能不能 parse?
第二层:字段值是否满足业务规则?

第二层最容易被忽略:格式对了,但金额是负的、日期是未来、分类不在允许范围。 schema 管形状,代码管业务。

第四步:失败兜底

解析失败时不要直接抛错给用户。可选方案:

  • 重试一次,并把错误信息附在提示里(「上次输出缺少 category 字段」);
  • 降级成纯文本输出,人工处理;
  • 进失败队列,稍后重跑。

选哪个取决于业务:客服场景可以降级,财务场景应该进队列。

一个完整流程

  1. 用户输入 → 组装提示(含 schema)。
  2. 调用模型,拿到结构化结果。
  3. 校验格式,失败则重试一次。
  4. 校验业务规则,失败则记日志并按策略处理。
  5. 通过后写入,保留原始响应以便追溯。

常见错误

  • 只在提示里写格式:等于没有约束。
  • schema 过严:信息不足时模型会硬填,不如允许 null。
  • 不存原始响应:出问题时无法复现。
  • 忽略流式:流式输出下 JSON 是分片的,要按完整响应解析。

自测

  1. 你的解析失败率是多少?有没有被监控?
  2. 失败时是重试、降级,还是直接报错?哪种对用户更好?

下一步

涉及的概念