02.3 — 记忆管理与检索
定位: Agent 记忆系统的"操作系统"——理解记忆的写入策略、检索策略、更新机制、以及至关重要的遗忘策略 面试高频度: ⭐⭐⭐⭐ 考查方式: 设计题(设计 Agent 的记忆管理系统)、对比题(不同检索策略的优劣)、问题排查(记忆系统性能问题)
一、这是什么?为什么需要它?
是什么
记忆管理 是控制 Agent "记住什么、怎么记、怎么回忆、什么时候忘"的一组策略和机制。它决定了 Agent 记忆系统的效率、准确性和可持续性。
为什么需要记忆管理?
没有管理的记忆:
什么都记 → 存储爆炸
检索不准 → 每次返回大量无关信息
从不遗忘 → 噪音累积、性能下降
更新冲突 → 旧信息覆盖新信息
有管理的记忆:
只记重要的 → 存储高效
精准检索 → 只返回最相关的
智能遗忘 → 保持系统"清醒"
版本管理 → 新旧信息有序排列核心洞察:记忆管理的目标不是"记住所有事",而是"在正确的时间记住正确的事"。
二、原理拆解
2.1 写入策略(什么值得记住?)
不是所有信息都需要存储。写入策略决定了哪些信息会进入长期记忆。
| 策略 | 原理 | 适用场景 |
|---|---|---|
| 全量存储 | 所有交互都记录 | 需要完整审计日志 |
| 重要性筛选 | LLM 评分,只存高分内容 | 日常对话 |
| 摘要压缩 | 压缩多条为一条摘要 | 长会话 |
| 关键事件 | 只存特定类型(决策、错误、反馈) | 任务执行 |
| 用户显式指令 | 用户说"记住这个" | 用户偏好 |
python
# 重要性评分的写入策略
class ImportanceBasedMemory:
def __init__(self, threshold: float = 0.6):
self.threshold = threshold
self.memory_store = []
def should_store(self, content: str, context: dict) -> bool:
importance = self._rate_importance(content, context)
return importance >= self.threshold
def _rate_importance(self, content: str, context: dict) -> float:
"""重要性评分(0-1)"""
criteria = [
"包含明确的用户偏好?",
"包含任务的关键决策?",
"包含错误或成功经验?",
"用户要求记住?",
"对后续任务有参考价值?"
]
# 实际实现中会用 LLM 进行评估
score = llm.call(f"评估以下信息的重要性:{content}\n标准:{criteria}")
return float(score)写入策略的选择原则:
信息密度高(一句话包含很多信息) → 直接存储
信息密度低(闲聊、寒暄) → 不存储
用户明确要求 → 一定存储
关键决策点 → 一定存储
错误和异常 → 一定存储2.2 检索策略(如何找到相关记忆?)
检索策略决定了 Agent 如何从海量记忆中快速找到最相关的信息。
| 策略 | 机制 | 优点 | 缺点 |
|---|---|---|---|
| 向量检索 | 语义相似度搜索 | 理解语义,灵活 | 训练数据偏差 |
| 关键词检索 | BM25 精确匹配 | 精确、可解释 | 无法处理同义词 |
| 混合检索 | 向量 + 关键词加权 | 兼顾语义和精确 | 需调权重参数 |
| 时间检索 | 按时间范围筛选 | 适合"最近"场景 | 单一维度 |
| 图检索 | 知识图谱遍历 | 适合关系查询 | 构建成本高 |
| MMR | 最大边际相关性 | 结果多样性 | 可能遗漏高相关 |
混合检索的最佳实践:
python
def hybrid_retrieve(query: str, top_k: int = 5, alpha: float = 0.5):
"""
alpha=0.5: 语义和关键词权重各半
alpha=0.7: 偏语义理解
alpha=0.3: 偏精确匹配
"""
# 1. 向量检索
vector_results = vector_store.similarity_search(query, k=top_k * 2)
# 2. 关键词检索
keyword_results = bm25_search(query, k=top_k * 2)
# 3. 融合排序
combined = {}
for doc in vector_results:
combined[doc.id] = combined.get(doc.id, 0) + alpha * doc.score
for doc in keyword_results:
combined[doc.id] = combined.get(doc.id, 0) + (1 - alpha) * doc.score
# 4. 返回 Top-K
sorted_ids = sorted(combined, key=combined.get, reverse=True)[:top_k]
return [doc_store[i] for i in sorted_ids]检索质量优化的关键参数:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| chunk_size | 256-512 tokens | 太小上下文不完整,太大噪音多 |
| chunk_overlap | 10-20% | 避免分块截断导致信息丢失 |
| top_k | 3-5 | 返回太少可能遗漏,太多噪音 |
| retrieval_score_threshold | 0.7 | 低于此阈值的认为不相关 |
| rerank_top_k | 20 | 重排序阶段初选数量 |
2.3 更新策略(什么时候更新记忆?)
记忆不是一成不变的——Agent 需要根据新信息更新已有记忆。
| 场景 | 策略 | 实现 |
|---|---|---|
| 新信息补充 | 追加 | 直接新增一条,不修改旧记录 |
| 信息修正 | 版本更新 | 标记旧版本为 superseded,新增版本 |
| 信息强化 | 权重增加 | 多次提及的内容提高检索权重 |
| 信息冲突 | 置信度比较 | 保留置信度高的,标记冲突待确认 |
python
class MemoryUpdater:
def update(self, existing_memories, new_info: str):
analysis = llm.call(f"""
分析新信息和已有记忆的关系:
已有记忆: {existing_memories}
新信息: {new_info}
输出格式:
- "补充": 新信息是已有记忆的补充
- "修正": 新信息修正了旧信息
- "冲突": 新信息和旧信息矛盾
- "无关": 新信息和已有记忆无关
""")
if "补充" in analysis:
return "append"
elif "修正" in analysis:
return "update_with_version"
elif "冲突" in analysis:
return "flag_for_review"
else:
return "store_separately"2.4 遗忘策略(该忘什么?)
遗忘和记忆同样重要。没有遗忘,记忆系统会被噪音淹没。
| 策略 | 机制 | 适用场景 |
|---|---|---|
| 时间衰减 | 旧记忆权重随时间降低 | 通用场景 |
| 容量限制 | 超过上限时淘汰 | 存储有限时 |
| 重要性淘汰 | 淘汰评分最低的 | 保证质量 |
| 显式遗忘 | 用户说"忘掉这个" | 隐私/控制 |
| 一致性淘汰 | 与当前知识矛盾的淘汰 | 知识更新 |
python
# 综合遗忘策略
class ForgettingStrategy:
def __init__(self, max_items: int = 10000, decay_days: int = 90):
self.max_items = max_items
self.decay_days = decay_days
def should_forget(self, memory: dict) -> bool:
reasons = []
# 1. 时间衰减:超过 N 天未使用
days_since_access = (now() - memory["last_accessed"]).days
if days_since_access > self.decay_days:
reasons.append("time_decay")
# 2. 重要性过低
if memory["importance"] < 0.2:
reasons.append("low_importance")
# 3. 已被新版本替代
if memory.get("superseded_by"):
reasons.append("superseded")
return len(reasons) > 0
def make_room(self) -> None:
"""移除最不重要的记忆腾出空间"""
if len(memory_store) <= self.max_items:
return
# 按 (访问频率 * 重要性 / 年龄) 排序,移除最低的
scores = {}
for mem in memory_store:
recency = 1 / (1 + (now() - mem["last_accessed"]).days)
scores[mem.id] = mem["importance"] * recency
to_remove = sorted(scores, key=scores.get)[:len(memory_store) - self.max_items]
for id in to_remove:
del memory_store[id]遗忘策略的对比:
时间衰减:自然的遗忘——像人类一样慢慢忘记
优点:实现简单,效果自然
缺点:可能忘记重要的旧知识
容量限制:确定性的淘汰
优点:存储可控
缺点:可能淘汰未来有用的信息
重要性淘汰:质量优先
优点:保留最有价值的
缺点:重要性评估本身可能不准
推荐:组合使用——时间衰减 + 重要性淘汰 + 容量上限三、图解全景
┌──────────────────────────────────────────────────────────────┐
│ 记忆生命周期管理图 │
│ │
│ ┌─────────┐ │
│ │ 新信息 │ │
│ └────┬────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ 写入策略决策 │ │
│ │ 重要性 ≥ 阈值? │──── 否 ──→ 丢弃 │
│ └──────┬───────┘ │
│ │ 是 │
│ ▼ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ 编码与存储 │───→│ 长期记忆 │ │
│ │ 向量化 + 元数据│ │ 向量数据库/文件 │ │
│ └──────────────┘ └──────────────────┘ │
│ │
│ ┌─────────┐ │
│ │ 检索请求 │ │
│ └────┬────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 检索策略执行 │───→│ 主动遗忘检查 │ │
│ │ 向量/关键词/混合 │ │ 是否应该忘记? │── 是 → 删除 │
│ └──────┬───────────┘ └──────────────────┘ │
│ │ 返回结果 │
│ ▼ │
│ ┌──────────────┐ │
│ │ 重排序+注入 │ │
│ │ Rerank → Prompt │
│ └──────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ 定期维护任务 │ │
│ │ 时间衰减评分 → 容量检查 → 冲突检测 → 压缩 │ │
│ └─────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘四、实战验证
4.1 构建一个完整的记忆管理系统
python
class AgentMemorySystem:
"""完整的 Agent 记忆管理系统"""
def __init__(self):
self.short_term = [] # 短期(in-context)
self.long_term = VectorStore() # 长期(向量数据库)
self.episodic = [] # 情景记忆
self.max_short_term = 20
self.max_episodic = 1000
def write(self, content: str, memory_type: str = "long", importance: float = None):
"""写入记忆"""
if memory_type == "short":
self.short_term.append({"content": content, "time": now()})
self._trim_short_term()
elif memory_type == "long":
if importance is None:
importance = self._estimate_importance(content)
if importance >= 0.5: # 重要性阈值
embedding = embed(content)
self.long_term.add(embedding, content, {"importance": importance})
elif memory_type == "episodic":
self.episodic.append({
"content": content,
"time": now(),
"importance": importance or 0.5
})
self._trim_episodic()
def read(self, query: str, top_k: int = 3) -> list:
"""检索记忆"""
results = []
# 1. 从短期记忆中检索(关键词匹配 + 时间排序)
short_results = self._search_short_term(query, top_k)
results.extend(short_results)
# 2. 从长期记忆中检索(向量搜索)
long_results = self.long_term.similarity_search(query, k=top_k)
results.extend(long_results)
# 3. 从情景记忆中检索(相似事件匹配)
episodic_results = self._search_episodic(query, top_k)
results.extend(episodic_results)
# 4. 重排序
results = self._rerank(results, query)
return results[:top_k]
def forget(self, memory_id: str = None, condition: str = None):
"""显式或条件遗忘"""
if memory_id:
self.long_term.delete(memory_id)
elif condition == "old":
self._forget_old()
elif condition == "low_importance":
self._forget_low_importance()
def _trim_short_term(self):
"""短期记忆截断:压缩早期的内容"""
if len(self.short_term) > self.max_short_term:
old = self.short_term[:-self.max_short_term]
summary = llm.call(f"摘要压缩:{old}")
self.write(summary, "long", importance=0.7)
self.short_term = self.short_term[-self.max_short_term:]
def _trim_episodic(self):
"""情景记忆淘汰"""
if len(self.episodic) > self.max_episodic:
self.episodic.sort(key=lambda x: x["importance"] * self._recency(x["time"]))
self.episodic = self.episodic[-self.max_episodic:]
def maintenance(self):
"""定期维护:遗忘 + 整合 + 压缩"""
self._apply_time_decay()
self._consolidate_similar_memories()
self._enforce_capacity_limits()
# 使用示例
memory = AgentMemorySystem()
memory.write("用户喜欢简洁的回答", "long", importance=0.9)
memory.write("2026-07-15: 用户完成了数据分析项目", "episodic", importance=0.7)
results = memory.read("用户偏好")
print(results)4.2 记忆系统性能优化
bash
# 记忆系统关键指标及优化目标
# 1. 检索延迟
# 目标: < 200ms(含向量检索)
# 优化: 使用 IVFFlat/HNSW 索引, 减小 top_k
# 2. 存储增长率
# 目标: < 1MB/天/用户
# 优化: 提高重要性阈值, 加大压缩力度
# 3. 检索命中率
# 目标: > 80%(检索结果与任务相关)
# 优化: 调优 chunk_size, 使用混合检索
# 4. 注入信息利用率
# 目标: > 60%(注入 prompt 的信息被实际使用)
# 优化: 减少 top_k, 提高检索精度
# 监控脚本示例
watch -n 60 'echo "记忆条数: $(wc -l memory_store/*)";
echo "检索命中率: $(calculate_hit_rate)";
echo "存储大小: $(du -sh memory_store/)";'五、面试视角
| 追问 | 答案要点 |
|---|---|
| Agent 记忆管理的核心挑战? | 三大挑战:信息过载(存储无限增长)、检索质量(大海捞针地找到相关记忆)、记忆一致性(新旧冲突、更新策略) |
| 如何防止 Agent 记忆系统"爆炸"? | 多层次控制:写入过滤器(不存不重要信息)、遗忘策略(定期淘汰)、压缩(合并相似信息)、容量上限(hard limit) |
| 忘记重要信息怎么办? | 多重保障:重要性评分保障高频使用的不被淘汰、用户显式标记"重要"的优先保留、软删除(先标记再不重要再删除)、用户可查回收站 |
| Agent 如何在检索时融合多段记忆? | 重排序 + 去重:先用 MMR 保证多样性、再用 LLM 判断哪些真正有用、最后按时间/逻辑顺序注入 prompt |
| 不同检索策略如何选择? | 语义检索(理解意思)做主力、关键词检索(精确匹配)做补充、时间检索(最近优先)做过滤。混合检索是默认最佳实践 |
| 短期记忆和长期记忆如何配合? | 三层流转:短期积累 → 压缩转长期 → 长期持久化。短期满了就压缩摘要写入长期,检索时从两层同时查 |
📚 相关链接
- **记忆分类与架构** — 四种记忆类型
- **RAG与长期记忆** — RAG 与长期记忆实现
- **感知-行动循环** — 记忆在 Agent 循环中的角色
- **护栏与人类监督** — 记忆的隐私与安全
- ← 返回 **Agent记忆系统索引**