第十二章 Agent Memory系统¶
⚠️ 时效性说明:本章涉及前沿模型/价格/榜单等信息,可能随版本快速变化;请以论文原文、官方发布页和 API 文档为准。
让Agent"记住"过去、"理解"上下文、"学会"经验
导航: 上一章:从零构建Agent框架 | 下一章:Deep Research Agent | 目录
1. 为什么Agent需要记忆¶
1.1 LLM 的无状态本质¶
大语言模型本质上是一个无状态函数:
每次调用都是独立的——模型不会"记住"上一次对话说了什么。所谓的"多轮对话",其实是把全部历史消息重新发送给模型。
1.2 上下文窗口的局限¶
即便是最先进的模型,上下文窗口也是有限的:
| 模型 | 上下文窗口 | 约等于 |
|---|---|---|
| GPT-4o | 128K tokens | ~300页文本 |
| Claude 3.5 | 200K tokens | ~500页文本 |
| DeepSeek-V3 | 128K tokens | ~300页文本 |
| Gemini 2.0 | 2M tokens | ~5000页文本 |
看似很大,但在实际 Agent 场景中: - 每次工具调用结果可能占 1000+ tokens - 10 轮工具交互就消耗 10K+ tokens - 加上系统提示和工具定义:很快就接近上限
更关键的是:上下文越长,LLM 的注意力越分散("Lost in the Middle" 问题),检索准确率下降。
1.3 记忆 vs 上下文工程的关系¶
| 维度 | 上下文工程 (Context Engineering) | 记忆系统 (Memory System) |
|---|---|---|
| 时间范围 | 单次对话内 | 跨对话、跨任务 |
| 存储位置 | LLM上下文窗口 | 外部存储(向量库、数据库) |
| 管理方式 | 精心选择放入上下文的内容 | 自动存储、检索、遗忘 |
| 关系 | 记忆系统为上下文工程提供素材 | 上下文工程决定何时调用记忆 |
💡 核心洞见:记忆系统的目标不是"记住所有东西",而是在正确的时间提供正确的信息。
2. 记忆系统分类¶
借鉴认知科学,Agent 的记忆可以分为以下五类:
┌─────────────────────────────────────────────────────┐
│ Agent 记忆系统 │
├─────────┬─────────┬──────────┬─────────┬────────────┤
│ 短期记忆 │ 长期记忆 │ 情景记忆 │ 语义记忆 │ 程序记忆 │
│ Working │ Long- │ Episodic │Semantic │ Procedural │
│ Memory │ term │ Memory │ Memory │ Memory │
├─────────┼─────────┼──────────┼─────────┼────────────┤
│ 当前对话 │ 向量库 │ 任务经验 │ 知识图谱 │ 技能/工作流│
│ 缓冲区 │ 持久存储 │ 历史回放 │ 实体关系 │ SOP流程 │
├─────────┼─────────┼──────────┼─────────┼────────────┤
│ 几分钟 │ 永久 │ 永久 │ 永久 │ 永久 │
└─────────┴─────────┴──────────┴─────────┴────────────┘
各类记忆的作用¶
- 短期记忆:当前对话的上下文缓冲区,类似人类的"工作记忆"
- 长期记忆:跨对话的持久化存储,用户偏好、历史结论等
- 情景记忆:过去任务的执行轨迹,"上次我是怎么解决这类问题的"
- 语义记忆:结构化的知识(实体、关系),"张三是公司CEO"
- 程序记忆:学到的技能和流程,"写报告应该先搜索再分析再总结"
3. 短期记忆实现¶
短期记忆是最基础也最常用的记忆类型——管理当前对话的消息历史。
3.1 核心挑战¶
短期记忆需要解决的关键问题:
- Token 预算管理:消息越来越多,如何不超限?
- 信息优先级:哪些消息更重要,应该保留?
- 截断策略:丢弃消息时如何最小化信息损失?
3.2 完整实现¶
"""agent_memory/short_term.py - 短期记忆(工作记忆)"""
from __future__ import annotations
import json
import time
from dataclasses import dataclass, field
from enum import Enum
from typing import Any
import tiktoken
# 同时继承str和Enum:枚举值既是Enum成员又是str,可直接用于字符串比较和JSON序列化
class MessageRole(str, Enum):
SYSTEM = "system"
USER = "user"
ASSISTANT = "assistant"
TOOL = "tool"
@dataclass
class ChatMessage:
"""增强型消息结构"""
role: MessageRole
content: str
timestamp: float = field(default_factory=time.time)
token_count: int = 0
importance: float = 1.0 # 重要性评分 (0-1)
metadata: dict[str, Any] = field(default_factory=dict)
def to_openai_format(self) -> dict[str, str]:
"""转换为OpenAI API格式"""
return {"role": self.role.value, "content": self.content}
class ShortTermMemory:
"""
短期记忆管理器。
实现三种截断策略:
1. FIFO (先进先出) - 最简单
2. 滑动窗口 + 摘要 - 保留首尾,压缩中间
3. 重要性评分 - 优先丢弃低重要性消息
"""
def __init__(
self,
max_tokens: int = 8000,
strategy: str = "sliding_window", # "fifo", "sliding_window", "importance"
encoding_name: str = "cl100k_base",
) -> None:
self.max_tokens = max_tokens
self.strategy = strategy
self._encoder = tiktoken.get_encoding(encoding_name)
self._messages: list[ChatMessage] = []
self._compressed_summary: str = ""
def add(
self,
role: str | MessageRole,
content: str,
importance: float = 1.0,
**metadata: Any,
) -> None:
"""添加消息到短期记忆"""
if isinstance(role, str):
role = MessageRole(role)
token_count = len(self._encoder.encode(content))
msg = ChatMessage(
role=role,
content=content,
token_count=token_count,
importance=importance,
metadata=metadata,
)
self._messages.append(msg)
self._apply_strategy()
def get_messages(self) -> list[dict[str, str]]:
"""获取当前所有消息(OpenAI格式)"""
result = []
if self._compressed_summary:
result.append({
"role": "system",
"content": f"[对话历史摘要]\n{self._compressed_summary}",
})
for msg in self._messages:
result.append(msg.to_openai_format())
return result
@property
def total_tokens(self) -> int:
"""当前总Token数"""
total = sum(m.token_count + 4 for m in self._messages) # +4为每条消息的格式开销Token
if self._compressed_summary:
total += len(self._encoder.encode(self._compressed_summary))
return total
def _apply_strategy(self) -> None:
"""根据策略执行截断"""
if self.total_tokens <= self.max_tokens:
return
if self.strategy == "fifo":
self._strategy_fifo()
elif self.strategy == "sliding_window":
self._strategy_sliding_window()
elif self.strategy == "importance":
self._strategy_importance()
def _strategy_fifo(self) -> None:
"""先进先出:直接删除最旧的消息"""
while self.total_tokens > self.max_tokens and len(self._messages) > 1:
removed = self._messages.pop(0)
def _strategy_sliding_window(self) -> None:
"""
滑动窗口策略:
- 保留第一条消息(通常是system prompt或首次提问)
- 保留最近的N条消息
- 中间部分标记为可压缩
"""
while self.total_tokens > self.max_tokens and len(self._messages) > 2:
# 保护第一条和最后两条
self._messages.pop(1) # 总是删除第二条(最旧的非首条)
def _strategy_importance(self) -> None:
"""重要性策略:优先删除低重要性消息"""
while self.total_tokens > self.max_tokens and len(self._messages) > 1:
# 找到重要性最低的非最后一条消息
min_importance = float("inf")
min_idx = 0
for i, msg in enumerate(self._messages[:-1]):
if msg.importance < min_importance:
min_importance = msg.importance
min_idx = i
self._messages.pop(min_idx)
def set_summary(self, summary: str) -> None:
"""设置压缩摘要"""
self._compressed_summary = summary
def clear(self) -> None:
"""清空短期记忆"""
self._messages.clear()
self._compressed_summary = ""
def get_stats(self) -> dict[str, Any]:
"""获取记忆统计信息"""
return {
"message_count": len(self._messages),
"total_tokens": self.total_tokens,
"max_tokens": self.max_tokens,
"utilization": f"{self.total_tokens / self.max_tokens * 100:.1f}%",
"has_summary": bool(self._compressed_summary),
"strategy": self.strategy,
}
3.3 LLM-based 摘要压缩¶
"""agent_memory/summarizer.py - 对话摘要压缩器"""
from __future__ import annotations
from openai import OpenAI
class ConversationSummarizer:
"""使用LLM对对话历史进行摘要压缩"""
SUMMARIZE_PROMPT = """请将以下对话历史压缩为一段简洁的摘要。
要求:
1. 保留用户的核心需求和关键上下文
2. 保留重要的数据、结论和决策
3. 丢弃寒暄、重复和不重要的细节
4. 控制在150字以内
5. 使用第三人称描述
对话历史:
{conversation}
摘要:"""
def __init__(self, client: OpenAI, model: str = "gpt-4o-mini") -> None:
self.client = client
self.model = model
def summarize(self, messages: list[dict[str, str]]) -> str:
"""
将消息列表压缩为摘要。
Args:
messages: OpenAI格式的消息列表
Returns:
压缩后的摘要字符串
"""
# 格式化对话
conversation = "\n".join(
f"{m['role'].upper()}: {m['content']}" for m in messages
)
prompt = self.SUMMARIZE_PROMPT.replace("{conversation}", conversation)
response = self.client.chat.completions.create(
model=self.model,
messages=[{"role": "user", "content": prompt}],
temperature=0.3, # 低温度保证摘要的准确性
max_tokens=300,
)
return response.choices[0].message.content or ""
def incremental_summarize(
self,
existing_summary: str,
new_messages: list[dict[str, str]],
) -> str:
"""
增量摘要:在现有摘要基础上融入新消息。
比全量重新摘要更省Token。
"""
new_conversation = "\n".join(
f"{m['role'].upper()}: {m['content']}" for m in new_messages
)
prompt = f"""基于现有摘要和新的对话内容,生成更新后的摘要。
现有摘要:
{existing_summary}
新对话:
{new_conversation}
更新后的摘要(150字以内):"""
response = self.client.chat.completions.create(
model=self.model,
messages=[{"role": "user", "content": prompt}],
temperature=0.3,
max_tokens=300,
)
return response.choices[0].message.content or ""
4. 长期记忆实现¶
长期记忆让 Agent 能够跨对话保存和检索信息。核心技术是向量数据库。
4.1 向量检索原理¶
将文本转换为高维向量(embedding),通过余弦相似度找到语义最相关的记忆:
相似度范围为 \([-1, 1]\),值越大表示语义越接近。
4.2 安装依赖¶
4.3 完整实现¶
"""agent_memory/long_term.py - 长期记忆(向量存储)"""
from __future__ import annotations
import hashlib
import json
import time
from dataclasses import dataclass, field
from typing import Any
import chromadb
from chromadb.config import Settings
from openai import OpenAI
@dataclass
class MemoryItem:
"""长期记忆条目"""
content: str # 记忆内容
memory_type: str = "general" # 类型:general, fact, preference, task_result
importance: float = 0.5 # 重要性评分 (0-1)
created_at: float = field(default_factory=time.time)
last_accessed: float = field(default_factory=time.time)
access_count: int = 0 # 被检索次数
metadata: dict[str, Any] = field(default_factory=dict)
@property
def memory_id(self) -> str:
"""基于内容生成唯一ID"""
# 注意:MD5用于生成非安全用途的内容ID是可以的,但如需更强的唯一性
# 可改用 hashlib.sha256(...).hexdigest()[:16]
return hashlib.md5(self.content.encode()).hexdigest()[:16]
class LongTermMemory:
"""
长期记忆管理器,基于ChromaDB向量数据库。
核心功能:
- 记忆存储与向量索引
- 语义检索(基于余弦相似度)
- 重要性评分
- 记忆衰减与遗忘
"""
def __init__(
self,
collection_name: str = "agent_memory",
persist_dir: str = "./memory_store",
embedding_model: str = "text-embedding-3-small",
openai_api_key: str | None = None,
decay_rate: float = 0.995, # 每次检索后的时间衰减率
) -> None:
self.embedding_model = embedding_model
self.decay_rate = decay_rate
# 初始化OpenAI(用于embedding)
self.openai_client = OpenAI(api_key=openai_api_key)
# 初始化ChromaDB
self.chroma_client = chromadb.PersistentClient(path=persist_dir)
self.collection = self.chroma_client.get_or_create_collection(
name=collection_name,
metadata={"hnsw:space": "cosine"}, # 使用余弦相似度
)
def store(self, item: MemoryItem) -> str:
"""
存储一条记忆。
Args:
item: 记忆条目
Returns:
记忆ID
"""
memory_id = item.memory_id
# 生成embedding
embedding = self._get_embedding(item.content)
# 元数据
metadata = {
"memory_type": item.memory_type,
"importance": item.importance,
"created_at": item.created_at,
"last_accessed": item.last_accessed,
"access_count": item.access_count,
**{k: str(v) for k, v in item.metadata.items()}, # **解包字典推导式:将元数据值转str后合并到外层字典
}
# 存入ChromaDB
self.collection.upsert(
ids=[memory_id],
embeddings=[embedding],
documents=[item.content],
metadatas=[metadata],
)
return memory_id
def retrieve(
self,
query: str,
top_k: int = 5,
memory_type: str | None = None,
min_importance: float = 0.0,
) -> list[dict[str, Any]]:
"""
语义检索相关记忆。
Args:
query: 查询文本
top_k: 返回数量
memory_type: 过滤记忆类型
min_importance: 最低重要性阈值
Returns:
相关记忆列表,按相关性排序
"""
query_embedding = self._get_embedding(query)
# 构建过滤条件
where_filter: dict[str, Any] | None = None
conditions = []
if memory_type:
conditions.append({"memory_type": {"$eq": memory_type}})
if min_importance > 0:
conditions.append({"importance": {"$gte": min_importance}})
if len(conditions) == 1:
where_filter = conditions[0]
elif len(conditions) > 1:
where_filter = {"$and": conditions}
# 执行查询
results = self.collection.query(
query_embeddings=[query_embedding],
n_results=top_k,
where=where_filter,
include=["documents", "metadatas", "distances"],
)
# 整理结果
memories = []
if results["documents"] and results["documents"][0]:
for i, doc in enumerate(results["documents"][0]):
meta = results["metadatas"][0][i] if results["metadatas"] else {}
distance = results["distances"][0][i] if results["distances"] else 0
# 余弦距离转相似度
similarity = 1 - distance
# 应用时间衰减
created_at = float(meta.get("created_at", time.time()))
age_days = (time.time() - created_at) / 86400
decay_factor = self.decay_rate ** age_days
final_score = similarity * decay_factor
memories.append({
"content": doc,
"similarity": similarity,
"final_score": final_score,
"metadata": meta,
})
# 更新访问统计
memory_id = results["ids"][0][i]
self._update_access(memory_id, meta)
# 按综合评分排序
memories.sort(key=lambda x: x["final_score"], reverse=True) # 原地降序排序,最相关记忆排在最前
return memories
def forget(self, min_importance: float = 0.1, max_age_days: float = 90) -> int:
"""
遗忘机制:清除低重要性且长时间未访问的记忆。
Args:
min_importance: 低于此重要性的记忆会被清除
max_age_days: 超过此天数未访问的记忆会被清除
Returns:
清除的记忆数量
"""
cutoff_time = time.time() - (max_age_days * 86400)
# 获取所有记忆
all_records = self.collection.get(
include=["metadatas"]
)
ids_to_delete = []
if all_records["ids"]:
for i, memory_id in enumerate(all_records["ids"]):
meta = all_records["metadatas"][i] if all_records["metadatas"] else {}
importance = float(meta.get("importance", 0.5))
last_accessed = float(meta.get("last_accessed", time.time()))
if importance < min_importance and last_accessed < cutoff_time:
ids_to_delete.append(memory_id)
if ids_to_delete:
self.collection.delete(ids=ids_to_delete)
return len(ids_to_delete)
def get_stats(self) -> dict[str, Any]:
"""获取长期记忆统计"""
count = self.collection.count()
return {
"total_memories": count,
"collection_name": self.collection.name,
"decay_rate": self.decay_rate,
}
def _get_embedding(self, text: str) -> list[float]:
"""调用OpenAI Embedding API"""
response = self.openai_client.embeddings.create(
model=self.embedding_model,
input=text,
)
return response.data[0].embedding
def _update_access(self, memory_id: str, current_meta: dict) -> None:
"""更新记忆的访问时间和次数"""
access_count = int(current_meta.get("access_count", 0)) + 1
self.collection.update(
ids=[memory_id],
metadatas=[{
**current_meta, # **解包保留原有元数据,仅覆盖更新访问时间和次数
"last_accessed": time.time(),
"access_count": access_count,
}],
)
4.4 记忆重要性评分¶
不是所有信息都值得记住。用 LLM 自动评估记忆的重要性:
"""agent_memory/importance.py - 记忆重要性评估"""
from openai import OpenAI
class ImportanceScorer:
"""使用LLM评估记忆的重要性"""
SCORING_PROMPT = """请评估以下信息对于AI助手的长期价值,给出0到1之间的重要性评分。
评分标准:
- 1.0: 极其重要(用户的核心偏好、关键决策、重要事实)
- 0.7: 比较重要(有用的上下文、中期相关的信息)
- 0.4: 一般重要(可能未来有用的细节)
- 0.1: 不太重要(临时性信息、寒暄、可轻易再获取的内容)
信息内容:
{content}
请只返回一个0到1之间的数字,不要有其他内容。"""
def __init__(self, client: OpenAI, model: str = "gpt-4o-mini") -> None:
self.client = client
self.model = model
def score(self, content: str) -> float:
"""
评估一段内容的重要性。
Returns:
0-1之间的重要性评分
"""
prompt = self.SCORING_PROMPT.replace("{content}", content)
response = self.client.chat.completions.create(
model=self.model,
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
max_tokens=10,
)
try:
score = float(response.choices[0].message.content.strip())
return max(0.0, min(1.0, score))
except (ValueError, AttributeError):
return 0.5 # 默认中等重要性
5. 情景记忆与经验学习¶
情景记忆让 Agent 能够从过去的任务执行经验中学习,避免重复犯错。
5.1 核心思想¶
┌──────────────────────────────────────────┐
│ 情景记忆工作流 │
│ │
│ 任务执行 ──→ 记录轨迹 ──→ 评估结果 │
│ │ │
│ ┌─────────┴────────┐ │
│ ▼ ▼ │
│ 成功经验 失败教训│
│ │ │ │
│ ▼ ▼ │
│ 存入记忆库 存入记忆库│
│ │ │ │
│ └────────┬─────────┘ │
│ ▼ │
│ 下次类似任务时 │
│ 检索相关经验 │
│ 作为Few-shot示例 │
└──────────────────────────────────────────┘
5.2 实现¶
"""agent_memory/episodic.py - 情景记忆(经验回放)"""
from __future__ import annotations
import json
import time
from dataclasses import dataclass, field
from typing import Any
from .long_term import LongTermMemory, MemoryItem
@dataclass
class Episode:
"""一次完整的任务执行记录"""
task: str # 任务描述
steps: list[dict[str, Any]] # 执行步骤
result: str # 最终结果
success: bool # 是否成功
duration_seconds: float = 0.0 # 耗时
reflection: str = "" # 反思总结
timestamp: float = field(default_factory=time.time)
def to_text(self) -> str:
"""将情景转为文本(用于存储和检索)"""
status = "✅成功" if self.success else "❌失败"
steps_summary = "\n".join(
f" Step {i+1}: {s.get('action', 'think')} → {s.get('result', '')[:100]}"
for i, s in enumerate(self.steps)
)
return (
f"任务: {self.task}\n"
f"状态: {status}\n"
f"步骤:\n{steps_summary}\n"
f"结果: {self.result[:200]}\n"
f"反思: {self.reflection}"
)
class EpisodicMemory:
"""
情景记忆管理器。
功能:
- 记录任务执行轨迹
- 检索相似任务的历史经验
- 提取成功/失败模式
- 动态生成Few-shot示例
"""
def __init__(self, long_term_memory: LongTermMemory) -> None:
self.ltm = long_term_memory
def save_episode(self, episode: Episode) -> str:
"""保存一次任务执行经验"""
item = MemoryItem(
content=episode.to_text(),
memory_type="episode",
importance=0.8 if episode.success else 0.6,
metadata={
"task": episode.task,
"success": str(episode.success),
"step_count": len(episode.steps),
"duration": episode.duration_seconds,
},
)
return self.ltm.store(item)
def recall_similar(
self,
current_task: str,
top_k: int = 3,
success_only: bool = False,
) -> list[dict[str, Any]]:
"""
检索与当前任务相似的历史经验。
Args:
current_task: 当前任务描述
top_k: 返回数量
success_only: 是否只返回成功的经验
"""
results = self.ltm.retrieve(
query=current_task,
top_k=top_k * 2, # 多检索一些,后面过滤
memory_type="episode",
)
if success_only:
results = [
r for r in results
if r["metadata"].get("success") == "True"
]
return results[:top_k]
def generate_few_shot_examples(
self,
current_task: str,
max_examples: int = 2,
) -> str:
"""
根据历史经验动态生成Few-shot示例。
Returns:
格式化的Few-shot示例文本
"""
similar_episodes = self.recall_similar(
current_task, top_k=max_examples, success_only=True
)
if not similar_episodes:
return ""
examples = ["以下是类似任务的成功经验供参考:\n"]
for i, ep in enumerate(similar_episodes, 1):
examples.append(f"--- 经验 {i} ---")
examples.append(ep["content"])
examples.append("")
return "\n".join(examples)
class ReflectionEngine:
"""
反思引擎:在任务完成后进行自我反思,
提取可复用的经验和教训。
"""
REFLECTION_PROMPT = """分析以下任务执行过程,提取关键经验:
任务: {task}
执行结果: {result}
是否成功: {success}
执行步骤:
{steps}
请简洁总结:
1. 哪些策略有效?
2. 哪些步骤可以改进?
3. 下次遇到类似任务的建议。
总结(100字以内):"""
def __init__(self, client: Any, model: str = "gpt-4o-mini") -> None:
self.client = client
self.model = model
def reflect(self, episode: Episode) -> str:
"""对一次任务执行进行反思"""
steps_text = "\n".join(
f"Step {i+1}: {json.dumps(s, ensure_ascii=False)}"
for i, s in enumerate(episode.steps)
)
prompt = self.REFLECTION_PROMPT.format(
task=episode.task,
result=episode.result,
success="是" if episode.success else "否",
steps=steps_text,
)
response = self.client.chat.completions.create(
model=self.model,
messages=[{"role": "user", "content": prompt}],
temperature=0.3,
max_tokens=200,
)
reflection = response.choices[0].message.content or ""
episode.reflection = reflection
return reflection
6. 语义记忆与知识管理¶
语义记忆存储结构化的知识——实体、关系、属性——使 Agent 能够进行基于知识的推理。
6.1 知识图谱简介¶
知识图谱由三元组 \((h, r, t)\) 组成: - \(h\) = 头实体 (head entity) - \(r\) = 关系 (relation) - \(t\) = 尾实体 (tail entity)
例如:(张三, 担任, CEO)、(GPT-4, 开发者, OpenAI)
6.2 简化版知识图谱实现¶
"""agent_memory/semantic.py - 语义记忆(知识图谱)"""
from __future__ import annotations
import json
import re
from dataclasses import dataclass, field
from typing import Any
from openai import OpenAI
@dataclass
class Triple:
"""知识三元组"""
head: str # 头实体
relation: str # 关系
tail: str # 尾实体
confidence: float = 1.0 # 置信度
source: str = "" # 信息来源
def __str__(self) -> str:
return f"({self.head}, {self.relation}, {self.tail})"
class KnowledgeGraph:
"""
简化版知识图谱。
使用邻接表存储三元组关系,
支持实体查询和关系推理。
"""
def __init__(self) -> None:
# 邻接表: entity -> [(relation, target, confidence), ...]
self._graph: dict[str, list[tuple[str, str, float]]] = {}
# 全部三元组
self._triples: list[Triple] = []
def add_triple(self, triple: Triple) -> None:
"""添加一个知识三元组"""
self._triples.append(triple)
# 正向关系
if triple.head not in self._graph:
self._graph[triple.head] = []
self._graph[triple.head].append(
(triple.relation, triple.tail, triple.confidence)
)
# 反向索引(方便反向查询)
if triple.tail not in self._graph:
self._graph[triple.tail] = []
self._graph[triple.tail].append(
(f"被{triple.relation}", triple.head, triple.confidence)
)
def query_entity(self, entity: str) -> list[dict[str, Any]]:
"""查询实体的所有关系"""
relations = self._graph.get(entity, [])
return [
{"relation": r, "target": t, "confidence": c}
for r, t, c in relations
]
def query_relation(
self, head: str, relation: str
) -> list[str]:
"""查询特定关系的目标实体"""
relations = self._graph.get(head, [])
return [t for r, t, _ in relations if r == relation] # 列表推导+元组解包:_忽略置信度,筛选匹配关系的目标实体
def find_path(
self, start: str, end: str, max_depth: int = 3
) -> list[list[str]] | None:
"""
查找两个实体之间的关系路径(BFS)。
用于多跳推理。
"""
if start == end:
return [[start]]
from collections import deque
queue: deque[list[str]] = deque([[start]]) # BFS队列,每个元素是一条路径(实体列表)
visited = {start}
paths = []
while queue:
path = queue.popleft()
if len(path) > max_depth * 2: # 路径包含实体和关系交替
continue
current = path[-1]
for rel, target, _ in self._graph.get(current, []):
if target == end:
paths.append(path + [rel, target])
elif target not in visited:
visited.add(target)
queue.append(path + [rel, target])
return paths if paths else None
def to_text(self, entity: str | None = None) -> str:
"""将知识转为文本(用于注入LLM上下文)"""
if entity:
relations = self.query_entity(entity)
lines = [f"关于 [{entity}] 的知识:"]
for r in relations:
lines.append(f" - {r['relation']}: {r['target']}")
return "\n".join(lines)
else:
lines = ["当前知识图谱:"]
for triple in self._triples:
lines.append(f" - {triple}")
return "\n".join(lines)
@property
def entity_count(self) -> int:
return len(self._graph)
@property
def triple_count(self) -> int:
return len(self._triples)
class KnowledgeExtractor:
"""使用LLM从文本中提取知识三元组"""
EXTRACTION_PROMPT = """从以下文本中提取知识三元组(实体-关系-实体)。
文本:
{text}
请以JSON数组格式返回,每个元素包含 head, relation, tail 三个字段:
[
{{"head": "实体A", "relation": "关系", "tail": "实体B"}},
...
]
注意:
- 只提取明确陈述的事实
- 关系用简洁的动词或动词短语表示
- 如果没有可提取的知识,返回空数组 []
只返回JSON数组:"""
def __init__(self, client: OpenAI, model: str = "gpt-4o-mini") -> None:
self.client = client
self.model = model
def extract(self, text: str) -> list[Triple]:
"""从文本中提取知识三元组"""
prompt = self.EXTRACTION_PROMPT.replace("{text}", text)
response = self.client.chat.completions.create(
model=self.model,
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
max_tokens=500,
)
content = response.choices[0].message.content or "[]"
content = content.strip().strip("```json").strip("```").strip()
try:
raw_triples = json.loads(content)
except json.JSONDecodeError:
return []
triples = []
for item in raw_triples:
if all(k in item for k in ("head", "relation", "tail")): # 校验三元组必须包含头实体、关系、尾实体
triples.append(Triple(
head=item["head"],
relation=item["relation"],
tail=item["tail"],
source=text[:100],
))
return triples
6.3 使用示例¶
from openai import OpenAI
client = OpenAI(api_key="sk-xxx")
# 提取知识
extractor = KnowledgeExtractor(client)
triples = extractor.extract(
"OpenAI成立于2015年,由Sam Altman担任CEO。"
"GPT-4是OpenAI开发的大语言模型,于2023年发布。"
)
# 构建知识图谱
kg = KnowledgeGraph()
for t in triples:
kg.add_triple(t)
print(f" 提取: {t}")
# 查询
print(kg.to_text("OpenAI"))
# 输出:
# 关于 [OpenAI] 的知识:
# - 成立于: 2015年
# - CEO: Sam Altman
# - 开发了: GPT-4
# 路径查找
paths = kg.find_path("Sam Altman", "GPT-4")
print(f"Sam Altman → GPT-4 路径: {paths}")
7. MemGPT 架构解析¶
MemGPT 是一种创新的记忆架构,让 LLM 自主管理自己的记忆,类似操作系统的虚拟内存。
7.1 核心思想¶
传统 Agent 的记忆管理是被动的(程序员写好规则)。MemGPT 让 Agent 主动决定何时读写记忆。
┌───────────────────────────────────────┐
│ MemGPT 内存层级 │
│ │
│ ┌─────────────────────────────┐ │
│ │ Main Context │ │
│ │ (LLM 上下文窗口) │ ← 快 │
│ │ 系统提示 + 工作记忆 │ │
│ └──────────┬──────────────────┘ │
│ │ page in/out │
│ ┌──────────▼──────────────────┐ │
│ │ Recall Storage │ │
│ │ (对话历史数据库) │ ← 中 │
│ │ 可搜索的完整聊天记录 │ │
│ └──────────┬──────────────────┘ │
│ │ │
│ ┌──────────▼──────────────────┐ │
│ │ Archival Storage │ │
│ │ (长期知识库) │ ← 慢 │
│ │ 向量数据库 / 文档库 │ │
│ └─────────────────────────────┘ │
└───────────────────────────────────────┘
7.2 关键机制¶
- 自主内存操作:Agent 拥有特殊的"内存工具",如
core_memory_append、archival_memory_search - 页面置换:当上下文满时,自动将旧内容移到 Recall Storage
- 心跳机制:Agent 定期检查是否需要主动回忆某些信息
7.3 简化实现¶
"""agent_memory/memgpt.py - MemGPT风格的记忆管理"""
from __future__ import annotations
from typing import Any
from dataclasses import dataclass, field
from .short_term import ShortTermMemory
from .long_term import LongTermMemory, MemoryItem
@dataclass
class CoreMemory:
"""核心记忆块:始终在上下文中的关键信息"""
persona: str = "你是一个有帮助的AI助手。" # Agent自我描述
human: str = "" # 用户画像
custom_blocks: dict[str, str] = field(default_factory=dict) # 可扩展的自定义记忆块,每实例独立
def to_text(self) -> str:
text = f"[Persona]\n{self.persona}\n\n[Human]\n{self.human}"
for name, content in self.custom_blocks.items():
text += f"\n\n[{name}]\n{content}"
return text
@property
def total_length(self) -> int:
return len(self.to_text())
class MemGPTController:
"""
MemGPT控制器:管理三级记忆层级。
提供给Agent的记忆工具:
- core_memory_append: 向核心记忆追加信息
- core_memory_replace: 替换核心记忆中的内容
- recall_memory_search: 搜索对话历史
- archival_memory_insert: 存入长期知识库
- archival_memory_search: 搜索长期知识库
"""
def __init__(
self,
short_term: ShortTermMemory,
long_term: LongTermMemory,
core: CoreMemory | None = None,
) -> None:
self.short_term = short_term
self.long_term = long_term
self.core = core or CoreMemory()
def core_memory_append(self, section: str, content: str) -> str:
"""向核心记忆的指定部分追加信息"""
if section == "persona":
self.core.persona += f"\n{content}"
elif section == "human":
self.core.human += f"\n{content}"
else:
existing = self.core.custom_blocks.get(section, "")
self.core.custom_blocks[section] = f"{existing}\n{content}".strip()
return f"✅ 已追加到核心记忆 [{section}]"
def core_memory_replace(
self, section: str, old_content: str, new_content: str
) -> str:
"""替换核心记忆中的内容"""
if section == "persona":
self.core.persona = self.core.persona.replace(old_content, new_content)
elif section == "human":
self.core.human = self.core.human.replace(old_content, new_content)
else:
if section in self.core.custom_blocks:
self.core.custom_blocks[section] = \
self.core.custom_blocks[section].replace(old_content, new_content)
return f"✅ 核心记忆 [{section}] 已更新"
def recall_memory_search(self, query: str, top_k: int = 5) -> str:
"""搜索对话历史"""
messages = self.short_term.get_messages()
# 简单的关键词匹配(生产中应使用向量检索)
relevant = [
m for m in messages
if query.lower() in m.get("content", "").lower()
]
if not relevant:
return "未找到相关对话记录。"
result = "\n".join(
f"[{m['role']}] {m['content'][:200]}" for m in relevant[-top_k:]
)
return f"找到 {len(relevant)} 条相关记录:\n{result}"
def archival_memory_insert(self, content: str) -> str:
"""存入长期知识库"""
item = MemoryItem(content=content, memory_type="archival", importance=0.7)
memory_id = self.long_term.store(item)
return f"✅ 已存入长期知识库 (ID: {memory_id})"
def archival_memory_search(self, query: str, top_k: int = 5) -> str:
"""搜索长期知识库"""
results = self.long_term.retrieve(query, top_k=top_k, memory_type="archival")
if not results:
return "长期知识库中未找到相关内容。"
lines = []
for r in results:
lines.append(f"[相似度: {r['similarity']:.2f}] {r['content'][:200]}")
return "\n".join(lines)
def get_memory_tools_schema(self) -> list[dict[str, Any]]:
"""获取所有记忆工具的Schema(用于Function Calling)"""
return [
{
"type": "function",
"function": {
"name": "core_memory_append",
"description": "向核心记忆追加重要信息(用户偏好、关键事实等)",
"parameters": {
"type": "object",
"properties": {
"section": {
"type": "string",
"enum": ["persona", "human"] +
list(self.core.custom_blocks.keys()),
"description": "要追加到的记忆部分",
},
"content": {
"type": "string",
"description": "要追加的内容",
},
},
"required": ["section", "content"],
},
},
},
{
"type": "function",
"function": {
"name": "archival_memory_search",
"description": "搜索长期知识库中的相关信息",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索查询",
},
},
"required": ["query"],
},
},
},
{
"type": "function",
"function": {
"name": "archival_memory_insert",
"description": "将重要信息存入长期知识库",
"parameters": {
"type": "object",
"properties": {
"content": {
"type": "string",
"description": "要存储的内容",
},
},
"required": ["content"],
},
},
},
]
8. 记忆系统集成实战¶
8.1 统一记忆接口¶
"""agent_memory/unified.py - 统一记忆接口"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from .short_term import ShortTermMemory
from .long_term import LongTermMemory, MemoryItem
from .episodic import EpisodicMemory, Episode
from .semantic import KnowledgeGraph, Triple
from .importance import ImportanceScorer
@dataclass
class MemoryQueryResult:
"""记忆查询的统一结果"""
source: str # "short_term", "long_term", "episodic", "semantic"
content: str
relevance: float
metadata: dict[str, Any]
class UnifiedMemory:
"""
统一记忆系统:整合所有记忆模块,
提供单一接口进行记忆存储和检索。
"""
def __init__(
self,
short_term: ShortTermMemory,
long_term: LongTermMemory,
episodic: EpisodicMemory | None = None,
knowledge_graph: KnowledgeGraph | None = None,
importance_scorer: ImportanceScorer | None = None,
) -> None:
self.short_term = short_term
self.long_term = long_term
self.episodic = episodic
self.kg = knowledge_graph
self.scorer = importance_scorer
def remember(
self,
content: str,
memory_type: str = "general",
auto_score: bool = True,
) -> str:
"""
存储一条记忆,自动评估重要性并分配到合适的存储层。
Args:
content: 要记忆的内容
memory_type: 记忆类型
auto_score: 是否自动评估重要性
Returns:
存储结果描述
"""
importance = 0.5
if auto_score and self.scorer:
importance = self.scorer.score(content)
# 根据重要性选择存储策略
if importance >= 0.7:
# 高重要性:同时存入长期记忆
item = MemoryItem(
content=content,
memory_type=memory_type,
importance=importance,
)
memory_id = self.long_term.store(item)
return f"高重要性({importance:.1f}),已存入长期记忆 [{memory_id}]"
else:
# 低重要性:仅保留在短期记忆中
return f"中低重要性({importance:.1f}),保留在短期记忆中"
def recall(
self,
query: str,
top_k: int = 5,
sources: list[str] | None = None,
) -> list[MemoryQueryResult]:
"""
综合检索所有记忆源。
Args:
query: 查询文本
top_k: 每个源返回的最大数量
sources: 指定检索的记忆源,None表示全部
Returns:
按相关性排序的记忆列表
"""
sources = sources or ["long_term", "episodic", "semantic"]
results: list[MemoryQueryResult] = []
# 长期记忆检索
if "long_term" in sources:
lt_results = self.long_term.retrieve(query, top_k=top_k)
for r in lt_results:
results.append(MemoryQueryResult(
source="long_term",
content=r["content"],
relevance=r["final_score"],
metadata=r["metadata"],
))
# 情景记忆检索
if "episodic" in sources and self.episodic:
ep_results = self.episodic.recall_similar(query, top_k=top_k)
for r in ep_results:
results.append(MemoryQueryResult(
source="episodic",
content=r["content"],
relevance=r["final_score"],
metadata=r["metadata"],
))
# 知识图谱检索
if "semantic" in sources and self.kg:
# 简单的实体匹配
kg_results = self.kg.query_entity(query)
if kg_results:
content = self.kg.to_text(query)
results.append(MemoryQueryResult(
source="semantic",
content=content,
relevance=0.8,
metadata={"entity": query},
))
# 按相关性排序
results.sort(key=lambda x: x.relevance, reverse=True) # 按相关性降序,截取前top_k条返回
return results[:top_k]
def build_context(self, query: str, max_tokens: int = 2000) -> str:
"""
为LLM构建记忆上下文:
将检索到的相关记忆格式化为可注入的文本块。
"""
memories = self.recall(query, top_k=10)
if not memories:
return ""
context_parts = ["[相关记忆]"]
current_tokens = 10 # 预估标题token
for mem in memories:
# 粗略估算token(1个中文字≈2 tokens)
estimated_tokens = len(mem.content) * 2
if current_tokens + estimated_tokens > max_tokens:
break
source_label = {
"long_term": "💾",
"episodic": "📝",
"semantic": "🔗",
}.get(mem.source, "📌")
context_parts.append(
f"{source_label} [{mem.source}] (相关性:{mem.relevance:.2f})\n{mem.content}"
)
current_tokens += estimated_tokens
return "\n\n".join(context_parts)
def get_stats(self) -> dict[str, Any]:
"""获取全部记忆系统的统计信息"""
stats: dict[str, Any] = {
"short_term": self.short_term.get_stats(),
"long_term": self.long_term.get_stats(),
}
if self.kg:
stats["knowledge_graph"] = {
"entities": self.kg.entity_count,
"triples": self.kg.triple_count,
}
return stats
8.2 带记忆的 Agent 完整实现¶
"""memory_agent.py - 带完整记忆系统的Agent"""
import os
from openai import OpenAI
from agent_memory.short_term import ShortTermMemory
from agent_memory.long_term import LongTermMemory
from agent_memory.episodic import EpisodicMemory, Episode
from agent_memory.semantic import KnowledgeGraph, KnowledgeExtractor
from agent_memory.unified import UnifiedMemory
from agent_memory.importance import ImportanceScorer
def create_memory_agent() -> None:
"""创建并运行一个带完整记忆系统的Agent"""
api_key = os.getenv("OPENAI_API_KEY", "sk-xxx")
client = OpenAI(api_key=api_key)
# ---- 初始化记忆系统 ----
short_term = ShortTermMemory(max_tokens=6000, strategy="sliding_window")
long_term = LongTermMemory(
collection_name="demo_agent",
persist_dir="./demo_memory",
openai_api_key=api_key,
)
kg = KnowledgeGraph()
episodic = EpisodicMemory(long_term)
scorer = ImportanceScorer(client)
unified = UnifiedMemory(
short_term=short_term,
long_term=long_term,
episodic=episodic,
knowledge_graph=kg,
importance_scorer=scorer,
)
knowledge_extractor = KnowledgeExtractor(client)
print("🧠 记忆增强Agent已启动")
print(" 特殊命令: /stats 查看记忆统计, /remember <内容> 手动记忆")
print(" 输入 quit 退出\n")
while True:
user_input = input("👤 你: ").strip()
if not user_input:
continue
if user_input.lower() in ("quit", "exit"):
break
# 特殊命令
if user_input == "/stats":
import json
print(json.dumps(unified.get_stats(), indent=2, ensure_ascii=False))
continue
if user_input.startswith("/remember "):
content = user_input[10:]
result = unified.remember(content)
print(f"📝 {result}")
continue
# 1. 添加到短期记忆
short_term.add("user", user_input)
# 2. 检索相关记忆
memory_context = unified.build_context(user_input, max_tokens=1500)
# 3. 从对话中提取知识
triples = knowledge_extractor.extract(user_input)
for t in triples:
kg.add_triple(t)
# 4. 构建消息
system_prompt = (
"你是一个拥有长期记忆的智能助手。"
"你能记住用户的偏好和过去的对话内容。\n\n"
)
if memory_context:
system_prompt += memory_context + "\n\n"
system_prompt += "请基于以上记忆和当前对话为用户提供帮助。"
messages = [{"role": "system", "content": system_prompt}]
messages.extend(short_term.get_messages())
# 5. 调用LLM
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
temperature=0.7,
)
answer = response.choices[0].message.content or ""
print(f"🤖 助手: {answer}\n")
# 6. 保存assistant回复
short_term.add("assistant", answer)
# 7. 自动评估并存储重要信息
full_exchange = f"用户问: {user_input}\n助手答: {answer}"
unified.remember(full_exchange, memory_type="conversation")
if __name__ == "__main__":
create_memory_agent()
9. 记忆评估与优化¶
9.1 评估指标¶
| 指标 | 定义 | 计算方式 |
|---|---|---|
| 检索准确率 (Precision@K) | 检索到的K条记忆中有多少是相关的 | \(P@K = \frac{\text{相关记忆数}}{K}\) |
| 检索召回率 (Recall@K) | 所有相关记忆中有多少被检索到 | \(R@K = \frac{\text{被检索的相关记忆数}}{\text{总相关记忆数}}\) |
| 上下文利用率 | 注入的记忆对回答质量的提升 | A/B测试(有记忆 vs 无记忆) |
| Token效率 | 每个Token带来的信息增益 | \(\text{质量提升} / \text{额外Token}\) |
9.2 评估代码¶
"""agent_memory/evaluation.py - 记忆系统评估"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
@dataclass
class RetrievalMetrics:
"""检索质量指标"""
precision_at_k: float
recall_at_k: float
f1_at_k: float
avg_relevance: float
latency_ms: float
def evaluate_retrieval(
retrieved: list[dict[str, Any]],
ground_truth: list[str],
k: int = 5,
) -> RetrievalMetrics:
"""
评估记忆检索质量。
Args:
retrieved: 检索结果列表
ground_truth: 真实相关记忆列表
k: 评估的前K个结果
"""
top_k = retrieved[:k]
# 计算有多少检索结果在ground truth中
relevant_count = sum(
1 for r in top_k
if any(gt in r.get("content", "") for gt in ground_truth) # 检查检索结果是否命中任一真实答案
)
precision = relevant_count / k if k > 0 else 0
recall = relevant_count / len(ground_truth) if ground_truth else 0
f1 = (2 * precision * recall / (precision + recall)) if (precision + recall) > 0 else 0
avg_relevance = sum(r.get("final_score", 0) for r in top_k) / k if k > 0 else 0 # 前k条检索结果的平均相关性分数
return RetrievalMetrics(
precision_at_k=precision,
recall_at_k=recall,
f1_at_k=f1,
avg_relevance=avg_relevance,
latency_ms=0, # 需要在调用时计时
)
def benchmark_memory_strategies(
strategies: list[str],
test_cases: list[dict[str, Any]],
) -> dict[str, RetrievalMetrics]:
"""
对比不同记忆策略的性能。
Args:
strategies: 策略名称列表 ["fifo", "sliding_window", "importance"]
test_cases: 测试用例 [{"query": ..., "ground_truth": [...]}, ...]
"""
results: dict[str, list[RetrievalMetrics]] = {s: [] for s in strategies} # 字典推导式:为每种策略初始化空指标列表
for strategy in strategies:
from .short_term import ShortTermMemory
memory = ShortTermMemory(max_tokens=4000, strategy=strategy)
for tc in test_cases:
# 填充记忆
for msg in tc.get("history", []):
memory.add(msg["role"], msg["content"])
# 评估(此处简化,实际需结合检索模块)
# ...
# 汇总
return {
s: RetrievalMetrics(
precision_at_k=sum(m.precision_at_k for m in metrics) / len(metrics),
recall_at_k=sum(m.recall_at_k for m in metrics) / len(metrics),
f1_at_k=sum(m.f1_at_k for m in metrics) / len(metrics),
avg_relevance=sum(m.avg_relevance for m in metrics) / len(metrics),
latency_ms=sum(m.latency_ms for m in metrics) / len(metrics),
)
for s, metrics in results.items()
if metrics
}
9.3 优化建议¶
| 优化方向 | 具体方法 |
|---|---|
| 检索质量 | 使用 Reranker(如 Cohere Rerank)对初始检索结果二次排序 |
| 存储效率 | 定期运行遗忘机制,清除低重要性/过期记忆 |
| Embedding质量 | 使用领域专用的嵌入模型,或对通用模型进行微调 |
| 响应延迟 | 预计算热门查询的embedding缓存 |
| 上下文注入 | 使用 Contextual Retrieval(给chunk加入上下文前缀再embedding) |
10. 练习与面试题¶
练习¶
练习1:实现记忆衰减可视化(⭐)¶
使用 matplotlib 绘制记忆衰减曲线。给定衰减率 \(\lambda\) 和初始重要性 \(I_0\),绘制:
其中 \(t\) 是天数。观察不同 \(\lambda\) 值(0.99, 0.995, 0.999)的效果。
练习2:实现混合检索策略(⭐⭐)¶
结合关键词检索(BM25)和语义检索(向量相似度),实现 Hybrid Search:
其中 \(\alpha \in [0, 1]\) 控制两种检索的权重。
练习3:实现自动知识图谱更新(⭐⭐⭐)¶
让 Agent 在每次对话后自动提取新知识并更新知识图谱,同时处理知识冲突(如用户更正了之前的信息)。
面试题¶
Q1:Agent的记忆系统和RAG有什么关系和区别?
RAG (Retrieval-Augmented Generation) 是记忆系统的一个子集。RAG 主要解决外部知识检索问题,而 Agent 记忆系统还包括:工作记忆管理、经验学习、知识图谱、自主记忆管理等。可以说 RAG 是长期记忆模块的核心技术,但记忆系统远不止 RAG。
Q2:如何解决 "Lost in the Middle" 问题?
Lost in the Middle 指 LLM 对长上下文中间部分的注意力较弱。解决方案: 1. 将最重要的信息放在上下文的开头和结尾 2. 使用摘要压缩减少上下文长度 3. 分块检索 + Reranker,只注入最相关的片段 4. 使用结构化格式(如 Markdown 标题)帮助模型定位信息
Q3:MemGPT 与传统记忆管理有什么本质区别?
传统方法是程序员定义规则来管理记忆(如滑动窗口、Token 阈值),MemGPT 是让 LLM 自主决定何时读写记忆。本质区别在于:控制权从开发者转移到了 Agent 自身。这带来更高的灵活性,但也增加了 Token 开销(因为需要额外的 function calling 来操作记忆)。
Q4:设计一个记忆系统,让Agent能够学习用户的偏好。要求跨会话保持。
方案: 1. 偏好提取:每次对话后用 LLM 提取用户偏好("喜欢简洁回答"、"偏好Python") 2. 向量存储:将偏好存入 ChromaDB,附带时间戳和置信度 3. 偏好融合:对同类偏好做加权平均,新偏好权重更高 4. 上下文注入:每次对话开始时,检索用户偏好注入 system prompt 5. 偏好更新:用户明确纠正时覆盖旧偏好,隐式变化时缓慢调整置信度
📝 本章小结¶
本章系统学习了Agent Memory系统的核心知识:
- ✅ 理解了LLM的无状态本质以及Agent为什么需要记忆系统
- ✅ 掌握了记忆的五大分类(短期、长期、情景、语义、程序性记忆)
- ✅ 实现了短期记忆管理(FIFO、滑动窗口、重要性保留三种截断策略)
- ✅ 实现了基于LLM的对话摘要压缩(全量摘要与增量摘要)
- ✅ 实现了基于ChromaDB向量数据库的长期记忆系统(含时间衰减与遗忘机制)
- ✅ 实现了记忆重要性评分系统(LLM判断 + 规则辅助)
- ✅ 实现了情景记忆与经验回放机制(含反思引擎)
- ✅ 实现了语义记忆与知识图谱(实体/关系抽取 + BFS路径查找)
- ✅ 理解了MemGPT架构(三级记忆层次:工作记忆/召回存储/归档存储)
- ✅ 实现了统一记忆接口(UnifiedMemory整合所有记忆模块)
- ✅ 完成了记忆增强Agent的完整实现与交互式主循环
- ✅ 掌握了记忆系统评估指标(检索准确率、召回率、NDCG、延迟)
✅ 学习检查清单¶
- 能解释LLM无状态性与Agent记忆系统的必要性
- 能区分五种记忆类型及其在Agent中的应用场景
- 能实现短期记忆的三种截断策略(FIFO/滑动窗口/重要性保留)
- 能实现基于LLM的对话摘要压缩
- 能使用ChromaDB实现长期记忆的存储与语义检索
- 能实现记忆重要性评分与时间衰减机制
- 能实现情景记忆与经验回放机制
- 能用知识图谱实现语义记忆
- 能解释MemGPT的三级记忆架构及其设计思想
- 能将各记忆模块整合为统一接口并构建记忆增强Agent
- 能使用检索准确率、召回率、NDCG等指标评估记忆系统
🔗 下一步¶
下一章我们将学习深度研究Agent,探索如何构建能够自主完成复杂研究任务的Agent。
继续学习: 13-深度研究Agent
祝你学习愉快! 🎉
最后更新日期:2026-02-12 适用版本:AI Agent开发实战教程 v2026