AI Agent记忆持久化:从向量检索到知识图谱

记忆持久化的核心挑战 Agent的会话记忆在对话结束后就消失了。要让Agent"记住"用户偏好、历史交互和学到的知识,需要将记忆持久化到外部存储。如何存储、如何检索、如何遗忘——这是记忆持久化的三大问题。 存储方案对比 方案一:向量数据库 最主流的记忆存储方案: class VectorMemory: def __init__(self, vector_db): self.db = vector_db async def store(self, content, metadata=None): embedding = await self.embed(content) self.db.insert({ "content": content, "embedding": embedding, "metadata": metadata, "timestamp": datetime.now() }) async def retrieve(self, query, top_k=5): query_vec = await self.embed(query) results = self.db.search(query_vec, top_k=top_k) return results 优点: 语义检索、灵活查询 缺点: 缺乏结构化关系、时间感知弱 方案二:关系数据库+摘要 class RelationalMemory: def __init__(self, db): self.db = db async def store_interaction(self, user_id, session_data): # 存储完整交互 self.db.insert("interactions", { "user_id": user_id, "session_id": session_data.id, "summary": await self.summarize(session_data), "key_points": json.dumps(session_data.key_points), "timestamp": session_data.start_time }) async def get_user_context(self, user_id): """获取用户上下文""" interactions = self.db.query( "SELECT * FROM interactions WHERE user_id = ? ORDER BY timestamp DESC LIMIT 10", [user_id] ) return self.build_context(interactions) 优点: 结构化、可精确查询 缺点: 无法语义检索 方案三:知识图谱 class GraphMemory: def __init__(self, graph_db): self.db = graph_db async def store_fact(self, subject, predicate, obj): """存储三元组""" self.db.run( "MERGE (s:Entity {name: $subject}) " "MERGE (o:Entity {name: $object}) " "MERGE (s)-[r:RELATION {type: $predicate}]->(o)", subject=subject, predicate=predicate, object=obj ) async def query_relations(self, entity): """查询实体关系""" return self.db.run( "MATCH (e:Entity {name: $entity})-[r]->(related) " "RETURN e, r, related", entity=entity ) 优点: 关系推理能力强、结构化 缺点: 构建成本高、灵活性低 ...

2026-07-16 · 3 min · 521 words · 硅基 AGI 探索者
Agent记忆系统设计:短期、长期与情景记忆的实现

Agent记忆系统设计:短期、长期与情景记忆的实现

Agent记忆系统:让智能体拥有"记住"的能力 人类的记忆系统是一个精妙的分层结构:工作记忆处理当前任务,长期记忆存储知识和经验,情景记忆记录具体事件。2026年的Agent系统也在向这个方向演进——一个没有记忆的Agent就像一个每天失忆的员工,每次对话都从零开始,无法积累经验、无法理解上下文。 记忆系统三层架构 ┌───────────────────────────────────────────────┐ │ 记忆系统架构 │ ├───────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ Layer 1: 短期记忆 (Working Memory) │ │ │ │ - 当前对话上下文 │ │ │ │ - 当前任务状态 │ │ │ │ - 最近的工具调用结果 │ │ │ │ 容量: ~32K tokens | TTL: 会话结束 │ │ │ └─────────────────────────────────────────┘ │ │ ↓ 溢出压缩 │ │ ┌─────────────────────────────────────────┐ │ │ │ Layer 2: 情景记忆 (Episodic Memory) │ │ │ │ - 具体事件记录(时间、地点、人物) │ │ │ │ - 对话历史摘要 │ │ │ │ - 任务执行日志 │ │ │ │ 容量: 无限 | TTL: 90天衰减 │ │ │ └─────────────────────────────────────────┘ │ │ ↓ 知识提取 │ │ ┌─────────────────────────────────────────┐ │ │ │ Layer 3: 长期记忆 (Long-term Memory) │ │ │ │ - 用户偏好和习惯 │ │ │ │ - 学到的知识和规则 │ │ │ │ - 经验教训 │ │ │ │ - 语义关联 │ │ │ │ 容量: 无限 | TTL: 永久 │ │ │ └─────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────┘ Layer 1: 短期记忆(Working Memory) 短期记忆是Agent在当前会话中保持的上下文信息,主要通过LLM的上下文窗口实现。 ...

2026-06-30 · 6 min · 1188 words · 硅基 AGI 探索者
agent memory implementation

Agent 记忆系统实现:从短期到长期

为什么 Agent 需要记忆 LLM 本身是无状态的——每次调用都是独立的。对话历史塞进 Context Window 是最简单的"记忆",但有致命缺陷:token 成本线性增长、上下文长度有上限、无法跨会话持久化。一个真正有用的 Agent 需要像人一样拥有多层次记忆系统。 四种记忆类型 记忆类型 类比人类 生命周期 存储介质 示例 工作记忆 工作台上的文件 当前任务 Redis/内存 当前对话上下文、临时变量 情景记忆 个人经历 天~月 向量数据库 “用户上周问了XX问题” 语义记忆 知识事实 长期 向量数据库 + 图数据库 “用户是Java开发者” 程序记忆 肌肉记忆 长期 规则库/技能库 “调用API的固定流程” 架构设计 ┌──────────────────────────────────────────────────┐ │ Agent 记忆系统 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 工作记忆 │ │ 情景记忆 │ │ 语义记忆 │ │ │ │ (Redis) │ │(Qdrant) │ │(Qdrant) │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ └──────────────┼──────────────┘ │ │ ▼ │ │ ┌──────────────┐ │ │ │ 记忆管理器 │ │ │ │ (Memory Mgr) │ │ │ └──────┬───────┘ │ │ ▼ │ │ ┌──────────────┐ │ │ │ 程序记忆 │ │ │ │ (规则库) │ │ │ └──────────────┘ │ └──────────────────────────────────────────────────┘ 核心实现 1. 记忆数据结构 from dataclasses import dataclass, field from datetime import datetime from enum import Enum import uuid class MemoryType(Enum): WORKING = "working" EPISODIC = "episodic" SEMANTIC = "semantic" PROCEDURAL = "procedural" @dataclass class Memory: id: str = field(default_factory=lambda: str(uuid.uuid4())) type: MemoryType = MemoryType.EPISODIC content: str = "" embedding: list[float] = field(default_factory=list) metadata: dict = field(default_factory=dict) importance: float = 0.5 # 0-1, 影响遗忘策略 created_at: datetime = field(default_factory=datetime.now) last_accessed: datetime = field(default_factory=datetime.now) access_count: int = 0 decay_factor: float = 1.0 # 随时间衰减 2. 记忆写入 import redis import json from qdrant_client import QdrantClient from qdrant_client.models import Distance, VectorParams, PointStruct class MemoryStore: def __init__(self): self.redis = redis.Redis(host='localhost', port=6379, db=0) self.qdrant = QdrantClient(host='localhost', port=6333) self._init_collections() def _init_collections(self): """初始化向量集合""" for collection in ["episodic", "semantic"]: if not self.qdrant.collection_exists(collection): self.qdrant.create_collection( collection_name=collection, vectors_config=VectorParams(size=1024, distance=Distance.COSINE) ) async def write(self, memory: Memory): """写入记忆""" if memory.type == MemoryType.WORKING: # 工作记忆写入 Redis,设置过期时间 key = f"working:{memory.id}" self.redis.setex( key, 3600, # 1小时过期 json.dumps({ "content": memory.content, "metadata": memory.metadata }) ) elif memory.type in (MemoryType.EPISODIC, MemoryType.SEMANTIC): # 情景/语义记忆写入向量库 self.qdrant.upsert( collection_name=memory.type.value, points=[PointStruct( id=memory.id, vector=memory.embedding, payload={ "content": memory.content, "metadata": memory.metadata, "importance": memory.importance, "created_at": memory.created_at.isoformat(), "last_accessed": memory.last_accessed.isoformat(), "access_count": memory.access_count } )] ) async def search(self, query_vector, memory_type: MemoryType, top_k=5): """检索记忆""" if memory_type == MemoryType.WORKING: # 工作记忆:返回所有未过期的 keys = self.redis.keys("working:*") results = [] for key in keys: data = json.loads(self.redis.get(key)) results.append(data) return results # 向量检索 hits = self.qdrant.search( collection_name=memory_type.value, query_vector=query_vector, limit=top_k, score_threshold=0.7 ) return [hit.payload for hit in hits] 3. 记忆检索与排序 class MemoryRetriever: """记忆检索器:综合相关性、重要性、时效性""" def __init__(self, store: MemoryStore): self.store = store async def retrieve(self, query: str, query_vector: list, context: dict = None) -> list[dict]: # 并行检索三种记忆 import asyncio tasks = [ self.store.search(query_vector, MemoryType.WORKING), self.store.search(query_vector, MemoryType.EPISODIC, top_k=5), self.store.search(query_vector, MemoryType.SEMANTIC, top_k=5), ] working, episodic, semantic = await asyncio.gather(*tasks) # 融合排序 all_memories = [] for mem in episodic + semantic: score = self._compute_score(mem, query_vector) all_memories.append((mem, score)) all_memories.sort(key=lambda x: x[1], reverse=True) # 返回 top-K + 工作记忆 return { "working": working, "long_term": [m[0] for m in all_memories[:5]] } def _compute_score(self, mem, query_vector): """综合评分 = 相关性 × 时效性 × 重要性 × 访问频率""" import numpy as np from datetime import datetime, timedelta # 相关性(向量相似度,假设payload中存了) relevance = mem.get("score", 0.5) # 时效性衰减 created = datetime.fromisoformat(mem["created_at"]) days_old = (datetime.now() - created).days recency = np.exp(-days_old / 30) # 30天半衰期 # 重要性 importance = mem.get("importance", 0.5) # 访问频率(越常访问越重要) access_factor = np.log1p(mem.get("access_count", 0)) return relevance * (0.3 + 0.4 * recency) * importance * (1 + 0.1 * access_factor) 4. 遗忘机制 class ForgettingManager: """遗忘机制:模拟人类遗忘曲线""" async def decay_memories(self): """定期执行,降低旧记忆的重要性""" from datetime import datetime, timedelta cutoff = datetime.now() - timedelta(days=7) # 在向量库中批量更新 self.store.qdrant.set_payload( collection_name="episodic", payload={"decay_factor": 0.8}, # 每次衰减20% filters={ "must": [ {"field": "last_accessed", "range": {"lt": cutoff.isoformat()}} ] } ) async def cleanup_memories(self): """删除重要性低于阈值的记忆""" self.store.qdrant.delete( collection_name="episodic", points_selector={ "filter": { "must": [ {"field": "importance", "range": {"lt": 0.1}}, {"field": "decay_factor", "range": {"lt": 0.3}} ] } } ) 实战建议 重要性评分策略:不要让 Agent 自己打分(LLM 评分不稳定)。用规则:用户明确要求记住的 → 1.0,任务关键信息 → 0.8,普通对话 → 0.3。 ...

2026-06-24 · 3 min · 617 words · 硅基 AGI 探索者
鲁ICP备2026018361号