结构化输出模式
让返回结果每次都可被机器解析:显式契约、枚举纪律、NULL 出口,以及校验修复循环。
「返回 JSON」这句话的问题
要求返回 JSON,不等于真的能拿到 JSON。你可能得到裹在反引号里的散文、尾随逗号、对象前面的一段闲话,或者几乎匹配 schema 的键名。
三个动作能修掉绝大部分问题。
1. 陈述契约,而不是描述它
把确切结构连同类型写出来:
只返回符合以下结构的 JSON 对象,前后不要任何说明文字:
{
"verdict": "pass" | "fail",
"severity": 1 | 2 | 3,
"issues": [{ "file": string, "line": number, "note": string }],
"confidence": number // 0.0 - 1.0
}
写成 "pass" | "fail" 胜过写「pass 或 fail 之一」——模型看到的是可以直接输出的字面 token。
2. 允许它弃权
没有退出口,模型就会编造而不是承认不确定。要显式给出一个选项:
如果输入信息不足,请返回:
{ "verdict": "unknown", "missing": ["<你还需要什么>"] }
仅此一项就能大幅减少自信胡说,因为「我不知道」变成了合法答案。
3. 校验并修复,但要设上限
第 1 次 → 解析失败 → 附上错误信息重试
第 2 次 → 解析失败 → 上报或返回 null
把解析错误原样喂回去(Unexpected token } at position 214)——模型对具体错误的纠正能力很强。绝不无限重试,两次后就退出。
选择强制力度
| 方式 | 可靠性 | 成本 | 何时用 |
|---|---|---|---|
| 提示词中的契约 | 良好 | 免费 | 默认起步方案 |
| 校验 + 重试 | 很好 | 失败时多一次调用 | 大多数场景 |
| 原生 JSON/schema 模式 | 近乎完美 | 少量开销 | 严格流水线 |
先用提示词契约。立刻加上校验——它很便宜,能兜住剩余问题。只有在解析失败完全不可接受时才升级到原生 schema 强制。
实测有效的排版细节
- 格式说明放在最后,紧贴输入之前。结尾处的指令被遵循得更可靠。
- 在正文里重复字段名,不要只出现在示例中——冗余线索有帮助。
- 避免过深嵌套。 三层以上准确率开始下滑,能压平就压平。
- 优先用「扁平对象组成的数组」,而不是以任意字符串为键的对象。
什么时候不该用结构化输出
聊天回复、解释说明,以及任何人类直接阅读的内容都不需要。在对话场景里强塞 JSON 会让答案变差,而集成也没变简单。真需要结构时,在对话之后再抽取。