SpringAI 结构化输出 02:Schema 校验和自纠错

默认的 .entity(…) 调用只是请求模型输出符合JSON Schema规范的内容,并无法强制模型一定遵守。当模型返回多余字段、缺失必填字段,或者在JSON前后附带大段自然文本描述时,解析器就会抛出异常。

处理格式异常输出最简单的方案就是:检测错误,然后重试。Spring AI 只需在 EntityParamSpec 配置器上开启一个开关即可自动完成这套逻辑:

自修复重试循环工作原理

配置 spec -> spec.validateSchema() 会开启一套自修复重试循环:

  1. 大模型返回响应结果;
  2. Spring AI 使用目标类型对应的JSON Schema校验这份响应;
  3. 如果校验通过,直接返回强类型对象;
  4. 如果校验失败,会把具体校验错误信息(例如:缺失必填字段actor期望数组类型,但得到字符串)追加到用户提示词中,重新发起请求。默认最多重试3次

注意: 每一次重试,模型都能看到上一轮具体出错原因,并不是无意义的盲目重试:模型明确知道哪里不符合规范,可以针对性修正输出。

该能力由 StructuredOutputValidationAdvisor(结构化输出校验切面)提供。开启 validateSchema() 时该切面会自动注册,开发者无需手动装配任何组件,只需要打开这个配置开关即可。

⚠️ 开启 validateSchema() 之后不支持流式调用:该切面需要拿到完整响应报文才能执行校验。

自定义校验切面(Advisor)

StructuredOutputValidationAdvisor 默认最大重试次数为3,使用Spring AI内置的 JsonMapper。 如果你需要自定义行为:调高重试次数、传入预先定义好的Schema、更换JSON映射器,可以手动构建实例并注册到 ChatClient手动注册的切面会覆盖系统自动注册的版本。

切面有二选一的配置方式,不能同时使用:

  1. outputType:根据Java类型自动推导生成JSON Schema;
  2. outputJsonSchema:直接传入预先准备好的Schema字符串。

核心行为特性

  1. 根据输出类型自动推导JSON Schema,或者直接使用外部传入的Schema字符串;
  2. 按照 JSON Schema DRAFT_2020_12 规范校验大模型返回结果;
  3. 校验失败自动重试,默认最多3次;
  4. 重试阶段会把校验错误信息追加到提示词,引导模型自行修正输出;
  5. 累加每一轮重试的Token消耗,最终返回的ChatResponse会统计全部多次请求的总用量,而不是仅统计最后一次调用(参考文档:多步骤流程下累计Token用量);
  6. 支持接入自定义 JsonMapper

想要了解该切面背后递归Advisor的内部机制,查阅 StructuredOutputValidationAdvisor 文档。

和厂商原生结构化输出组合使用

validateSchema() 属于响应侧的兜底防护:拿到模型返回结果之后检测错误,出错再重试。 useProviderStructuredOutput() 属于互补的请求侧约束,在向模型发起请求时就告诉服务端强制遵循Schema。两者可以叠加同时启用:

这种组合方式对于厂商存在边界缺陷的场景尤其有用。例如 Ollama 的推理模型,有时会先输出大段推理思考文本,而不是直接输出JSON。详见文档【已知限制】章节。

原文:Schema Validation & Self-Correction