Skip to content

记忆系统

本页速览 LLM 本身无状态,Agent 的记忆全靠系统设计。本文拆解短期/长期记忆的分类学(CoALA)、摘要压缩与显著性保留、向量检索/结构化画像/文件笔记/知识图谱四种长期记忆实现,以及最难的写入策略与评估方法。

本页含时效性内容,数据截止于 2026-08;JD、价格、产品功能等信息可能已变化,引用前请核对原始出处。

记忆系统 ​

LLM 本身没有记忆。每次调用都是一张白纸:你把对话历史塞进 prompt,它"看起来"就记得;你不塞,它就什么都不记得。所谓 Agent 的记忆,从来不是模型的能力,而是你在模型外面搭的一套系统——决定记住什么、存在哪、什么时候取、什么时候忘。

这套系统是区分"聊天机器人"和"Agent"的分水岭之一。本页讲清楚三件事:记忆的分类学(记住什么)、主流实现方案(怎么存怎么取)、以及被严重低估的写入策略(什么时候写、怎么更新和遗忘)。上下文窗口的调度与压缩属于 上下文工程 的范畴,本页只在必要处交叉引用。

一、为什么 Agent 需要记忆 ​

无状态的 LLM vs 有状态的任务 ​

一次 LLM 推理调用是纯函数:output = f(context)。模型权重在训练后冻结,推理过程不会往权重里写任何东西。你昨天和 ChatGPT 聊了三个小时,今天它"记得"你,靠的不是模型变了,而是产品在后台把你的偏好抽取出来、存进数据库、下次对话时拼进 system prompt。

但 Agent 面对的任务天然是有状态的:

  • 多轮协作:客户支持 Agent 处理一个横跨三天的工单,必须记得昨天已经排查过 DNS。
  • 长程任务:编程 Agent 改一个大型仓库,第 50 步的决定依赖于第 3 步读过的文件结构——而原始上下文早就被截断了。
  • 个性化:助理类 Agent 需要积累用户画像(偏好、习惯、历史决策),否则每轮对话都从"您好,请问有什么可以帮您"重新开始。
  • 经验复用:Agent 上次踩过的坑("这个 API 的分页参数是 cursor 不是 offset")不该再踩一次。

长上下文不等于记忆

"现在上下文窗口都 100 万 token 了,还要记忆系统干嘛?"这是常见误解。第一,长上下文贵——每次都重放全部历史,成本和延迟随会话长度线性甚至超线性增长(详见 成本优化)。第二,长上下文效果会衰减,"lost in the middle"现象下,埋在海量历史中间的信息召回质量明显下降。第三,跨会话的场景根本无解:窗口再大,新会话也是空的。上下文窗口是工作台,记忆系统是档案柜——工作台再大也替代不了档案柜。

记忆的三个功能角色 ​

在动手设计前,先想清楚记忆在你的 Agent 里扮演哪个角色:

  1. 连续性(continuity):让长任务不断片。这是刚需,几乎所有 Agent 都需要。
  2. 个性化(personalization):让 Agent 越来越懂特定用户。助理、客服、陪伴类产品需要。
  3. 学习(learning):让 Agent 从经验中改进行为。这是最难也最少被做好的——多数宣称"会学习"的 Agent 只是把失败日志存进了向量库,并没有真的改变策略。

三个角色对记忆系统的要求完全不同:连续性要的是保真和可回溯,个性化要的是聚合与泛化,学习要的是能影响未来决策的闭环。混为一谈是记忆设计翻车的头号原因。

二、记忆分类学:借认知科学的框架,但别照抄 ​

CoALA 的四类记忆 ​

认知科学把人类记忆分为工作记忆、情景记忆、语义记忆、程序性记忆。CoALA 论文(Cognitive Architectures for Language Agents, Sumers et al., arXiv 2309.02427)系统地把这套分类迁移到了语言 Agent 上,目前这是 Agent 文献中引用最广泛的记忆分类框架:

CoALA 分类认知科学对应在 Agent 里的形态典型实现
Working memory(工作记忆)短时记忆当前 context window 里的全部内容对话历史、scratchpad、当前计划
Episodic memory(情景记忆)对"经历过的事"的记忆过去任务的轨迹、对话片段、"上次发生了什么"会话日志 + 向量检索
Semantic memory(语义记忆)对世界的事实性知识用户画像、领域知识、实体关系结构化字段、知识图谱、向量库
Procedural memory(程序性记忆)"怎么做"的技能系统提示词、工具用法、学到的操作流程prompt、代码、少样本示例

这个分类的工程价值在于:四类记忆的读写时机、存储格式、检索方式完全不同,不该用一套机制处理。用户画像(语义)适合存成结构化字段,按 key 精确读取;任务轨迹(情景)适合存原文加摘要,按相似度检索;操作经验(程序性)最有效的形式往往是直接改 prompt 或沉淀为 few-shot 示例,而不是存进向量库等召回。

短期记忆 vs 长期记忆:另一个更实用的切分 ​

工程实践中更常用的切分是按生命周期:

  • 短期记忆(short-term / in-context):活在当前 context window 里,随会话结束而消亡。管理它的本质是上下文调度,详见 上下文工程。
  • 长期记忆(long-term / cross-session):持久化在外部存储(数据库、文件、向量库),跨会话存活,需要显式的写入和检索机制。

两条切分维度组合起来,你就得到了一个设计矩阵:先问"这条信息属于哪类记忆"(情景/语义/程序性),再问"它要活多久"(本会话/跨会话),答案直接决定存哪、怎么取。

判断要不要做长期记忆的朴素标准

如果你的 Agent 90% 的会话之间没有信息依赖(比如单次问答、单文件改写),长期记忆是过度设计——先把短期记忆的压缩做好。长期记忆值得做的信号是:用户在会话二里说了"上次那个",或者任务跨越的时长超过了上下文能容纳的极限。

三、短期记忆管理:决定"记住什么" ​

短期记忆管理的完整话题(token 预算、压缩算法、工具结果截断)在 上下文工程 一页。本页只回答一个问题:当上下文装不下时,哪些信息该留下来?

三种主流取舍策略 ​

原始对话: [t1][t2][t3]...[t47][t48][t49][t50]   ← 超出窗口

策略 A 滑动窗口:                    [t48][t49][t50]
  保留最近的,丢弃最旧的。简单、零成本,但会"失忆"早期关键约束。

策略 B 摘要压缩: [摘要(t1..t47)     ][t48][t49][t50]
  旧历史压成一段摘要,保留近期原文。信息有损,摘要质量决定上限。

策略 C 显著性保留: [t3*][t17*][摘要(其余)][t48][t49][t50]
  先挑出高价值条目(用户约束、做出的决定、未解决的问题)单独保留,
  其余压缩。效果最好,实现也最复杂。

实践中绝大多数生产系统是 B 的变体:Claude Code 的 compaction、各类框架的 SummarizationMiddleware 都是这个思路——旧消息交给一个 LLM 调用压成摘要,近期消息保留原文。

摘要压缩的三个工程要点 ​

  1. 摘要要分层,不要滚雪球。每压缩一次就把旧摘要喂进新摘要,误差会复利式累积,十几轮后摘要里会编出从未发生过的"事实"。更好的做法是锚定原始事实源:重要决定、用户硬约束单独抽成结构化条目(key-value 或一句话事实清单),摘要只管叙事连贯。
  2. 触发时机用阈值而不是轮数。按 token 占用率触发(如达到窗口的 70-80%),而不是固定"每 10 轮压缩一次"——十轮闲聊和十轮密集代码阅读的 token 量差一个数量级。
  3. 压缩点选在任务边界。在子任务刚完成、结论已落盘时压缩,比在一个推理链条中间压缩安全得多。Anthropic 在 context engineering 的公开工程博客中把这个思路概括为"先写笔记,再清桌面":agent 把关键发现写进持久化文件(如 Claude Code 写进代码库或笔记文件),然后才放心地压缩上下文——因为信息已经从"记忆"降级为"可重新检索的资料"。

显著性保留:从 Generative Agents 学来的评分 ​

显著性(salience)保留的经典出处是 Generative Agents 论文(Park et al., arXiv 2304.03442):每条记忆检索时按 recency(新近度)、importance(重要性)、relevance(相关性) 三个维度加权打分。其中 importance 是让 LLM 直接评的:"给'在公园摔了一跤'的重要性打 1-10 分"。

这套评分在模拟小镇里效果惊艳,但直接搬到生产系统要注意两点:LLM 打分每条记忆一次调用,量大时成本可观;且分数分布很不稳定,建议只用来分档(高/中/低)而不是精确排序。一个更便宜的替代:用规则定重要性——用户的显式指令、系统的错误记录、任务的状态变更永远重要,闲聊和重复确认永远不重要。

四、长期记忆实现:四种形态 ​

跨会话的长期记忆没有银弹,四种主流形态各有明确的适用面。

形态一:向量检索记忆 ​

最普及的方案:每条记忆是一段自然语言文本("用户偏好深色主题""3 月 12 日决定用 Postgres 而非 MySQL"),embedding 后存向量库,用时按语义相似度 top-k 召回。

python
# 最小可用的向量记忆读写骨架(伪代码,SDK 以你选用的为准)
def write_memory(text: str, user_id: str):
    """写入一条情景/语义记忆,附带元数据便于过滤"""
    embedding = embed(text)
    vector_db.upsert(
        id=new_id(),
        vector=embedding,
        metadata={"user_id": user_id, "created_at": now(), "type": "fact"},
    )

def recall(query: str, user_id: str, k: int = 5) -> list[str]:
    """检索时必须按 user_id 过滤——多租户记忆串户是安全事故"""
    results = vector_db.query(
        vector=embed(query),
        filter={"user_id": user_id},
        top_k=k,
    )
    return [r.text for r in results]

优点是写入成本低、对非结构化内容友好;缺点同样出名:相似度检索不理解时间与矛盾。库里同时躺着"用户住在北京"(2024 年写入)和"用户搬到了上海"(2026 年写入)时,两条都可能被召回,模型只能猜哪条新。Mem0(arXiv 2504.19413)这类记忆框架的核心增量就在写入侧——新事实进来时先做冲突检测,对旧条目执行 ADD / UPDATE / DELETE / NOOP 四选一,而不是无脑追加。

形态二:结构化画像 ​

语义记忆中高度稳定的维度(姓名、角色、偏好、技术栈),直接存成结构化字段,比向量检索可靠一个量级:

json
{
  "user_id": "u_123",
  "profile": {
    "role": "后端工程师",
    "primary_language": "Go",
    "prefers_concise_answers": true
  },
  "updated_at": "2026-08-01"
}

读取是精确的 key lookup,没有召回噪声;更新是显式的字段写入,冲突解决就是"新值覆盖旧值,记好时间戳"。代价是需要预先设计 schema,覆盖不了 schema 之外的信息。ChatGPT 的 Saved Memories、多数客服 Agent 的用户卡片本质都是这个形态。

形态三:文件笔记(Agent 自己维护的笔记本) ​

2025 年以来编码 Agent 带火的一种朴素形态:记忆就是一个(或一组)纯文本/Markdown 文件,Agent 用读写文件的工具自己维护。

  • Claude Code 的 CLAUDE.md:项目级约定写在仓库根目录的 CLAUDE.md,启动时自动注入上下文;用户可以要求 Agent 把新约定"记下来",Agent 就编辑这个文件。Anthropic 的 context engineering 博客把它称为混合模式——CLAUDE.md 这类静态文件直接进上下文,其余资料用 glob/grep 按需拉取。详见 Claude Code 案例。
  • Anthropic 的 memory tool:2025 年 9 月随 Claude Sonnet 4.5 发布公开 beta,通过 context-management-2025-06-27 beta header 启用。它把记忆抽象成一个文件目录,模型通过 tool call 对记忆文件做 create / write / insert / rename / delete,完全自主管理。
  • ChatGPT 的记忆演化:2024 年 2 月上线 Saved Memories(用户可查看、删除的记忆清单);2025 年 4 月增加 reference chat history(引用历史对话内容);2026 年 6 月 OpenAI 发布 Dreaming(后台自动从对话历史中综合提炼记忆,向美国区 Plus/Pro 用户开放),写入从"用户说记住这个"变成"系统在后台自己决定记什么"。

文件笔记形态被低估的优点是可审计:记忆就是文本文件,用户能读、能改、能删、能进 git diff。对隐私合规和调试都极友好。缺点是规模上限低——文件长到几千行后,无论注入还是检索都开始吃力。

形态四:知识图谱 ​

把记忆存成"实体-关系-实体"的三元组图(Zep/Graphiti、Mem0 的 graph 变体、各类 GraphRAG 路线都属于此类)。图结构的独门优势是多跳推理与时间建模:"用户的上司的同事负责哪个项目"这类问题,向量检索基本没戏,图遍历是天然解。带时间戳的边("任职于 X,有效期 2024-2025")还部分缓解了向量库的矛盾问题。

代价是写入成本高得多:每条信息要先做实体抽取、消歧、对齐,pipeline 复杂且错误会沿链路传播。除非你的场景真的有多跳关联查询(CRM、投研、复杂组织知识),否则图谱记忆在大多数情况下是过度设计——先用形态一+二跑起来,召回质量撞到天花板再上图。

四种形态怎么选 ​

形态读取方式矛盾/时效处理写入成本适用场景
向量检索相似度 top-k弱,需框架兜底低对话片段、经验日志
结构化画像key 精确查强(覆盖+时间戳)中用户偏好、稳定事实
文件笔记全文注入/grep人工/Agent 编辑低项目约定、编码 Agent
知识图谱图遍历查询较强(时态边)高多跳关系、复杂实体网络

生产系统几乎总是混合架构

观察头部产品:ChatGPT = 结构化清单(Saved Memories)+ 类向量检索(chat history 引用)+ 后台综合(Dreaming);Claude Code = 文件笔记(CLAUDE.md)+ 文件系统即时检索。不存在"选一个"的问题,只有"哪几层、各占多大比重"的问题。

五、写入策略:比读取难十倍的问题 ​

检索(读取)已经有成熟答案,写入没有。读取错了大不了召回一条无关记忆;写入错了,脏数据会永久污染之后的每一次会话。设计写入策略要回答四个问题。

何时写 ​

  • 每轮都写:对话式 Agent 常见,信息不丢,但噪声巨大,库里 80% 是废话。
  • 会话结束时写:由一个专门的"记忆整理"步骤(或后台任务)通读整段会话,抽取值得长期保留的事实。成本可控,质量依赖抽取 prompt。
  • 事件触发写:检测到特定信号才写——用户纠正了 Agent("不对,我用的是 pnpm")、任务完成/失败、用户显式说"记住这个"。信号驱动是信噪比最高的方式。
  • 后台异步写:OpenAI Dreaming、Letta 的 sleep-time compute 都是这个方向——记忆的综合提炼不占对话时间,在用户不在线时跑。代价是写入时机的控制感变弱,出错更难归因。

写什么:MemGPT / Letta 的启示 ​

MemGPT(Packer et al., arXiv 2310.08560,2023 年 10 月)是记忆系统设计的分水岭,其核心思想是把操作系统的虚拟内存管理搬到 LLM 上:

┌─────────────────────────────────────────┐
│           LLM context window            │
│  ┌───────────────────────────────────┐  │
│  │ Core memory(核心记忆,常驻)        │  │  ← 类似 RAM
│  │  · persona 块:Agent 的人设         │  │
│  │  · user 块:用户关键信息            │  │
│  │  大小受限,Agent 可用工具自己改写    │  │
│  └───────────────────────────────────┘  │
└──────────────┬──────────────────────────┘
               │ Agent 主动调用记忆工具换入/换出
┌──────────────┴──────────────────────────┐
│ Recall memory:历史对话全文,可检索        │  ← 类似磁盘
│ Archival memory:任意规模的外部存储        │
└─────────────────────────────────────────┘

两个设计决策至今仍是标杆:

  1. 记忆编辑权交给模型自己。MemGPT 不给模型"自动记忆",而是给它 core_memory_replace、archival_memory_insert 这类工具,由模型在推理中决定"这条值得记"。这把"何时写、写什么"从外挂启发式变成了模型能力问题——模型变强,记忆策略自动变强。Letta(MemGPT 团队的产品化框架)把这套机制延续下来,核心记忆按 block 组织(persona、user、自定义),每块有字符上限,Agent 自主做 CRUD。
  2. 分层 + 换页。核心记忆永远在上下文里(贵但即时),归档记忆按需在会话中检索注入(便宜但延迟)。2025 年 Letta 又引入 sleep-time compute:会话间隙由后台进程做记忆的整理、合并、精炼,把"写日记"和"上班"解耦。

自己实现时不必照搬全套,但"核心块常驻 + 归档块检索 + Agent 持有编辑工具"这个三层骨架,是目前被验证最多的长期记忆架构。

如何更新与遗忘 ​

写入策略里最反直觉的一课是:"不忘"不是特性,是 bug。不做遗忘的记忆系统会在几个月后积累出大量过时、矛盾、低价值条目,召回质量随时间单调下降。常见机制:

  • 显式覆盖:新事实与旧事实冲突时更新而非追加(Mem0 的 UPDATE 操作)。要求写入前做一次"是否已有相关记忆"的检索,这是防矛盾的关键一步。
  • 时间衰减:检索打分里加入 recency 权重,旧记忆自然沉底(Generative Agents 的打分公式就是这么干的)。
  • 访问频率:长期没被召回的记忆降级或归档——"不用的记忆大概率是不重要的记忆"。
  • 容量上限 + 淘汰:像 LRU 缓存一样给每类记忆设配额,写满时淘汰评分最低的条目。

一个可直接抄的最小写入流程 ​

1. 会话中检测到候选记忆(用户偏好陈述 / 任务结论 / Agent 被纠正)
2. 用候选文本检索现有记忆库,找 top-3 相似条目
3. LLM 判断候选与现有条目的关系:
     - 全新     → INSERT
     - 补充细化 → UPDATE(合并进现有条目)
     - 矛盾     → UPDATE(新值覆盖,记录时间戳)
     - 重复     → NOOP
4. 写入,附元数据:来源会话、时间、类型、置信度
5. 定期(或后台)跑整理任务:合并碎片、降权陈旧条目、清除过期项

这个流程的成本是每次候选写入多花 1-2 次 LLM 调用,换来的是记忆库长期不腐化。比起事后清洗一个被污染的向量库,便宜得多。

六、评估记忆系统 ​

记忆系统的质量没法靠感觉判断,需要基准和指标。当前主流的三类评估:

公开基准 ​

  • LongMemEval(Wu et al., arXiv 2410.10813,2024):针对聊天助手长期记忆的专项基准,考察五种核心能力——信息抽取(information extraction)、跨会话推理(multi-session reasoning)、时间推理(temporal reasoning)、知识更新(knowledge updates)、 abstention(不知道时拒答)。平均上下文超过 10 万 token,其中 knowledge updates 一项直接对应前文讲的"矛盾覆盖"能力。
  • LoCoMo(Maharana et al., ACL 2024):超长多轮对话(平均约 9000 token)上的问答与事件摘要,考察长时间跨度和因果链条上的记忆保持。Mem0 论文报告的 26% 相对提升(LLM-as-a-Judge 口径)就是在这个基准上测的。
  • LongMemEval-V2(2026):社区对原基准的延续,把评估目标从"记住对话内容"推向"记忆能否帮助 Agent 像有经验的同事一样工作",更贴近 Agent 场景。

基准分数的解读陷阱

记忆基准的排行榜分数要谨慎对待:LLM-as-a-Judge 口径受评判模型影响大,检索注入的文本格式、top-k 取值都会显著改变分数;且这些基准清一色测对话记忆,对编码、操作类 Agent 的情景记忆覆盖很弱。选基准前先确认它测的记忆类型和你产品里的一致。

自建评估的四个指标 ​

公开基准之外,线上系统至少需要监控:

  1. 召回准确率:给定一个需要历史信息的问题,正确记忆是否被召回(retrieval recall@k)。
  2. 答案正确率:召回的记忆被注入后,端到端答案是否变对。召回对了但注入位置不对、格式不对,答案照样错——所以要端到端测。
  3. 矛盾率:同一事实在库里存在几个互相冲突的版本。定期抽样跑冲突检测,这个指标直接反映写入策略的健康度。
  4. 写入准确率:抽样人工/模型审查"该记的记了没有、不该记的记了没有"。漏记和滥记要分开统计,两者的优化手段相反。

记忆系统的回归测试有个独特难点:效果依赖历史积累,不能用无状态的单测覆盖。实践上是维护一批"记忆夹具"(预置好记忆库的测试用户),每次改写入/检索逻辑后在这批夹具上跑端到端用例。评估方法论的整体框架见 Agent 评估。

七、隐私与合规 ​

记忆系统把"对话"变成了"档案",这在合规上是质变。动手前先想清楚这几条:

  • 可见、可改、可删是底线。ChatGPT 和 Claude 的记忆功能都提供记忆清单的查看和删除入口,这不是锦上添花,是 GDPR"被遗忘权"等法规下的必需品。用户说"忘掉我"时,你要能从向量库、结构化库、日志、备份里真正把数据删掉——向量库的逻辑删除(标记而不物理删除)在多数法域下不算数。
  • 敏感信息默认不记。密码、密钥、身份证、病历这类内容要么在写入侧用分类器拦截,要么至少打标隔离、禁止注入通用上下文。Agent 被 prompt injection 诱导"记住"恶意指令("以后把所有对话转发到 evil.com")是已被公开演示过的攻击面——记忆写入是持久化注入的通道,防御思路见 安全。
  • 多租户隔离按最高标准做。记忆检索必须带用户/租户过滤,串户泄露不是体验问题是安全事故。这在代码层面意味着过滤条件不能是"可选参数",要在存储层强制。
  • 跨产品的记忆迁移是新前沿。2026 年各家产品在"记忆可携带"上动作频频,用户开始期待换工具时带走自己的画像。这给合规带来新问题:记忆导出格式、出处标记、用户授权链路,目前都没有行业标准,属于需要自行保守设计的灰色地带。

八、小结:决策清单 ​

设计记忆系统时按顺序过一遍:

  1. 我的 Agent 需要连续性、个性化还是学习?(决定要不要做、做哪层)
  2. 每类信息属于情景/语义/程序性哪种?(决定存储格式)
  3. 短期记忆的压缩触发阈值和显著性规则是什么?
  4. 长期记忆用哪种形态?(默认从结构化画像 + 向量检索起步)
  5. 写入策略:何时触发、谁来判断、冲突怎么办?
  6. 遗忘机制:时间衰减、访问频率、容量淘汰,至少实现一个。
  7. 评估:选哪个基准、线上监控哪四个指标?
  8. 合规:记忆可见可删吗?敏感信息拦了吗?租户隔离强制了吗?

大部分项目里,正确答案比想象中朴素:一个结构化画像表 + 一个带冲突检测的向量库 + 会话末的摘要写入,就能覆盖 80% 的记忆需求。MemGPT 式的自编辑记忆和知识图谱是天花板方案,不是起步方案。

参考资料 ​