一、什么是递归 Advisor?
递归 Advisor 是一种特殊类型的 Advisor,能够多次循环执行下游 Advisor 链。这种模式在需要重复调用 LLM 直到满足特定条件时非常有用,例如:
-
在循环中执行工具调用,直到不再需要调用任何工具
-
验证结构化输出并在验证失败时重试
-
通过修改请求来实现评估逻辑
-
通过修改请求来实现重试逻辑
CallAdvisorChain.copy(CallAdvisor after) 方法是实现递归 Advisor 模式的关键工具。它会创建一个新的 Advisor 链,仅包含原始链中指定 Advisor 之后的所有 Advisor,并允许递归 Advisor 根据需要调用此子链。这种方法确保:
-
递归 Advisor 可以循环执行链中剩余的 Advisor
-
链中的其他 Advisor 可以观察并拦截每次迭代
-
Advisor 链保持正确的顺序和可观测性
-
递归 Advisor 不会重新执行它之前的 Advisor

二、内置递归 Advisor
Spring AI 提供了两个内置的递归 Advisor 来演示此模式:
2.1 ToolCallAdvisor
ToolCallAdvisor 将工具调用循环作为 Advisor 链的一部分实现,而不是依赖模型的内部工具执行。这使得链中的其他 Advisor 能够拦截和观察工具调用过程。
主要特性:
-
通过设置 setInternalToolExecutionEnabled(false) 禁用模型的内部工具执行
-
循环执行 Advisor 链,直到不再出现工具调用
-
支持"直接返回"功能 - 当工具执行设置了 returnDirect=true 时,它会中断工具调用循环,并将工具执行结果直接返回给客户端应用程序,而不是将其发送回 LLM
-
使用 callAdvisorChain.copy(this) 创建用于递归调用的子链
-
包含空安全检查,以处理聊天响应可能为 null 的情况
使用示例:
java
var toolCallAdvisor = ToolCallAdvisor.builder()
.toolCallingManager(toolCallingManager)
.advisorOrder(BaseAdvisor.HIGHEST_PRECEDENCE + 300)
.build();
var chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(toolCallAdvisor)
.build();
直接返回功能
"直接返回"功能允许工具绕过 LLM,将其结果直接返回给客户端应用程序。这在以下情况下非常有用:
-
工具的输出是最终答案,不需要 LLM 处理
-
您希望通过避免额外的 LLM 调用来减少延迟
-
工具结果应按原样返回,无需解释
当工具执行设置了 returnDirect=true 时,ToolCallAdvisor 将:
-
正常执行工具调用
-
检测 ToolExecutionResult 中的 returnDirect 标志
-
跳出工具调用循环
-
将工具执行结果作为 ChatResponse 直接返回给客户端应用程序,其中工具的输出作为生成内容
2.2 StructuredOutputValidationAdvisor
StructuredOutputValidationAdvisor 根据生成的 JSON 模式验证结构化 JSON 输出,并在验证失败时重试调用,最多重试指定次数。
主要特性:
-
根据预期的输出类型自动生成 JSON 模式
-
根据模式验证 LLM 响应
-
如果验证失败,重试调用,最多可配置重试次数
-
在重试时向提示词添加验证错误消息,以帮助 LLM 纠正其输出
-
使用 callAdvisorChain.copy(this) 创建用于递归调用的子链
-
可选择支持自定义 ObjectMapper 进行 JSON 处理
java
var validationAdvisor = StructuredOutputValidationAdvisor.builder()
.outputType(MyResponseType.class)
.maxRepeatAttempts(3)
.advisorOrder(BaseAdvisor.HIGHEST_PRECEDENCE + 1000)
.build();
var chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(validationAdvisor)
.build();