JSON mode 怎么用:结构化输出的解码原理、调用侧校验与五类常见坑
JSON 结构化输出不是把提示词写成“请返回 JSON”那么简单,它依赖解码阶段的语法约束,还要在调用侧做校验与容错。本文讲清它的实现原理、JSON mode 的正确用法,以及截断、包裹、类型漂移、流式增量解析、缓存与成本这五类常见坑的排查思路。
把大模型接进业务系统,真正让人头疼的往往不是回答质量,而是回答的格式。同一个提示词,模型可能这次返回一段解释文字,下次把字段名写成中文,再下次给数字加上引号,调用侧的解析代码就得跟着改。JSON 结构化输出要解决的就是这件事:让模型不再自由发挥,而是按约定好的字段与类型把内容交出来,下游程序拿到即可用。判断一个接口是否真的支持它,看的不是文档里有没有要求返回 JSON,而是解码阶段有没有做约束。
先说清概念。很多人把结构化输出等同于在提示词里要求返回 JSON,这只能算软约束,模型仍然有概率不听话。真正的结构化输出是在解码环节动手:给定一份 schema,把所有可能的输出限制在符合该 schema 的 JSON 语法集合内,理论上只要采样过程不被打断,产出的就一定是可解析的合法 JSON。
原理并不神秘。系统先把 schema 或 JSON 语法编译成一个有限状态机,每生成一个 token 就推进一次状态;在每一步采样前,把会让状态机走入死路的候选 token 掩掉,再在剩下的合法候选里做采样。麻烦之处在于 token 的切分边界和语法边界通常对不齐,一个 token 可能同时包含冒号、引号和部分字符串,所以需要预先算好状态与 token 的映射表,这也是不同平台结构化输出稳定性差异的主要来源。
还有一个常被忽略的区别:JSON mode 和 schema 严格模式不是一回事。前者只承诺输出是合法 JSON,字段名、字段类型对不对得上全靠模型自觉;后者会把字段名、必填项、枚举值一起约束进解码过程。调用侧如果只开了 JSON mode,就必须自己承担校验责任,不能默认字段齐全。
写 schema 的功夫决定了后期返工量。字段尽量少、层级尽量浅,能用枚举就不用自由文本,必填项明确标注,避免深层嵌套和复杂的联合类型。把 schema 当成服务之间的接口契约来维护:先定契约,再写提示词,最后写解析与校验代码。schema 越精简,约束状态机越小,首 token 延迟和输入 token 开销也越低。
实际落地中最常见的坑是截断。模型还没写完闭合括号,就达到了 max_tokens 上限,返回的是一段半个 JSON,解析器直接抛异常。排查时要先看结束原因字段,如果是长度限制导致的中断,重试前把上限调高,或者把 schema 拆小、分批生成,同时记得对未闭合的输出做兜底识别,而不是让它触发业务异常。
第二个坑是包裹。即使开了 JSON mode,有些模型仍习惯在 JSON 外面加一句“好的,以下是结果”,或者用代码块围栏把内容包起来。稳妥做法是解析前做一次容错抽取,定位第一个左花括号和最后一个右花括号,取中间部分再解析。更好的办法是把这类前缀在提示词模板里彻底禁掉,减少无效输出,也省 token。
第三个坑是类型漂移与枚举幻觉。schema 里写的是整数,模型可能返回字符串形式的数字;枚举里只有三个值,它偏偏编出第四个。约束解码能大幅降低概率,但不能指望它百分之百。调用侧必须用 jsonschema 或 Pydantic 之类的库做一次强校验,校验失败时把具体错误信息回灌给模型重试一次,再失败就走降级逻辑,别让脏数据流进数据库。
如果业务用流式输出,还有第四个坑:增量 JSON 无法逐块解析。每来一个分片就调用一次解析函数,必然报错,因为大括号还没闭合。正确做法是接一个增量解析器,按已到达的部分逐步提取已完成字段,或者先累积到缓冲区、等结束再整体解析。对延迟敏感的场景,前者体验更好,但要求调用侧能容忍字段乱序到达。
第五个坑涉及成本与缓存。schema 会作为输入的一部分反复发送,长 schema 在按量计费的接口上是一笔不显眼但持续的开销。做结果缓存时也要注意,同一份语义内容如果字段顺序或空白不同,哈希值就不同,缓存命中率会很难看。解决办法是解析成对象后做规范化序列化再当缓存键,字段顺序由服务端模板固定下来。
把这些环节串起来看,结构化输出考验的其实是两侧的配合:模型侧负责语法约束,调用侧负责业务校验。快米兔的模型 API 中转在这件事上的价值在于,它沿用统一的调用方式,模型 API 中转注册送 5 元测试金、按量计费,调用侧只需更换接入地址、模型名和密钥,就能在同一套 JSON mode 代码下横向验证不同国产模型的字段稳定性,先把测试数据跑出来再决定生产用哪个模型,试错成本相对可控。
最后给一份落地清单:schema 先行并保持精简,明确区分 JSON mode 与严格模式,始终检查结束原因,解析前做容错抽取,解析后做强校验,流式场景用增量解析器,缓存键做规范化,重试策略要带错误反馈且有次数上限。把这些做到位,结构化输出才能从大多数时候能用,变成可以放心接进生产链路。具体接口参数与计费细节以官方说明为准。