首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Agent 为什么总是「失忆」?聊透上下文记忆管理这件事

Agent 为什么总是「失忆」?聊透上下文记忆管理这件事

作者头像
老周聊架构
发布2026-07-27 14:51:45
发布2026-07-27 14:51:45
460
举报
先说一个让人崩溃的场景:

你跟 Agent 聊了一个小时,建立了很多上下文——它知道你在做什么项目、你的技术偏好、你踩过哪些坑。然后你关掉窗口,隔天再开,Agent 完全不认识你了。你得重新解释一遍。

更崩溃的版本:不用隔天,就在同一个长对话里,你在第 3 轮告诉过它「我们用的是 PostgreSQL」,到第 30 轮它又问你「你们用什么数据库」——它忘了。

这不是模型的问题,这是架构的问题

理解这件事,先要接受一个反直觉的事实:模型本身没有记忆。

每一次你调用模型 API,它都是全新的一个实例,没有任何上一轮的记忆。你以为它「记得」,是因为你每轮都把历史对话原文塞回了 prompt 里,它「读了」,看起来像是「记得」。

所以所谓的「记忆」,本质是 Harness 每轮重新拼好、喂回去的上下文。

这就引出了核心矛盾:上下文窗口是有限的。

哪怕现在主流模型的上下文窗口已经到了几十万 token,也依然有限。更重要的是,越长越贵、越慢,还有一个叫做「lost-in-the-middle」的问题——研究发现,模型对上下文头部和尾部的注意力最强,中间那段很容易被忽略。你把所有历史塞进去,不代表它全都能有效利用。

上下文记忆管理,本质就是在解一道取舍题:在有限的窗口里,每一轮该放进去哪些信息?


先把「记忆」分清层次

业界对 Agent 记忆有一套标准分类,搞清楚层次,才能谈管理策略。

短期 / 工作记忆(Working Memory)

就是当前对话窗口里的内容。直接在 prompt 里,模型能直接「看到」,不需要任何检索。这是最快、最可靠的记忆——代价是占用宝贵的窗口空间。

类比人类:你现在正在读的这段文字,就是你的工作记忆。

长期记忆(Long-term Memory)

存在外部系统里(向量库、图库、数据库),按需检索、临时调进窗口。长期记忆又分三种:

情节记忆(Episodic):「上次发生了什么」。具体的对话片段、历史事件。比如「三天前用户问过一个关于并发锁的问题,当时的解决方案是……」。存的是原始事件,优点是保真,缺点是量大、检索成本高。

语义记忆(Semantic):「关于这个人/世界的事实」。不存原始对话,存提炼出来的事实:「用户偏好 TypeScript」「他是左撇子」「他们公司用的是微服务架构」。量小、检索精准,但需要一个额外的「提炼」步骤。

过程记忆(Procedural):「该怎么做事」。沉淀下来的流程、技能、操作规范——就是 Harness Engineering 那张图里讲的 Skill。比如「每次部署前要先跑回归测试」「回复用户问题时要先确认版本号」。这类记忆最稳定,一旦形成很少变化。

这三层长期记忆,对应了不同的检索策略和存储选择。不是所有记忆都应该用同一种方式存、用同一种方式取。


六种上下文管理技术

理解了层次,再来看工程上怎么在有限窗口里腾挪。

技术一:截断 / 滑动窗口(Truncation / Sliding Window)

最简单,只保留最近 N 轮对话,超出就截掉。

优点:零成本,不需要任何额外组件。缺点:失忆。对话超过 N 轮,早期的上下文全部消失。

适合:对话轮次少、任务局部性强的场景。绝大多数简单聊天机器人在用这个,只是大家不说。

技术二:摘要压缩(Summarization)

不截掉历史,而是把老对话压成一段摘要,塞回去替代原文。省 token 同时保留「大意」。

实际产品里更常见的是「滚动摘要 + 保留最近几轮原文」的组合——最近 5 轮原文保真,5 轮之前的历史压成摘要。

优点:比截断聪明,能保留更长周期的上下文。缺点:摘要必然丢细节,「用户三天前提到过一个具体的 API 名字」这种细节,摘要里可能消失了。

技术三:RAG 式检索记忆(Retrieval-Augmented Memory)

把历史对话切块,存进向量库,每轮用当前的问题做语义相似度检索,把最相关的几条历史召回,拼进当前轮的 prompt。

这是目前最主流的长期记忆实现方式。优点:理论上能记任意长的历史,只要相关的就能找出来。缺点:依赖向量检索的质量,相关性是模糊的,偶尔会召回不对的东西;向量库运维也是额外复杂度。

技术四:抽取式记忆(Fact Extraction)

不存原始对话,而是让模型从每轮对话里抽出结构化的事实,存为键值或结构体,按需检索。

比如对话结束后,有一步「记忆更新」:模型读完对话,输出「用户喜好:TypeScript;技术栈:K8s;当前任务:重构认证模块」。下一轮检索这些事实,而不是检索原始对话。

优点:精度比 RAG 高,存的都是提炼过的信息。缺点:抽取步骤有额外成本,且依赖抽取质量——模型判断「这条值得记住」不一定准。

技术五:知识图谱 / 时序图记忆(Knowledge Graph Memory)

把实体和关系存成图结构,并且记录时间戳。

为什么需要图?因为纯向量存的是「片段」,表达不了「关系」和「变化」。比如「他去年在 A 公司,今年跳到了 B」——向量库里你可能搜到两条矛盾的信息,不知道哪条是最新的。图库能存「实体 → 属性 → 时间」,查询时能推理出「最新状态是什么」。

适合:长周期、多实体、有时间维度的场景。复杂度也最高。

技术六:分层调页(Hierarchical Paging / MemGPT 思路)

把上下文管理类比成操作系统的内存管理:主上下文(当前 prompt)= RAM,近期历史 = 一级缓存,长期记忆 = 磁盘。

模型自己通过函数调用决定:「我现在需要把这段信息存到长期记忆」「我现在需要从历史里调出某段信息」。Agent 有了对自己记忆的主动管理能力。

这是最复杂、最自主的方式,落地难度也最高——模型的调页决策本身就可能出错。


业界主流工具怎么选

这些技术不用自己从零实现,业界已经有成熟的开源方案。

Mem0(最流行,48K+ GitHub Star)

一个「记忆层」,框架无关,bolt-on 到你现有的 Agent 上,三行代码接入。

核心思路:从每轮对话里抽取结构化事实,存进向量库,按需检索。同时做去重和冲突处理——如果新的事实和已有事实矛盾,会自动更新而不是追加。

代码语言:javascript
复制
from mem0 import Memory
 
m = Memory()
 
# 每轮对话结束后,自动抽取并存储记忆
m.add("用户说他们用的是 PostgreSQL,不用 MySQL", user_id="user_123")
 
# 下一轮开始前,检索相关记忆
memories = m.search("数据库选型", user_id="user_123")
# 返回:[{__STR0__: __STR1__, __STR2__: 0.92}]

适合:聊天机器人、个人助手、需要跨会话记忆的场景。

Zep(生产级,混合向量 + 知识图谱)

不只是向量存储,而是用 LLM 从对话里抽取实体关系,构建一个时序知识图谱。

举个例子:Mem0 存的可能是「用户在 Anthropic 工作」这条事实。Zep 存的是一个图节点:User → worksAt → Anthropic(since 2024-03),时间戳精确,关系明确,之后即使「用户跳槽了」,也能在图里更新关系而不是产生矛盾的两条记录。

适合:长周期对话、有复杂关系和时间维度的场景,比如 CRM 类 Agent、陪伴 Agent。

Letta(前身 MemGPT,分层调页思路的工程实现)

把记忆做成一个类操作系统的 Agent 运行时。主上下文(in-context)+ recall storage(近期历史)+ archival storage(长期归档),模型通过函数调用主动决定什么时候存、什么时候取。

适合:要自部署、要 Agent 对自己记忆有强控制权的场景。比如长期运行的个人 AI 助手、自主 Agent。

LangMem(LangGraph 生态内置)

LangGraph 团队自己做的记忆方案,和 LangGraph 的状态管理深度集成。如果你已经在用 LangGraph 搭 Agent,直接用 LangMem 是最省事的选择。

怎么选,一句话判断:

简单个人助手 / 跨会话聊天记忆 → Mem0,接入最快,48K star 说明坑都被踩完了。

长会话、要处理关系和时间变化 → Zep,图 + 时序,专门为这个场景设计的。

想要 Agent 自己管理自己的记忆 → Letta,MemGPT 思路,自部署友好。

已经在 LangGraph 上 → LangMem,不引额外依赖。

只想要检索、不想引第三方 → 自己实现 RAG + pgvector,完全掌控。


工程上最容易踩的几个坑

坑一:以为更大的上下文窗口解决了一切

每次有新模型宣传「支持 100 万 token 上下文」,就会有人说「记忆管理不需要了」。

这是错的。更大的窗口能解决短期问题,但无法解决:跨会话记忆、cost 随长度平方级上升、lost-in-the-middle 的注意力衰减。生产环境里,你不可能把用户三年的对话历史全塞进去,即便能塞,你也付不起那个 API 账单。

坑二:把所有记忆用同一种方式存

情节记忆适合 RAG 式检索(原文保真),语义记忆适合抽取式存储(精度优先),过程记忆适合固化成 Prompt 或 Skill(稳定性优先)。混在一起用一个向量库,检索精度会很差。

坑三:没有记忆更新机制

用户今天说「我用 React」,明天说「我们换成 Vue 了」。如果记忆系统只追加不更新,两条矛盾的记录同时存在,检索出来的结果会让模型困惑。

好的记忆系统需要:抽取 → 存储 → 去重 / 冲突检测 / 更新,缺了最后一步,记忆会越来越脏。

坑四:记忆召回没有评估

你怎么知道召回的记忆是对的、是有用的?大多数项目上了记忆功能就算完事,从来不评估召回质量。建议把记忆召回纳入 Langfuse 的 Trace,定期抽查:这条检索出来的记忆,跟当前问题真的相关吗?


放回大图里看

Agent 记忆管理,本质是 Harness Engineering 里「Memory」组件的深度展开。

在我之前讲的 Harness 框架里,Memory 是最容易被第一版跳过、然后在用户反馈「它怎么总是忘事」之后不得不补的组件。

做得好的记忆系统,有三个标准:

  • 该记的,准确记住——关键事实不漏,不是全量存储,是有选择地提炼
  • 该忘的,干净忘掉——过期信息、矛盾信息及时清理,不让脏数据污染上下文
  • 该调的,精准调进来——检索要准,召回的东西要真的跟当前任务相关

这三条,不是靠更大的上下文窗口硬撑出来的,是靠工程设计控制出来的。

「记忆」这件事,模型不会主动帮你做好,是工程师的责任。

你现在的 Agent 用的是哪种记忆方案?踩过哪些坑?评论区聊聊。

— 完 —

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老周聊架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 先把「记忆」分清层次
  • 六种上下文管理技术
  • 业界主流工具怎么选
  • 工程上最容易踩的几个坑
  • 放回大图里看
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档