01
@GetMapping("/chat")public String chat(@RequestParamString question) {return chatClient.prompt().user(question).call().content();}
用户:你叫什么名字?AI:我是你的AI助手。用户:继续AI:...你在说什么继续?我不知道你指的是什么。
02
第一轮:用户问好 → AI回复 → 存入记忆第二轮:用户说"继续" → 从记忆读取 → AI知道上文 → 回复
ChatMemoryRepository(存储层接口)↑ChatMemory(管理器)↑MessageChatMemoryAdvisor(拦截器,注册到ChatClient)
03
用户:你叫什么名字?AI:我是你的AI助手。用户:继续AI:你是问我叫什么名字吗?我是你的AI助手,我们可以聊聊任何话题。
@RestController@RequestMapping("chat/memory")public class ChatMemoryController {@Resourceprivate MiniMaxChatModel miniMaxChatModel;// Spring AI 默认有一个ChatMemory实例@Resourceprivate ChatMemory chatMemory; // 自动配置的InMemory@GetMapping(value = "v1", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<String> streamEvent(@RequestParam("question") String question) {// 关键5行代码// 这里引入一个新的概念:Advisor,后续文章会讲解它的作用ChatClient chatClient= ChatClient.builder(miniMaxChatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();return chatClient.prompt().user(question).stream().content();}}
ChatClient chatClient = ChatClient.builder(miniMaxChatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();
读取历史消息,加入Prompt 把新消息写入记忆
04
InMemory(开发测试用)
// 直接注入,框架已经配好了@Resourceprivate ChatMemory chatMemory;
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId></dependency>
spring.ai.chat.memory.repository.jdbc.initialize-schema=embedded<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-chat-memory-repository-redis</artifactId></dependency>
spring.ai.chat.memory.redis.host=localhostspring.ai.chat.memory.redis.port=6379spring.ai.chat.memory.redis.time-to-live=24h
05
用户请求↓MessageChatMemoryAdvisor(拦截器)├── 读取:chatMemory.get(sessionId) → 历史消息├── 拼接:历史消息 + 当前问题 → 完整Prompt↓发给AI Model↓AI回复↓MessageChatMemoryAdvisor(拦截器)├── 写入:chatMemory.add(sessionId, 用户消息, AI回复)↓返回给用户
// 给不同用户分配不同记忆空间String sessionId = user.getId();// 用户ID维度隔离MessageChatMemoryAdvisor(chatMemory, sessionId)
06
// 保留最近N条消息(推荐10-20)MessageWindowChatMemory.builder().maxMessages(10).build();// 或者按Token数量TokenWindowChatMemory.builder().maxTokens(2000).build();
简单问答: maxMessages=10复杂对话: maxMessages=20超长对话:考虑 maxTokens=2000
07
// ❌ 错误:所有用户共享同一个会话MessageChatMemoryAdvisor(chatMemory, "global")// ✅ 正确:按用户ID隔离MessageChatMemoryAdvisor(chatMemory, user.getId())
maxMessages,或者用TokenWindowChatMemory。08
Advisor机制:MessageChatMemoryAdvisor自动管理记忆 会话隔离:不同用户/场景用不同sessionId


夜雨聆风