模式验证与自我纠正 :: Spring AI 参考
Schema 验证与自我纠正
默认情况下,.entity(…) 调用请求模型生成符合 schema 的 JSON,但无法强制其遵守。当模型返回额外字段、遗漏必需字段,或将 JSON 包裹在文本中时,解析器会抛出异常。
处理格式错误的输出的最简单方法是检测并重新尝试。Spring AI 通过在 EntityParamSpec 消费者上设置单个开关即可自动执行此操作:
ActorsFilms films = chatClient.prompt()
.user("Generate the filmography for a random actor.")
.call()
.entity(ActorsFilms.class, spec -> spec.validateSchema());
自校正循环如何运作
spec → spec.validateSchema() 消费者启用了一个自纠正的重试循环:
-
模型进行响应。
-
Spring AI 针对目标类型的 JSON Schema 验证响应内容。
-
如果验证通过,你将获得一个强类型的记录。
-
如果验证失败,验证错误(例如,"缺少必需字段
actor"、"期望array,但得到string")会被追加到用户提示中,并重新发起调用——默认最多尝试 3 次。
模型在每次重试时都会看到具体的错误,因此第二次尝试并非盲目重试:模型知道问题所在,并可以对其进行修正。

这由 StructuredOutputValidationAdvisor 提供支持,它是一个在调用 validateSchema() 时自动注册的递归顾问。您无需进行任何额外配置;该开关即为完整的配置项。
当 validateSchema() 处于激活状态时,不支持流式传输。顾问(advisor)需要完整的响应内容才能对其进行验证。
自定义 Advisor
StructuredOutputValidationAdvisor 默认设置为 3 次重试尝试,并使用 Spring AI 默认的 JsonMapper。如需进行自定义——例如增加尝试次数、提供预定义的 schema 或使用其他 mapper——请自行创建实例并将其注册到 ChatClient 上。显式注册的 advisor 将替代自动注册的 advisor:
var validationAdvisor = StructuredOutputValidationAdvisor.builder()
.outputType(ActorsFilms.class)
.maxRepeatAttempts(5)
.build();
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(validationAdvisor)
.build();
Advisor 可通过 outputType(自动推导 schema)或 outputJsonSchema(预置的 schema 字符串)进行配置;这两个选项互斥。
var validationAdvisor = StructuredOutputValidationAdvisor.builder()
.outputJsonSchema(myConverter.getJsonSchema())
.build();
关键行为:
-
从预期输出类型推导 JSON Schema,或接受预提供的 Schema 字符串。
-
使用 JSON Schema
DRAFT_2020_12对 LLM 响应进行验证。 -
当验证失败时重试调用(默认:最多尝试 3 次)。
-
在重试尝试中,将验证错误消息添加到提示中,以帮助模型自我纠正。
-
累积所有验证尝试中的 token 使用量,因此返回的
ChatResponse报告的是所有重试的累计使用情况,而不仅仅是最后一次尝试的情况(参见多步骤流程中的累计使用情况)。 -
可选支持自定义
JsonMapper。
有关此顾问背后递归顾问机制的详细信息,请参阅 StructuredOutputValidationAdvisor。
与 Provider 原生输出结合
validateSchema() 是一个响应端的安全网——它在事后捕获无效输出并重试。useProviderStructuredOutput() 是一种互补的请求端约束。这两者可以自然组合使用:
ActorsFilms films = chatClient.prompt()
.user("Generate the filmography for a random actor.")
.call()
.entity(ActorsFilms.class, spec -> spec
.useProviderStructuredOutput()
.validateSchema());
这在处理提供商的边缘情况时特别有用,尤其是在原生强制机制仅部分生效的情况下——例如,Ollama 推理模型可能会输出纯文本推理轨迹,而非 JSON。参见 已知限制。