大模型输出 JSON 总出错?一文讲透生产环境保证 JSON 100% 可用的七层方案
大模型输出 JSON 总出错?一文讲透生产环境保证 JSON 100% 可用的七层方案
前言
很多人刚开始做 AI 应用时,都遇到过这样的问题:
{
"name": "张三",
"age": 18,
}
多了一个逗号。
或者:
当然可以,下面是结果:
{
"name": "张三",
"age": 18
}
前面多了一段解释。
再或者:
{
"name": "张三"
"age": 18
}
少了一个逗号,程序直接报错。
很多开发者的第一反应是:
「是不是 Prompt 写得不够好?」
其实不是。
生产环境里,从来不会相信大模型一次就能输出正确 JSON。
真正稳定的做法是:
构建一套「生成 → 修复 → 校验 → 重试 → 兜底」的完整流水线。
为什么大模型容易输出错误 JSON?
因为大模型本质上是在预测下一个 Token,它并不是一个真正的 JSON 生成器。
它只能尽可能模仿:
{
"name": "张三",
"age": 18
}
但无法从底层保证:
- 括号一定闭合
- 引号一定成对
- 字段一定完整
- 类型一定正确
- 业务规则一定满足
所以,任何生产级 AI 应用,都必须建立多层防护机制。
七层 JSON 兜底方案
模型约束
↓
Prompt约束
↓
文本修复
↓
Schema校验
↓
业务规则校验
↓
重试与自修复
↓
人工兜底
下面逐层介绍。
第一层:模型原生约束(优先级最高)
1. JSON Mode
目前主流模型基本都支持 JSON 模式,例如:
- GPT
- DeepSeek
- 豆包
- 通义千问
调用时开启:
response_format={"type": "json_object"}
优点
能够保证:
- JSON 语法合法
- 不会输出 Markdown
- 不会输出解释文字
缺点
不能保证:
- 字段完整
- 字段类型正确
- 业务规则正确
例如:
{
"age": "十八"
}
JSON 合法,但业务不可用。
2. Structured Output
例如:
class User(BaseModel):
name: str
age: int
llm.with_structured_output(User)
模型直接生成:
User(
name="张三",
age=18
)
而不是:
"{...}"
稳定性比纯 JSON Mode 更高。
3. Function Calling(推荐)
这是现在 Agent 应用最常见的方法。
例如:
class GenerateQuestion(BaseModel):
questions: List[Question]
模型返回:
{
"tool_name": "generate_question",
"arguments": {
...
}
}
优点:
- 字段名固定
- 类型约束更强
- 缺失字段概率更低
非常适合:
- 智能客服
- AI 出题系统
- Agent 工作流
4. Grammar Constraint(终极方案)
例如:
- CFG
- BNF
- Json Schema Constraint
代表框架:
- vLLM
- Outlines
- Guidance
这种方式会直接限制模型生成 Token 的路径,从根源杜绝非法 JSON。
理论上:
合法 JSON 率接近 100%
第二层:Prompt 工程约束
很多人的 Prompt:
请输出 JSON。
基本等于没写。
正确写法应该包含四部分
① 身份定义
你是一个 JSON 输出引擎。
② 输出 Schema
{
"name": "",
"age": 0
}
③ Few-shot 示例
{
"name": "张三",
"age": 18
}
④ 强制禁令
禁止输出:
- markdown
- 解释
- 注释
- 多余文本
这些约束可以显著降低异常输出概率。
第三层:文本后处理修复
即便前两层做得很好,模型偶尔还是会输出:
好的,以下是 JSON:
{
...
}
或者:
```json
{
...
}
```
此时可以先进行轻量修复。
去除 Markdown
import re
match = re.search(
r"```json(.*?)```",
text,
re.DOTALL
)
提取最外层 JSON
first = text.find("{")
last = text.rfind("}")
json_str = text[first:last+1]
修复尾随逗号
错误:
{
"a":1,
}
修复:
{
"a":1
}
推荐工具
json_repair
安装:
pip install json_repair
使用:
from json_repair import repair_json
fixed = repair_json(response)
dirtyjson
安装:
pip install dirtyjson
第四层:Schema 校验
很多项目只做:
json.loads()
然后认为数据已经安全。
这是错误的。
合法 JSON 不代表可用
例如:
{
"age": "十八"
}
完全合法,但业务无法使用。
使用 Pydantic 校验
class User(BaseModel):
age: int
User.model_validate(data)
类型错误会直接报异常。
建议开启严格模式
model_config = ConfigDict(
extra="forbid"
)
禁止出现额外字段。
第五层:业务规则校验
这一层是最容易被忽略的。
例如出题系统:
单选题
只能有一个正确答案
多选题
至少两个正确答案
判断题
只能有:
正确
错误
简答题
options 必须为空
这些规则:
- JSON Mode 不管
- Function Calling 不管
- Pydantic 也不管
必须自己实现 Validator。
第六层:重试与自修复
简单重试
for i in range(3):
try:
...
except:
retry()
很多时候第二次就正常了。
自修复重试
把错误反馈给模型:
你的 JSON 存在以下问题:
1. 缺少 analysis 字段;
2. 单选题出现多个正确答案。
请修正后重新输出完整 JSON。
这种方式的成功率非常高。
LangChain 已经提供支持
OutputFixingParser
RetryOutputParser
第七层:人工兜底
真正的企业系统一定会有最终兜底:
LLM
↓
校验失败
↓
自动重试失败
↓
人工审核
↓
重新生成
永远不要无限重试。
否则:
- 浪费 Token
- 增加延迟
- 容易进入死循环
一套生产级 JSON 流水线
LLM
↓
JSON Mode / Function Calling
↓
Prompt Schema
↓
json_repair
↓
Pydantic 校验
↓
Business Validator
↓
Retry
↓
Self Correction
↓
Fallback
我的推荐方案
小项目
Prompt
↓
json.loads
中型项目
Prompt
↓
json_repair
↓
Pydantic
LangChain 项目
Structured Output
↓
Pydantic
Agent 项目
Function Calling
↓
Pydantic
↓
Business Validator
高可靠生产环境
Grammar Constraint
↓
Function Calling
↓
Pydantic
↓
Business Validator
↓
Retry
↓
Fallback
总结
很多人想找到一种方法,让大模型一次性输出正确 JSON。
但在生产环境里,真正的思路不是:
如何让模型永远不出错。
而是:
当模型出错时,如何自动发现错误、修复错误,并保证最终进入系统的数据一定正确。
所以,保证 JSON 可用性的核心从来不是某一个技巧,而是一套完整的工程体系:
生成
↓
修复
↓
校验
↓
重试
↓
兜底
这才是生产级 AI 应用处理结构化输出的标准答案。
更多推荐



所有评论(0)