LLM 输出 JSON Schema 不稳定时怎么设计重试
让大模型“只输出 JSON”并不等于下游一定拿得到可用对象。实际接入时,失败至少有三层:文本不是合法 JSON、JSON 结构不符合 Schema,以及结构正确但业务值不可用。稳妥的做法是把解析和 JSON Schema 校验放在模型调用之后,只针对前两类可修复的格式问题做有限重试;超时、拒答、鉴权失败和业务校验失败应走各自的处理路径。
- JSON Mode 主要解决“能解析”,Schema 校验才负责字段、类型和枚举约束。
- 一次初始调用加两次修复重试通常足够,重试必须带上结构化错误而不是一句“再试试”。
- 合法 JSON 也可能不满足业务规则,格式通过后仍要做独立的业务验收。
- 生产日志至少保留尝试次数、错误类别、Schema 版本和最终处理结果。
先把 JSON Schema 当作应用契约
示例做一个“工单分类”小项目:模型返回分类、优先级和一句摘要。Schema 不只声明字段类型,还用 required 固定必填项,用 enum 限制可接受的优先级,并用 additionalProperties: false 拒绝模型随手增加的字段。
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"properties": {
"category": {"type": "string", "enum": ["bug", "question", "request"]},
"priority": {"type": "string", "enum": ["low", "normal", "high"]},
"summary": {"type": "string", "minLength": 8, "maxLength": 120}
},
"required": ["category", "priority", "summary"]
}
这一步解决的是“契约写清楚了吗”,不是“模型一定听话”。如果供应商支持 Structured Outputs,可以在请求层传入同一份 Schema;仍建议在应用侧再次校验,因为模型、供应商和业务规则并不总是完全一致。

把解析与 Schema 校验放在模型调用之后
校验函数先处理语法,再处理结构。不要捕获所有异常后只返回“格式错误”,否则模型无法知道是缺少字段、类型不对还是枚举值超出范围。下面的代码用 Draft202012Validator.iter_errors 收集多个问题,并保留字段路径。
import json
from jsonschema import Draft202012Validator
SCHEMA = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": False,
"properties": {
"category": {"type": "string", "enum": ["bug", "question", "request"]},
"priority": {"type": "string", "enum": ["low", "normal", "high"]},
"summary": {"type": "string", "minLength": 8, "maxLength": 120},
},
"required": ["category", "priority", "summary"],
}
validator = Draft202012Validator(SCHEMA)
def parse_and_validate(raw: str):
# 先判断文本是不是 JSON,再判断对象是否符合字段契约。
try:
payload = json.loads(raw)
except json.JSONDecodeError as exc:
return None, f"非法 JSON:{exc.msg}"
# 按字段路径排序,让修复提示稳定、便于日志聚合。
errors = sorted(validator.iter_errors(payload), key=lambda item: list(item.path))
if errors:
details = []
for error in errors[:4]:
path = ".".join(str(part) for part in error.path) or "$"
details.append(f"{path}: {error.message}")
return None, ";".join(details)
return payload, None
只对可修复的格式错误做有限重试
重试不是把原问题重复发送,而是把“返回 JSON、不要新增字段、修复这些具体错误”变成下一次调用的明确约束。示例设置总尝试次数为 3,即初始请求加两次修复请求;同时截断上一轮输出,避免错误响应不断膨胀上下文。
def classify_ticket(call_model, ticket_text: str, max_attempts: int = 3):
# call_model 只负责调用模型并返回文本,网络重试应在它自己的层处理。
prompt = f"将下面工单整理为 JSON,只返回对象:{ticket_text}"
raw = call_model(prompt)
for attempt in range(max_attempts):
value, error = parse_and_validate(raw)
if value is not None:
# Schema 通过后,再交给业务层检查,不在这里混合规则。
return value
if attempt == max_attempts - 1:
raise ValueError(f"JSON 输出连续失败,attempts={max_attempts},error={error}")
# 修复提示只携带必要上下文,避免让模型重复解释或输出 Markdown。
repair_prompt = (
"只返回符合给定 JSON Schema 的 JSON 对象,不要 Markdown 代码块。"
f"\n校验错误:{error}\n上一次输出:{raw[-6000:]}"
)
raw = call_model(repair_prompt)
raise AssertionError("不可达分支")
如果使用 Hugging Face Inference Providers,文档区分了 JSON Mode 和 Structured Outputs:前者强调可解析 JSON,后者把预定义 Schema 作为响应约束。即使上游有严格结构化输出,这段应用侧校验仍然适合做版本兼容、字段最小长度和业务前置检查。
把业务失败与格式失败分开验收
| 现象 | 是否做 Schema 重试 | 处理建议 |
|---|---|---|
| 缺少字段、类型错误、枚举值不对 | 可以,最多两次 | 回传字段路径和允许值 |
| 超时、鉴权失败、供应商 5xx | 不做格式重试 | 交给网络层退避并记录请求 ID |
| JSON 合法但工单编号不存在 | 不做 Schema 重试 | 走业务校验或人工兜底 |
| 连续达到尝试上限 | 停止 | 保存错误类别、Schema 版本和原始响应摘要 |
验收时至少观察三项:成功率按“初次成功/修复后成功/最终失败”拆分;平均尝试次数;不同错误类型的占比。若大量请求都在同一字段失败,优先检查 Schema 与提示词是否冲突,而不是继续增加重试次数。

常见问题
JSON 能被 json.loads 解析,还需要 Schema 校验吗?
需要。解析只说明语法成立,不能证明字段存在、类型正确、枚举值合法或没有额外字段。
每次失败都把完整原文塞回提示词可以吗?
不建议。保留截断后的原文和精简错误即可,完整响应应进入受控日志,避免上下文和敏感数据无边界增长。
把最大重试次数调到 10 次是不是更稳?
通常不是。超过两三次仍失败往往意味着 Schema、提示词或模型能力不匹配,应转人工兜底或切换结构化输出能力更合适的模型。
Go slice alias full slice expression 如何限制 append 覆盖
- 上一篇
- Go slice alias full slice expression 如何限制 append 覆盖
- 下一篇
- LiblibAI AI画图怎么从草图起稿?上传参考图到局部调整的入门步骤
-
- 科技周边 · 人工智能 | 5小时前 |
- 本地模型量化时怎么比较 4-bit 与 8-bit 代价
- 481浏览 收藏
-
- 科技周边 · 人工智能 | 6小时前 |
- 语音转写带说话人分离时如何处理重叠发言
- 115浏览 收藏
-
- 科技周边 · 人工智能 | 7小时前 |
- 扩散模型固定 seed 后为什么仍有细节差异
- 457浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 | 人工智能 · OCR · 文档理解 · OCR 表格识别 行列关系 Table Transformer
- OCR 识别表格时如何保留行列关系
- 147浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 |
- RAG 文档切片的重叠长度怎么按检索目标调整
- 280浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 | 人工智能 · 向量数据库 · 索引选型 · 向量检索 vector index HNSW FLAT
- 向量索引选型时如何比较召回、内存和更新代价
- 485浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 |
- 图像输入的说明文字和图片内容冲突时如何设计提示
- 404浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 | openai · 工具调用 · 函数调用 · Responses API tool_choice allowed_tools
- OpenAI 工具选择策略怎么限制模型只调用指定工具
- 463浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 84次使用
-
- OpenCompass
- OpenCompass是上海AI实验室推出的开源大模型评测平台,提供CompassKit、CompassHub和CompassRank三大核心组件,支持LLM及多模态模型的一站式标准化评估与排行榜查询。
- 19次使用
-
- SuperCLUE
- SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
- 245次使用
-
- C-Eval
- 深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
- 170次使用
-
- AI Prompt Library
- 探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
- 101次使用
-
- 接口返回 200 但前端仍报错怎么办:从响应格式到跨域一步步排查
- 2026-06-14 332浏览
-
- golang生成JSON以及解析JSON
- 2023-01-17 329浏览
-
- Go如何实现json字符串与各类struct相互转换
- 2023-01-07 377浏览
-
- Go中使用gjson来操作JSON数据的实现
- 2023-01-07 141浏览
-
- Go 语言 json解析框架与 gjson 详解
- 2023-01-08 203浏览

