4-Advisor

1 核心概念和作用

定义:Advisors 是 Spring AI 中用于拦截、修改和增强 AI 交互的组件,可封装通用的生成式 AI 模式,实现数据转换和跨模型复用。

核心价值:

  • 封装对话历史管理、检索增强(RAG)等重复模式。
  • 支持请求和响应的预处理与后处理,提升 LLM 交互灵活性。
  • 集成可观测性,记录执行指标和追踪信息。

使用场景:

  • 对话记忆管理(维护历史消息)。
  • 检索增强生成(结合向量存储补充上下文)。
  • 内容安全过滤(防止有害输出)。
  • 日志记录与调试。

2 核心组件与接口

基础接口

  • Advisor:所有顾问的基接口,继承 Ordered,需实现 getName() 和 getOrder()。
  • CallAroundAdvisor:同步顾问接口,处理非流式请求,核心方法 aroundCall(AdvisedRequest, CallAroundAdvisorChain)
  • StreamAroundAdvisor:流式顾问接口,处理响应式请求,核心方法 aroundStream(AdvisedRequest, StreamAroundAdvisorChain)。

请求与响应载体

  • AdvisedRequest:包含可修改的 Prompt 数据(用户文本、参数)和共享上下文adviseContext。
  • AdvisedResponse:包含 LLM 响应ChatResponse和上下文,用于顾问链间数据传递。

顾问链

  • CallAroundAdvisorChain:同步顾问链,通过 nextAroundCall() 按顺序调用下一个顾问。
  • StreamAroundAdvisorChain:流式顾问链,通过 nextAroundStream() 处理响应式流。

3 执行流程与顺序控制

执行流程

  • 框架将用户 Prompt 转换为 AdvisedRequest,并初始化空上下文。

  • 顾问链按顺序处理请求,可修改 Prompt 或阻塞请求(不调用下一个顾问)。

  • 最后一个顾问将请求发送给 LLM,响应沿顾问链反向处理,最终转换为 AdvisedResponse。

顺序控制

  • 通过 getOrder() 确定执行顺序:值越小优先级越高 (Ordered.HIGHEST_PRECEDENCE 为最小)。
  • 同步场景下,顾问链类似栈结构:先执行的顾问后处理响应,后执行的顾问先处理响应。
  • 示例:设置 getOrder() = 0 使顾问优先执行,getOrder() = Integer.MAX_VALUE 最后执行。

4 自定义顾问实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.springframework.ai.chat.client.advisor.api.*;
import reactor.core.publisher.Flux;

public class SimpleLoggerAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {
@Override
public String getName() { return "SimpleLoggerAdvisor"; }
@Override
public int getOrder() { return 0; } // 优先执行

@Override
public AdviseResponse aroundCall(AdivsedRequest req, CallAroundAdvisorChain chain){
System.out.println("请求前:" + req);
AdvisedResponse res = chain.nextAroundCall(req);
System.out.println("响应后:" + req);
return res;
}

@Override
public Flux<AdvisedResponse> aroundStream(AdvisedRequest req, StreamAroundAdvisorChain chain) {
System.out.println("流式请求前:" + req);
Flux<AdvisedResponse> flux = chain.nextAroundStream(req);
return flux.doOnNext(res -> System.out.println("响应后:" + req));
}
}

在使用的时候添加上对应的Advisor即可

1
2
3
4
5
6
7
8
9
10
@Test
void coreApiCall2() {
// 核心API的使用
ChatResponse chatResponse = client.prompt()
.advisors(new SimpleLoggerAdvisor())
.user("中国的面积有多大?")
.system("你是一个地理专家,能够回复用户的各种地理问题")
.call().chatResponse();
System.out.println(chatResponse);
}

核心方法说明

  • aroundCall/aroundStream:拦截请求,调用 chain.nextAroundCall/Stream() 继续链执行,可修改 AdvisedRequest 或直接返回响应。
  • updateContext:通过 advisedRequest.updateContext(map -> {…}) 修改共享上下文(生成新不可变 map)。

5 内置顾问与常用场景

对话记忆顾问(Chat Memory Advisors)

  • MessageChatMemoryAdvisor:从记忆存储中获取历史消息,以消息集合形式添加到 Prompt。
  • PromptChatMemoryAdvisor:将历史消息合并到系统消息中。
  • VectorStoreChatMemoryAdvisor:从向量存储检索相关记忆,添加到系统消息

检索增强顾问(RAG)

  • QuestionAnswerAdvisor:结合向量存储,检索相关文档并追加到 Prompt,实现检索增强生成。

内容安全顾问

  • SafeGuardAdvisor:过滤有害内容,防止模型生成不当响应。

日志顾问

  • SimpleLoggerAdvisor:记录请求和响应数据,用于调试(需设置日志级别为 DEBUG)。

6 最佳实践

在 C hatClient.Builder 中通过 defaultAdvisors() 注册全局顾问:

1
2
3
4
5
6
ChatClient client = ChatClient.builder(model)
.defaultAdvisors(
new MessageChatMemoryAdvisor(chatMemory),
new QuestionAnswerAdvisor(vectorStore)
)
.build();

运行时通过 advisors(Advisor…) 动态覆盖:和上面的案例一样

1
2
3
4
5
6
7
8
9
10
@Test
void coreApiCall2() {
// 核心API的使用
ChatResponse chatResponse = client.prompt()
.advisors(new SimpleLoggerAdvisor())
.user("中国的面积有多大?")
.system("你是一个地理专家,能够回复用户的各种地理问题")
.call().chatResponse();
System.out.println(chatResponse);
}

最佳实践

  • 单一职责:每个顾问专注于一个功能(如仅记录日志或仅处理记忆)。
  • 上下文共享:通过 adviseContext 在顾问间传递状态(如对话 ID、检索结果)。
  • 兼容两种模式:同时实现 CallAroundAdvisor 和 StreamAroundAdvisor 以支持同步 / 流式场景。
  • 顺序测试:通过 getOrder() 严格控制执行顺序,避免逻辑冲突。

4-Advisor
http://www.zivjie.cn/2025/11/22/spring框架/springAI/SpringAi框架/4-Advisor/
作者
Francis
发布于
2025年11月22日
许可协议