跳转到内容

07 - Agent 记忆与长期知识

07 - Agent 记忆与长期知识

学习目标

本章将带你分析 LlamaIndex 的记忆系统。你将学到:

  • 对话缓冲层(ChatMemoryBuffer、ChatSummaryMemoryBuffer、VectorMemory)
  • 新版 Memory + MemoryBlocks 架构
  • StaticMemoryBlock、VectorMemoryBlock、FactExtractionMemoryBlock
  • InsertMethod 模式
  • 记忆与 Agent 的集成方式
  • Token 窗口管理的陷阱

前置知识


项目实践

记忆分层架构

LlamaIndex 的记忆系统分为两层:对话缓冲(短期)和 Memory Blocks(长期)。

对话缓冲层

ChatMemoryBuffer:最基础的记忆缓冲,使用 token 窗口管理对话历史。

from llama_index.core.memory import ChatMemoryBuffer
memory = ChatMemoryBuffer(token_limit=4000)
memory.put(ChatMessage(role="user", content="你好"))
history = memory.get() # 返回最近的对话,总 token 数不超过 limit

管理策略:当对话超出 token_limit 时,直接截断最早的消息

陷阱:硬截断可能切断正在进行的推理链。如果 Agent 正在进行多步推理(如 Thought-Action-Observation 循环),截断中间的 Thought 可能导致 LLM 丢失推理上下文。

ChatSummaryMemoryBuffer:自动摘要压缩,避免硬截断问题。

from llama_index.core.memory import ChatSummaryMemoryBuffer
memory = ChatSummaryMemoryBuffer(llm=Settings.llm, token_limit=4000)
# 当对话超出限制时,自动调用 LLM 对早期对话生成摘要
# 摘要 + 最近对话 = 压缩后的记忆

代价:每次压缩需要额外一次 LLM 调用。

VectorMemory:通过向量检索动态检索相关记忆。

from llama_index.core.memory import VectorMemory
memory = VectorMemory(index=vector_index, similarity_top_k=5)
# 根据当前查询的语义相似度检索最相关的历史对话

适用场景:长对话历史中,用户可能反复提到不同主题。VectorMemory 按语义相似度检索,而非按时间顺序。

新版 Memory + MemoryBlocks 架构

新版记忆系统引入 Memory 类和可插拔的 MemoryBlock

from llama_index.core.memory import Memory, StaticMemoryBlock, VectorMemoryBlock
memory = Memory()
memory.add_block(StaticMemoryBlock(content="用户偏好:使用中文回答"))
memory.add_block(VectorMemoryBlock(index=vector_index))

三种 MemoryBlock

类型策略适用场景
StaticMemoryBlock固定内容,始终注入用户偏好、系统指令
VectorMemoryBlock向量检索动态获取大量历史知识的语义检索
FactExtractionMemoryBlock从对话中提取事实存储自动记录用户提供的关键信息

InsertMethod 模式:每个 MemoryBlock 定义了如何插入新记忆:

class InsertMethod(Enum):
APPEND = "append" # 追加到末尾
REPLACE = "replace" # 替换旧内容
VECTOR_INDEX = "vector" # 向量索引后检索

记忆与 Agent 集成

Agent 通过 Context.store 管理记忆:

# Agent 在每个推理步骤中
ctx.data["memory"] = memory.get() # 获取当前记忆
ctx.data["memory"].put(new_message) # 追加新消息

记忆注入时机:在 setup_agent 步骤中,Agent 从 Context.store["memory"] 读取对话历史,注入到 LLM 输入中。

多 Agent 记忆隔离

在多 Agent 场景中,每个 Agent 的 memory 键独立存储:

# Context.store 结构
{
"memory:researcher": [...], # 研究者的对话历史
"memory:analyst": [...], # 分析者的对话历史
"state:shared": {...}, # 跨 Agent 共享状态
}

设计原因:不同 Agent 处理不同任务,共享对话历史会导致上下文混乱。需要跨 Agent 传递的信息通过 state 显式传递。

问题与规避

陷阱对策
ChatMemoryBuffer 硬截断丢失推理上下文使用 ChatSummaryMemoryBuffer 代替
ChatSummaryMemoryBuffer 增加 LLM 调用成本仅在对话即将超出限制时触发摘要
VectorMemory 检索结果不相关调整 embedding 模型;使用 metadata 过滤
FactExtractionMemoryBlock 提取的事实不准确在 prompt 中明确提取规则;定期清理低质量事实
多 Agent 记忆混淆使用独立的 memory 键(memory:{agent_name}

设计取舍

Token 窗口 vs 自动摘要

维度Token 窗口 (ChatMemoryBuffer)自动摘要 (ChatSummaryMemoryBuffer)
成本无(纯截断)额外 LLM 调用
信息保留低(丢失早期内容)中(摘要保留关键信息)
推理链完整性可能断裂摘要保留推理脉络
延迟中(摘要需要 LLM 调用)

选择建议:简单对话(<50 轮)用 ChatMemoryBuffer;长对话或多轮复杂推理用 ChatSummaryMemoryBuffer。

参考来源

  • LlamaIndex 记忆源码:llama-index-core/llama_index/core/memory/