Spring AI Advisor 完全指南:拦截器机制与实战全解

场景

SpringAI+Ollama本地模型实现快速对话入门实例:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/160983728

在上面基础上实现Advisor 拦截器机制与实战全解。

在 Spring AI 的体系中,Advisor(顾问) 类似于 Web 应用中的过滤器(Filter)或 Spring 切面(AOP Around Advice),

它提供了一种无侵入的方式,在调用 AI 模型的前后对请求和响应进行拦截、修改甚至短路。通过 Advisor,

我们可以把日志记录、多轮对话记忆、安全过滤、性能监控等横切关注点模块化,并灵活组合成处理链,让业务代码保持干净。

本文将聚焦于 Spring AI 1.1.2 版本的 Advisor 机制,从概念、内置实现到自定义实战,

结合完整的代码示例和常见问题,帮助你彻底掌握 Advisor 的使用。

Advisor 核心概念

执行生命周期

ChatClient 请求 → Advisor1.before → Advisor2.before → ... → 调用 AI 模型

Advisor1.after ← Advisor2.after ← ... ← AI 模型响应

before:在请求发送给模型之前执行,可以修改请求内容或中断链路。

after:在模型返回响应之后执行,可以修改响应内容。

Advisor 链

Advisor 以链式组织,通过 Ordered 接口控制执行顺序(值越小优先级越高)。

请求沿 Order 由小到大执行 before,响应沿 Order 由大到小执行 after。

核心 API

目的 1.0.0-M4(旧) 1.1.2(新)

简单修改(不短路) RequestResponseAdvisor BaseAdvisor

非流式短路 CallAroundAdvisor CallAdvisor

流式短路 StreamAroundAdvisor StreamAdvisor

请求对象 AdvisedRequest ChatClientRequest

响应对象 AdvisedResponse ChatClientResponse

短路是指 Advisor 直接返回一个响应,不再调用后续 Advisor 和 AI 模型,常用于安全过滤等场景。

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

实现

SimpleLoggerAdvisor:快速日志记录

SimpleLoggerAdvisor 是 Spring AI 内置的日志 Advisor,开启后可在 DEBUG 级别记录每次请求和响应,非常便于调试。

注册方式:

复制代码
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatConfig {

    @Bean
    public ChatClient chatClient(ChatModel chatModel) {
        return ChatClient.builder(chatModel)
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }
}

开启日志:在 application.yml 中配置:

复制代码
logging:
  level:
    org.springframework.ai.chat.client.advisor: DEBUG

启动后在调用接口时,控制台会输出类似:

DEBUG ... SimpleLoggerAdvisor - request: AdvisedRequest[...]

DEBUG ... SimpleLoggerAdvisor - response: AdvisedResponse[...]

MessageChatMemoryAdvisor:多轮对话记忆

1、MessageChatMemoryAdvisor 可以将对话历史存储在 ChatMemory 中,并在后续请求中自动附加上下文。

注意:

InMemoryChatMemory 在 Spring AI 1.1.2 版本中已被移除。

为了更精细地控制记忆逻辑(例如防止超出模型 Token 限制),框架的 API 进行了重构,

将存储职责与记忆管理策略分离了。

直接后果是 InMemoryChatMemory 被废弃,取而代之的是 InMemoryChatMemoryRepository 和 MessageWindowChatMemory 组合

在 Spring AI 的较新版本(如 1.1.2 及其后续版本)中,框架提供了更完善的自动配置能力。

通过配置文件定制参数:

在 application.yml 中添加配置,以控制记忆的最大消息数量。

复制代码
spring:
  ai:
    chat:
      memory:
        max-messages: 10

完整配置文件

复制代码
​
server:
  port: 886

spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        model: qwen2.5:7b-instruct
        options:
          temperature: 0.7
          num-ctx: 4096                         # 上下文窗口大小
    chat:
      memory:
        max-messages: 10

logging:
  level:
    # 将 Advisor 包的日志级别设置为 DEBUG,才能看到日志输出
    org.springframework.ai.chat.client.advisor: DEBUG

​

2、注册 Advisor

复制代码
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;

@Bean
public ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {
    return ChatClient.builder(chatModel)
            .defaultAdvisors(
                MessageChatMemoryAdvisor.builder(chatMemory).build()
            )
            .build();
}

3、控制器传入会话ID

每个会话需要唯一标识,通过请求参数动态传入:

复制代码
package com.badao.ai.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class ToolChatController {

    private final ChatClient chatClient;

    public ToolChatController(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    @PostMapping("/chat/multi")
    public ChatResponse multiTurnChat(@RequestBody MultiTurnChatRequest request) {
        String result = chatClient.prompt()
                .user(request.message())
                .advisors(advisor -> advisor
                        // 动态传入会话 ID,告诉 MessageChatMemoryAdvisor 这是哪个会话
                        .param("chat_memory_conversation_id", request.conversationId())
                )
                .call()
                .content();
        return new ChatResponse(200, "success", result);
    }

    public record MultiTurnChatRequest(String message, String conversationId) {}
    public record ChatResponse(int code, String msg, String data) {}
}

自定义 Advisor 实战:敏感词过滤

许多业务需要对用户输入进行安全审查,并在发现敏感词时直接返回警告,不调用 AI 模型(短路)。

1、BaseAdvisor 是 Spring AI 1.1.2 新增的便捷基类,它统一了 Call 和 Stream 模式,你只需重写 before 和 after 方法

复制代码
package com.badao.ai.advisor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.api.AdvisorChain;
import org.springframework.ai.chat.client.advisor.api.BaseAdvisor;
import org.springframework.core.Ordered;
import java.util.Arrays;
import java.util.List;

public class SensitiveWordGuardAdvisor implements BaseAdvisor {

    private final Logger logger = LoggerFactory.getLogger(SensitiveWordGuardAdvisor.class);
    private final List<String> sensitiveWords = Arrays.asList("暴力", "违禁");

    @Override
    public ChatClientRequest before(ChatClientRequest request, AdvisorChain chain) {
        String userText = request.prompt().getContents();
        if (containsSensitiveWord(userText)) {
            logger.warn("BaseAdvisor 检测到敏感词: {}", userText);
        }
        return request; // BaseAdvisor 无法直接短路,仅做记录或修改
    }

    @Override
    public ChatClientResponse after(ChatClientResponse response, AdvisorChain chain) {
        return response;
    }

    private boolean containsSensitiveWord(String text) {
        return sensitiveWords.stream().anyMatch(text::contains);
    }

    @Override
    public String getName() {
        return "SensitiveWordGuardAdvisor";
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

2、注册到链中

复制代码
package com.badao.ai.config;

import com.badao.ai.advisor.SensitiveWordGuardAdvisor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ai.chat.model.ChatModel;

@Configuration
public class ChatConfig {

    @Bean
    public ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {
        return ChatClient.builder(chatModel)
                .defaultAdvisors(
                        new SensitiveWordGuardAdvisor(), // 自定义安全检查 Advisor
                        new SimpleLoggerAdvisor(), // 将 SimpleLoggerAdvisor 注册为全局 Advisor
                        MessageChatMemoryAdvisor.builder(chatMemory)   // 对话记忆 ← 使用 builder
                                .build() // 记忆 Advisor
                )
                .build();
    }
}

测试验证

测试记忆和日志功能

传递001,告诉名字,然后再询问名字

传递002,询问名字

敏感词测试

相关推荐
a752066281 小时前
AI 智能体 OpenClaw 飞书插件安装配置 全程命令行实操
人工智能·飞书·openclaw部署·ai 办公自动化
禾刀围玉1 小时前
深度学习-线性回归
人工智能·深度学习·线性回归
qyr67891 小时前
全球罐底扫描仪市场前景分析与行业报告
大数据·人工智能·数据分析·市场报告·罐底扫描仪
XiYang-DING1 小时前
【Java EE】 HTTPS协议
java·https·java-ee
智享食事1 小时前
一个配置,多平台使用:飞书/企微/钉钉/QQ全接入
人工智能
yqcoder1 小时前
突破性能瓶颈:深入理解 JavaScript TypedArray
java·开发语言·javascript
ch.ju1 小时前
Java Programming Chapter 3——Traversal of array
java·开发语言
zhoupenghui1681 小时前
如何设置PyTorch程序在 GPU上运行
人工智能·pytorch·python·gru·cuda
he___H1 小时前
子串----
java·数据结构·算法·leetcode