欢迎光临
我们一直在努力

Spring AI Alibaba 多轮AI对话记忆功能实战详解

一、前言

在企业级 AI 对话业务开发中,单轮对话无记忆无法满足真实用户需求。例如:在线智能客服、业务顾问、AI 辅助办公、智能问答系统等场景,用户往往需要连续多轮提问,且模型需要记住上文对话内容,实现上下文连贯应答。

Spring AI Alibaba 针对 Java 生态提供了标准化的对话记忆(Chat Memory)能力,无需开发者手动拼接历史消息、无需自行维护上下文,可快速实现用户级、会话级多轮记忆对话。

二、核心原理

2.1、为什么默认对话没有记忆?

ChatModel / ChatClient 原生调用为无状态调用:每次请求都是独立的,大模型不会自动保存上一轮对话内容,必须开发者主动将 历史消息 + 当前提问 一并传入模型。

2.2、Spring AI 记忆核心机制

Spring AI 提供 ChatMemory 顶层接口,核心实现:

  • InMemoryChatMemory:内存级记忆(适合单实例、临时会话)

  • RedisChatMemory:分布式持久化记忆(生产推荐)

核心工作流程:

  • 根据 sessionId 会话ID 隔离不同用户对话

  • 每次请求自动读取该会话历史消息

  • 拼接 (历史上下文 + 当前用户提问) 发送给大模型

  • 模型应答后,自动将本轮问答存入记忆

  • 2.3、核心组件依赖关系

    ChatMemory(记忆存储)→ ChatClient(业务调用)→ ChatModel(底层模型通信)

    企业规范:业务层统一使用 ChatClient + Memory 实现多轮对话

    三、业务场景介绍

    本文模拟企业 AI 业务咨询助手场景:

    • 不同用户通过唯一 sessionId 区分会话

    • 同一个 session 下支持无限多轮上下文对话

    • 不同 session 对话记忆相互隔离、互不干扰

    • 支持清空指定会话记忆、重置对话上下文

    四、搭建项目

    4.1、技术栈介绍

    1、SpringBoot 版本 3.3.10

    2、Spring AI Alibaba 版本 1.1.2.0

    注意: Spring AI Alibaba在很多地方进行优化和重构,与老版本有些许差异

    4.2、创建项目步骤

    4.2.1、项目依赖

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.3.10</version>
    </parent>
    <groupId>com.wn</groupId>
    <artifactId>dashscope</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dashscope</name>
    <description>dashscope</description>
    <properties>
    <java.version>17</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
    <!– Spring Boot Web starter:提供构建 Web 应用(包括 RESTful)所需的核心依赖,如 Tomcat、Spring MVC 等 –>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!– 单元测试依赖 –>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    <!– Spring AI Alibaba DashScope Starter:集成阿里云通义千问(DashScope)大模型能力,提供 ChatModel 等核心组件 –>
    <dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
    <version>1.1.2.0</version>
    </dependency>
    <!– Lombok:通过注解简化 Java 代码,自动生成 getter/setter、构造函数、toString 等方法,减少样板代码 –>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    </dependency>
    </dependencies>

    4.2.2、application.yml配置文件

    spring:
    ai:
    dashscope:
    api-key: ${DASHSCOPE_API_KEY}
    chat:
    options:
    model: qwen-turbo
    # 温度系数(Temperature),控制生成文本的随机性和创造性
    # 取值范围通常为 0.0 到 1.0(部分模型支持更高)
    # 0.9 表示较高的随机性,生成的回答会更加多样化和富有创意,但可能稍微降低准确性
    temperature: 0.9
    # 最大生成令牌数(Max Tokens)
    # 限制模型单次响应输出的最大 token 数量
    # 设置为 2048 可以平衡响应长度与成本,防止生成过长的无用内容或超出上下文限制
    max-tokens: 2048

    4.2.3、核心配置类

    import org.springframework.ai.chat.client.ChatClient;
    import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
    import org.springframework.ai.chat.memory.ChatMemory;
    import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
    import org.springframework.ai.chat.memory.MessageWindowChatMemory;
    import org.springframework.ai.chat.model.ChatModel;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    @Configuration
    public class AiChatMemoryConfig {

    /**
    * 配置对话记忆组件 (ChatMemory)
    * 在 Spring AI 1.1.x 版本中,推荐使用 MessageWindowChatMemory 替代旧版的简单内存实现。
    * 它基于“消息窗口”策略,只保留最近 N 条消息,既能节省 Token 消耗,又能保持上下文连贯性。
    * @return ChatMemory 实例
    */
    @Bean
    public ChatMemory chatMemory() {
    // 1. 创建内存存储库
    // InMemoryChatMemoryRepository 是 ChatMemory 的底层存储实现,负责实际保存和读取消息列表。
    // 这里使用内存存储,适用于单节点或测试环境;生产环境可替换为 RedisChatMemoryRepository 等持久化实现。
    InMemoryChatMemoryRepository repository = new InMemoryChatMemoryRepository();

    // 2. 构建 MessageWindowChatMemory 实例
    // MessageWindowChatMemory 是 ChatMemory 接口的具体实现类,它封装了“窗口滑动”的逻辑。
    return MessageWindowChatMemory.builder()
    .chatMemoryRepository(repository) // 注入底层存储库
    .maxMessages(10) // 设置窗口大小:仅保留最近的 10 条消息(包含用户提问和AI回答)
    .build();
    }

    /**
    * 构建支持多轮记忆的 ChatClient
    *
    * ChatClient 是 Spring AI 提供的高级抽象,用于简化与大模型的交互。
    * 通过注入 ChatMemory 并配置 Advisor,可以实现自动化的上下文管理。
    *
    * @param chatModel 底层大模型对话模型 (由 spring-ai-alibaba-starter-dashscope 自动配置并提供)
    * @param chatMemory 对话记忆组件 (由上方的 chatMemory() Bean 提供)
    * @return 具备多轮记忆能力的 ChatClient 实例
    */
    @Bean
    public ChatClient memoryChatClient(ChatModel chatModel, ChatMemory chatMemory) {
    return ChatClient.builder(chatModel)
    // 植入记忆拦截器 (Advisor)
    // MessageChatMemoryAdvisor 负责在发送请求前从 ChatMemory 加载历史消息,
    // 并在收到响应后将新的对话内容存回 ChatMemory。
    // builder(chatMemory).build() 是 Spring AI 1.1.x 中创建 Advisor 的标准方式。
    .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
    // 设置全局默认系统提示词 (System Prompt)
    // 该提示词会附加在每次对话的最前面,用于定义 AI 的角色、行为准则和业务规范。
    .defaultSystem("你是企业智能业务咨询助手,回答专业、简洁、贴合业务,支持上下文连贯对话。")
    .build();
    }
    }

    4.2.4、业务工具类(封装记忆对话能力)

    /**
    * AI 对话记忆管理工具类
    *
    * 该类封装了 Spring AI 的 ChatClient 和 ChatMemory 组件,
    * 提供基于会话 ID (SessionId) 的多轮对话支持和记忆清理功能。
    * 适用于需要在 Service 层或 Controller 层灵活控制对话上下文的场景。
    */
    @Component
    public class AiChatMemoryUtil {

    /**
    * 具备多轮对话能力的 ChatClient 实例
    * 由 Spring 容器自动注入配置好的 Bean(通常已配置了 MessageChatMemoryAdvisor)
    */
    private ChatClient chatClient;

    /**
    * 对话记忆存储组件
    * 用于直接操作底层记忆数据(如清空指定会话的历史记录)
    */
    private ChatMemory chatMemory;

    /**
    * 构造函数注入
    *
    * @param chatClient 预配置的 ChatClient,负责与大模型交互并自动处理上下文拼接
    * @param chatMemory 预配置的 ChatMemory,负责历史消息的持久化存储与检索
    */
    public AiChatMemoryUtil(ChatClient chatClient, ChatMemory chatMemory) {
    this.chatClient = chatClient;
    this.chatMemory = chatMemory;
    }

    /**
    * 执行带记忆的多轮对话
    *
    * 该方法通过动态参数覆盖默认的 Advisor 配置,实现针对特定会话的个性化记忆控制。
    *
    * @param sessionId 会话唯一标识符,用于隔离不同用户或不同对话窗口的上下文
    * @param userMessage 用户当前输入的文本消息
    * @return 大模型生成的回复内容
    */
    public String callChatMemory(String sessionId, String userMessage) {
    return chatClient.prompt()
    // 配置 Advisors 的动态参数
    .advisors(advisor -> advisor
    // 指定当前对话所属的会话 ID
    // ChatMemoryAdvisor 会根据此 ID 从存储中加载对应的历史消息
    .param("chat_memory_conversation_id", sessionId)

    // 动态设置最大保留消息数
    // 此处覆盖默认配置,仅保留最近 20 条消息作为上下文
    // 有助于控制 Token 消耗并避免超出模型上下文窗口限制
    .param("chat_memory_max_messages", 20)
    )
    // 设置用户当前发送的消息
    .user(userMessage)
    // 发起同步调用并获取纯文本回复
    .call()
    .content();
    }

    /**
    * 清空指定会话的对话记忆
    *
    * 该操作会从底层存储(如内存、Redis 或数据库)中删除该 sessionId 关联的所有历史消息。
    *
    * 适用场景:
    * 1. 用户点击“新建对话”或“重置上下文”按钮
    * 2. 用户退出登录或会话过期
    * 3. 检测到敏感话题需要强制清除历史记录
    *
    * @param sessionId 需要清空记忆的会话唯一 ID
    */
    public void clearChatMemory(String sessionId) {
    // 调用 ChatMemory 接口的 clear 方法,物理删除指定会话的历史数据
    chatMemory.clear(sessionId);
    }
    }

    4.2.5、Controller层(提供带记忆的接口)

    import com.wn.dashscope.utils.AiChatMemoryUtil;
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;

    /**
    * 通义千问(DashScope)带记忆对话控制器
    *
    * 提供基于会话 ID (SessionId) 的多轮对话接口,支持上下文连贯交互及记忆管理。
    * 遵循 RESTful 风格,通过 GET 请求暴露服务(生产环境建议根据安全性要求调整为 POST)。
    */
    @RestController
    @RequestMapping("/memory")
    public class DashScopeChatController {

    /**
    * AI 对话记忆管理工具类
    * 封装了 ChatClient 和 ChatMemory 的核心逻辑,负责实际的模型调用与状态管理
    */
    private AiChatMemoryUtil aiChatMemoryUtil;

    /**
    * 构造函数注入依赖
    * @param aiChatMemoryUtil 预配置的对话工具类 Bean
    */
    public DashScopeChatController(AiChatMemoryUtil aiChatMemoryUtil) {
    this.aiChatMemoryUtil = aiChatMemoryUtil;
    }

    /**
    * 带上下文记忆的多轮对话接口
    *
    * 接收用户提问,结合历史会话记录生成 AI 回复。
    * 每次调用会自动将新的问答对存入记忆库,供后续对话参考。
    *
    * @param sessionId 会话唯一标识符(由前端生成并维护,用于隔离不同用户的上下文)
    * @param msg 用户当前的提问内容
    * @return AI 生成的文本回复,或在参数非法时返回错误提示
    */
    @GetMapping("/call")
    public String chatMemory(@RequestParam String sessionId, @RequestParam String msg) {
    // 1. 参数合法性校验
    // 防止空指针异常或无效请求,确保业务逻辑执行的稳定性
    if (!StringUtils.hasText(sessionId) || !StringUtils.hasText(msg)) {
    return "会话ID和提问内容不能为空";
    }
    // 2. 执行带记忆的对话调用
    // 委托给 AiChatMemoryUtil 处理复杂的上下文加载、Prompt 构建及模型调用
    return aiChatMemoryUtil.callChatMemory(sessionId, msg);
    }

    /**
    * 清空指定会话的记忆
    *
    * 用于重置对话上下文,适用于用户开启新话题、退出登录或发现上下文污染的场景。
    * 操作完成后,该 sessionId 关联的历史消息将从存储中彻底删除。
    *
    * @param sessionId 需要清空记忆的会话唯一标识符
    * @return 操作结果提示信息
    */
    @GetMapping("/clear")
    public String clearMemory(@RequestParam String sessionId) {
    // 1. 参数合法性校验
    if (!StringUtils.hasText(sessionId)) {
    return "会话ID不能为空";
    }
    // 2. 执行记忆清除操作
    // 直接调用底层 ChatMemory 组件清除数据
    aiChatMemoryUtil.clearChatMemory(sessionId);
    // 3. 返回成功反馈
    return "会话[" + sessionId + "]上下文记忆已清空";
    }
    }

    4.2.6、接口测试效果

    请求1:

    请求2:

    赞(0)
    未经允许不得转载:171主机测评 » Spring AI Alibaba 多轮AI对话记忆功能实战详解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址