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/