做大模型应用开发的朋友一定遇到过这个问题你跟 AI 说我叫张三下一轮对话问它我叫什么它一脸茫然地回你抱歉我不知道你的名字。原因很简单 —— LLM 是无状态的。每次请求都是一次全新的开始它不会记得上一轮你们聊了什么。要实现多轮对话你得把之前的聊天记录每次都打包发给大模型。Spring AI 提供了一套 ChatMemory 组件来帮你干这件事。但存储方案怎么选内存、数据库、Redis、向量库各自的取舍是什么这篇就来把对话记忆的实现方案一次讲透。一、ChatMemory 架构Spring AI 2.0 的记忆体系先看一个最直观的例子。没有记忆的时候大模型的表现是这样的TestpublicvoidtestChatOptions(){StringcontentchatClient.prompt().user(我叫张三).call().content();System.out.println(content);contentchatClient.prompt().user(我叫什么).call().content();System.out.println(content);}第一轮告诉它名字第二轮问它它答不上来。因为两次调用之间没有任何状态共享。Spring AI 2.0 的解法是ChatMemory MessageWindowChatMemory核心架构可以简单理解成ChatClient -- MessageChatMemoryAdvisor -- ChatMemory(MessageWindowChatMemory) -- ChatMemoryRepository(存储实现)ChatMemory是接口MessageWindowChatMemory是默认实现负责对话轮次的窗口淘汰策略。底层真正的存储交给ChatMemoryRepository自动配置类会注入默认的InMemoryChatMemoryRepositoryAutoConfigurationConditionalOnClass({ChatMemory.class,ChatMemoryRepository.class})publicclassChatMemoryAutoConfiguration{BeanConditionalOnMissingBeanChatMemoryRepositorychatMemoryRepository(){returnnewInMemoryChatMemoryRepository();}BeanConditionalOnMissingBeanChatMemorychatMemory(ChatMemoryRepositorychatMemoryRepository){returnMessageWindowChatMemory.builder().chatMemoryRepository(chatMemoryRepository).build();}}1.1 基本使用2.0 中推荐使用MessageChatMemoryAdvisor替代 1.0 的PromptChatMemoryAdvisorSpringBootTestpublicclassChatMemoryTest{ChatClientchatClient;BeforeEachpublicvoidinit(AutowiredDeepSeekChatModelchatModel,AutowiredChatMemorychatMemory){chatClientChatClient.builder(chatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}TestpublicvoidtestChatOptions(){StringcontentchatClient.prompt().user(我叫张三).call().content();System.out.println(content);contentchatClient.prompt().user(我叫什么).call().content();System.out.println(content);}}这次大模型能记住你叫张三了。2.0 变化PromptChatMemoryAdvisor→MessageChatMemoryAdvisor。后者以消息方式注入记忆更自然且与工具调用兼容性更好。1.2 配置最大存储数量聊天的消息发给大模型是算 token 的token 有上限。DEFAULT_MAX_MESSAGES默认 20 条即 10 轮对话超出后按先进先出淘汰最早的消息BeanChatMemorychatMemory(ChatMemoryRepositorychatMemoryRepository){returnMessageWindowChatMemory.builder().maxMessages(10).chatMemoryRepository(chatMemoryRepository).build();}1.3 多用户隔离不同用户的对话不能串记忆通过CONVERSATION_ID隔离TestpublicvoidtestChatOptions(){// 用户1的对话StringcontentchatClient.prompt().user(我叫张三).advisors(advisorSpec-advisorSpec.param(ChatMemory.CONVERSATION_ID,1)).call().content();contentchatClient.prompt().user(我叫什么).advisors(advisorSpec-advisorSpec.param(ChatMemory.CONVERSATION_ID,1)).call().content();// 用户2的对话 —— 记忆隔离contentchatClient.prompt().user(我叫什么).advisors(advisorSpec-advisorSpec.param(ChatMemory.CONVERSATION_ID,2)).call().content();}不同的CONVERSATION_ID各自独立记忆互不干扰。1.4 ChatMemoryRepository 存储实现一览2.0 中ChatMemoryRepository支持的存储实现实现类存储介质特点适用场景InMemoryChatMemoryRepositoryJVM 内存默认实现零配置开发测试、单机 DemoJdbcChatMemoryRepositoryJDBC 数据库持久化支持 MySQL/PostgreSQL 等生产环境、需要可靠存储RedisChatMemoryRepositoryRedis读写快天然过期机制高并发、短时记忆场景CassandraChatMemoryRepositoryCassandra分布式、高可用大规模分布式场景Neo4jChatMemoryRepositoryNeo4j图数据库关系推理需要记忆关联推理的场景MongoDbChatMemoryRepositoryMongoDB文档型存储灵活 schema 场景注2026 年还有一个比较值得关注的动态 —— Spring AI 正在孵化全新的 Session API采用事件溯源 上下文压缩的方式管理短期记忆目标是 Spring AI 2.1预计 2026 年 11 月届时ChatMemory将被标记为 deprecated。如果你正在做技术选型这个时间节点值得关注。二、数据库存储让记忆不再昙花一现默认的InMemoryChatMemoryRepository有两个致命问题一是 JVM 内存有限聊多了会 OOM二是重启就全丢了。生产环境必须上持久化存储。2.1 添加依赖dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-model-chat-memory-repository-jdbc/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdcom.mysql/groupIdartifactIdmysql-connector-j/artifactIdscoperuntime/scope/dependency2.2 配置spring.ai.chat.memory.repository.jdbc.initialize-schemaalways spring.ai.chat.memory.repository.jdbc.schemaclasspath:/schema-mysql.sqlspring:datasource:username:rootpassword:123456url:jdbc:mysql://localhost:3306/springai?characterEncodingutf8useSSLfalseserverTimezoneUTCdriver-class-name:com.mysql.cj.jdbc.Driver2.3 配置类ConfigurationpublicclassChatMemoryConfig{BeanChatMemorychatMemory(JdbcChatMemoryRepositorychatMemoryRepository){returnMessageWindowChatMemory.builder().maxMessages(10).chatMemoryRepository(chatMemoryRepository).build();}}2.4 建表 SQLresources/schema-mysql.sqlCREATETABLEIFNOTEXISTSSPRING_AI_CHAT_MEMORY(conversation_idVARCHAR(36)NOTNULL,contentTEXTNOTNULL,typeVARCHAR(10)NOTNULL,timestampTIMESTAMPNOTNULL,INDEXSPRING_AI_CHAT_MEMORY_CONVERSATION_ID_TIMESTAMP_IDX(conversation_id,timestamp));2.5 测试验证SpringBootTestpublicclassChatMemoryTest{ChatClientchatClient;BeforeEachpublicvoidinit(AutowiredDeepSeekChatModelchatModel,AutowiredChatMemorychatMemory){chatClientChatClient.builder(chatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}TestpublicvoidtestChatOptions(){StringcontentchatClient.prompt().user(你好我叫张三).advisors(advisorSpec-advisorSpec.param(ChatMemory.CONVERSATION_ID,1)).call().content();System.out.println(content);contentchatClient.prompt().user(我叫什么).advisors(advisorSpec-advisorSpec.param(ChatMemory.CONVERSATION_ID,1)).call().content();System.out.println(content);}}跑完测试去数据库里看一眼SPRING_AI_CHAT_MEMORY表对话记录已经持久化进去了。如果你设置了maxMessages(1)数据库里每个conversation_id只会存最后一条消息 —— 这就是窗口淘汰策略的效果。Q1为什么我设置了 maxMessages(10)但数据库里存的消息超过 10 条maxMessages控制的是发送给大模型的消息窗口大小不是数据库存储条数。数据库会完整记录对话历史但MessageWindowChatMemory在加载记忆时会按maxMessages截取最近的 N 条。所以你看到的数据库条数 窗口大小是正常的。三、Redis 存储更快的读写更简单的部署数据库方案虽然可靠但如果你需要更快的读写速度、或者想利用 Redis 天然的 TTL 过期机制来管理记忆生命周期Redis 是更好的选择。3.1 方案选择Spring AI 官方没有直接提供RedisChatMemoryRepository你需要自己实现ChatMemoryRepository接口增、删、查。但 alibaba-ai 有现成的实现还包括 ES 版本。3.2 添加依赖propertiesjedis.version5.2.0/jedis.version/propertiesdependencygroupIdcom.alibaba.cloud.ai/groupIdartifactIdspring-ai-alibaba-starter-memory-redis/artifactId/dependencydependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion${jedis.version}/version/dependency3.3 配置spring:ai:memory:redis:host:localhostport:6379timeout:5000password:3.4 配置类ConfigurationpublicclassRedisMemoryConfig{Value(${spring.ai.memory.redis.host})privateStringredisHost;Value(${spring.ai.memory.redis.port})privateintredisPort;Value(${spring.ai.memory.redis.password})privateStringredisPassword;Value(${spring.ai.memory.redis.timeout})privateintredisTimeout;BeanpublicRedisChatMemoryRepositoryredisChatMemoryRepository(){returnRedisChatMemoryRepository._builder_().host(redisHost).port(redisPort)// .password(redisPassword).timeout(redisTimeout).build();}}Q2数据库 vs Redis到底怎么选维度JDBC 数据库Redis读写性能中等磁盘 IO高内存持久化强持久化不会丢依赖 RDB/AOF有丢失风险过期机制需自己实现定时清理天然 TTL 支持部署成本中等额外维护 Redis 实例适用场景对话需要长期保存高并发、可接受记忆丢失我的建议是如果你的应用对记忆持久性要求高比如客服系统需要保留对话记录做质检用数据库如果只是让 AI 在会话期间记住上下文会话结束后可以丢弃Redis 更轻量。四、2.0 新特性向量记忆与工具调用的博弈4.1 VectorStoreChatMemoryAdvisor2.0 新增了VectorStoreChatMemoryAdvisor把对话记忆存入向量数据库通过语义检索召回相关历史对话ChatClientchatClientChatClient.builder(chatModel).defaultAdvisors(VectorStoreChatMemoryAdvisor.builder(vectorStore).build()).build();这个思路跟前面的窗口淘汰完全不同。MessageWindowChatMemory是最近 N 条不管相不相关VectorStoreChatMemoryAdvisor是语义最相关的 N 条跨越任意时间。简单理解MessageWindowChatMemory -- 近期记忆按时间窗口截取 VectorStoreChatMemoryAdvisor -- 语义记忆按相关性检索Q3窗口记忆和向量记忆能不能一起用可以而且推荐一起用。这引出了多层次记忆架构的概念后面会详细讲。4.2 Memory 与 Tool Calling 的 order 博弈当 Memory Advisor 和 Tool Calling 一起使用时执行顺序很关键AdvisorOrder 值说明ToolCallingAdvisorHIGHEST_PRECEDENCE 300管理工具调用循环MessageChatMemoryAdvisorHIGHEST_PRECEDENCE 200管理记忆注入和持久化因为MessageChatMemoryAdvisor的 order200小于ToolCallingAdvisor的 order300Memory 会在工具调用循环外部执行 —— 即记忆只在循环开始前加载一次、循环结束后持久化一次。这是推荐的行为避免了每次工具调用都刷新记忆。如果你确实需要在循环内部每次工具调用后都更新记忆可以调整 order 让 Memory Advisor 的 order 300或者使用disableInternalConversationHistory()来精细控制。五、多层次记忆架构模仿人类大脑痛点无论你用什么存储方案都只能保证存的性能。但一旦聊天记录多了依然会超过大模型的 token 上限。这是个根本矛盾记忆多 聪明 -- token 超限 报错 记忆少 安全 -- 记不住上下文 笨解法三层记忆模仿人类的记忆机制把记忆分层层级实现方案容量作用近期记忆ChatMemoryMessageWindowChatMemory~10 条保留最近几轮对话直接在上下文窗口中中期记忆VectorStoreChatMemoryAdvisor~5 条通过 RAG 检索相关历史对话长期记忆定时批处理 / 关键点实时处理无限制关键信息的固化总结架构关系用户对话 -- 近期记忆(ChatMemory, 10条) -- 中期记忆(VectorStore RAG, 5条) -- 长期记忆(总结提炼) ↑ 上下文窗口内 ↑ 语义检索召回 ↑ 关键信息固化长期记忆有两种实现方式方式一定时批处理—— 通过定时任务对积累的对话进行总结和提炼适合非实时场景方式二关键点实时处理—— 在对话中识别出关键信息点时立即提取并存储适合需要即时固化的场景说白了这就是在 token 上限和记忆完整性之间找平衡近期记忆保证上下文连贯中期记忆保证语义相关性长期记忆保证关键信息不丢失。最后总结开发测试阶段直接用默认的InMemoryChatMemoryRepository零配置开箱即用生产环境、需持久化JdbcChatMemoryRepository MySQL数据可靠不丢失高并发、短时记忆RedisChatMemoryRepository读写快、天然 TTL 过期需要语义召回VectorStoreChatMemoryAdvisor跨越时间的上下文关联终极方案三层记忆架构近期 中期 长期在 token 上限和记忆完整性之间找平衡需要关注的是Spring AI 2.1预计 2026 年 11 月将引入全新的 Session API届时ChatMemory可能会被 deprecated。但核心思路 —— 窗口淘汰、持久化存储、语义检索、分层记忆 —— 不会变变的只是 API 形态。参考资料 致谢[1] Spring AI 官方文档 - Chat Memory[2] Spring AI 官方文档 - Advisors API[3] MessageWindowChatMemory API 文档[4] VectorStoreChatMemoryAdvisor API 文档[5] Spring AI Session API - 官方博客[6] Spring AI 2.0 中文文档 - 聊天记忆[7] alibaba-ai memories - GitHub[8] Spring2.0 - 语雀
企业数字化 ERP 产品动态
相关推荐
【C语言基础】运算符、分支结构与循环结构知识详解 引言C语言是经典且应用广泛的编程语言,也是许多开发者学习编程的入门选择。掌握其基础语法,是进一步学习指针、结构体、文件操作等内容的前提。本文围绕数据类型、运算符、分支结构和循环结构四个核心部分展开,通过清晰的讲解和可运行的示例代… · 2026/9/27 22:23:29
Nature|Paper2Agent框架将研究论文转化为可交互且可靠的AI智能体 摘要
作者提出了Paper2Agent这一自动化框架,用于将研究论文转化为人工智能(artificial intelligence,AI)智能体。该框架把传统被动型研究成果重构为主动型系统,以加速方法使用与科学发现。常规论文要求读者自行理解并改… · 2026/9/27 22:23:29
内容团队如何把干货文章落到实处 内容团队如何把干货文章落到实处
核心摘要- 截至2025年底,我国规模以上制造业企业人工智能技术应用普及率已较高比例。 - 国家已布局30余个人工智能应用中试基地,推动中央企业、国有企业开放1000余个应用场景。 - 截至2025年12月,我国生成式… · 2026/9/27 23:02:16
3DGS 端侧重建结果发糊不是算法玄学:采集覆盖率、模糊帧与轨迹回环怎么做门禁 3DGS 端侧重建结果发糊不是算法玄学:采集覆盖率、模糊帧与轨迹回环怎么做门禁
同一台设备拍同一个物体,有时模型完整,有时背面塌掉、纹理发糊。把问题全部归到重建算法,通常会错过真正能控制的变量:输入帧是否清晰、视… · 2026/9/27 23:02:03
Java面试被问烂的JVM,这样答直接加分 别背“堆栈方法区”,画一张内存图面试官问内存模型,不是考你记忆力,是考你脑子里有没有一幅图。你可以说:“我习惯把JVM内存想象成一栋楼。程序计数器是每层楼的门牌号,记录线程执行到哪一行;虚拟机栈是每个… · 2026/9/27 23:01:57
视频通话弱网测试笔记:用网络损伤仪把上行限到800kbps 接着前面的选型记录,这篇把网准通 NetAccura ChaosBridge 网络损伤仪的使用方法写具体一点:怎么接线,怎么把视频通话的上行限到800kbps,以及画面卡住以后去哪里找原因。这一轮适合用DPDK引擎,重点是上下行分开设置、队… · 2026/9/27 23:01:57
ChromaPanel 与其他 React 颜色选择器对比:功能、包体积、可访问性等 选择一个 React 颜色选择器,听起来很简单,直到你开始认真考虑自己的应用到底需要什么。
也许你只需要一个很小的 HEX 颜色选择器。
也许你需要 RGB 和 HSL 控制、预设的调色板、一个吸管工具、从图片中取色、渐变功能、可访问性、表单支持,… · 2026/9/27 23:01:57
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01