Spring AI 对话记忆入门:让模型记住上一轮问题
Spring AI 对话记忆入门让模型记住上一轮问题假设你做了一个客服 AI。用户第一轮问线上服务怎么申请扩容模型回答完以后用户第二轮接着问我刚才问的是什么如果这时模型说“不知道”不是它记性差。而是大模型本身是无状态的。第二次调用时你没有把上一轮对话带进去它当然接不上前文。很多 Java 开发者会在 Service 里手动处理查历史消息 → 拼到 prompt → 调模型 → 保存本轮问题和回答能跑但项目一大就麻烦。客服助手要记忆知识库问答要记忆日志分析 Agent 也要记住上下文。每个入口都手写一遍最后业务代码会变成“对话记忆处理中心”。Spring AI 里的MessageChatMemoryAdvisor就是为了解决这个问题。它不是让模型真的拥有长期记忆而是在每次调用前后帮你维护当前会话需要的上下文。一、先别手动拼历史消息最常见的手写方式大概是这样ListMessagehistorychatHistoryRepository.findRecentMessages(userId,10);ListMessagemessagesnewArrayList();messages.addAll(history);messages.add(newUserMessage(question));PromptpromptnewPrompt(messages);ChatResponseresponsechatModel.call(prompt);chatHistoryRepository.save(userId,question,response);这段代码的问题不是不能跑而是不适合长期维护。第一容易重复。每个 AI 入口都要查历史、拼消息、保存回复。第二容易漏。有的接口只查了历史忘了保存本轮回复有的只按userId查用户开多个会话就串了。第三策略不好统一。今天保留最近 5 轮明天改成 10 轮后天想做摘要压缩。如果逻辑散在各个 Service 里改起来很累。更合理的做法是业务代码只负责提问对话记忆交给统一的 Advisor 处理。二、Spring AI 怎么拆这件事Spring AI 的对话记忆不是一个类包办而是几层分工MessageChatMemoryAdvisor → 在 ChatClient 调用前后介入 ChatMemory → 决定给模型带哪些历史消息 MessageWindowChatMemory → 按窗口保留最近消息 ChatMemoryRepository → 负责存储和读取消息这里最容易混的是ChatMemory和ChatMemoryRepository。ChatMemory管的是“给模型看的上下文”。它关心的是下一次调用模型时要带哪些历史消息ChatMemoryRepository管的是消息存储。Spring AI 1.1.7 默认会自动配置MessageWindowChatMemory InMemoryChatMemoryRepositoryMessageWindowChatMemory默认最多保留 20 条消息。注意是 20 条消息不是 20 轮对话。一轮对话通常包含一条用户消息和一条助手消息所以 20 条消息大概就是最近 10 轮左右。超过窗口后较早的消息会被移出但 system message 会保留。InMemoryChatMemoryRepository是内存存储适合 Demo。生产环境别直接依赖它。应用一重启历史就没了多实例部署时每个实例也各存各的。三、最小接入方式如果你的项目已经能正常注入ChatModel接入对话记忆主要三步。1. 准备 ChatMemory只跑 Demo可以先用内存版ConfigurationpublicclassChatMemoryConfig{BeanpublicChatMemorychatMemory(){returnMessageWindowChatMemory.builder().maxMessages(20).chatMemoryRepository(newInMemoryChatMemoryRepository()).build();}}如果你不声明自己的ChatMemorySpring AI 也会按默认规则自动配置一套。这里显式写出来是为了看清两个配置maxMessages(20)控制窗口大小chatMemoryRepository(...)控制消息存在哪里。2. 配置 MessageChatMemoryAdvisor接着把MessageChatMemoryAdvisor配到ChatClientConfigurationpublicclassChatClientConfig{BeanpublicChatClientchatClient(ChatModelchatModel,ChatMemorychatMemory){returnChatClient.builder(chatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}配置完成后每次通过这个ChatClient调用模型Advisor 都会参与。它会在调用前读取历史消息把历史作为Message注入请求同时记录本轮用户消息调用后再把模型回复写回记忆。这点很重要MessageChatMemoryAdvisor不是把历史拼成一大段字符串而是把历史作为消息列表交给模型。3. 调用时传 conversationId业务代码可以保持很干净ServicepublicclassChatService{privatefinalChatClientchatClient;publicChatService(ChatClientchatClient){this.chatClientchatClient;}publicStringchat(StringconversationId,Stringquestion){returnchatClient.prompt().user(question).advisors(a-a.param(ChatMemory.CONVERSATION_ID,conversationId)).call().content();}}重点是这一行.advisors(a-a.param(ChatMemory.CONVERSATION_ID,conversationId))在 Spring AI 1.1.7 里内置记忆 Advisor 必须传ChatMemory.CONVERSATION_ID。不传会抛IllegalArgumentException。原因很简单Advisor 必须知道这次调用属于哪个会话才能读取和维护对应的历史消息。四、两轮对话时发生了什么第一次调用chatService.chat(conv-001,线上服务怎么申请扩容);这时conv-001还没有历史。Advisor 会把当前用户问题发给模型并把这条用户消息记下来。模型返回后再把助手回复写入同一个会话。第二次调用chatService.chat(conv-001,我刚才问的是什么);这次 Advisor 会先取出conv-001的历史消息。模型看到的就不只是当前问题而是上一轮用户问题 上一轮模型回复 当前用户问题所以它才能回答你刚才问的是线上服务怎么申请扩容。业务代码没有手动查历史也没有手动拼 prompt。这些都交给 Advisor 处理了。五、conversationId 别乱传conversationId是对话记忆里最容易踩坑的点。不建议直接用userId。因为一个用户可能同时有多个会话。比如他在客服助手里问扩容在知识库助手里问报销又在日志分析 Agent 里查异常。如果都用同一个userId历史就会混在一起。更合适的做法是给每段连续对话一个稳定 IDWeb 场景chatId或sessionIdApp 场景threadId或conversationUUID多 Agent 场景userId agentType chatId也不要每次请求都重新生成一个新的conversationId。那样每次都是新会话模型当然接不上前文。记住一句话同一段连续对话里conversationId 必须稳定不同会话之间conversationId 必须隔离。六、生产环境注意两件事1. 换掉内存存储InMemoryChatMemoryRepository适合本地开发不适合生产。它有三个问题应用重启后历史消息丢失多实例部署时每个实例各存各的不方便统一排查和运维。Spring AI 提供了多种ChatMemoryRepository实现比如 JDBC、MongoDB、Neo4j、Cassandra、Cosmos DB。如果你们公司已经有统一存储也可以自己实现ChatMemoryRepository。2. 不要把 ChatMemory 当完整聊天记录表ChatMemory管的是“给模型看的上下文”。它不是完整聊天记录库。如果你需要用户查看历史、后台审计、客服质检、数据分析建议单独设计业务聊天记录表。可以这样分工ChatMemory → 给模型看的短期上下文 业务聊天记录表 → 给用户、后台、审计和分析看的完整记录这两个东西不要混在一起。七、排查问题先看这三点如果第二轮还是“记不住”先查三件事两轮调用的conversationId是否一致ChatClient有没有配置MessageChatMemoryAdvisor是否用了内存存储并且应用重启或部署了多个实例。另外maxMessages20不是 20 轮对话而是 20 条消息。记忆窗口也不是越大越好。历史越多上下文越长成本越高也更容易把模型带偏。一般先从默认窗口跑通再根据实际效果调整。写在最后对话记忆的本质很简单每次调用前把当前会话需要的历史消息带进去。Spring AI 把这件事拆成了几层ChatMemory → 管理记忆窗口 ChatMemoryRepository → 存储和读取消息 MessageChatMemoryAdvisor → 调用前后维护记忆 conversationId → 区分不同会话业务代码不用在每个 Service 里查历史、拼 prompt、保存回复。把记忆交给MessageChatMemoryAdvisor。把会话隔离交给conversationId。把生产存储换成持久化ChatMemoryRepository。这套链路理清以后Spring AI 的对话记忆就不难了。我是 Dilee11 年 Java 老兵专注 AI 落地应用。关注我后续会继续更新 Spring AI、RAG、Memory、Tool Calling、MCP 等实战内容。

相关新闻

MTL咨询洞察:营销投入高、转化低?华为MTL帮你打通增长堵点

MTL咨询洞察:营销投入高、转化低?华为MTL帮你打通增长堵点

存量竞争时代,不少企业陷入“高投入、低转化”的营销困境:广告、展会投入不菲,客户却仅停留在“感兴趣”阶段,购买转化寥寥。核心症结在于缺乏从市场洞察到线索培育的完整闭环——MTL(Market to Lead)流程&…

2026/6/17 19:37:12阅读更多 →
从代码到图表:Mermaid Live Editor如何重塑你的技术文档创作体验

从代码到图表:Mermaid Live Editor如何重塑你的技术文档创作体验

从代码到图表:Mermaid Live Editor如何重塑你的技术文档创作体验 【免费下载链接】mermaid-live-editor Edit, preview and share mermaid charts/diagrams. New implementation of the live editor. 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid-l…

2026/6/17 19:37:12阅读更多 →
2026杭州GEO优化公司推荐:技术实力与效果口碑权威榜单

2026杭州GEO优化公司推荐:技术实力与效果口碑权威榜单

杭州GEO优化优质服务商盘点随着生成式AI技术的普及,AI搜索已经成为当下用户获取信息的主流渠道,对应的GEO(生成式引擎优化)也逐步成为企业数字营销布局的核心板块。有行业调研数据显示,目前已有接近八成的企业开始布局…

2026/6/17 19:37:12阅读更多 →
电源接口EMC设计实战:从浪涌防护到滤波优化

电源接口EMC设计实战:从浪涌防护到滤波优化

1. 电源接口EMC设计的核心挑战 电源接口就像电子产品的"咽喉要道",所有能量都从这里进出。我在设计第一款智能家居网关时,就曾因为电源接口EMC问题栽过跟头——产品在雷雨季节故障率飙升,返修率高达15%。后来拆解发现,压…

2026/6/17 21:03:53阅读更多 →
实战指南:构建LLM工具生态系统的完整Agentic解决方案

实战指南:构建LLM工具生态系统的完整Agentic解决方案

实战指南:构建LLM工具生态系统的完整Agentic解决方案 【免费下载链接】agentic Your API ⇒ Paid MCP. Instantly. 项目地址: https://gitcode.com/GitHub_Trending/ag/agentic Agentic作为LLM工具生态系统的核心枢纽,为开发者和企业提供了将API快…

2026/6/17 21:03:53阅读更多 →
HUD阳光倒灌太阳光模拟器系统

HUD阳光倒灌太阳光模拟器系统

在汽车科技快速发展的今天,抬头显示(HUD)技术已成为众多车型的标配。它能将重要的行车信息投影到挡风玻璃上,让驾驶员无需低头看仪表盘,大大提高了行车安全性。然而,HUD系统在实际使用中面临着一个棘手的问…

2026/6/17 21:03:53阅读更多 →
中医AI助手终极指南:如何用智能辨证系统快速提升中医学习效率?[特殊字符]

中医AI助手终极指南:如何用智能辨证系统快速提升中医学习效率?[特殊字符]

中医AI助手终极指南:如何用智能辨证系统快速提升中医学习效率?🚀 【免费下载链接】CMLM-ZhongJing 首个中医大语言模型——“仲景”。受古代中医学巨匠张仲景深邃智慧启迪,专为传统中医领域打造的预训练大语言模型。 The first-ev…

2026/6/17 21:03:53阅读更多 →
PP-Seg(PP-LiteSeg)模型零基础完整学习教程(原理+实战+部署)

PP-Seg(PP-LiteSeg)模型零基础完整学习教程(原理+实战+部署)

目录 一、PP-LiteSeg 核心概述与优势 1.1 什么是 PP-LiteSeg 1.2 对比传统分割模型优势 二、PP-LiteSeg 核心网络原理 2.1 整体网络结构 2.2 三大核心创新模块(核心考点) (1)SPPM 简易金字塔池化 (2&#xff0…

2026/6/17 21:03:53阅读更多 →
ArchivePasswordTestTool:基于7zip引擎的加密压缩包密码恢复技术解析

ArchivePasswordTestTool:基于7zip引擎的加密压缩包密码恢复技术解析

ArchivePasswordTestTool:基于7zip引擎的加密压缩包密码恢复技术解析 【免费下载链接】ArchivePasswordTestTool 利用7zip测试压缩包的功能 对加密压缩包进行自动化测试密码 项目地址: https://gitcode.com/gh_mirrors/ar/ArchivePasswordTestTool 在软件开发…

2026/6/17 20:53:24阅读更多 →
飞书机器人接入 OpenClaw 完整落地部署指南(含安装包)

飞书机器人接入 OpenClaw 完整落地部署指南(含安装包)

OpenClaw 2.7.9 对接飞书机器人完整配置教程 本文讲解借助长连接模式打通 OpenClaw 与飞书的操作流程,配置完成后,可在飞书私聊、群组内发送指令,调用本地 AI 实现电脑自动化操作。整体流程分为飞书平台创建应用、权限配置、密钥填写三大环节…

2026/6/17 10:40:20阅读更多 →
嵌入式处理器技术演进与飞思卡尔实战解析:从架构选型到系统设计

嵌入式处理器技术演进与飞思卡尔实战解析:从架构选型到系统设计

1. 嵌入式处理器:从“大脑”到“神经系统”的进化 在电子设备无处不在的今天,我们很少会去思考一个智能设备是如何“思考”和“行动”的。无论是汽车引擎的精准控制、工厂机械臂的流畅运转,还是智能家居的自动响应,其背后都离不开…

2026/6/17 10:40:20阅读更多 →
如何高效使用BallonTranslator:3分钟完成漫画翻译的完整实用指南

如何高效使用BallonTranslator:3分钟完成漫画翻译的完整实用指南

如何高效使用BallonTranslator:3分钟完成漫画翻译的完整实用指南 【免费下载链接】BallonsTranslator 深度学习辅助漫画翻译工具, 支持一键机翻和简单的图像/文本编辑 | Yet another computer-aided comic/manga translation tool powered by deeplearning 项目地…

2026/6/17 10:40:20阅读更多 →