如何让大模型稳定输出json
在大模型应用里,让模型“稳定输出 JSON”是一个非常常见、也非常容易被低估的问题。很多人一开始会在提示词里写一句“请以 JSON 格式返回”,但上线后很快会遇到各种小事故:模型多说了一句解释、字段名拼错、数组变成对象、布尔值变成字符串、输出里混入 Markdown 代码块,或者在复杂任务中漏掉必填字段。
稳定输出 JSON 的关键,不是单靠一句提示词,而是把“输出格式”当成一个完整的工程约束来设计:从提示词、Schema、模型接口、解析校验、失败重试到业务降级,都要形成闭环。
一、先明确 JSON 的边界
让模型输出 JSON 前,首先要想清楚:你到底需要模型输出什么。
很多不稳定来自需求本身不清楚。例如:
请分析这篇文章,并返回结构化结果。
这句话对人来说好像能理解,但对模型来说边界很模糊。结构化结果里应该有哪些字段?字段类型是什么?可以为空吗?枚举值有哪些?数组最多多少项?如果文章没有相关信息该怎么办?
更好的方式是先定义清楚数据结构:
{
"title": "string",
"summary": "string",
"keywords": ["string"],
"sentiment": "positive | neutral | negative",
"confidence": 0.0
}
当输出边界清楚后,模型才有机会稳定;当边界不清楚时,后面的解析和重试都只是在补锅。
二、使用明确的 Schema,而不是自然语言描述
自然语言提示可以帮助模型理解任务,但 JSON 结构最好用 Schema 或样例表达。Schema 比普通描述更精确,也更容易在程序里复用。
例如,可以在提示词中写:
你必须只返回一个合法 JSON 对象,不要返回 Markdown,不要返回解释文字。
JSON 结构如下:
{
"is_relevant": boolean,
"category": "product" | "operation" | "finance" | "other",
"reason": string,
"tags": string[]
}
字段要求:
- is_relevant: 判断内容是否与业务相关。
- category: 只能从给定枚举中选择一个。
- reason: 用一句话说明判断依据。
- tags: 返回 0 到 5 个关键词。
这里有几个要点:
- 说明“只返回 JSON”。
- 给出完整结构。
- 标明字段类型。
- 标明枚举范围。
- 标明数组长度或数量限制。
- 说明空值处理方式。
越是机器要消费的内容,越不能只靠“你应该懂”的默契。
三、优先使用模型接口的结构化输出能力
如果你使用的模型 API 支持结构化输出、JSON Schema、函数调用或工具调用,优先使用这些能力,而不是只靠提示词。
相比普通文本生成,结构化输出能力通常可以在解码阶段约束模型,让它更接近“按格式生成”,而不是“生成一段看起来像 JSON 的文本”。
常见方式包括:
- JSON mode:要求模型输出合法 JSON。
- JSON Schema:要求模型输出符合指定 Schema 的 JSON。
- Function calling / Tool calling:让模型填充函数参数。
- Constrained decoding:在生成过程中限制可选 token。
在生产环境中,推荐优先级通常是:
结构化输出 / Tool calling > JSON mode > 强提示词 + 后处理
提示词仍然有用,但它应该是辅助说明,而不是唯一防线。
四、提示词里不要制造格式冲突
很多 JSON 输出不稳定,是提示词自己造成的。
例如:
请用 JSON 返回结果,并解释你的思考过程。
这句话同时要求模型输出 JSON,又要求解释思考过程。模型可能会在 JSON 外面补充说明,也可能把解释塞进某个字段里,最终导致解析失败。
再比如:
请返回如下格式:
```json
{
"answer": "..."
}
如果你不希望模型输出 Markdown 代码块,就不要在最终格式里强调代码块。样例可以用,但必须明确:
```text
下面只是结构示例。最终输出不要包含 ```json 或 ```。
稳定输出 JSON 的提示词应该保持单一目标:只输出机器可解析的 JSON。
五、给模型一个“无法判断”的合法出口
很多格式错误,本质上是模型不知道该如何表达异常情况。
比如你要求:
{
"company_name": "string",
"founding_year": "number"
}
但输入文本里根本没有成立年份。模型可能会猜一个年份,也可能输出 "unknown",导致类型错误。
更稳的设计是提前定义空值策略:
{
"company_name": "string | null",
"founding_year": "number | null"
}
并在提示词里说明:
如果原文没有明确信息,对应字段返回 null,不要猜测。
这类“合法出口”非常重要。没有出口,模型就容易编造;有了出口,模型更容易遵守结构。
六、减少自由文本字段的不可控性
JSON 结构里最容易失控的是长文本字段,例如 reason、analysis、description。这些字段可能包含换行、引号、列表、冒号,甚至嵌套 JSON,增加解析和下游处理难度。
可以通过限制文本字段来提高稳定性:
reason 字段必须是一句话,不超过 50 个中文字符。
或者把长文本拆成更结构化的字段:
{
"conclusion": "string",
"evidence": ["string"],
"risk_level": "low | medium | high"
}
不要让一个字段承担过多含义。字段越短、类型越明确、枚举越多,输出越稳定。
七、解析前先清洗,但不要过度依赖清洗
实际工程中,即使提示词写得很好,模型仍可能偶尔输出:
```json
{"name": "Alice"}
或者:
```text
这是结果:
{"name": "Alice"}
因此可以做一些轻量清洗:
- 去掉 Markdown 代码块标记。
- 截取第一个
{到最后一个}之间的内容。 - 去掉首尾空白字符。
但要注意,清洗只能兜底,不能成为主方案。如果大量请求都依赖复杂正则才能解析成功,说明前面的格式约束不够强。
推荐做法是:
- 首先要求模型接口返回结构化内容。
- 然后用 JSON parser 解析。
- 再用 Schema 校验。
- 失败时触发修复或重试。
八、必须做 Schema 校验
JSON 能解析,不代表结果可用。
例如下面是合法 JSON:
{
"is_relevant": "yes",
"tags": "finance"
}
但如果业务要求 is_relevant 是布尔值、tags 是数组,这个结果就是错误的。
所以生产环境中应该至少校验:
- 是否是合法 JSON。
- 是否包含必填字段。
- 字段类型是否正确。
- 枚举值是否合法。
- 数组长度是否超限。
- 数字范围是否合理。
- 是否出现未知字段。
在 Python 中可以使用 Pydantic,在 JavaScript/TypeScript 中可以使用 Zod、Ajv 等工具。Schema 校验是把模型输出从“看起来对”变成“程序确认对”的关键步骤。
九、失败后让模型修复,而不是直接放弃
当 JSON 解析或 Schema 校验失败时,可以把错误信息反馈给模型,让它只修复格式。
例如:
上一次输出不是合法 JSON,错误原因:
tags 字段应为 string[],但实际是 string。
请基于原始任务重新输出,必须只返回合法 JSON,不要解释。
这种修复提示通常比从头重试更有效,因为错误边界更明确。
不过要控制重试次数,例如最多 1 到 2 次。超过次数后应进入降级逻辑,例如返回空结果、人工审核、记录异常队列,而不是无限重试。
十、把稳定性做成链路,而不是一句提示词
一个比较稳的 JSON 输出链路可以这样设计:
输入数据
-> 构造明确任务提示
-> 使用结构化输出或 JSON Schema
-> 模型生成
-> JSON 解析
-> Schema 校验
-> 失败修复 / 重试
-> 业务消费
-> 日志与监控
其中每一步都很重要:
- 提示词负责让模型理解任务。
- Schema 负责定义机器契约。
- 解析器负责确认语法正确。
- 校验器负责确认结构可用。
- 重试机制负责处理偶发失败。
- 日志监控负责发现长期问题。
稳定性不是模型单方面给你的,而是系统设计共同塑造出来的。
十一、一个可直接复用的提示词模板
下面是一个通用模板,可以根据业务调整:
你是一个信息抽取助手。请根据用户输入抽取结构化信息。
要求:
1. 只返回一个合法 JSON 对象。
2. 不要返回 Markdown 代码块。
3. 不要返回解释、前缀或后缀文本。
4. 如果信息不存在,字段值返回 null,不要猜测。
5. 所有字段名必须与 Schema 完全一致。
JSON Schema:
{
"name": "string | null",
"organization": "string | null",
"event_time": "string | null",
"topics": "string[]",
"risk_level": "low | medium | high | unknown",
"confidence": "number between 0 and 1"
}
用户输入:
{{input}}
如果 API 支持真正的 JSON Schema,应该把 Schema 放到接口参数里,而不是只写在提示词里。提示词模板适合用来补充语义要求。
十二、常见坑位清单
上线前可以用下面这份清单检查:
- 是否要求模型只输出 JSON。
- 是否禁止 Markdown 代码块。
- 是否定义了完整字段结构。
- 是否明确字段类型和枚举范围。
- 是否定义了缺失信息的返回方式。
- 是否避免让模型输出思考过程。
- 是否对长文本字段做了长度限制。
- 是否使用 JSON parser,而不是手写脆弱正则。
- 是否做了 Schema 校验。
- 是否有失败重试和降级策略。
- 是否记录了解析失败的原始输出。
- 是否用真实样本做过压力测试。
结语
让大模型稳定输出 JSON,本质上是把自然语言生成纳入工程约束。提示词是起点,但不是终点。真正可靠的方案,需要结构化输出能力、清晰 Schema、严格校验、可控重试和持续监控一起工作。
一句话总结:
不要相信“模型应该会按格式输出”,要让系统确认“输出确实符合格式”。
更多推荐

所有评论(0)