Skip to content

解密 AI 记忆体系:为什么现代 Agent 都在重做上下文系统

>[!tip] 先记住一句话 >AI 不是像人脑一样“天然会记住你”。大多数情况下,所谓 AI 记忆,本质上是系统在下一次提问时,把和当前任务相关的历史信息重新放进模型能看到的上下文里。


一、AI 的记忆和上下文是什么?

很多初学者第一次接触 AI 时,会有一个很自然的感觉:

“我刚刚明明跟它说过,它为什么又忘了?”

这个问题的关键在于,你看到的是一个连续聊天界面,但模型本身处理的是一轮一轮独立的请求

换句话说:

  • 你在页面上看到的是“连续对话”
  • 模型实际接收到的,是“本轮调用时系统发给它的一包信息”

这包信息里如果没有带上历史内容,模型就看不到过去发生了什么。

1. 先不要把 AI 记忆想成人脑记忆

人脑的记忆是自然形成的。
而大模型的“记忆”,通常不是模型自己偷偷记住了你,而是产品系统在背后做了三件事:

  1. 保存历史信息
  2. 判断哪些历史信息还有用
  3. 在你下一次提问时,把有用的信息再发给模型

所以,严格来说:

  • 模型负责“根据当前输入生成回答”
  • 上下文是“模型这一次能看到的全部信息”
  • 记忆系统是“帮模型保存、挑选、取回这些信息的外部机制”

2. 用一个最小例子理解

下面不看完整 API 请求,只看最关键的 messages

第一次提问

你告诉 AI:

json
[
  { "role": "user", "content": "我今年18岁,请记住" }
]

AI 回答:

text
好的,我记住了。

这时候,AI 只是在这一次对话里看到了“18岁”这条信息。

第二次提问

过一会儿你又问:

json
[
  { "role": "user", "content": "我今年多少岁?" }
]

AI 可能回答:

text
我不知道,你刚才没有告诉我。

为什么?因为这一次传给模型的内容里,根本没有“你今年18岁”这条历史信息。

第三次提问

如果你把历史一起带上:

json
[
  { "role": "user", "content": "我今年18岁,请记住" },
  { "role": "assistant", "content": "好的,我记住了。" },
  { "role": "user", "content": "我今年多少岁?" }
]

AI 就能回答:

text
你今年18岁。

原因很简单:这一次模型真的“看见了”前面的历史。

3. 从这个例子里,你应该记住什么?

这个例子至少说明了三件事:

  1. 模型本体不会自动跨请求记住你 每次调用默认都是新的。
  2. 上下文就是模型当前能看到的信息 包括用户提问、历史消息、系统提示词、工具结果、外部检索结果等。
  3. AI 记忆通常不是“模型脑子里多了东西” 而是系统在下一轮把相关信息重新塞回上下文。

4. 用一个生活类比再理解一次

你可以把整个过程想成三部分:

  • 模型像一个临时来答题的人
  • 上下文像你递给他的资料包
  • 记忆系统像替你整理资料的助教 这个“答题的人”本身不会记住昨天的所有事。
    他每次能回答什么,取决于你这次递给他的资料包里有什么。

所以,很多产品里所谓“AI 有记忆”,本质上并不是模型突然拥有了人类式长期记忆,而是系统把“该带回来的历史信息”重新带回来了。

5. 这一章的结论

可以把这几个概念压成一句话:

>AI 的记忆,本质上不是“永久记住聊天记录”,而是“让模型在当前这一轮看到它这次真正需要看到的信息”。


二、为什么现代 Agent 要把记忆设计成分层上下文系统?

如果只是做一个简单问答机器人,保存最近几轮聊天记录,很多时候就够用了。
但 Agent 不一样。

Agent 往往要做的是:

  • 多步骤任务
  • 长周期任务
  • 带工具调用的任务
  • 多角色协作任务
  • 需要跨会话延续状态的任务

这时,“把所有历史一股脑全塞进 prompt(也就是本轮发给模型的输入内容)”很快就会出问题。

>[!tip] 先说结论 >现代 Agent 把记忆做成“分层上下文系统”,不是为了概念高级,而是为了让系统在有限上下文里,稳定拿到最重要的信息,同时避免无关历史干扰当前推理。

1. 如果不分层,会马上遇到什么问题?

问题一:上下文窗口不是无限的

模型虽然能处理很长的输入,但这不代表你可以把所有内容都塞进去。

如果历史越来越长,会出现三个直接问题:

  • 输入越来越贵
  • 响应越来越慢
  • 模型越来越容易抓不住重点

所以系统必须做选择:

  • 最近最关键的内容,保留原文
  • 稍早但还有价值的内容,压缩成摘要
  • 长期稳定的信息,单独存起来,需要时再取

问题二:信息越多,不一定越聪明

很多人直觉上觉得:“记忆越多越好。”

其实不对。
对模型来说,无关信息本身就是噪声

比如用户现在问的是“帮我写 React 页面”,结果你把一大堆和上一次旅游计划、上上次餐饮偏好有关的历史都塞进去,这些内容只会分散模型注意力。

所以现代 Agent 的核心不是“记得多”,而是:

>该出现的信息一定出现,不该出现的信息尽量别出现。

问题三:长任务很容易“越做越偏”

Agent 做长任务时,最怕的不是暂时不会做,而是:

  • 忘了原始目标
  • 重复做已经做过的事
  • 把旧结论和新事实混在一起
  • 中途把关键阶段结果弄丢

这就是为什么长任务里经常要做:

  • 阶段总结
  • 中间结果沉淀
  • 上下文压缩
  • 必要时拉起新的干净上下文继续做

问题四:多 Agent 协作时,不能所有人看所有东西

如果一个系统里有 Planner、Researcher、Coder、Reviewer 多个 Agent,最差的做法就是让所有角色共享全部上下文。

这样会带来:

  • 噪声变多
  • 角色边界变模糊
  • 中间思路互相干扰
  • 整个系统很难控制

所以多 Agent 系统通常会采用:

  • 少量公共记忆共享
  • 每个角色保留自己的局部工作记忆
  • 大体量中间结果放到外部工件里,需要时再引用

问题五:不同信息,本来就适合不同存法

下面几种信息,本质上就不是一类东西:

  • 用户长期偏好
  • 当前会话里的临时偏好
  • 某次任务的中间过程
  • 固定规则和 SOP
  • 文档、代码、表格、报告

如果把它们都塞进同一个桶里,系统后面会越来越难维护。

2. 那“分层”到底是在分什么?

对初学者来说,可以先把 Agent 记忆理解成四层:

层级里面放什么保存多久主要作用
运行时上下文当前任务输入、系统规则、工具权限、环境信息只在本次运行有效告诉模型“现在是什么场景”
短期记忆最近消息、当前计划、工具结果、阶段总结当前会话内有效保证任务连续性
长期记忆用户偏好、项目背景、历史经验、稳定事实跨会话保存让下一次任务还能延续之前的信息
外部工件文档、代码、表格、报告、搜索结果按需长期保存存放大体量内容,避免直接挤占上下文

这个分法背后的逻辑很简单:

  • 不是所有信息都应该和当前问题一起出现
  • 不是所有信息都应该用同一种形式保存
  • 不是所有信息都应该保存一样久

3. 除了分层,还要分类型

现代 Agent 不只是“按层拆开”,还会“按记忆类型分类”。 最常见的三类是:

Semantic memory:事实型记忆

也就是“知道什么”。 比如:

  • 用户喜欢中文回答
  • 这个项目是 React + FastAPI
  • 某个仓库的启动命令是什么

Episodic memory:经历型记忆

也就是“发生过什么”。 比如:

  • 上次修这个 bug 用了哪些步骤
  • 某个 Agent 之前试过哪些工具
  • 某次调研的中间过程和结论是什么

Procedural memory:规则型记忆

也就是“应该怎么做”。 比如:

  • 系统提示词
  • 标准操作流程
  • 审批规范
  • 输出格式要求

用大白话说:

  • 事实型记忆回答“世界是什么样”
  • 经历型记忆回答“以前发生过什么”
  • 规则型记忆回答“现在该怎么做”

4. 分层之后,直接能得到什么好处?

分层不是为了好看,而是为了实用。

它带来的好处通常很直接:

好处一:任务更连续

用户不用每次从头解释自己是谁、正在做什么。
系统也不用每轮都“重新认识”用户和任务。

好处二:长任务更稳定

阶段结果可以被保存、压缩、再利用,不容易随着对话变长而丢失重点。

好处三:成本更低

因为不是把全部历史都塞进去,而是只放当前真正相关的内容。

好处四:多 Agent 更可控

每个角色只看自己该看的信息,协作成本会低很多。

好处五:系统更容易治理

你能知道:

  • 哪条记忆是长期偏好
  • 哪条只是临时状态
  • 哪条应该过期
  • 哪条应该覆盖旧值

这对真实生产系统非常重要。

三、怎么样设计一个记忆系统?

理解“什么是记忆”之后,下一步就是一个更实际的问题:

如果让你自己做一个 Agent,记忆系统该怎么设计?

对入门者来说,最重要的不是一上来就上最复杂的架构,而是先掌握一个清晰的设计顺序:

>[!tip] 设计顺序 >先决定“什么值得记”,再决定“放在哪里”,然后再决定“什么时候写入、怎么取回、怎样防止旧信息干扰新任务”。

1. 第一步:先想清楚“什么值得记”

不是每一句话都值得进入长期记忆。
真正值得记下来的,通常满足下面几个条件里的一个或多个:

  • 跨会话还有价值
  • 对未来任务有帮助
  • 相对稳定,不是一闪而过的信息
  • 对当前用户或任务很重要
  • 来自用户明确表达,而不是模型自己瞎猜

通常值得记的内容包括:

  • 用户长期偏好
  • 用户明确禁忌
  • 项目背景
  • 稳定事实
  • 过去任务里可复用的经验
  • 当前任务必须遵守的重要约束

而下面这些内容就不一定要进长期记忆:

  • 一次性的闲聊
  • 短期临时状态
  • 不确定的猜测
  • 和未来任务大概率无关的噪声信息

2. 第二步:把记忆拆成几个明确的“盒子”

对大多数项目来说,一套能落地的最小设计,至少要有这四个盒子:

盒子一:运行时上下文

放当前这次运行一开始就确定的内容,比如:

  • 系统提示词
  • 当前任务目标
  • 当前约束
  • 工具权限
  • 环境信息 这部分不属于“回忆”,而是当前运行的基础条件。

盒子二:短期记忆

放当前会话里的内容,比如:

  • 最近几轮对话
  • 当前计划
  • 当前步骤结果
  • 当前会话里的临时偏好

它的目标只有一个:让这次任务做得连贯

盒子三:长期记忆

放跨会话仍然有价值的内容,比如:

  • 用户长期偏好
  • 项目背景
  • 历史经验
  • 稳定事实 这部分不能每次全量塞给模型,而是应该按需检索。

盒子四:外部工件

放体积大的内容,比如:

  • 长文档
  • 代码文件
  • 报告
  • 表格
  • 搜索结果

这类内容通常太大,不适合一直放在 prompt(输入上下文)里,更适合按引用读取。

3. 第三步:设计“写入规则”

Memory 系统里最容易犯的错,就是“什么都想记”。

真正好的系统,一定有写入门槛。

一个简单可用的写入规则可以是:

  1. 先从当前对话中抽取候选记忆
  2. 给候选记忆打标签
  3. 去重
  4. 检查冲突
  5. 再决定要不要持久化

常见标签包括:

  • type:这是偏好、事实、经验,还是规则
  • scope:它属于全局、当前会话,还是当前任务
  • importance:重要程度
  • confidence:置信度
  • expires_at:什么时候过期

一个最小的数据结构可以长这样:

json
{
  "content": "本次任务优先使用 React",
  "type": "temporary_preference",
  "scope": "session",
  "importance": 4,
  "confidence": 0.95,
  "expires_at": "2026-03-26T10:00:00Z"
}

这个结构不复杂,但已经足够表达一个关键事实:

>记忆不是一段纯文本而已,它最好带上类型、作用范围、重要性和过期时间。

4. 第四步:设计“读取规则”

Memory 的价值不在“存”,而在“取”。

一个基本的读取流程通常是:

  1. 先理解当前问题要解决什么
  2. 判断这次需要哪类记忆
  3. 从不同通道召回候选记忆
  4. 按规则排序
  5. 只选少量最相关内容注入上下文

这里有两个原则特别重要。

原则一:不要把所有记忆都塞给模型

一般只需要 Top-3Top-8 条最相关记忆。
很多时候,5 条高质量相关记忆,比 20 条历史记录更有用。

原则二:排序不能只看相似度

排序时至少要同时看:

  • 和当前问题像不像
  • 这条记忆重不重要
  • 是新的还是很久以前的
  • 它是长期偏好、临时偏好,还是历史行为

比如,“这次先用中文输出”这种临时偏好,往往应该优先于“用户平时喜欢英文输出”这种长期偏好。

5. 第五步:设计“压缩规则”

短期记忆不能无限增长,所以必须压缩。 最容易理解的一种方式是分层保留:

  • 最近 1 到 5 轮:保留原文
  • 更早的几轮:压成摘要
  • 再早的内容:只保留关键事实

这样做比“一刀切全量总结”更稳,因为你不会一下子丢掉太多细节。

你可以把它理解成:

  • 新内容看细节
  • 旧内容看摘要
  • 更旧内容只看结论

6. 第六步:设计“防污染机制”

真正难的,从来不是“让系统有记忆”,而是“别让旧记忆把当前任务带偏”。

要防止记忆污染,至少要考虑下面几件事:

机制一:时间衰减

越旧的记忆,默认权重越低。
但注意,这不是绝对规则。

例如:

  • “用户对花生过敏”这种长期禁忌,哪怕很久以前写入,也应该保持高优先级
  • “今天想吃日料”这种偏好,过几天就应该自动变弱甚至失效

机制二:区分长期偏好和临时偏好

这两个不能混在一起。 比如:

  • 长期偏好:用户习惯中文回答
  • 临时偏好:这次先输出英文版本

读取时,当前任务里的临时偏好应该优先。

机制三:TTL 和过期机制

很多记忆应该自带有效期。

比如:

  • 当前任务状态:任务结束就失效
  • 今天的临时偏好:24 小时后失效
  • 长期背景信息:长期有效

机制四:用户最新明确指令优先

如果用户明确说:

  • “这次不要按我以前的风格来”
  • “先忽略之前方案”
  • “我改主意了”

那系统应该立即把新指令放到高优先级,而不是还被旧记忆牵着走。

机制五:冲突检测

系统最好能知道,新旧记忆之间到底是:

  • 重复
  • 覆盖
  • 并存
  • 冲突

例如:

  • 旧记忆:用户喜欢粤菜
  • 新记忆:我现在想吃日料

这不一定是“删除旧值”,更像是“当前场景下临时偏好覆盖长期偏好”。

7. 一个新手也能落地的最小方案

如果你现在就要开始做,不想一上来就搞得太复杂,可以先从下面这个方案起步:

最小方案组成

  • system prompt 放角色定义、固定规则、输出要求,也就是每次都要先告诉模型的基础说明
  • session_state 放当前任务目标、当前约束、当前关键决策
  • recent_messages 放最近 6 到 10 轮对话
  • user_profile 放稳定的用户偏好和基础事实
  • memory_notes 放历史经验和重要摘要

每次请求时怎么组装上下文

可以按这个顺序来:

  1. 固定规则
  2. 当前任务目标
  3. 当前会话状态
  4. 最近几轮对话
  5. 从长期记忆里检索出的 3 到 5 条相关内容

这样就已经是一套能工作的“记忆系统”了。

回答结束后再做什么

回答完成后,不要立刻把整轮对话全写进长期记忆。
更合理的是再做一步:

  1. 抽取候选记忆
  2. 判断是否值得长期保存
  3. 分类
  4. 去重
  5. 持久化

这个闭环比“每句话都存”可靠得多。

8. 一次完整请求的闭环流程

把整套系统串起来,大致是这样:

  1. 用户发来新问题
  2. 系统识别当前任务目标和约束
  3. 取出短期记忆里的最近对话和当前状态
  4. 从长期记忆里按需召回候选内容
  5. 对候选记忆做排序和筛选
  6. 组装成当前 prompt 所需的上下文包,也就是这一轮真正发给模型的内容
  7. 模型生成回答
  8. 回答结束后抽取新的候选记忆
  9. 做分类、去重、冲突检测、过期控制
  10. 更新短期记忆和长期记忆

如果这个闭环跑顺了,你的 Agent 才算真正有了“记忆系统”,而不是只有一份越来越长的聊天记录。


四、一句话总结

如果把全文压成一句话,那就是:

>AI 的记忆,不是简单保存聊天记录,而是把“当前问题真正需要的信息”在正确的时间、以正确的形式重新放回上下文。


五、怎么快速判断一套记忆系统靠不靠谱?

不要只看它有没有向量库,也不要只看它能不能“记住你说过的话”。

真正该看的,是这四点:

  1. 它有没有区分短期记忆和长期记忆
  2. 它是不是按需取回,而不是把全量历史都塞进 prompt(输入上下文)
  3. 它有没有压缩、过期、冲突处理这些治理机制
  4. 它能不能支持长任务和多 Agent 协作,而不被上下文膨胀拖垮

满足这些,才算真正进入了现代 Agent 的记忆系统设计。


参考资料

评论区

欢迎留言、补充或勘误。

xiaoba.blog