Spring AI Alibaba 实现多轮对话记忆:ChatMemory 与 Redis 持久化实战
前言在构建智能对话应用时多轮对话的上下文记忆能力是刚需。Spring AI Alibaba 提供了一套优雅的 ChatMemory 机制将对话历史的管理、存储和恢复过程封装得极为简洁。本文将带大家从零掌握如何用 Spring AI Alibaba 集成 ChatMemory涵盖内存存储、Redis 持久化、流式 SSE 输出等场景并给出可直接用于生产的配置方案。一、架构流程与核心组件整个记忆链路如下前端请求 → ChatClient → MessageChatMemoryAdvisor记忆拦截器↓ 自动读取/写入会话历史ChatMemory消息窗口策略滑动窗口限制消息条数↓ 底层存储ChatMemoryRepository存储层内存/Redis/MySQL↓ 底层调用DashScopeChatModel → DashScopeApi → 阿里灵积 DashScope 平台1. ChatMemoryRepository 存储仓库负责对话消息持久化存储Spring AI Alibaba 内置三种实现InMemoryChatMemoryRepository内存存储单机测试专用重启丢失数据RedisChatMemoryRepositoryRedis 持久化集群/生产推荐会话自动过期支持两种构建模式Jedis 直连、复用 Spring Redis 连接工厂JdbcChatMemoryRepository数据库持久化长期留存对话记录2. ChatMemory 记忆策略层标准实现MessageWindowChatMemory滑动窗口淘汰机制配置maxMessages限制最大保存消息条数自动丢弃最早对话防止上下文 Token 超限、API 计费暴涨。3. MessageChatMemoryAdvisor 记忆拦截器挂载在 ChatClient 的 Advisor 链路中请求前自动根据conversationId加载历史消息模型返回后自动保存用户/助手消息业务代码无需手动拼接历史。4. ConversationId 会话唯一标识不同用户、不同聊天窗口分配独立 ID实现会话隔离同一个 ID 自动复用历史对话不同 ID 完全互不干扰。5. ChatModel vs ChatClient 记忆能力区分ChatModel底层原始接口无内置记忆管理能力需要手动拼接消息列表代码冗余ChatClient上层封装搭配 Advisor 一键集成 ChatMemory支持全局系统提示词、消息自动管理、流式、函数调用企业开发首选。二、Maven 核心依赖与配置2.1 基础依赖!-- 基础 DashScope 对话依赖必引 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-alibaba-starter-dashscope/artifactId/dependency内存存储无需额外依赖Redis 持久化需引入记忆扩展包并根据连接模式补充对应依赖!-- Redis记忆扩展包两种模式都必须引入 --dependencygroupIdcom.alibaba.cloud.ai/groupIdartifactIdspring-ai-alibaba-starter-memory-redis/artifactId/dependency!-- 方式AJedis直连模式需要该依赖 --dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactId/dependency!-- 方式B复用Spring Redis连接工厂模式需要该依赖 --!--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency--2.2 application.yml 基础配置spring:ai:dashscope:api-key: sk-xxxxxxxxxxxxxxxxxxxxchat:options:model: qwen-turbotemperature: 0.7# Redis配置Jedis直连模式通过Value读取连接池复用模式由SpringDataRedis自动读取data:redis:host: 127.0.0.1port: 6379password: database: 0三、方案1内存版 ChatMemory本地测试首选内存实现适用于开发调试提供两种写法极简自动装配与手动配置定制窗口大小。3.1 方式A极简自动装配90% 测试场景零配置类Spring AI Alibaba 自动配置了InMemoryChatMemoryRepository我们只需通过Bean定义ChatMemory和ChatClient即可无需手动创建仓库。配置类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.context.annotation.Bean;import org.springframework.context.annotation.Configuration;Configurationpublic class AiMemoryConfig {// 使用自动装配的 InMemoryChatMemoryRepositoryBeanpublic ChatMemory chatMemory(InMemoryChatMemoryRepository repository) {return MessageWindowChatMemory.builder().chatMemoryRepository(repository).maxMessages(10) // 最多保存10条消息5轮对话.build();}Beanpublic ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {return ChatClient.builder(chatModel).defaultSystem(你是资深Java后端专家结合上下文简洁回答问题).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}Controller 示例RestControllerRequestMapping(/ai/chat)public class MemoryChatController {Autowiredprivate ChatClient chatClient;Autowiredprivate ChatMemory chatMemory;/*** 同步多轮对话* param conversationId 会话ID前端生成UUID* param userMsg 用户提问*/GetMapping(/sync)public String syncChat(RequestParam String conversationId,RequestParam String userMsg) {return chatClient.prompt().user(userMsg).advisors(spec - spec.param(ChatMemory.CONVERSATION_ID, conversationId)).call().content();}// 清空指定会话记忆DeleteMapping(/memory/clear)public String clearMemory(RequestParam String conversationId) {chatMemory.clear(conversationId);return 会话[ conversationId ]记忆已清空;}}3.2 方式B手动配置类自定义窗口上限推荐工程化写法若需完全掌控 Bean 创建过程可手动声明 Repository 和 ChatMemoryConfigurationpublic class AiMemoryConfig {Beanpublic InMemoryChatMemoryRepository memoryRepository() {return new InMemoryChatMemoryRepository();}Beanpublic ChatMemory chatMemory(InMemoryChatMemoryRepository repository) {return MessageWindowChatMemory.builder().chatMemoryRepository(repository).maxMessages(20) // 自定义窗口大小.build();}Beanpublic ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {return ChatClient.builder(chatModel).defaultSystem(你是资深Java后端专家结合上下文简洁回答问题).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}四、方案2Redis 持久化 ChatMemory生产环境集群推荐内存存储致命缺陷服务重启、多实例集群时会话记忆丢失线上必须使用 Redis 持久化。RedisChatMemoryRepository提供两套构建方式4.1 方式AJedis 直连简单 Demo组件内部自建 Jedis 连接不共享项目 Redis 连接池yml 配置通过Value读取。Configurationpublic class RedisMemoryConfig {Value(${spring.data.redis.host})private String host;Value(${spring.data.redis.port})private int port;Value(${spring.data.redis.password:})private String password;Value(${spring.data.redis.database:0})private int database;Beanpublic RedisChatMemoryRepository redisChatMemoryRepository() {return RedisChatMemoryRepository.builder().host(host).port(port).password(password).database(database).build();}Beanpublic ChatMemory chatMemory(RedisChatMemoryRepository redisChatMemoryRepository) {return MessageWindowChatMemory.builder().chatMemoryRepository(redisChatMemoryRepository).maxMessages(20).build();}Beanpublic ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {return ChatClient.builder(chatModel).defaultSystem(你是通义千问对话助手记住用户全部历史提问).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}4.2 方式B复用 Spring Data Redis 连接工厂生产推荐项目已引入spring-boot-starter-data-redis时使用连接池、哨兵、集群配置统一管理。Configurationpublic class RedisMemoryConfig {Beanpublic RedisChatMemoryRepository redisChatMemoryRepository(RedisConnectionFactory redisConnectionFactory) {return RedisChatMemoryRepository.builder().redisConnectionFactory(redisConnectionFactory).build();}Beanpublic ChatMemory chatMemory(RedisChatMemoryRepository redisChatMemoryRepository) {return MessageWindowChatMemory.builder().chatMemoryRepository(redisChatMemoryRepository).maxMessages(20).build();}Beanpublic ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {return ChatClient.builder(chatModel).defaultSystem(你是通义千问对话助手记住用户全部历史提问).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}Redis 记忆特性会话数据序列化存入 Redis服务重启不丢失支持配置 Key 过期时间自动清理长期未使用会话微服务多实例集群共享 Redis多节点对话上下文统一。重要区分Jedis 直连模式内部新建独立 Jedis 连接不和业务 Redis 共用连接池适合简单 DemoRedisConnectionFactory 模式复用项目已有 Redis 连接池适合正式业务系统。五、流式 SSE 接口实现带记忆打字机效果结合 ChatMemory 实现带历史上下文的实时流式输出基于 WebFlux Flux SSERestControllerRequestMapping(/ai/chat)public class StreamMemoryChatController {Autowiredprivate ChatClient chatClient;/*** 流式带记忆对话SSE实时推送*/GetMapping(value /stream, produces text/event-stream;charsetutf-8)public FluxString streamChatWithMemory(RequestParam String conversationId,RequestParam String userMsg) {return chatClient.prompt().user(userMsg).advisors(spec - spec.param(ChatMemory.CONVERSATION_ID, conversationId)).stream().content();}}六、总结与选型建议开发测试使用内存版InMemoryChatMemoryRepository极简配置快速验证多轮对话逻辑。单机生产内存版不持久化若可接受重启丢失历史也可用否则切换至 Redis 持久化。集群/微服务必须选择Redis 持久化并推荐复用 Spring Data Redis 连接工厂实现连接池统一管理保证多实例会话共享。流式输出只需在ChatClient基础上调用.stream().content()即可获得 SSE 流记忆配置无需额外改动。Spring AI Alibaba 的 ChatMemory 体系将对话上下文管理复杂度降到最低配合 ChatClient 的 Advisor 机制让我们能更专注于业务逻辑。希望本文能帮助大家快速落地多轮对话功能如有疑问欢迎在评论区交流。

相关新闻

Python量化实战:如何自动化扫雷高负债与高商誉个股?基于 QuantDash API 的风险避坑指南

Python量化实战:如何自动化扫雷高负债与高商誉个股?基于 QuantDash API 的风险避坑指南

📌 摘要 / 快速解答 (Direct Answer) 在量化选股与基本面风控中,高资产负债率(如 >70%)与高商誉占比(如商誉/净资产 >20%)是诱发个股“业绩暴雷”与“商誉减值黑天鹅”的核心因素。传统方案依赖复杂…

2026/11/1 17:32:23 阅读更多 →
Linux系统——进程概念(上)

Linux系统——进程概念(上)

💁‍♂️个人主页:进击的荆棘 👇作者其它专栏: 《数据结构与算法》《算法》《C起始之路》《Linux》 目录 1.冯诺依曼体系结构 2.操作系统(Operator System) 3.进程 4.命令行参数和环境变量 5.程序地址…

2026/10/30 8:36:06 阅读更多 →
80-版本列表分页与历史治理:为什么版本越多越要重视列表管理

80-版本列表分页与历史治理:为什么版本越多越要重视列表管理

适合对象:关注版本历史、分页浏览、长期治理、版本资产清理的测试平台负责人和后端工程师。 先说结论 版本列表分页与历史治理不是一个孤立功能,而是精准测试平台里帮助团队做判断的一环。 它重点解决的是:为什么版本越多越要重视列表管理。 用大白话讲,版本能力的重点不…

2026/10/27 11:01:15 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/1 0:24:43 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/1 10:36:53 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/1 10:36:51 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/1 1:06:58 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/1 10:35:11 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/1 9:35:41 阅读更多 →

日新闻

周新闻

月新闻