ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Agent 跨会话记忆的生产落地:LangGraph MemoryStore 如何让 Agent 记住你是谁

Agent 跨会话记忆的生产落地:LangGraph MemoryStore 如何让 Agent 记住你是谁 Agent 最让人头疼的问题之一就是它不记事。用户上一轮告诉你我偏好用 Python 写后端下一轮对话 Agent 又问你你用什么语言。用户说帮我查一下上周那个工单的状态Agent 反问哪个工单——因为每个新会话都是一张白纸。如果你的 Agent 接入的是客服、运维、或者任何需要持续服务的场景这种每次对话都失忆的问题直接决定了用户愿不愿意用第二次。对话级记忆和跨会话记忆的区别很多团队已经在做一件事在单次对话里管理上下文。比如用滑动窗口截断历史、把旧对话摘要塞进系统提示词、或者用 Compaction API 压缩长对话。这些手段解决的是这次对话别超 Token 上限的问题但解决不了这次对话认不出上次对话的人。这是两个不同的记忆维度会话内记忆within-thread当前对话的上下文包括历史消息、中间状态、工具调用结果。对话结束就清空。跨会话记忆cross-thread跨越多次对话的持久化信息比如用户偏好、关键事实、历史行为。对话结束这些信息还在。会话内记忆靠的是上下文窗口管理而跨会话记忆需要的是一个存储层。以前这个存储层得自己搭——选数据库、设计 Schema、写 CRUD、还要考虑怎么把存进去的东西跟 Agent 的推理流程衔接起来。LangGraph v0.5 发布的 MemoryStore就是把这件事从你自己搭变成了框架帮你接好。MemoryStore 做了什么LangGraph 之前已经有 Checkpoint 机制用来保存每个 step 的执行状态支持断点续跑。但 Checkpoint 是按 thread 隔离的thread A 看不到 thread B 的数据。MemoryStore 是独立于 thread 的持久化存储所有 thread 共享同一个 store天然支持跨会话数据共享。它的核心 API 只有三个操作store.put(namespace, key, value) # 写入记忆 store.get(namespace, key) # 读取单条记忆 store.search(namespace, query) # 搜索记忆Namespace 是一个元组用来做数据隔离。最常见的用法是按用户隔离store.put( namespace(user, user_id, preferences), keyprogramming_language, value{lang: Python, framework: FastAPI} )这样每个用户的记忆互不干扰不同 namespace 之间天然隔离。同一个 namespace 下的多条 key 可以按 query 搜索框架内置了向量搜索能力不依赖外部向量数据库。从单次对话到持续记忆的工程转变接入 MemoryStore 之后Agent 的工作流多了一个记忆层。以前一个典型的 Agent 循环是接收用户输入组装上下文当前对话历史 系统提示词调用 LLM 获取回复如果 LLM 请求工具调用执行工具返回结果重复 2-4接入 MemoryStore 之后第 2 步之前多了一个步骤从 store 中检索当前用户的相关记忆注入到上下文中。第 4 步工具执行完之后如果产生了有价值的信息同步写入 store。这个变化看起来不大但对 Agent 的行为影响是质的用户说按上次的方案来Agent 真的知道上次的方案是什么用户说不要发邮件用 Slack 通知Agent 记住这个偏好之后所有对话都不再问用户说帮我查一下昨天那个异常Agent 知道昨天那个异常指的是哪个记忆检索的时机和粒度MemoryStore 的 search 方法支持按 query 做语义匹配不是简单的前缀匹配。这意味着 Agent 可以检索和当前问题相关的记忆而不是和关键词完全匹配的记忆。但这里有一个工程上容易踩的坑检索时机。如果每轮对话都全量检索Token 消耗会迅速膨胀。特别是当 store 里积累了上百条记忆时把所有记忆一股脑塞进上下文和没做记忆管理的效果一样差——Token 照样爆。比较好的做法是分层检索高频记忆在 Agent 初始化时加载比如用户的语言偏好、通知偏好、时区设置。这些信息几乎每次对话都会用到适合常驻上下文。场景记忆根据当前对话的意图触发检索。比如用户提到工单时才去检索和历史工单相关的记忆。临时记忆工具执行过程中产生的中间结果只在当前 step 使用不需要持久化。MemoryStore 的 namespace 设计天然支持这种分层。高频记忆放在(user, uid, profile)场景记忆放在(user, uid, context, tickets)search 的时候限定 namespace 范围减少无效检索。记忆写入的判定标准比检索更难的是什么时候该写记忆。LLM 的回复里包含大量信息但并不是所有信息都值得记住。如果每轮对话都把 Agent 的回复原文写进 storestore 很快就会变成一堆垃圾数据检索时反而引入噪声。MemoryStore 自己不做什么值得记的判定——这个判定需要应用层来做。常见的做法是让 Agent 在完成关键工具调用后通过一个专门的记忆写入工具来触发存储class WriteMemory(Tool): 当发现对后续对话有价值的用户信息时写入记忆。 def execute(self, namespace: tuple, key: str, value: dict): store.put(namespace, key, value) return 记忆已保存这个工具的调用权交给 LLM由 LLM 判断这条信息值得记住。实际效果取决于 Prompt 中对什么值得记的定义。如果 Prompt 写得太宽泛LLM 会把什么都记进去写得太严格又可能漏掉关键信息。一个更可控的方式是在工具执行结果返回后在应用层用规则做一次过滤只有满足条件的信息才写入 store。比如用户明确表达偏好、工具返回了关键数据、用户的指令对后续对话有约束力。记忆的更新和冲突跨会话记忆还有一个容易被忽略的问题记忆更新。用户在第一次对话中说我偏好 Pythonstore 里记了{lang: Python}。第五次对话时用户说最近切到 Go 了这时候应该更新还是追加MemoryStore 的 put 方法是按 key 覆盖的同一个 key 的多次 put 以最后一次为准。这符合大多数场景的需求——用户的最新偏好覆盖旧偏好。但有些场景需要保留历史版本比如用户偏好频繁变化时需要知道变化轨迹。这种情况下可以用时间戳作为 key 的一部分或者自己在 value 里维护版本号。MemoryStore 本身不做版本管理这部分需要应用层自己处理。生产环境的三个关注点第一存储后端的选择。InMemoryStore 只适合开发和测试。生产环境需要对接持久化存储LangGraph 提供了对 PostgreSQL、Redis 等后端的支持。选择时需要考虑跨线程/跨进程的并发写入冲突——同一个用户的两次对话可能同时写入 store需要做好乐观锁或最后写入者胜出的策略。第二检索的延迟预算。MemoryStore 的 search 如果走向量检索延迟会比 key-value 的 get 高一个数量级。在 Agent 的主循环里每一步的延迟都是累加的。如果每次检索记忆都要等 200ms十步对话就多出两秒。建议高频记忆走 get毫秒级场景记忆走 search可接受百毫秒级并根据对话的实时性要求做取舍。第三记忆量的增长管理。跨会话记忆会随着时间持续增长不像会话内记忆在对话结束后就释放。需要定期做记忆的归档和清理。比如三个月前的用户偏好如果再也没有被更新过可以归档到冷存储空 namespace 可以清理掉。这部分不是 MemoryStore 的能力范围需要在应用层配合定时任务。什么时候该上跨会话记忆不是所有 Agent 都需要跨会话记忆。如果你的 Agent 场景是每次对话独立、用户不关心上下文延续比如一次性的文档问答、单次代码生成那会话内记忆就够用了。但如果你正在做的是用户持续使用的服务型 Agent——客服助手、运维机器人、个人助理、开发辅助——跨会话记忆就是必需品。没有它用户每次对话都要重新交代背景体验和第一版聊天机器人没有区别。LangGraph MemoryStore 的价值不在于它做了什么特别复杂的事而在于它把跨会话记忆这个原本需要自己从头搭建的能力变成了框架内的一等公民。三个 API 方法、一个 namespace 概念接上就能用。对于已经在用 LangGraph 的团队这是一个低成本、高回报的工程选择——前提是搞清楚记忆的写入策略和检索边界不要一股脑全存、全搜。最后我们整理出这套 AI 大模型突围资料包✅ 从零到一的 AI 学习路径图✅ 大模型调优实战手册附医疗/金融等大厂真实案例✅ 百度/阿里专家闭门录播课✅ 大模型当下最新行业报告✅ 真实大厂面试真题✅ 2025 最新岗位需求图谱所有资料 ⚡️ 朋友们如果有需要 《AI大模型入门进阶学习资源包》下方扫码获取~资料展示下面是我整理的AI大模型学习资料和工具包预览适合收藏后按主题逐步学习。需要这份AI大模型资料清单的话在评论区回复「清单」即可我会根据大家的问题继续补充对应的实战内容。
返回列表