用结构化输出跑批处理或做表单填充时,最常见的就是模型回了一段看着像 JSON 又解析不了的东西,或者校验器告诉你少字段、多字段、类型不对。这篇不重讲提示词怎么写,而是给一套排查顺序:先分清是解析失败还是校验失败,再按层次往下查,最后落到重试与兜底方案。
跑批处理或者做表单填充的时候,最让人头疼的不是模型答得不好,而是它回了一段看着像 JSON、丢进解析器就炸的东西。这时候先别急着改提示词,因为失败原因可能压根不在提示词上。这篇给一套排查顺序:先分清是解析失败还是校验失败,再一层层往下查,最后落到重试和兜底。
思路很简单:把「模型不听话」这个大帽子摘掉,换成几个能单独验证的小问题。链路问题、schema 设计问题、任务本身模糊,三者的修法完全不一样,混在一起查只会越查越乱。
先分清是哪一类失败
第一步永远是分类。解析失败是文本根本不是合法 JSON;校验失败是能解析,但不符合你的 schema。前者要修输出格式,后者要修结构定义,修法南辕北辙。把每次失败的原始返回体和报错一起打日志,别只看解析器抛的那行异常,很多问题在原文里一眼就能看出来。
| 失败类型 | 典型表现 | 优先怀疑方向 |
|---|---|---|
| 截断 | JSON 到一半就没了 | 长度上限、流式提前结束 |
| 包裹 | 前后带解释文字或代码块标记 | 提示词要求、解析前清洗 |
| 字段偏差 | 缺必填、多字段、嵌套多一层 | schema 复杂度、契约是否下发 |
| 类型偏差 | 数字给成字符串、枚举给成近义词 | 枚举范围、字段描述 |
这里有个容易踩的坑:各家模型对严格模式的支持程度不一样,别照搬别家的结论。当前哪些模型支持、支持到什么程度,到站内 模型资料库(/models) 核对当时的说明,再决定要不要上严格模式。
先怀疑接口契约,再怀疑模型
模型没按格式回,很多时候是它压根没收到你的格式要求。有的兼容层会在转发时把 schema 字段丢掉,请求发出去看着没错,实际到模型那边只剩一句普通提问。先用最小 schema 跑一次,两个必填字段就够,能通过说明链路没问题,问题在 schema 复杂度上。
- 确认请求里 schema 是否真的被下发,抓一份实际发出的请求体看,别只看自己代码里写了什么
- 确认严格模式或对应开关有没有打开,开了和没开的约束强度不一样
- 确认返回的是整体对象还是被包了一层 data 或 result,嵌套多一层是高频误判
- 用两个必填字段的最小 schema 做对照实验,区分链路问题和设计问题
如果你的调用是走中转站转发的,兼容层的行为差异会更明显。同一份请求换一条链路结果不同,那就先怀疑转发环节,而不是继续磨提示词。
Schema 本身能改的地方
确定了链路没问题,再看 schema 是不是定得太狠。必填字段越少越稳,能靠后处理的就别塞进必填;枚举给全,别让模型猜「差不多意思」的写法。层级也别太深,扁平结构比三层嵌套稳得多,真出问题时定位成本也低得多。
字段描述是给模型看的约束,不是写给人看的注释。写清用途和取值范围,比换个更强的模型管用。但如果任务本身就模糊,比如自由文本归类、开放式抽取,那就先降低结构预期,别硬套一层强 schema,硬套只会把失败率推上去。
- 必填字段
- 能后处理补出来的就别放进必填
- 枚举
- 取值范围给全,别给模型留猜的余地
- 嵌套层级
- 能扁平就扁平,深层嵌套出错难定位
- 字段描述
- 写用途和取值范围,它是约束不是注释
哪些结构写法在主流模型上更稳,各家的差异可以直接到站内 工具目录(/tools/speed-test) 里的相关条目对照着测一遍,比看别人的结论靠谱。
重试、降级与兜底顺序
解析失败优先做一次原样重试,不要立刻改 schema。偶发失败和稳定失败要分开看:偶尔一次多半是采样波动,连续几次都挂说明结构或任务有问题。重试要有上限,别在一个请求上无限绕。
- 第一次重试原样再发一次,不改任何参数,先判断是不是偶发
- 第二步降级还失败就拆两步:先让模型输出纯文本,再由第二次调用转成结构
- 第三步兜底宽容解析加本地修补,去掉代码块包裹、补齐默认值,但修补必须写日志
- 统计失败率按字段统计失败次数,某个字段反复出错说明 schema 和任务不匹配
兜底不是把错误吞掉,是把错误记录下来再让流程继续跑。
这里的不适用情况要说清:如果业务本身不允许字段缺失,比如对账或风控场景,那就不该用补齐默认值的兜底,宁可整条失败打回重跑,也别让一条带着假数据的记录流进下游。
让它不再反复出问题
手工试单个样例只能证明「这次能过」,证明不了「以后都能过」。攒一批固定用例,把边界输入和曾经失败过的输入都放进去,每次改 schema 或者换模型之前先跑一遍,跑完再决定改不改。
- 用例里要含曾经失败过的真实输入,失败样本比随机样本有用得多
- 每条用例记录失败类型,是解析失败还是字段偏差,便于判断问题出在链路还是模型
- 换模型或换上游之后重跑同一批用例,别用单个成功样例下结论
- 把失败样本留在回归集里,比每次手工重试有效得多
想让这套回归真正跑起来,得先知道自己在用的模型和链路当前是什么水平。各家官方接口的能力差异和价格情况,到站内 价格追踪(/price-watch) 页面看当时的数字,再结合自己的失败率决定要不要换。
下一步先按上面的顺序把手上这次失败归类,再决定是改 schema、换链路还是加兜底;如果怀疑是转发环节的问题,可以先到站内看各条线路的实测情况再动手。→常见问题
模型返回的 JSON 前后带了说明文字,这算哪类问题?
属于包裹型解析失败,表现是文本里有合法 JSON 但不是纯 JSON。处理办法分两层:一是在提示或参数上要求只输出 JSON;二是本地解析时用括号配对或正则先截出 JSON 片段再解析。注意截取逻辑要能处理嵌套和字符串里的括号,否则会把合法内容截坏。
为什么同样的 schema,换一个模型就大面积失败?
不同模型对结构化约束的支持强度差别很大,有的支持严格模式,有的只当普通提示处理。换模型前先确认它是靠参数强约束还是靠提示词软约束,软约束的模型更容易在长输出里跑偏。建议先用最小 schema 试跑,再决定是否把复杂抽取任务交给它。
重试几次能好,但失败率还是降不下来,该往哪查?
优先看失败集中在哪类字段。如果集中在少数几个必填或枚举字段,多半是 schema 设计与任务不匹配,比如要求模型判断一个它拿不到的取值。这时应该拆步骤:先让它输出原始信息,再用规则或第二次调用做归一化,而不是一味加重试次数。