Skip to content

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_size256-512 tokens太小上下文不完整,太大噪音多
chunk_overlap10-20%避免分块截断导致信息丢失
top_k3-5返回太少可能遗漏,太多噪音
retrieval_score_threshold0.7低于此阈值的认为不相关
rerank_top_k20重排序阶段初选数量

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记忆系统索引**

Knowledge4J — Java 知识库