大型语言模型(LLM)是无状态的,这意味着它们不会保留先前交互的信息。当您希望在多次交互中保持上下文或状态时,这可能成为一个局限。为了解决这个问题,Spring AI 提供了聊天记忆功能,使您能够在与 LLM 的多次交互中存储和检索信息。
一、简单例子
下面就以将聊天记忆放在内存中举个例子
@Configurationpublic class AIConfigration {@Autowiredprivate ChatMemoryRepository chatMemoryRepository;@Beanpublic ChatClient openaiChatClient(OpenAiChatModel openAiChatModel,ChatMemory chetMemory){return ChatClient.builder(openAiChatModel) //设置模型.defaultSystem("您是一位只会说事实的程序员,不会说一些没有根据的事情") //在这里设置系统提示词,这样所有请求都会带上这个//.defaultAdvisors(new MySimpleLoggerAdvisor()).defaultAdvisors(SimpleLoggerAdvisor.builder().build(),MessageChatMemoryAdvisor.builder(chetMemory).build()) //设置记忆.build();//创建对象}@Beanpublic ChatMemory chetMemory(){return MessageWindowChatMemory.builder().//chatMemoryRepository(new InMemoryChatMemoryRepository())//基于内存可以直接newchatMemoryRepository(chatMemoryRepository)//也可以用注入.maxMessages(4)//消息窗口大小4.build();}}
使用的时候要设置用户ID
@GetMapping("/ask5")public String ask5(String topic){String result = openaiChatClient.prompt().user(u -> u.text("{topic}").param("topic",topic)).advisors(a ->a.param(ChatMemory.CONVERSATION_ID, 1)).call().content();return result;}
这样就可以有聊天记忆了,但是消息窗口大小只有4,会随着聊天记忆的增加前面的会直接抛弃,在发送给大模型的时候,消息类型为AssistantMessage。
二、内存记忆策略
1. MessageWindowChatMemory(默认)
- 核心机制:维护固定大小消息窗口,消息数量超出上限时淘汰最早的消息;system 消息会一直保留,不会被清理
- 默认窗口大小:20 条消息
- 适用场景:大部分简单多轮对话,兼顾上下文完整度和 token 消耗
2. VectorStoreChatMemory(语义记忆)
- 核心机制:对话内容向量化存入向量库,依靠语义相似度检索召回相关历史,不是按顺序截断
- 适用场景:超长对话、需要精准语义匹配的复杂业务场景
3、 补充区分一句话
MessageWindowChatMemory+ 存储仓库:滑动窗口截断,按顺序保留最近 N 条(最常用)VectorStoreChatMemory:语义检索,按需召回相关历史,不固定窗口,解决长上下文 token 爆炸
三、支持的存储后端
表格
| 存储类型 | 实现类 | 特点 | 适用场景 |
|---|---|---|---|
| 内存存储 | InMemoryChatMemoryRepository | 底层ConcurrentHashMap,轻量、访问快 |
开发测试、演示环境 |
| Redis | RedisChatMemoryRepository | 分布式、高性能,支持 TTL 过期 | 线上生产、多实例部署 |
| JDBC | JdbcChatMemoryRepository | 关系型数据库持久化,支持事务 | 需要长期持久保存对话、依赖事务能力 |
| Cassandra | CassandraChatMemoryRepository | 分布式 NoSQL,高可用 | 超大规模分布式系统 |
