Skip to content
Spring AI 文档版本 2.1.0-SNAPSHOT 源快照 272cb1ec 更新于 2026-10-16

模式校验与自我纠正

默认的 .entity(...) 调用要求模型产出匹配模式的 JSON,但无法强制它。 当模型多返回一个字段、漏掉一个必填字段,或把 JSON 包裹在文字里时,解析器会抛出异常。

处理格式错误输出的最简单方式是检测它并重试。 Spring AI 通过 EntityParamSpec 消费者上的一个开关自动完成这一点:

java
ActorsFilms films = chatClient.prompt()
    .user("Generate the filmography for a random actor.")
    .call()
    .entity(ActorsFilms.class, spec -> spec.validateSchema());

自我纠正循环如何工作

spec -> spec.validateSchema() 消费者会开启一个自我纠正的重试循环:

  1. 模型给出响应。
  2. Spring AI 依据目标类型的 JSON 模式校验该响应。
  3. 如果校验通过,你就能拿回有类型的记录。
  4. 如果校验失败,验证错误(例如“missing required field actor”、“expected array, got string”)会被追加到用户提示词,并重新发起调用——默认最多 3 次尝试。

在每次重试时模型都会看到具体的错误,因此第二次尝试并非盲目重试:模型知道哪里出了问题并能纠正它。

这由 StructuredOutputValidationAdvisor 驱动,它是一个在你调用 validateSchema() 时自动注册的递归顾问。 你无需装配任何东西;这个开关就是全部配置。

NOTE

当 validateSchema() 处于启用状态时,不支持流式传输。

该顾问需要完整的响应才能对其进行校验。

定制顾问

StructuredOutputValidationAdvisor 默认为 3 次重试尝试,并使用 Spring AI 默认的 JsonMapper。 要定制——例如更多次尝试、预先给定的模式,或不同的映射器——请构建你自己的实例并注册到 ChatClient 上。 显式注册的顾问会替换自动注册的那个:

java
var validationAdvisor = StructuredOutputValidationAdvisor.builder()
    .outputType(ActorsFilms.class)
    .maxRepeatAttempts(5)
    .build();

ChatClient chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(validationAdvisor)
    .build();

该顾问可通过 outputType(自动派生模式)或 outputJsonSchema(预先给定的模式字符串)来配置;这两种选项互斥。

java
var validationAdvisor = StructuredOutputValidationAdvisor.builder()
    .outputJsonSchema(myConverter.getJsonSchema())
    .build();

关键行为:

  • 从期望的输出类型派生一个 JSON 模式,或接受一个预先给定的模式字符串。
  • 使用 JSON 模式 DRAFT_2020_12 依据模式校验 LLM 响应。
  • 校验失败时重试调用(默认:最多 3 次尝试)。
  • 在重试尝试时用验证错误消息增强提示词,以帮助模型自我纠正。
  • 在每次验证尝试间累计令牌用量,因此返回的 ChatResponse 报告所有重试的累计用量,而不仅仅是最后一次(参见 多步流程中的累计用量)。
  • 可选地支持自定义 JsonMapper。

关于此顾问背后递归顾问机制的细节,参见 StructuredOutputValidationAdvisor。

与服务商原生输出结合

validateSchema() 是一层响应侧的安全网——它在事后捕获错误输出并重试。 useProviderStructuredOutput() 是一层互补的请求侧约束。 两者能自然地组合:

java
ActorsFilms films = chatClient.prompt()
    .user("Generate the filmography for a random actor.")
    .call()
    .entity(ActorsFilms.class, spec -> spec
        .useProviderStructuredOutput()
        .validateSchema());

这对于原生强制仅为部分生效的服务商边缘情况尤其有用——例如,Ollama 推理模型可能输出纯文本的推理轨迹而非 JSON。 参见 已知限制。

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。