让模型稳定输出 JSON 的几个层次

2026 / 10 / 12#json#prompt#工程

层次一:提示里写清 schema

给出字段名、类型、是否可空,最好带一个完整示例:

只输出一个 JSON 对象,不要 Markdown 代码围栏,不要任何解释文字。
结构:
{"title": string, "tags": string[], "score": number}

这一层能解决大部分场景,但不保证。总会有一小部分输出带前后缀或多余换行。

层次二:解析时容错

不要假设输出永远干净。常见处理:

  • 去掉 ```json 和 ``` 围栏
  • 取第一个 { 到最后一个 } 之间的子串
  • 解析失败就重试一次,并在重试时把错误信息一起喂回去
try {
  return JSON.parse(raw);
} catch {
  const m = raw.match(/\{[\s\S]*\}/);
  if (m) return JSON.parse(m[0]);
  throw new Error("unparseable");
}

"解析失败重试"这个动作能覆盖掉一大半偶发问题,成本极低。

层次三:用结构化解码约束

要真正稳定,靠提示是不够的,得在生成时限制候选 token:

  • 支持 function calling / tool use 的接口,把参数定义交给 API
  • 支持 JSON Schema 约束(结构化输出)的接口
  • 本地推理可以用语法约束解码(grammar-constrained decoding),直接把输出空间限制成合法 JSON

这一层是数学上保证输出符合 schema,不依赖模型听话。

怎么选

场景 层次
内部脚本、偶尔跑一次 一 + 二
线上服务、结果直接入库 二 + 三
输出要进强类型系统 必须三

一个提醒

即使 schema 完全合法,语义也可能错 —— 字段都在、类型都对,但值是编的。格式校验和事实校验是两件事,别把前者当成后者的保证。

本文为个人学习记录,可能存在错误或已过时,仅供参考。
← 返回笔记列表