三层记忆架构——短期上下文 / 向量长期 / 结构化事实
- 理解为什么 Agent 记忆需要分层,而不是一股脑存进向量库
- 弄清三层记忆各自的边界:短期上下文、向量长期记忆、结构化事实记忆
- 能说出每层"存什么 / 怎么取 / 适合什么场景"
- 了解三层如何协作,以及文件式记忆(下一节)与这三层的关系
你有没有遇到过这种 Agent:问它上周帮你改的那份合同叫什么,它一问三不知;但你要让它精确记住你的企业名称和签约方,它又总是前后矛盾?
问题不是"记忆太少",问题是没分层。
让 Agent 记住东西,不是往里塞一个大数据库那么简单。不同类型的信息,存取方式完全不同——把所有东西都塞向量库,召回慢、精度差;把所有东西都放上下文,token 不够用、费钱还容易跑偏。真实可用的 Agent 记忆,是分三层来设计的。
这节就把这三层架构讲清楚:每层存什么、怎么取、适合什么,以及三层怎么配合工作。
为什么记忆要分层
先讲直觉:人脑的记忆也是分层的。
你现在正在读这句话——这是当下的工作记忆,撑不了太久,但访问最快。昨天和朋友聊的大致内容——这是模糊的长期记忆,细节记不全,但"关键词一触发"就能浮现出来。你的身份证号、公司注册地址——这是精确的事实记忆,不会模糊,你需要的时候可以一字不差地调出来。
Agent 记忆面临同样的问题:
- 上下文窗口是有限的。不可能把所有历史全塞进去,token 贵、模型也会分心。
- 不是所有信息都需要精确。"这次会话里用户问了什么"和"用户的公司注册名是什么",对精确度的要求天差地别。
- 检索方式不一样。有些信息靠语义相似度找("上次我们聊过类似的问题"),有些信息靠精确匹配取("用户的 ID 是 001")。
一套架构解决不了所有问题,所以分层。
第一层:短期记忆(上下文窗口)
存什么
当前这次会话里产生的全部内容:用户发的消息、Agent 的回复、工具调用结果、系统提示。简单说,就是 messages 列表里的内容——你在 上一节 里看到 Agent 为什么要有状态,这就是那个状态的具体载体。
怎么取
直接就在上下文里,模型天然能看到。不需要任何检索操作,也不需要额外的召回步骤。
适合什么
- 当次会话里的来回对话
- 刚刚执行的工具调用结果
- 用户在这次对话里表达的偏好和指令
- 需要"在当前轮次里保持连贯"的所有中间结果
局限
上下文窗口有长度上限(各模型不同,以官方文档为准)。超出后要么截断、要么压缩,早期的对话细节会丢失。跨会话更是完全丢失——下次打开新会话,第一层天然清空。
第二层:向量长期记忆(向量库 + embedding)
这就是 RAG(Retrieval-Augmented Generation) 式的记忆。
存什么
历史会话的摘要、用户上传的文档、过往任务的执行记录、知识库条目——总之是"量大、不确定哪段最相关、靠语义理解来匹配"的信息。
具体操作是:把这些内容切成合适大小的块(chunk),用 embedding 模型转成向量,存进向量数据库(比如 Chroma、Pinecone、Qdrant 等,具体选哪个看你的部署场景)。
怎么取
语义相似度检索。当 Agent 需要回忆历史时,把"当前问题"也转成向量,在向量库里找最相似的几条,把它们拼回文本后注入上下文。
用户问:"上次帮我改的那份合同里,乙方是谁?"
↓ embedding 当前问题
↓ 向量库检索 top-k 相似段落
↓ 找到:上次会话摘要里有"乙方:北京某某科技有限公司"
↓ 注入上下文
↓ Agent 能回答了
这一层通常不是直接"存整个对话",而是先摘要、再存。原始对话太冗余,摘要后既省空间也让 embedding 更干净。
适合什么
- 跨会话的历史记忆("上周我们聊过...")
- 大量文档的知识库查询
- "可能相关"但不确定是哪条的信息
- 模糊语义匹配而非精确查找的场景
局限
向量检索是概率性的,不是精确的。"公司注册地址是什么"这类问题,如果地址被淹没在一大段文本里,召回质量会不稳定。精确、结构化的信息,靠这一层是危险的。
第三层:结构化事实记忆(KV / 表 / 文件)
存什么
确定的、精确的、需要可靠调取的事实:用户 ID、企业名称、用户偏好配置、已完成任务的状态、上次运行的结果编号……这类数据的特点是"一字不能错,必须精确"。
存储形式很灵活:键值对(Redis、字典文件)、关系型数据库里的一张表、本地 JSON 文件,甚至一个简单的 SQLite 数据库都行。关键不在形式,在于可以精确查询。
怎么取
精确匹配查询,不是语义检索。SELECT name FROM users WHERE user_id = 'u001' 或者 profile["company_name"]——要什么取什么,不存在"找到差不多的"这种情况。
适合什么
- 用户画像和偏好(语言偏好、输出格式偏好)
- 任务执行的状态追踪("第 3 步已完成")
- 需要在多次会话间精确保留的关键信息
- 工作流节点的中间结果(比如审批流程走到哪一步了)
局限
存啥要提前设计结构,不够灵活。"这段历史对话里有什么有用的信息"这类模糊问题,结构化存储回答不了。
三层怎么协作
三层不是非此即彼,是同时在线、各司其职。
一个常见的模式是:
- 短期层托底当下:当次对话全程在上下文里,Agent 直接能感知。
- 结构化层保"必须准":会话开始时,从结构化存储取出用户配置、历史状态,注入 system prompt 或工具参数。
- 向量层按需召回:当 Agent 判断需要回忆历史(比如用户提到"上次那个方案"),触发向量检索,把相关片段追加进当前上下文。
┌─────────────────────────────────────────────────┐
│ Agent 当次会话 │
│ │
│ [上下文窗口] │
│ ├── system prompt(含用户配置,来自结构化层) │
│ ├── 当前对话 messages │
│ └── 召回的历史摘要(来自向量层,按需注入) │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 向量库 │ │ 结构化存储 │ │
│ │ (历史/文档) │ │ (用户/状态) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────┘
三句话记住分工:
短期放当下,向量放"可能相关",结构化放"必须准"。
三层对比表
| 维度 | 短期记忆(上下文) | 向量长期记忆 | 结构化事实记忆 |
|---|---|---|---|
| 存什么 | 当次会话消息、工具结果 | 历史摘要、文档、知识库 | 用户属性、状态、精确事实 |
| 怎么取 | 直接在上下文,无需检索 | 语义相似度检索(top-k) | 精确查询(key / SQL) |
| 精确度 | 100%(就在上下文里) | 概率性,召回不保证完整 | 100%(精确匹配) |
| 容量 | 受上下文窗口限制,小 | 可以非常大 | 取决于数据库,可扩展 |
| 跨会话 | 不支持,会话结束即清空 | 支持,持久化存储 | 支持,持久化存储 |
| 适合场景 | 当次连贯对话 | "上次讲过的"、语义搜索 | 用户配置、任务状态 |
| 典型实现 | messages 列表 |
Chroma、Pinecone、Qdrant | Redis、SQLite、JSON 文件 |
| 主要局限 | 容量有限,跨次丢失 | 召回不精确,需要 embedding | 结构需预设计,不灵活 |
和文件式记忆的关系
上面三层是"运行时记忆"的常见分法,但不是唯一架构。
还有一种文件式记忆:把 Agent 的记忆直接写成文件(Markdown、JSON、YAML),Agent 通过读写文件来记忆和回忆。这种方式结构清晰、可读性强、不需要向量库——Hermes agent 就是典型代表。
下一节(4.3) 专门讲文件式记忆怎么做,以及它和这三层相比的优劣。
简单说:文件式记忆是结构化层的一种具体实现,也可以带一点"向量化"——用文件目录做粗粒度索引,用语义搜索做细粒度召回。三层架构是骨架,文件式记忆是其中一种填充方式。
知识库式记忆:第二层的延伸
如果你要给 Agent 接一个公司内部知识库——几百篇产品文档、几年的客服记录——这正是向量长期记忆的标准用法。
4.5 节 会带你做一个完整的 RAG 知识库实战:文档切块、embedding、存 Chroma、检索注入上下文,一套打通。如果你已经理解了三层架构,那节会很顺。
常见问题
Q:我能不能就用第一层,把所有信息都塞进上下文,不用向量库?
可以,而且很多简单场景确实够用。问题在于:当上下文超长,模型注意力会分散,"中间位置"的信息容易被忽视(这个现象有专门研究,叫 lost-in-the-middle)。更实际的问题是 token 成本——上下文越长,每次调用越贵。如果信息量不大、会话不跨次,只用第一层完全没问题;一旦要跨次、要跑大知识库,就得引入后两层。
Q:结构化层和向量层能合用同一个数据库吗?
可以,一些向量数据库(比如 Chroma、Qdrant)支持同时存元数据字段,你可以用精确过滤 + 向量检索组合查询。但逻辑上还是两层:一层做精确匹配("用户 ID = u001"),一层做语义检索("最相关的历史片段")。实现可以合并,概念要分清。
Q:每次 Agent 响应都要检索向量库,会不会很慢?
取决于实现方式。不是每次响应都需要检索——只有 Agent 判断"需要回忆"时才触发。你可以让 Agent 先判断一步("这个问题需要历史记忆吗"),只有判断"是"时才调向量检索工具。这样大多数简单问答走不到检索这步,延迟可控。
Q:向量长期记忆存的是原始对话还是摘要?
建议存摘要,而不是原始对话。原始对话冗余大、embedding 质量差、存储贵。一般做法是:会话结束后,用模型生成一段摘要,存摘要的 embedding;有时候再保存几个关键实体(时间、人名、决策)作为元数据,方便精确过滤。
Q:这套三层架构有现成的框架实现吗?
有,比如 LangChain 的 memory 模块、LlamaIndex 的记忆组件,都按类似的分层实现了封装。但框架会帮你屏蔽细节,建议先手写理解原理,再按需引入框架——用框架出了问题,你得知道是哪一层的事才能排查。
小结
- 记忆分层是必要的,因为不同信息的精确度要求、容量需求、跨会话需求完全不同。
- 三层分工:短期层托当下、向量层存历史、结构化层保精确。
- 三层协作不是串行,而是同时在线——结构化事实在 system prompt 里先注入,向量召回按需触发,短期上下文贯穿整个会话。
- 文件式记忆是结构化层的一种具体实现方式,下一节专门讲。
- 如果要给 Agent 接大规模知识库,去看 4.5 节 RAG 知识库实战。
👉 看看 AI 数字员工落地指南,或了解 数字员工搭建实战课。需要为企业落地方案,欢迎找我们聊 企业服务。