Kimi JSON mode 与 response_format 怎么用
数据截至 2026-08,价格与限额以各官网为准。本文只讲计费与接入机制,不列具体价格数字。
Kimi 的 response_format 不是一个开关,是两个模式。设成 {"type": "json_object"} 是 JSON Mode,官方的说法是保证输出为合法 JSON Object,但不约束具体字段;设成 {"type": "json_schema"} 并带上 schema 才是 Structured Output,字段名、类型、嵌套层级由你的 JSON Schema 定死。两者的实现机制在官方对比表里写得很清楚:前者是 Prompt 引导,后者是 Token 级约束解码(CFG),在采样阶段过滤非法 token。这一条差异决定了一件事——json_object 下模型仍然可能擅自增加字段、可能省略字段,所以凡是要往下游系统灌的结构化数据,官方的建议是始终用 json_schema 加 strict: true,避免在业务层编写大量防御性代码。
先搞清楚你到底要哪一种
官方文档把 response_format 支持的两种模式列成了一张表,type 取值就是 json_object 和 json_schema 两个。json_object 对应的适用场景,官方写的是简单 JSON 输出、字段灵活的场景;json_schema 对应的是需要严格结构、对接下游系统的场景。
结构上也有硬性差别:type 为 json_object 时不需要 json_schema 字段;type 为 json_schema 时,必须提供 json_schema.name 和 json_schema.schema。官方在这里用的措辞是「必须提供」,不是「建议提供」。至于少给一个具体会怎样,文档里明文给出的报错案例只有一个——json_schema.schema 传成了非 object 类型时返回 400;name 缺失时的报错示例官方文档里没有找到相关说明。所以稳妥的写法是两个字段一律按必填处理,别去试探边界。
至于不设 response_format 会怎样,官方 JSON Mode 页面提到该参数用于约束输出格式,默认是普通的、没有任何格式约束的文本内容(默认行为以官方文档当前版本为准)。也就是说,你光在 prompt 里写「请输出 JSON 格式的内容」,走的还是纯文本通道——官方专门举了两个典型翻车样子:模型在 JSON 文档之外额外输出解释性文字,或者末尾字段多一个逗号导致无法被正确解析。这两种毛病的根因不是提示词写得不够狠,是根本没开约束——走纯文本通道时,模型的输出并没有被任何格式规则限制住,写在 prompt 里的格式要求只是一段普通的自然语言请求。
json_object 的三步用法
官方把 JSON Mode 的用法拆成了三步,顺序不能省:
第一步,在 system 或 user prompt 中定义输出 JSON 的格式,包括具体的字段名称、字段类型;官方标注的最佳实践是给出具体的输出示例,并解释每个字段的具体含义。
第二步,把 response_format 参数设为 {"type": "json_object"}。
第三步,解析返回消息中的 content——注意官方的措辞,message.content 是一个合法的、被序列化成字符串的 JSON Object。它是字符串,不是对象,Python 侧要 json.loads,Node 侧要 JSON.parse,取的是 completion.choices[0].message.content。
官方的完整示例是个多类型消息的智能客服场景:system prompt 里约定 text、image、url 三个字段,模型一次回复里可以同时带文字、图片和链接,业务代码再逐个字段判断存在与否,分别走发文本、发图片、发链接卡片的接口。这个例子选得比「总结一篇文章」更有代表性,因为它展示了 JSON Mode 真正的价值:不是让模型少说废话,是让一次调用的结果能被路由到多个不同的下游动作。
这一节还有两条容易被忽略的注意事项,官方写在页尾:Kimi 大模型只会生成 JSON Object 类型的 JSON 文档,不要引导它生成 JSON Array 或其他类型的 JSON 文档;以及如果没有正确告知需要输出的 JSON Object 的格式,它会生成不符合预期的结果。第一条尤其要记住——你想要一个数组,正确做法是把数组包在一个对象的某个字段里,而不是让模型在顶层吐数组。
json_schema 的三个字段各管什么
Structured Output 的参数结构是 json_schema 对象下面挂三个东西,官方参数表逐个说明了:
json_schema.name,类型是 string,Schema 的标识名称,用于日志和调试json_schema.strict,类型是 boolean,是否严格按 schema 约束输出,官方建议显式设置为 truejson_schema.schema,类型是 object,JSON Schema 对象,定义输出结构
strict 这个参数值得多说两句,因为它的语义不是「更认真一点」。官方的说明是:strict 为 true 表示强制模型输出必须完全匹配 schema 定义,此时你的 schema 需要符合 MFJS(Moonshot Flavored JSON Schema)规范;如果 strict 设为 false,API 仅保证输出为合法 JSON 对象,但不强制约束内部字段结构。换句话说,strict 为 false 的 json_schema,效果上更接近 json_object,只是你多写了一份 schema。
模型之间的支持程度也有明文差异,官方在两处都提到了:kimi-k3 稳定支持 Structured Output,嵌套对象、数组、anyOf 等均能正常处理;kimi-k2.7-code 对 Structured Output 的支持最稳,包括嵌套对象、数组、anyOf、oneOf、$ref、additionalProperties: true 等都能正常处理;kimi-k2.6 在复杂 schema 下偶有不稳定表现,官方举的例子是 $ref 可能返回 Markdown 代码块、oneOf 可能被忽略、partial=true 可能输出 schema 外字段,因此建议在该模型上优先使用简单 schema,并在业务层做二次校验。这几条都是官方明文写的能力边界,不要跨模型互相推断。
additionalProperties 的行为官方也单独说了:设置为 false 时,模型不会输出 schema 中未定义的字段;设置为 true 或不指定时,kimi-k2.7-code 允许输出额外字段。所以你如果指望「我没写在 schema 里的字段就不会出现」,得自己把它显式关掉。
API 返回 200,不等于你的 schema 是兼容的
这是整篇里最反直觉的一条,也是最值钱的一条。
官方提供了一个叫 walle 的 CLI 工具用来自检 schema 的兼容性,安装命令是 go install github.com/moonshotai/walle/cmd/walle@latest,校验用法是 walle -schema '你的schema' -level strict。关键在紧接着那句提醒:即使 schema 包含 anyOf、oneOf、$ref,API 也常能正常返回 200,且响应中不会出现 warning 字段。因此官方给 walle 的定位是静态检查入口,实际兼容性以目标模型的在线调用结果为准。
这意味着你不能拿 HTTP 状态码当兼容性判据。官方在两模式对比表下面还补了一句更根本的话:约束解码对结构的保证,以 schema 符合 MFJS 规范为前提,复杂 schema 在 kimi-k2.6 等模型上仍可能不稳定。把这两句连起来读,逻辑就清楚了——200 只说明这个请求被受理了,说明不了「约束解码那一层的前提成立」。前提不成立时输出具体会变成什么样,官方文档里没有找到相关说明,所以也别指望从返回体的某个字段上看出端倪。官方给出的判定路径只有一条:walle 作为静态检查入口,实际兼容性以目标模型的在线调用结果为准。落到工程上就是两步都别省——schema 有变更时先跑一遍 walle,再对你真正要用的那个模型做一次实际调用确认。
真正会返回错误的是 schema 本身不合法的情况:官方给的例子是 json_schema.schema 不是 object 时,API 返回 400,错误类型为 invalid_request_error,报文里会点名是 response_format.json_schema.schema 这个字段非法。看到这个错先别怀疑模型,去检查你序列化 schema 的那段代码。
字段缺不缺,别让模型自己发挥
这一节的机制很值得单独拎出来。官方的原则是:声明在 required 中的字段必然出现在输出中。听起来是好事,但配上「输入里根本没有这个信息」的场景就会出问题——官方直说了,当输入缺少对应信息时,如果字段只声明了单一类型(比如 "integer"),模型可能编造内容或返回空字符串。
官方给的解法是改用联合类型声明可为 null,写成 "type": ["integer", "null"],让模型用 null 显式表示信息缺失,而不是给你一个表示未知的字符串或者干脆让字段消失。这样下游 json.loads 之后可以直接做强类型转换,无需防御性处理。官方同时提醒 kimi-k2.6 仍可能返回空字符串,建议在业务层保留一层空值校验。
顺带一提,官方特别强调提示词仍需提供上下文——格式由 schema 约束,但模型仍需理解业务内容,任务目标和数据来源还是得在 system prompt 或 user prompt 中清晰描述。schema 管形状,prompt 管内容,这两件事不互相替代。想省 prompt 的只能省掉格式描述那部分,官方把它列为 Structured Output 的优势之一:无需在 prompt 中反复描述格式,从而降低 prompt 工程的复杂度。
JSON 解析失败时的排查顺序
把官方散落在两页里的几种失败模式串起来,排查顺序大致是这样:
第一步看 finish_reason。 官方在 JSON Mode 页和 response_format 页都写了同一件事:如果 JSON 文档不完整或被截断导致无法正确解析,先检查返回值中的 finish_reason 字段是否为 length。是的话就是模型在输出完整 JSON 之前达到了 max_tokens 限制。官方给的三条建议是增大 max_tokens、简化 schema 的嵌套层级、缩短输入文本长度。输出长度这件事本身还有更通用的谈法,可以看控制 API 输出长度的通用做法。
第二步看你解析的是不是 content。 kimi-k3、kimi-k2.7-code 这类思考模型在返回 content 的同时,可能还会返回 reasoning_content。官方明确要求:只解析 choices[0].message.content 作为最终 JSON,不要直接用 json.loads 处理整个响应对象。这个坑很隐蔽,因为在不返回 reasoning_content 的模型上,那段偷懒代码是能跑通的。
第三步看内容里有没有 Markdown 代码块。 官方提到在 kimi-k2.6 等旧模型上,返回的 content 可能包含 Markdown 代码块,导致 json.loads 失败;同时 oneOf、$ref 等复杂 schema 未被严格遵守。官方的建议是使用 kimi-k2.7-code 进行 Structured Output 调用;如果必须使用 kimi-k2.6,在业务层先剥掉 Markdown 标记,再对解析结果做 schema 字段校验。
第四步才怀疑 schema 与 prompt 打架。 官方说当 schema 过于复杂或 prompt 与 schema 矛盾时,模型可能输出不完整的 JSON。这条和第一步是同一个症状不同病因,所以顺序上放最后。
和 Partial Mode、前缀缓存的关系
两条兼容性结论都在官方注意事项里,方向正好相反。
跟 Partial Mode 混用是有风险的:官方写的是 kimi-k2.7-code 在简单 schema 下与 partial=true 混用通常正常,但复杂 schema 仍可能破坏结构约束;kimi-k2.6 在 partial=true 下更容易输出 schema 外字段,因此不建议在该模型上混用。注意「简单 schema 下通常正常」这个限定条件不能丢,它不等于可以随便混用。
跟前缀缓存混用则是安全的:官方明确写了是否设置 response_format 不会破坏前缀缓存,可以放心按请求粒度调整该参数,不影响缓存命中率。这条结论在工程上挺重要——它意味着同一批请求里,有的开结构化输出有的不开,不会把你的缓存打散。缓存本身怎么计费是另一套机制,可以看API 缓存计费机制。
最后:三个最容易栽的坑
一是拿 200 当验收标准。官方的原话是:即使 schema 包含 anyOf、oneOf、$ref,API 也常能正常返回 200,且响应中不会出现 warning 字段。这句话有两个限定别丢:一是「常能」而不是「一定」;二是条件说的是 schema 里出现了这几个关键字,不是「schema 不兼容 MFJS」——同一份文档里明写 kimi-k2.7-code 对 anyOf / oneOf / $ref 的支持已比较完善,所以用到这些关键字并不等于不兼容。要记住的是结论那半句:状态码和 warning 字段都不构成兼容性证据。
二是required 用错。把字段塞进 required 不代表你能拿到真数据,只代表字段一定出现;真想区分「没有这个信息」和「值是空」,得用可为 null 的联合类型。
三是顶层要数组。官方明说了只生成 JSON Object,别去引导它在顶层吐 Array。
接入层面的准备工作(Base URL、密钥、OpenAI 兼容客户端怎么初始化)不在本文范围,可以看Kimi API 怎么接入;如果你是从别家 OpenAI 兼容接口迁过来的,OpenAI 兼容端点的通用差异那篇里的字段对照更值得先过一遍。至于各模型对 schema 特性的支持边界,官方文档会随版本更新,落地前以官方文档当前版本为准。