SpringAI Advisor 02:Advisors API

Spring AI 的 Advisors API 提供一套灵活、强大的机制,用于拦截、修改、增强 Spring 应用内 AI 交互流程。借助 Advisors API,开发者可以构建更加复杂、可复用、易维护的 AI 组件。

核心收益:

  • 封装各类重复出现的生成式AI业务模式;
  • 对发给大模型(LLM)、从大模型返回的数据做转换处理;
  • 在不同模型、不同业务场景之间实现业务逻辑可移植。

可以通过 ChatClient API 配置已有的 Advisor 组件,示例代码:

最佳实践:建议在构建 ChatClient 阶段,通过 defaultAdvisors() 注册全局默认Advisor。

Advisor 组件会接入可观测性体系,可以查看 Advisor 执行相关的指标与链路追踪信息。

核心组件 Core Components

API分为两套接口:

  1. 非流式场景CallAdvisorCallAdvisorChain
  2. 流式场景StreamAdvisorStreamAdvisorChain
  • ChatClientRequest:封装待发送给模型的请求(未处理的Prompt)
  • ChatClientResponse:封装大模型返回的对话响应对象>

两个对象内部都持有 advise‑context(Advisor上下文Map),用于在整条Advisor链之间共享状态。

类图定义如下:

adviseCall()(非流式)与 adviseStream()(流式)是Advisor的核心方法,通常可以完成这些工作:

  1. 读取原始Prompt数据;
  2. 定制、增强、改写Prompt内容;
  3. 调用Advisor链中下一个处理单元;
  4. 可选择拦截、终止本次请求;
  5. 读取大模型返回结果;
  6. 抛出异常代表处理失败。

此外 getOrder() 方法决定Advisor在链中的执行顺序;getName() 返回Advisor唯一名称。

Advisor链(Advisor Chain)由Spring AI框架自动创建,多个Advisor会按照 getOrder() 的数值顺序依次执行;框架会自动追加最后一个Advisor,由它真正把请求发送给LLM大模型。

执行流程说明

下图说明了 Advisor链和 ChatModel 的交互逻辑:

解释一下:

  1. Spring AI 框架把用户传入的 Prompt 构建成 ChatClientRequest,并初始化空的Advisor上下文;
  2. 链中每一个Advisor处理请求,可以修改请求对象,也可以不调用下游直接拦截请求并自行填充响应返回;
  3. 链末尾由框架内置Advisor,把处理完成的请求提交给 ChatModel;
  4. 模型返回响应,沿着Advisor链逆向回传,封装为 ChatClientResponse,携带共享的Advisor上下文;
  5. 每一个Advisor都可以读取、修改返回响应;
  6. 最终将处理完成的 ChatClientResponse 返回给调用方。

执行模式是环绕通知(Around)模式:Advisor先处理请求向下传递,拿到模型结果后,再逆向处理响应向上返回。

Advisor 执行顺序 Advisor Order

Advisor链的执行顺序完全由 getOrder() 返回值控制,重要规则:

  1. order数值越小,优先级越高,越先执行请求阶段逻辑
  2. Advisor链是栈式执行
    • 优先级最高的Advisor,第一个处理入站请求
    • 拿到模型返回结果后,最后一个处理出站响应
  3. 想要最先处理请求:设置值接近 Ordered.HIGHEST_PRECEDENCE
  4. 想要最后处理请求:设置值接近 Ordered.LOWEST_PRECEDENCE
  5. order值越大,代表优先级越低
  6. 多个Advisor拥有相同order,执行顺序不保证。

栈式执行带来一个容易踩坑点:同一个Advisor对象,请求阶段最先执行,响应阶段就会变成最后执行。 如果需要请求和响应都排在整个链条第一位:

  1. 拆分为两个独立Advisor实例;
  2. 设置不同order;
  3. 使用 advise‑context 上下文对象跨实例共享状态。

下面是 Spring Ordered 接口的语义说明:

API 概览

所有接口包路径:org.springframework.ai.chat.client.advisor.api

顶层基础接口

非流式同步接口

流式响应式接口

Advisor链接口,用来调用下游:

实现自定义Advisor

实现Advisor需要实现 CallAdvisorStreamAdvisor(二者选一或同时实现); 非流式重写 adviseCall(),流式重写 adviseStream();调用 nextCall() / nextStream() 放行给下游Advisor链。

示例1:日志打印Advisor

我们可以实现一个简易日志 Advisor,在调用责任链中下一个 Advisor之前打印ChatClientRequest,在调用之后打印ChatClientResponse。 请注意:该 Advisor 仅做请求、响应的观测,不会修改其中内容。此实现同时支持非流式与流式调用场景。

代码中的注意事项:

  1. 为该 Advisor 提供唯一名称。
  2. 可以通过设置order值控制执行顺序:数值越小,越优先执行
  3. MessageAggregator是一个工具类,它将 Flux 流式响应聚合为单个ChatClientResponse对象。当需要打印日志,或是做其他需要**观测完整响应(而非流中一条条分片数据)**的处理时,该工具类十分有用。 注意:MessageAggregator内部只能做只读操作,不可以修改响应内容

示例2:Re‑Reading(Re2)增强推理Advisor

Re‑Reading论文思想:把用户问题追加一遍,增强模型推理能力

Re2 需要一个类似下面这样的 Prompt 请求:

按照如下方式即可实现一个 Advisor,对用户输入的查询语句应用 Re2(二次重读) :

代码中的注意事项:

  1. before 方法运用**重读(Re‑Reading)**技术对用户输入的查询语句做增强处理。
  2. 可以通过设置 order 值来控制执行顺序:数值越小,执行优先级越高,会优先执行

Spring AI 内置Advisor Built‑in Advisors

  1. ChatMemoryAdvisor 对话记忆Advisor
    • MessageChatMemoryAdvisor:读取历史对话消息,追加到Prompt消息列表。
    • VectorStoreChatMemoryAdvisor:从向量库检索历史记忆,注入系统提示词,适合超长会话。
  2. QuestionAnswerAdvisor 问答检索Advisor
    • 实现简易RAG:查询向量库,把检索结果填充给Prompt。
    • RetrievalAugmentationAdvisor:模块化RAG架构的标准实现。
  3. ReasoningAdvisor推理增强
    • ReReadingAdvisor:Re2重读策略,增强大模型推理。
  4. ToolCallingAdvisor 工具调用Advisor

ChatClient默认自动注册,负责执行工具调用循环:调用工具、把结果送回模型,反复迭代直到不需要继续调用工具。 标记接口 ToolAdvisor 会防止重复注册该Advisor。

  1. SafeGuardAdvisor 内容安全Advisor 简单的护栏Advisor,拦截不安全输出。

流式与非流式 Streaming vs Non‑Streaming

  • 非流式 CallAdvisor:处理完整请求对象、完整响应对象;
  • 流式 StreamAdvisor:基于 Project Reactor Flux 处理分片流数据。

流式骨架代码模板:

最佳实践 Best Practices

  1. 单一职责:每个Advisor只做一件事,提高模块化、可复用;
  2. 状态共享优先使用 adviseContext,不要用实例成员变量存会话状态;
  3. 同时实现 CallAdvisor + StreamAdvisor,保证流式/非流式行为一致;
  4. 仔细设计 getOrder() 排序值,控制请求、响应处理顺序。

参考文档

原文链接:Advisors API