在 Spring AI 的浪潮中,越来越多开发者尝试构建智能 Agent——能自主规划、调用工具、与用户多轮交互的“数字员工”。然而,一个高频痛点反复出现:Agent 总是“忘事”。上一轮对话刚确认的用户偏好,下一轮就消失无踪;中间步骤生成的关键信息,在后续调用中无法复用;甚至简单任务也需要用户反复重复上下文。
问题出在哪?答案直指核心:你忽略了 Agent 的“记忆系统”设计。
Spring AI 提供了强大的工具调用和函数编排能力,但它本身不自动管理记忆。若不显式集成记忆机制,Agent 就像一个没有短期记忆的“金鱼”,每次请求都是孤立的“全新开始”。
本文将剖析 Spring AI Agent “失忆”的三大根源,并给出可落地的记忆增强方案。
一、“失忆”根源 1:无状态的 HTTP 请求模型
Spring Boot 应用默认基于无状态的 REST 架构。每一次用户请求都是独立的,上下文不会自动保留。
@PostMapping("/chat") public String chat(@RequestBody String userMessage) { // 每次调用都新建一个 Agent 实例? // 历史消息未传入 → Agent 不知道之前聊过什么 }
后果:即使你用 @Service 注入了 Agent,若未手动维护对话历史,LLM 的输入 prompt 中就只有当前消息,自然“失忆”。
二、“失忆”根源 2:忽略 ConversationMemory 的显式配置
Spring AI 提供了 ConversationMemory 接口(如 InMemoryConversationMemory、RedisConversationMemory),但它不会自动生效。
很多开发者直接这样写:
AIChatClient client = new OpenAIChatClient(apiKey); Prompt prompt = new Prompt(userMessage); return client.generate(prompt).getResult().getOutput().getContent();
这里完全没有加载历史对话!正确的做法是:
// 初始化带记忆的 ChatClient var memory = new InMemoryConversationMemory(); // 或 Redis 版本 var chatClient = new OpenAIChatClient(apiKey) .withDefaultMemory(memory); // 关键! // 在会话中持续使用同一个 memory 实例 String response = chatClient.generate(userMessage).getContent();
⚠️ 注意:
InMemoryConversationMemory仅适用于单机、单用户测试。生产环境必须用 Redis + sessionId 绑定 的分布式记忆。
三、“失忆”根源 3:工具调用结果未回写到记忆
Agent 的强大在于能调用工具(如查数据库、发邮件)。但很多实现只把工具结果返回给用户,却忘了告诉 LLM:“你刚才查到了这些信息,后面可以用”。
例如:
- 用户问:“我上周的订单状态?”
- Agent 调用
orderService.query(userId, lastWeek)得到结果。 - 但该结果未追加到对话历史,下一句用户问“那能取消吗?”,Agent 就不知道“那”指的是哪个订单。
正确做法:在工具执行后,主动将结果以“系统消息”形式写入记忆:
String toolResult = orderService.query(...); memory.addMessage(new SystemMessage("工具返回:订单 #12345 状态为 '已发货'"));
这样,后续 LLM 调用就能看到完整上下文。
四、实战:构建一个“不忘事”的 Spring AI Agent
步骤 1:配置 Redis 记忆(支持多用户)
@Bean public ConversationMemory conversationMemory(RedisTemplate<String, Object> redis) { return new RedisConversationMemory(redis, "ai:chat:{sessionId}"); }
步骤 2:在 Controller 中按 sessionId 复用记忆
@PostMapping("/chat/{sessionId}") public String chat( @PathVariable String sessionId, @RequestBody String message, @Autowired ConversationMemory memory ) { // 绑定当前会话 memory.setSessionId(sessionId); var agent = new SimpleAgent(chatClient, tools, memory); return agent.run(message); }
步骤 3:工具执行后自动回写
public class OrderLookupTool implements FunctionCallback { public FunctionResponse handle(FunctionCall call) { String result = queryOrder(...); // 关键:将结果注入记忆 conversationMemory.addMessage(new SystemMessage("查询结果:" + result)); return FunctionResponse.from(result); } }
五、高级技巧:分层记忆 + 记忆压缩
当对话过长,prompt 会超出 token 限制。此时需引入:
- 滑动窗口记忆:只保留最近 N 轮对话;
- 摘要记忆:用 LLM 自动总结历史,替换原始记录;
- 向量记忆:将关键事实存入向量库,按需检索(适合 RAG 场景)。
Spring AI 社区已出现 SummarizingConversationMemory 等扩展,可按需集成。
结语:记忆,是 Agent 从“工具”走向“伙伴”的桥梁
一个“不忘事”的 AI Agent,才能真正理解用户意图、积累上下文、提供连贯服务。在 Spring AI 中,记忆不是自动附赠的功能,而是需要你主动设计、显式管理的核心组件。
别再让你的 Agent 当“金鱼”了。
从今天起,给它装上可靠的“记忆引擎”——这才是智能体进化的第一步。
🌟 提示:Spring AI 1.0+ 已原生支持
ChatMemory抽象,建议升级并采用官方推荐模式,避免自行拼接 prompt 导致的安全与一致性问题。