在spring ai中从官网可以看出advisor是一个很重要的概念,因此这一篇文章来学习一下。
Spring AI 顾问(Advisors)API 提供了一种灵活且强大的方式,用于拦截、修改和增强 Spring 应用程序中由人工智能驱动的交互。通过利用Advisors API,开发人员可以创建更复杂、可重用且易于维护的人工智能组件。
其主要优势包括封装重复出现的生成式人工智能模式、转换发送到和从大型语言模型(LLMs)接收的数据,以及在各种模型和用例中提供可移植性。
您可以使用 ChatClient API 配置现有的顾问,如下例所示:
var chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(
new MessageChatMemoryAdvisor(chatMemory), // chat-memory advisor
new QuestionAnswerAdvisor(vectorStore) // RAG advisor
)
.build();
String response = this.chatClient.prompt()
// Set advisor parameters at runtime
.advisors(advisor -> advisor.param("chat_memory_conversation_id", "678")
.param("chat_memory_response_size", 100))
.user(userText)
.call()
.content();
建议在构建时使用构建器的 defaultAdvisors()
方法注册Advisor。
此外,Advisors也参与可观察性堆栈,因此您可以查看与其执行相关的指标和追踪信息。
核心组件
该 API 包括用于非流式场景的 CallAroundAdvisor
和 CallAroundAdvisorChain
,以及用于流式场景的 StreamAroundAdvisor
和 StreamAroundAdvisorChain
。它还包含用于表示未密封的 Prompt 请求的 AdvisedRequest
和用于表示 Chat Completion 响应的 AdvisedResponse
。两者都持有一个 advise-context
,用于在advisor链中共享状态。

nextAroundCall()
和 nextAroundStream()
是顾问的核心方法,通常执行以下操作:检查未密封的 Prompt 数据,自定义和增强 Prompt 数据,调用顾问链中的下一个实体,可选地阻止请求,检查聊天完成响应,以及抛出异常以指示处理错误。
此外,getOrder()
方法决定了顾问在链中的顺序,而 getName()
方法提供了一个唯一的顾问名称。
由 Spring AI 框架创建的顾问链允许按 getOrder()
值排序的多个顾问依次调用。值越低的顾问越先执行。自动添加的最后一个顾问将请求发送到 LLM。
下面的流程图描述了顾问链和聊天模型的交互:

1. Spring AI 框架会根据用户的 Prompt 创建一个 AdvisedRequest,并附带一个空的 AdvisorContext 对象。
2. 链中的每个顾问都会处理该请求,可能会对其进行修改。或者,它可以选择通过不调用下一个实体来阻止请求。在这种情况下,顾问需要自行填充响应。
3. 框架提供的最后一个顾问会将请求发送到聊天模型(Chat Model)。
4. 聊天模型的响应随后会通过顾问链返回,并被转换为 AdvisedResponse。后者包含了共享的 AdvisorContext 实例。
5. 每个顾问都可以处理或修改响应。
6. 最终的 AdvisedResponse 会通过提取 ChatCompletion 返回给客户端。
Advisor在链中的顺序
advisor在执行链中的顺序由getOrder()
方法来决定。理解的关键点如下:
- 顺序值较低的顾问会优先执行。
- 顾问链的工作方式类似于栈:
- 链中的第一个顾问是第一个处理请求的。
- 它也是最后一个处理响应的。
- 为了控制执行顺序:
- 将顺序值设置为接近
Ordered.HIGHEST_PRECEDENCE
,以确保顾问在链中首先执行(在请求处理时最先,在响应处理时最后)。 - 将顺序值设置为接近
Ordered.LOWEST_PRECEDENCE
,以确保顾问在链中最后执行(在请求处理时最后,在响应处理时最先)。
- 将顺序值设置为接近
- 较高的值被视为较低的优先级。
- 如果多个顾问具有相同的顺序值,则它们的执行顺序无法保证。
看似矛盾的顺序和执行序列之间的关系,是由于顾问链的栈式特性导致的:
- 具有最高优先级(最低顺序值)的顾问被添加到栈的顶部。
- 在栈展开时,它将是第一个处理请求的。
- 在栈回绕时,它将是最后一个处理响应的。
对于需要在输入端和输出端都位于链首的用例:
- 为每一端分别使用不同的顾问。
- 为它们配置不同的顺序值。
- 使用顾问上下文在它们之间共享状态。
自定义实现一个Advisor
spring的官网提到了一个Re-Reading (Re2) Advisor,《重读提升大型语言模型的推理能力》一文介绍了一种名为重读(Re-Reading,简称 Re2)的技术,该技术能够提升大型语言模型的推理能力。Re2 技术需要对输入的提示进行如下增强:
{Input_Query} |
实现一个对用户输入查询应用 Re2 技术的顾问可以这样操作:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.advisor.api.AdvisedRequest;
import org.springframework.ai.chat.client.advisor.api.AdvisedResponse;
import org.springframework.ai.chat.client.advisor.api.CallAroundAdvisor;
import org.springframework.ai.chat.client.advisor.api.CallAroundAdvisorChain;
import java.util.HashMap;
import java.util.Map;
public class ReReadingAdvisor implements CallAroundAdvisor {
private final Logger logger = LoggerFactory.getLogger(ReReadingAdvisor.class);
@Override
public String getName() {
return this.getClass().getSimpleName();
}
@Override
public int getOrder() {
return 0;
}
@Override
public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {
Map<String, Object> advisedUserParams = new HashMap<>(advisedRequest.userParams());
advisedUserParams.put("re2_input_query", advisedRequest.userText());
AdvisedRequest request = AdvisedRequest.from(advisedRequest)
.userText(
"""
{re2_input_query}
Read the question again: {re2_input_query}
"""
)
.userParams(advisedUserParams)
.build();
logger.info("ReReadingAdvisor request: {}", request);
AdvisedResponse advisedResponse = chain.nextAroundCall(request);
logger.info("ReReadingAdvisor aroundCall Request: {}", advisedResponse);
return advisedResponse;
}
}
运行程序可以看到对应的输出:

Spring AI中内置的Advisors
Spring AI 框架提供了几种内置的顾问来增强你的人工智能交互。以下是可用顾问的概述:
聊天记忆顾问(Chat Memory Advisors)
这些顾问在聊天记忆存储中管理对话历史:
- MessageChatMemoryAdvisor
检索记忆并将其作为消息集合添加到提示中。这种方法保留了对话历史的结构。注意,并非所有 AI 模型都支持这种方法。 - PromptChatMemoryAdvisor
检索记忆并将其整合到提示的系统文本中。 - VectorStoreChatMemoryAdvisor
从 VectorStore 检索记忆并将其添加到提示的系统文本中。这个顾问适用于从大型数据集中高效搜索和检索相关信息。
问答顾问(Question Answering Advisor)
- QuestionAnswerAdvisor
这个顾问使用向量存储来提供问答功能,实现了 RAG(检索增强生成)模式。
内容安全顾问(Content Safety Advisor)
- SafeGuardAdvisor
一个简单的顾问,旨在防止模型生成有害或不适当的内容。
流式和非流式的对比

- 非流式顾问处理完整的请求和响应。
- 流式顾问以连续流的形式处理请求和响应,使用响应式编程概念(例如,使用 Flux 处理响应)。
最佳实践
1. 让顾问专注于特定任务,以实现更好的模块化。
2. 在必要时,使用 adviseContext
在顾问之间共享状态。
3. 为实现最大的灵活性,同时实现顾问的流式和非流式版本。
4. 仔细考虑顾问链中的顺序,以确保数据的正确流动。