SpringAI 结构化输出 03:原生响应结构化输出

默认情况下,.entity(…)会将JSON Schema作为文本指令追加到提示词中。这属于响应侧方案:只是请求模型遵守格式,拿到返回结果之后再做解析。

与之互补的另一种方案是请求侧约束:在API调用层面告知模型服务商,响应必须严格遵循指定Schema。如今绝大多数主流大模型服务商都支持该能力:OpenAI的Structured Outputs、Anthropic结构化输出扩展、Gemini的responseSchema、Mistral的response_format

Spring AI提供跨厂商兼容开关,配置在EntityParamSpec回调中:

网络传输层面发生的变化如下:

  1. 系统提示词不再携带JSON格式指令(提示词更精简,消耗Token更少);
  2. Schema直接作为API请求字段发送给服务商;
  3. 由服务商运行时强制校验格式,从根源上杜绝输出非法JSON。

带来三点收益:

  • 可靠性更高:服务商保证输出严格匹配Schema;
  • 提示词更干净:无需追加大段格式说明文本;
  • 性能更优:模型内部可以针对结构化输出路径做优化。

Spring AI如何检测该能力支持

Spring AI检测依据:判断模型的聊天配置类是否实现StructuredOutputChatOptions接口。 如果模型不实现该接口,则该开关会被静默忽略,自动回退到基于提示词的默认实现。

支持的模型(Spring AI 2.0版本)

无论底层接入哪一家模型,同一套useProviderStructuredOutput()代码均可直接使用:

  1. OpenAI:GPT‑4o及之后支持JSON Schema的模型
  2. Anthropic:Claude 3.5 Sonnet以及更新版本
  3. Google GenAI:Gemini 1.5 Pro及之后版本
  4. Mistral AI:Mistral Small及之后支持JSON Schema的模型
  5. Ollama:支持JSON Schema的模型(因模型而异,详见已知限制

为什么该功能默认关闭

兼容性考量。老旧或者不支持该特性的模型会直接拒绝该类请求;而基于提示词的方案可以在全部模型上运行。

原生结构化输出在不同模型、不同服务商之间支持程度差异很大,因此默认不启用。仅当业务需要API层面强Schema约束时才开启,务必针对你实际使用的模型版本做充分测试

已知限制

即便厂商对外宣称支持该特性,原生结构化输出往往也是部分实现:可识别的JSON Schema子集有限。常见不支持特性:$ref引用、深层嵌套数组、allOf/anyOf/oneOf、正则表达式、递归类型。 正是这类Schema能力缺失会造成输出结构偏移,这正好是validateSchema()可以捕获的问题。

Ollama:模型层面存在不稳定性

并不是全部Ollama模型都可以稳定遵守结构化输出Schema约束。 尤其是带有内置推理/思考模式的模型(例如 qwen3:8b、qwen3.5:9b以及其他新版通义千问系列),会输出内部思考文本而不是JSON,触发BeanOutputConverter反序列化异常,报错示例:

遇到该问题的处理方案:

  1. 更换其他模型,例如 llama3.1:latest;
  2. 回退到默认基于提示词的实现;
  3. 组合开启两个开关,格式错误自动重试修复:

OpenAI:不支持顶层JSON数组

OpenAI原生结构化输出API,不允许根节点直接是数组(参考 OpenAI社区讨论)。 如果开启原生结构化输出,请求返回List会直接触发API报错。

两种替代方案: 方案1:使用容器Record把数组包装一层

方案2:使用默认基于提示词的模式(不开启原生输出)

注意事项: 默认提示词驱动的流程没有该限制,可以直接返回顶层数组。

全局开启原生结构化输出

useProviderStructuredOutput() 默认是单次调用的开关。 想要让该ChatClient实例每一次调用都启用原生结构化输出,可以设置顾问参数 AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT;既可以在构建器设置全局默认,也可以单次请求指定。

各服务商内置JSON模式补充说明

useProviderStructuredOutput()相互独立,部分大模型还提供独立配置项直接开启JSON输出模式:

  1. OpenAIspring.ai.openai.chat.response‑format,支持JSON_OBJECT(合法JSON对象)或者传入schema的JSON_SCHEMA
  2. Ollama:配置项spring.ai.ollama.chat.format,仅支持取值json
  3. Mistral AIspring.ai.mistralai.chat.response‑format;设置{"type":"json_object"}开启普通JSON模式;设置{"type":"json_schema"}并传入schema,则启用原生结构化输出。

原文:Provider‑Native Structured Output