OpenRouter 实测三种结构化输出路径:严格模式 216 次回复中 209 次合规,7 次失手全来自同一家不执行模式的供应商
核心概要
OpenRouter 用 24 条杂乱的客服消息在九个支持结构化输出的模型上比较了三种拿到可靠 JSON 的办法:发送严格 JSON Schema、强制一次工具调用、或改用只输出标签的决策模型。九个模型共 216 次回复中 209 次符合严格 schema,7 次失手全部来自一家忽略 schema 的供应商;只在提示词里要求 JSON 时则有 18 次因代码围栏失败。对只支持工具的 GLM 5.3 FlashX,强制工具调用得到 24 次中 22 次有效,而直接发 schema 是 0 次。
深度剖析
让大模型稳定吐出可被代码直接读取的 JSON,现在有三条可选路径,按模型端点实际支持的能力挑一条即可,不必为每个模型各写一套修补。 此前多数做法只在提示词里要求模型输出 JSON,模型偶尔会把 JSON 包进代码围栏、多给一个没要的字段,或把数字写成字符串,下游代码随即报错。 在 24 条杂乱的客服消息上,九个支持结构化输出的模型共 216 次回复中有 209 次符合严格 schema,7 次失手全部来自同一家忽略 schema 的供应商;而只在提示词里要求 JSON 时,有 18 次回复失败,每次都出在代码围栏上。
做法是把同一份 schema 交给模型,要么作为回复格式约束消息正文,要么作为唯一一个工具的参数并强制模型调用它,代码只取参数、从不真正执行这个工具。 严格模式要求每个键都写进 required、每个对象都设 additionalProperties 为 false,可能缺失的值改成可为 null 而不是省略;OpenRouter 实测这套最严规则写出的 schema 在每个试过的模型上都能用。 只支持工具的 GLM 5.3 FlashX 直接发 schema 时 24 次里 0 次有效,改用 tool_choice 为 required 强制调用后 24 次里 22 次有效,两次失败是 order_id 里出现了字符串 null。
只支持工具的模型也能拿到结构化输出,但供应商是否真的执行 schema 要自己验证,因为请求可能以 200 正常返回却给出不合规的内容。 结构化输出属于每个端点而非模型本身,同一模型有的端点支持、有的不支持;默认情况下请求照样发出,schema 被悄悄忽略。 在 provider 对象里设 require_parameters 为 true 后,没有端点支持所发参数时请求直接以 404 失败;GLM 5.3 FlashX 的端点列表曾把 required 标为不支持,但当天每次用 required 的调用都成功,说明这个字段只能当参考。
启示与展望
结论来自 24 条客服消息、九个支持结构化输出的模型加一个只支持工具的 GLM 5.3 FlashX,每次对照为单次运行,适用于需要从模型回复中读取字段或标签的工程场景。
供应商是否执行 schema 并不稳定,端点列表里的 supports_tool_choice 字段也可能与实际行为不符;Response Healing 只修语法、不读 schema,且对流式请求和工具调用参数不起作用;决策模型的概率在多次运行间会小幅漂移,退款金额这类算术判断需要先在自己的数据上测试。
