AI Agent 的记忆系统:从上下文窗口到长期记忆

深入拆解 AI Agent 的四种记忆类型、上下文窗口压缩策略、RAG 向量检索原理,以及三种典型失败模式和工程选型建议。

你有没有遇到过这种情况:和 AI 聊了很长的上下文之后,它突然”忘记”了前面说过的事情——不是因为它不聪明,而是因为它的记忆系统到达了物理上限。

记忆是 Agent 区别于普通 LLM 调用的核心能力之一。但”记忆”在工程上远比听起来复杂。


四种记忆类型

认知科学把人类记忆分为工作记忆、情节记忆、语义记忆等类型。AI Agent 的记忆系统有类似的分层:

1. In-context Memory(短期/工作记忆)

最基础的记忆形式——就是模型的上下文窗口(Context Window)

  • 容量:GPT-4 128K tokens,Claude 3.5 200K tokens,Gemini 1.5 Pro 1M tokens
  • 速度:最快,直接参与推理
  • 持久性:,会话结束即消失
  • 本质:把需要”记住”的内容全部塞进 prompt

这是 Agent 的默认记忆模式,也是最大的瓶颈所在。

2. External DB Memory(长期记忆)

把信息持久化到外部存储,需要时检索回来。

  • 向量数据库(Pinecone、Weaviate、Chroma、Qdrant):语义检索
  • 传统数据库(PostgreSQL、Redis):精确查询
  • 文件系统:结构化文档存储

这是 RAG(Retrieval-Augmented Generation)的基础。

3. Episodic Memory(情节记忆)

记录”发生过什么”——具体的交互历史、任务执行轨迹。

类比人类:你不记得所有知识是怎么学到的,但你记得”上周我做了一个项目,遇到了这个问题,用这个方法解决了”。

Agent 的情节记忆通常存储:

  • 过去的对话摘要
  • 任务执行日志
  • 错误和修复记录

4. Semantic Memory(语义记忆)

长期积累的知识和事实,不依附于具体情节。

类比人类:你知道”Python 的 GIL 是什么”,但你不记得是什么时候学的。

Agent 的语义记忆通常是:

  • 微调进模型权重(最彻底,但昂贵)
  • 知识库文档(通过 RAG 访问)
  • 系统提示中的固定知识

上下文窗口:本质限制与压缩策略

即使是 1M tokens 的超长上下文,也有用完的一天。更实际的问题是:长上下文不仅有容量限制,还有推理质量下降的问题。

研究表明,当关键信息被埋在超长上下文的中间时,模型表现会显著变差(“Lost in the Middle”现象)。

常见压缩策略

滑动窗口(Sliding Window)

[系统提示] [最近 N 轮对话] → 超出部分直接丢弃

最简单粗暴。缺点:丢失的信息无法恢复。适合对话连贯性要求不高的场景。

摘要压缩(Summary Compression)

当上下文超过阈值时:
旧对话 → LLM 生成摘要 → 摘要替换原始对话

保留了语义信息,损失了细节。适合长对话的渐进式压缩。

重要性排序(Importance Ranking)

对上下文中的每段信息打分 → 保留高分内容 → 丢弃低分内容

可以基于规则(包含关键词)或模型评分。更精细,但计算开销大。

层级记忆(Hierarchical Memory)

工作记忆(最近 N 轮)
    ↓ 定期 consolidate
情节记忆(摘要 + 关键事件)
    ↓ 提炼
语义记忆(核心知识/偏好)

模拟人类记忆的自然层级。MemGPT 是这一思路的代表实现。


RAG:用向量数据库实现外部记忆

RAG(Retrieval-Augmented Generation)是当前最主流的 Agent 长期记忆方案。

工作原理

写入阶段(Indexing)

原始文档(PDF/网页/代码)
    ↓ 切片(Chunking)
文本块(512 tokens 左右)
    ↓ Embedding 模型
向量(1536 维浮点数组)
    ↓ 写入
向量数据库(存储向量 + 原始文本)

检索阶段(Retrieval)

用户查询:"Python 如何处理并发?"
    ↓ 同一 Embedding 模型
查询向量
    ↓ cosine similarity 计算
向量数据库返回 top-k 最相似文本块
    ↓ 注入上下文
[系统提示 + 检索到的文档 + 用户问题] → LLM

Embedding 的本质

Embedding 把文本映射到高维向量空间,语义相近的文本在向量空间中距离更近

from sentence_transformers import SentenceTransformer

model = SentenceTransformer('BAAI/bge-m3')  # 支持中文的模型

texts = [
    "Python 处理并发的方式",
    "如何用 asyncio 写异步代码",
    "今天天气真好"
]

embeddings = model.encode(texts)
# embeddings[0] 和 embeddings[1] 的余弦相似度会远高于和 embeddings[2]

Cosine similarity 公式:

similarity(A, B) = (A · B) / (|A| × |B|)

值域 [-1, 1],1 表示完全相同,0 表示无关,-1 表示相反。


记忆写入时机:何时 Consolidate

不是所有信息都值得存入长期记忆。关键决策点:

触发条件写入内容存储类型
用户明确说”记住这个”原始信息情节/语义记忆
任务成功完成执行摘要 + 关键决策情节记忆
发现用户偏好/习惯偏好描述语义记忆
上下文窗口达到 70%旧对话摘要情节记忆
遇到错误并修复错误模式 + 修复方法语义记忆

不应该写入:中间推理步骤、临时变量、冗余信息。


三种典型失败模式

失败模式 1:记忆爆炸(Memory Explosion)

症状:把所有东西都写进长期记忆,没有淘汰机制,检索结果越来越噪。

根本原因:缺少重要性评估过期清理机制。

解决:设置 TTL(Time To Live),低相关度内容定期清理;写入时评估重要性得分。

失败模式 2:记忆遗忘(Memory Amnesia)

症状:明明存了信息,需要时却检索不到。

常见原因:

  • Chunking 策略不当(上下文被切断在块边界)
  • 查询和文档的 embedding 语义漂移(问法和存法不一致)
  • top-k 值太小,相关内容排在 k 之后被截断

解决:调整 chunk 大小和重叠度;使用 HyDE(Hypothetical Document Embedding)增强查询;增大 top-k 后用 reranker 精选。

失败模式 3:记忆污染(Memory Poisoning)

症状:错误信息被存入记忆,后续推理被持续误导。

场景:Agent 执行失败但误判为成功,把错误结论写入记忆;用户故意输入误导信息。

解决:写入长期记忆前增加验证步骤;高风险信息标记置信度;支持记忆修正机制。


工程选型:本地 Embedding vs 云端 API

维度本地(sentence-transformers)云端(OpenAI / 智谱 / 硅基流动)
延迟低(GPU 上 <10ms/chunk)高(网络 RTT + 排队,50–200ms)
成本一次性硬件投入按 token 计费
隐私完全本地,数据不出境数据上传第三方
质量中文:BGE-M3 ≈ OpenAI ada-002OpenAI text-embedding-3-large 最强
维护需要自己管理模型更新零维护

推荐组合

  • 隐私敏感 / 本地部署:BAAI/bge-m3 + Qdrant(本地 Docker)
  • 快速原型 / 质量优先:OpenAI text-embedding-3-small + Pinecone
  • 中文场景 + 性价比:智谱 embedding-3 + Chroma
# 本地方案示例
from sentence_transformers import SentenceTransformer
import chromadb

model = SentenceTransformer('BAAI/bge-m3')
client = chromadb.Client()
collection = client.create_collection("agent_memory")

def remember(text: str, metadata: dict):
    embedding = model.encode(text).tolist()
    collection.add(
        documents=[text],
        embeddings=[embedding],
        metadatas=[metadata],
        ids=[f"mem_{hash(text)}"]
    )

def recall(query: str, top_k: int = 5) -> list[str]:
    query_embedding = model.encode(query).tolist()
    results = collection.query(
        query_embeddings=[query_embedding],
        n_results=top_k
    )
    return results['documents'][0]

总结

Agent 的记忆系统是一个工程问题,不只是 API 调用问题。设计时需要回答:

  1. 哪些信息需要长期保存?(重要性评估)
  2. 如何在需要时找到它?(检索策略)
  3. 如何防止记忆腐烂和污染?(生命周期管理)

没有完美的记忆系统,只有适合当前任务的记忆系统。从最简单的滑动窗口开始,按需增加复杂度——这是最务实的工程路径。