程序抛出解析错误,把返回内容打印出来一看,明明是规规矩矩的 JSON——这种落差几乎每个接过大模型接口的人都遇到过。多数时候不是模型不会输出结构化数据,而是响应里混进了人话、代码围栏、注释,或者字段类型和约定的不一样。与其反复在提示词里加「请严格只输出 JSON」,不如按三步把问题定位清楚:先看原始响应,再分清是哪一层不合规,最后把契约同时写进请求和代码。下面按这个顺序拆。
第一步:先看原始响应,别只盯解析报错
把接口返回的原始文本完整写进日志,不要在打印前做裁剪、去空白或反序列化。最常见的三类污染是:整段结果被包在代码围栏里、前后带一句「好的,以下是结果」、正文中间夹了说明或注释。解析报错只告诉你「第几个字符不对」,原始文本才告诉你它为什么不对。
同时确认状态码和响应类型。上游 5xx 或网关超时时,返回的可能是错误页 HTML 或一段纯文本提示,而不是 JSON 对象;中间代理改写过响应体也会出现同样现象。先看 Content-Type 和正文首字符做一次分流,能省掉一半无谓的猜测。
解析报错是症状,原始响应才是证据。没看到原文之前,不要改提示词。
第二步:分清「语法不合法」与「字段不合规」
先用解析器只校验语法。高频问题集中在几处:结尾多一个逗号、用了单引号或中文引号、字符串里出现未转义的换行、注释、NaN 或 Infinity、半截 JSON 少了右括号。这类问题拿一小段样本在本地就能复现,不必反复打接口。
语法通过却依然报错,多半是契约层:约定必填的字段没出现、数字被写成字符串、数组变成对象、整体多包了一层 data、或者把空值写成了字符串 null。这类问题靠捕获异常兜不住,必须逐字段校验。还有一种混合情况:流式输出最后一段被截断,表现同样是解析失败,但根因在长度限制或连接中断,不在提示词。
语法错误改文本,字段错误改契约。把两类混在一起,就会一直在提示词里加「请严格输出」。
第三步:把契约写进请求,也写进代码
请求侧把字段名、类型、可空规则逐条列清楚,并给一组输入到输出的对照示例;模型支持结构化输出或 JSON 模式时,直接在请求里开启,让服务端做格式约束,比只靠提示词请求可靠得多。通过 https://api.aigcbreeze.cn 调用时,建议把原始响应留档再做解析,出错时能直接对账,不用靠回忆复现。
代码侧保留一层轻量清洗:去掉代码围栏、截取首个左花括号到最后一个右花括号之间的内容,再交给解析器。解析失败时把原始响应片段写进日志并只重试一次,仍失败就走默认值或人工处理,不要无限重试。上线前用五类脏样本自测:带围栏、带前后缀、缺字段、类型漂移、半截 JSON,五类都能正确处理才算稳。
常见问题
加了「只输出 JSON」为什么还会带解释
提示词是软约束,长上下文或多轮对话里模型容易延续上一轮的说话方式。把要求放进系统消息、给一个纯 JSON 的示例、代码侧保留清洗层,三层一起才稳;别指望一句话永远生效。
换更强的模型就能解决吗
换模型可能降低出现频率,但不会消除。根因常常在调用链里:拼接模板、流式分段合并、中间代理改写、下游解析器的隐含假设。先定位是哪一层把响应改坏了,再决定要不要换模型。
失败了该重试几次
一次通常足够。第一次失败说明这次输出不合规,原样重发大概率拿到同类结果;更有效的做法是把失败样本存下来做批量回归。重试一定要设上限并记录失败率,失败率突然抬升时,优先查上游是否有变更。