Java
Spring AI 2.0 把 JSON 输出变可靠了:结构化输出、自纠错重试和 json-repair 的分工
大模型最容易犯的错,不是答非所问,而是答得太像人:自然语言很顺,机器却没法稳定消费。Spring AI 2.0 把这个老问题拆成了两层保险:一层是在模型返回后做 schema 校验和自纠错重试,另一层是在请求阶段直接把 schema 交给支持结构化输出的模型提供方。

为什么结构化输出不是“把文本转 JSON”这么简单
只要下游系统要做路由、入库、权限判断、工单分派或任务编排,模型输出就不能只是“看起来像 JSON”。字段类型、必填项、数组层级、空值处理和异常恢复都要可控。否则前面一句话看着正常,后面一个解析异常就能把整条流程打断。
Spring AI 从一开始的 .entity() 就已经在做这件事:先把 record 转成 JSON schema,再把 schema 放进提示词,再把模型返回的结构化结果解析成类型对象。问题在于,这条链路是“希望模型遵守”,不是“强制模型遵守”。
validateSchema:把模型当成会犯错的同事
validateSchema() 的价值在于,它不把错误视为终点,而是把错误当作下一轮提示词的材料。模型如果少字段、类型错位、或混入解释文字,Spring AI 会把具体错误回灌给模型,默认最多重试 3 次,让模型自己修。
- 这不是简单的重试,而是带着错误上下文的重试。
- 适合字段少、 schema 清晰、纠错成本低的场景。
- 当模型偶尔失手时,能明显降低人工兜底成本。

useProviderStructuredOutput:把约束前移到模型提供方
第二层保险更像工程上的“硬闸门”:把 schema 直接交给模型提供方,让对方在生成阶段就遵守约束,而不是生成完再修。这样做更干净,也更省 token,因为系统提示词不再重复解释 JSON 格式。
但这个开关并不是越开越好。不同厂商对 JSON Schema 的支持不完全一致,深层嵌套、递归、oneOf/allOf、顶层数组、推理模型的特殊输出,都可能成为坑。真正稳妥的做法是:能前置约束就前置,剩余边角再用 validateSchema() 兜底。
json-repair 适合修什么,不适合修什么
如果错误只是字符串层面的破损,比如缺括号、多逗号、引号没闭合、文本里夹了一段可提取的 JSON,那么在应用层做 repair 往往比重新调用模型更划算。json-repair 走的是这条路,它修的是结构,不是语义。
它的边界也很明确:如果模型已经把业务字段理解错了,repair 并不能创造正确事实。它只能把“坏 JSON”修成“可解析 JSON”,不能把“错回答”修成“对回答”。
落地时的建议
- 优先设计稳定的 schema,不要把输出格式设计得像自由作文。
- 低风险场景先用 validateSchema(),高价值链路再叠加 provider structured output。
- 把 json-repair 当最后一层保险,不要当业务正确性的来源。
- 记录失败样本,持续优化 schema 和提示词,而不是只盯着一次成功率。
结论
Spring AI 2.0 的进步,不在于“模型更听话”,而在于它终于承认:结构化输出必须是工程问题。你要么在源头上约束,要么在结果侧自修,要么两者都做。真正成熟的做法,是把模型当成会出错的组件,然后给它加上跟生产系统一样的护栏。