结构化输出对照:GLM、Kimi、Grok、阶跃星辰的 response_format 差异
数据截至 2026-08,价格与限额以各官网为准。本文只讲计费与接入机制,不列具体价格数字。
把结论放前面:这几家的参数名几乎都叫 response_format,但档位不一样。按官方文档,GLM 的 response_format.type 枚举只有 text 和 json_object 两个取值;Kimi、Grok、阶跃星辰都提供了 json_schema 档,可以用 JSON Schema 精确约束字段;MiniMax 的文本对话文档里找不到 response_format 的说明,它文档中出现的 response_format 属于图像生成接口,含义是返回 url 还是 base64,跟结构化输出完全不是一回事。所以写跨家兼容层的时候,真正要分的不是”支不支持 JSON”,而是”有没有 json_schema 这一档”——没有这一档的,schema 只能写进 system prompt,校验必须落在你自己的业务代码里。
先把两档分清楚:json_object 和 json_schema 差在哪
Kimi 官方文档给了一张这两种模式的对照表,是这几家里把差异讲得最直白的一份,也适合当作理解其他家的坐标系。
按那份文档:json_object 和 json_schema + strict: true 都保证输出是合法的 JSON Object,区别在保证的粒度。json_object 下字段名”不保证,模型可能自由发挥”,字段类型不强制,额外字段可能擅自增加,字段也可能省略;json_schema + strict: true 下字段名强制固定、字段类型强制匹配、额外字段禁止(additionalProperties: false)、required 字段必现。
更关键的是实现机制那一行:文档写明 json_object 是”Prompt 引导”,而 json_schema + strict: true 是”Token 级约束解码(CFG),在采样阶段过滤非法 token”。这句话解释了很多现象——Prompt 引导本质上是请求模型配合,模型心情不好就可能在 JSON 前面加一句”以下是你需要的 JSON 文档”;而采样阶段过滤非法 token 是从生成侧堵死的,不合 schema 的 token 根本不会被采出来。
对应的使用场景建议也是分开的:json_object 用于快速原型、非关键路径;json_schema 用于生产环境、API 对接、数据入库。
GLM:只有 json_object 这一档,schema 要自己在客户端校验
智谱的对话补全接口文档里,response_format 是个 object,说明写着”指定模型的响应输出格式,默认为 text,仅文本模型支持此字段”,type 的 enum 只列出 text 和 json_object 两个值,默认 text。
有意思的是同一段描述里还有一句”type 取值收敛为三种”,但下面的 enum 实际只给了两个取值——这种文档内部不一致的地方,接入时以 enum 那一栏为准更稳妥,最终仍以官方文档当前版本为准。
官方的结构化输出指南里给的做法也印证了这一点:核心参数说明是三条——response_format 设为 {"type": "json_object"} 启用 JSON 模式、model 用支持结构化输出的模型、messages 里”在系统消息中定义期望的 JSON 结构和字段要求”。注意第三条,格式约束是靠系统消息传达的,不是靠一个 schema 参数。文档的 Schema 验证示例是在 Python 侧引入 jsonschema 库,把 schema 同时塞进 system prompt 和本地 validate() 调用,解析时分别捕获 jsonschema.exceptions.ValidationError 和 json.JSONDecodeError 两类异常。
也就是说,在 GLM 上做严格结构化,校验这一步天然是你的活。官方在文档末尾还留了一句提醒:JSON 模式要求模型严格按指定格式输出,在某些复杂场景下可能影响回答的自然性。GLM 各文本模型页把”结构化输出”列为能力卡片,具体到某个模型能不能用,还是要看它自己的模型页。更细的用法拆解可以看GLM 结构化输出怎么用。
Kimi:档位最全,但有一套自己的 schema 方言
Kimi 的 response_format 支持 json_object 与 json_schema 两种 type。走 json_schema 时,json_schema.name 和 json_schema.schema 必须提供,name 用于日志和调试,strict 是布尔值,官方建议始终显式设置为 true。
这里有一条别家没有的东西:strict 为 true 时,schema 需要符合 MFJS(Moonshot Flavored JSON Schema)规范。官方为此提供了 walle 这个 CLI 工具做静态自检,用 go install 安装后带 -schema 和 -level strict 参数校验。但文档同时给了一句很要命的提示:即使 schema 包含 anyOf / oneOf / $ref,API 也常能正常返回 200,且响应中不会出现 warning 字段。换句话说,你不能靠”接口没报错”来判断 schema 被完整遵守了,walle 更适合作为静态检查入口,实际兼容性以目标模型的在线调用结果为准。
模型之间的差异也写得很细: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 并在业务层做二次校验。
另外三条容易被忽略的细节:
一是思考模型返回 content 的同时可能还会返回 reasoning_content,官方明确要求只解析 choices[0].message.content 作为最终 JSON,不要直接把整个响应对象丢给 json.loads。
二是表达”信息缺失”的推荐写法。声明在 required 中的字段必然出现在输出里,如果字段只声明了单一类型(如 "integer"),输入里没有对应信息时模型可能编造内容或返回空字符串;官方建议改用联合类型声明可为 null(如 "type": ["integer", "null"]),让模型用 null 显式表示缺失。这条是我认为整篇文档里最实用的一句。
三是缓存:文档写明是否设置 response_format 不会破坏前缀缓存,可以按请求粒度调整这个参数。想细看 JSON Mode 那一档的用法,可以读Kimi JSON Mode 怎么用。
Grok:把 schema 支持面写成了一份规格说明
xAI 的结构化输出文档在”到底支持 JSON Schema 的哪些部分”这件事上写得最详细,几乎是一份可以拿来对照实现的规格。
首先是两条路径:主路径是 response_format,把 response_format.type 设为 "json_schema" 并在 response_format.json_schema 下提供 schema;这个参数也接受 "json_object"(只要求良构 JSON、不需要具体结构)和默认的 "text"。第二条路径是工具调用——文档说明 xAI 模型生成的工具调用参数总是严格符合工具的输入 JSON Schema,strict 标志隐式恒为 true。这一点值得记,因为它意味着”想要强约束”未必非得走 response_format。
支持的类型是明文枚举的:string、number、integer、boolean、null、enum、const、array、object、anyOf、oneOf(行为与 anyOf 相同)、allOf(仅限单个子模式)、$ref / $defs(仅限非循环引用)。schema 建议按 Draft 2020-12 编写,Draft-07 也接受。
additionalProperties 这一条要特别注意方向:官方注明它默认为 false,必须显式设为 true(默认行为以官方文档当前版本为准)。这跟 Kimi 那边”不指定时 kimi-k2.7-code 允许输出额外字段”的描述正好是相反的方向,跨家搬 schema 时这是第一个会咬人的地方。
format 关键字只对一批取值强制生效,官方列出的是 date、time、date-time、email、uuid、ipv4、ipv6、uri,其他 format 值会被接受但不强制。同属”接受但不结构化强制”的还有 not、if / then / else、多于一个子模式的 allOf,以及超出保证范围的约束——文档对 minLength / maxLength、minItems / maxItems、minProperties / maxProperties 设有保证上限,超过上限的 schema 仍会被接受,但符合度就要靠模型行为了,具体数值以官方文档为准。
会直接返回 400 的 schema 也列得很清楚:零变体的 enum 或 anyOf、schema 为 true 或 false 的属性、maxContains / minContains、以及把 items 写成数组(元组校验要改用 prefixItems)。
pattern 支持的是 ECMA-262 的一个实用子集。不支持的部分包括反向引用、Unicode 属性转义、单词边界、前瞻与后顾、内联修饰符。还有几条语义差异必须知道:. 会匹配换行;^ 和 $ 是隐式的,模式总是匹配整个字符串,不用自己加;捕获组没有语义效果,等同于非捕获组。这几条足以让一段从别处复制来的正则在这里行为不同。
SDK 层面还分了 parse() 与 response_format 两种用法:chat.parse(Model) 返回 (Response, Model) 元组、由 SDK 自动解析;用 response_format 配 sample() 或 stream() 则返回带 JSON 字符串的 Response,由你手动解析。官方给出的选择依据里明确写了一条——想在结构化输出上用流式就选后者,流式下 chunk 会逐步拼出 JSON 字符串。细节见Grok 结构化输出怎么配。
阶跃星辰:两套接口的字段名不一样,别混用
阶跃星辰要多注意一层:同一个能力在两个接口上的字段路径不同。
Chat Completions 接口里是 response_format,默认 {"type":"text"},type 可选 text、json_object、json_schema。走 json_schema 时 json_schema 对象必填,里面 name 与 schema 是 required,strict 是可选的、默认为 false(默认值以官方文档当前版本为准)——这一点和 Kimi”建议始终显式设为 true”的口径不同,照搬 Kimi 的代码而不显式传 strict 的话,严格程度会悄悄降一档。
Responses 接口则把它挪到了 text.format 下面:text 是可选的文本输出格式配置对象,里面的 format 对象带 type(同样是 text / json_object / json_schema 三选一)、name、strict、schema。同一套语义,路径不同,迁移时是个纯粹的体力坑。
JSON Mode 指南里的三步法和收尾提醒也值得抄下来:在 System Prompt 中放置期望输出的 JSON 结构和说明(推荐用 JSON Schema 描述)、请求时设置 response_format 为 { "type": "json_object" }、解析并验证结果。注意事项里特别点出:使用 JSON Mode 时需要检查返回结果的 finish_reason 是否为 stop,如果是 length,说明模型受 max_token 限制无法完整返回,拿到的 Message 可能无法被正常解析。Kimi 那边也有同款提醒,finish_reason=length 是这类接口共通的第一排查项。
MiniMax 和 Gemini:这次真没查到
MiniMax 的文本对话文档(OpenAI 兼容与 Anthropic 兼容两套)里,我没有找到 response_format 的说明。文档中确实出现了这个参数名,但都在图像生成接口下,含义是返回图片链接还是 Base64 编码——同名不同义,直接照搬会白折腾。
MiniMax 官方文档里给出的结构化路径是工具调用:tools 定义可调用函数列表(含函数名、描述和参数规范),响应里 function.arguments 是 JSON 格式字符串。它还有一条很硬的要求——在多轮 Function Call 对话中必须把完整的模型返回(assistant 消息)加回对话历史以保持思维链连续性,OpenAI SDK 下 content 字段里的 <think> 标签内容需要完整保留,启用 reasoning_split 后思考内容走 reasoning_details 字段,同样要完整保留。
Gemini 这边,本文查证所依据的官方文档里没有结构化输出相关章节,所以关于它的 schema 支持面,本文不做任何判断。
迁移时最容易栽的几处
把这几家放在一起看,跨家搬运时真正会出问题的是这么几条:
第一是档位错位。从有 json_schema 的一家迁到只有 json_object 的一家,schema 会静默失效——请求照样成功,输出照样是合法 JSON,只是字段名和类型不再受约束。这类问题不会报错,只会在下游解析时才暴露。
第二是默认值方向相反。additionalProperties 在 Grok 侧的官方说明是默认 false、需显式设 true;strict 在阶跃星辰侧默认 false,在 Kimi 侧官方建议显式设 true。凡是”不传就有默认行为”的字段,跨家迁移一律显式写出来,别赌默认值一致。
第三是同名参数不同义,MiniMax 的 response_format 就是活例子。迁移时按参数名做映射表,很容易映射到一个语义完全不同的字段上。
第四是解析口径。Kimi 明确要求只解析 message.content、不要拿整个响应对象去 json.loads;MiniMax 要求完整回传含思考字段的 assistant 消息。思考类模型普及之后,“响应体里不止一处文本”已经是常态,解析代码写死路径这件事本身就是隐患。
真要动手,建议按”最小可用 schema”起步:先用一层平铺的对象跑通,再逐步加嵌套、加 anyOf、加 pattern,每加一层就回官方文档确认这家支不支持。结构化输出的坑很少体现为报错,多数时候是安安静静地给你一个”看起来对”的结果。解析失败之后怎么定位,可以接着看结构化输出解析失败排查。