🧠 Agent 记忆系统完整实现(二):记忆系统架构全景------分层设计与核心模块

🎯 博主简介
CSDN 「新星创作者」 人工智能技术领域博主,码龄5年 ,累计发布
180+篇原创文章,博客总访问量24万+浏览!
🚀 持续更新AI前沿实战知识,专注于 AI 技术实战,多个专栏详细解析,包括:
- 🔥 生产级 RAG 系统--- 架构设计、多路召回、混合检索、生产优化
- 🤖 多 Agent 协作系统 --- Swarm 架构、任务编排、状态管理
- 🔌 MCP 协议 --- 协议规范与深度实现
- ⚡ OpenClaw超详细教程 --- AI 助手框架进阶应用
- ✨ Agent记忆系统 --- 深度解析Agent记忆系统
同时也涉猎计算机视觉、Java 后端与 Spring 生态、Transformer 等深度学习技术。坚持从架构到代码、从原理到部署的实战风格。每篇文章配套代码与扩展资料,欢迎交流探讨。
📱 公众号:
Anyi研习社--- 每天一点AI:资料、笔记、工具、趋势,一起进步。🤝 商务合作 :请搜索关注微信公众号
「Anyi研习社」
系列文章导读
- 第 1 篇:为什么 Agent 需要记忆系统?------从 LLM 的上下文限制说起
- 第 2 篇:记忆系统架构全景------分层设计与核心模块(本文)
- 第 3 篇:记忆编码与向量化------从文本到语义表示
- 第 4 篇:记忆存储引擎选型------向量数据库深度对比
- 第 5 篇:记忆检索算法------从相似度搜索到智能召回
- 第 6 篇:记忆遗忘策略------如何让 Agent "学会遗忘"
- 第 7 篇:实战:从零构建一个完整的 Agent 记忆系统
📋 目录
- [1. 引言:记忆系统架构概览](#1. 引言:记忆系统架构概览)
- [2. 分层设计:五层架构模型](#2. 分层设计:五层架构模型)
- [2.1 感知层(Perception Layer)](#2.1 感知层(Perception Layer))
- [2.2 编码层(Encoding Layer)](#2.2 编码层(Encoding Layer))
- [2.3 存储层(Storage Layer)](#2.3 存储层(Storage Layer))
- [2.4 检索层(Retrieval Layer)](#2.4 检索层(Retrieval Layer))
- [2.5 应用层(Application Layer)](#2.5 应用层(Application Layer))
- [3. 记忆的分类体系](#3. 记忆的分类体系)
- [3.1 按持续时间分类](#3.1 按持续时间分类)
- [3.2 按内容类型分类](#3.2 按内容类型分类)
- [3.3 记忆分类对比表](#3.3 记忆分类对比表)
- [4. 记忆的生命周期](#4. 记忆的生命周期)
- [4.1 编码(Encoding)](#4.1 编码(Encoding))
- [4.2 存储(Storage)](#4.2 存储(Storage))
- [4.3 巩固(Consolidation)](#4.3 巩固(Consolidation))
- [4.4 检索(Retrieval)](#4.4 检索(Retrieval))
- [4.5 遗忘(Forgetting)](#4.5 遗忘(Forgetting))
- [5. 核心模块详解](#5. 核心模块详解)
- [5.1 记忆编码器(Memory Encoder)](#5.1 记忆编码器(Memory Encoder))
- [5.2 存储引擎(Storage Engine)](#5.2 存储引擎(Storage Engine))
- [5.3 检索器(Retriever)](#5.3 检索器(Retriever))
- [5.4 遗忘策略(Forgetting Strategy)](#5.4 遗忘策略(Forgetting Strategy))
- [6. 与 RAG 的关系:互补还是替代?](#6. 与 RAG 的关系:互补还是替代?)
- [7. 主流记忆系统对比](#7. 主流记忆系统对比)
- [7.1 MemGPT](#7.1 MemGPT)
- [7.2 Hindsight](#7.2 Hindsight)
- [7.3 Zep](#7.3 Zep)
- [7.4 memclawz](#7.4 memclawz)
- [7.5 架构对比总表](#7.5 架构对比总表)
- [8. 架构设计最佳实践](#8. 架构设计最佳实践)
- [9. 常见问题 FAQ](#9. 常见问题 FAQ)
- [10. 参考文献](#10. 参考文献)
1. 引言:记忆系统架构概览
在构建具备长期交互能力的 AI Agent 时,记忆系统(Memory System)是核心基础设施之一。与 Stateless 的 LLM 调用不同,一个完整的记忆系统需要解决以下关键问题:
- 信息持久化:如何在多轮对话中保持上下文连贯?
- 信息检索:如何从海量历史信息中快速召回相关内容?
- 信息筛选:如何避免无关信息干扰当前决策?
- 信息遗忘:如何模拟人类的选择性遗忘机制?
本文将深入剖析 Agent 记忆系统的整体架构,从分层设计、记忆分类、生命周期到核心模块实现,为读者呈现一幅完整的记忆系统技术全景图。
1.1 为什么需要分层架构?
记忆系统的复杂性要求我们必须采用分层架构:
| 设计目标 | 分层架构的优势 |
|---|---|
| 关注点分离 | 每层只负责特定功能,降低实现复杂度 |
| 可扩展性 | 可以独立替换或升级某一层实现 |
| 可测试性 | 每层可独立测试,便于单元测试和集成测试 |
| 可维护性 | 清晰的接口定义,便于团队协作和维护 |
1.2 记忆系统整体架构图
👁️ 感知层 Perception Layer
🔄 编码层 Encoding Layer
💾 存储层 Storage Layer
🔍 检索层 Retrieval Layer
🎯 应用层 Application Layer
Agent Core
对话管理
任务规划
语义检索
关键词检索
混合检索
重排序
向量数据库
关系数据库
缓存层
日志存储
文本编码器
多模态编码器
元数据提取
输入解析
意图识别
实体提取
用户输入
2. 分层设计:五层架构模型
Agent 记忆系统采用经典的五层架构模型,数据流从下到上依次为:感知层 → 编码层 → 存储层 → 检索层 → 应用层。
2.1 感知层(Perception Layer)
感知层是记忆系统的"感官",负责接收和预处理原始输入数据。
2.1.1 核心职责
- 输入解析:处理文本、语音、图像等多模态输入
- 意图识别:理解用户当前交互意图
- 实体提取:识别关键实体(人名、地点、时间等)
- 上下文感知:检测对话场景和状态变化
2.1.2 技术实现
python
from dataclasses import dataclass
from typing import List, Dict, Optional, Any
from enum import Enum
import time
class InputType(Enum):
TEXT = "text"
VOICE = "voice"
IMAGE = "image"
MULTIMODAL = "multimodal"
@dataclass
class PerceptionResult:
"""感知层输出结果"""
raw_input: str
input_type: InputType
intent: str
entities: List[Dict[str, Any]]
sentiment: float # -1.0 to 1.0
timestamp: float
metadata: Dict[str, Any]
class IntentClassifier:
"""意图分类器"""
def classify(self, text: str) -> str:
intents = ["query", "command", "greeting", "farewell", "clarification"]
return "query"
class EntityExtractor:
"""实体提取器"""
def extract(self, text: str) -> List[Dict[str, Any]]:
return []
class SentimentAnalyzer:
"""情感分析器"""
def analyze(self, text: str) -> float:
return 0.0
class PerceptionLayer:
"""感知层实现"""
def __init__(self,
intent_classifier=None,
entity_extractor=None,
sentiment_analyzer=None):
self.intent_classifier = intent_classifier or IntentClassifier()
self.entity_extractor = entity_extractor or EntityExtractor()
self.sentiment_analyzer = sentiment_analyzer or SentimentAnalyzer()
def perceive(self,
raw_input: str,
input_type: InputType = InputType.TEXT) -> PerceptionResult:
"""处理原始输入,提取结构化信息"""
intent = self.intent_classifier.classify(raw_input)
entities = self.entity_extractor.extract(raw_input)
sentiment = self.sentiment_analyzer.analyze(raw_input)
metadata = self._extract_metadata(raw_input, entities)
return PerceptionResult(
raw_input=raw_input,
input_type=input_type,
intent=intent,
entities=entities,
sentiment=sentiment,
timestamp=time.time(),
metadata=metadata
)
def _extract_metadata(self, text: str, entities: List[Dict]) -> Dict[str, Any]:
metadata = {
"word_count": len(text.split()),
"has_question": "?" in text or "?" in text,
"has_command": any(word in text.lower() for word in ["请", "帮我", "需要"]),
"entity_count": len(entities),
"topics": []
}
return metadata
# 使用示例
if __name__ == "__main__":
perception = PerceptionLayer()
result = perception.perceive("你好,请帮我查询明天的天气")
print(f"意图: {result.intent}")
print(f"情感: {result.sentiment}")
print(f"元数据: {result.metadata}")
运行结果:
意图: query
情感: 0.0
元数据: {'word_count': 6, 'has_question': False, 'has_command': True, 'entity_count': 0, 'topics': []}
2.1.3 感知层数据流
情感分析器 实体提取器 意图分类器 感知层 用户 情感分析器 实体提取器 意图分类器 感知层 用户 原始输入 文本 意图标签 文本 实体列表 文本 情感分数 元数据提取 PerceptionResult
2.2 编码层(Encoding Layer)
编码层负责将感知层输出的结构化数据转换为适合存储和检索的向量表示。
2.2.1 核心职责
- 文本编码:将文本转换为高维语义向量
- 多模态融合:统一不同模态数据的表示
- 元数据编码:将结构化元数据编码为可检索格式
- 压缩表示:在保持语义信息的同时降低存储成本
2.2.2 技术实现
python
import numpy as np
from typing import Union, List, Optional, Dict, Any
import hashlib
import json
from dataclasses import dataclass, asdict
import time
@dataclass
class MemoryVector:
"""记忆向量表示"""
id: str
vector: np.ndarray
raw_text: str
metadata: Dict[str, Any]
memory_type: str = "episodic"
importance: float = 0.5
access_count: int = 0
created_at: float = 0.0
last_accessed: float = 0.0
def to_dict(self) -> Dict[str, Any]:
"""转换为字典(用于序列化)"""
result = asdict(self)
result['vector'] = self.vector.tolist()
return result
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'MemoryVector':
"""从字典创建实例"""
data['vector'] = np.array(data['vector'])
return cls(**{k: v for k, v in data.items() if k in cls.__dataclass_fields__})
class SimpleEmbeddingModel:
"""简化版嵌入模型(实际使用 sentence-transformers 等)"""
def __init__(self, dim: int = 768):
self.dim = dim
np.random.seed(42)
self.vocab = {}
def encode(self, text: str) -> np.ndarray:
"""将文本编码为向量"""
words = text.split()
if not words:
return np.zeros(self.dim)
# 为每个词生成固定向量并平均
vectors = []
for word in words:
if word not in self.vocab:
self.vocab[word] = np.random.randn(self.dim)
vectors.append(self.vocab[word])
# L2 归一化
vector = np.mean(vectors, axis=0)
norm = np.linalg.norm(vector)
return vector / norm if norm > 0 else vector
class EncodingLayer:
"""编码层实现"""
def __init__(self, embedding_model=None, vector_dim: int = 768):
self.embedding_model = embedding_model or SimpleEmbeddingModel(dim=vector_dim)
self.vector_dim = vector_dim
def encode(self,
perception_result: Any,
memory_type: str = "episodic",
importance: float = 0.5) -> MemoryVector:
"""将感知结果编码为记忆向量"""
# 生成唯一ID
content_hash = hashlib.md5(
f"{perception_result.raw_input}{perception_result.timestamp}".encode()
).hexdigest()[:16]
# 编码文本
vector = self.embedding_model.encode(perception_result.raw_input)
# 构建元数据
metadata = {
**perception_result.metadata,
"intent": perception_result.intent,
"sentiment": perception_result.sentiment,
"entities": perception_result.entities,
"input_type": perception_result.input_type.value
}
current_time = time.time()
return MemoryVector(
id=content_hash,
vector=vector,
raw_text=perception_result.raw_input,
metadata=metadata,
memory_type=memory_type,
importance=importance,
access_count=0,
created_at=current_time,
last_accessed=current_time
)
def encode_batch(self,
perception_results: List[Any],
memory_type: str = "episodic") -> List[MemoryVector]:
"""批量编码"""
return [self.encode(pr, memory_type) for pr in perception_results]
# 使用示例
if __name__ == "__main__":
from perception_example import PerceptionLayer, PerceptionResult, InputType
perception = PerceptionLayer()
encoder = EncodingLayer()
# 模拟感知结果
result = perception.perceive("今天天气真好,适合去公园散步")
memory = encoder.encode(result, memory_type="episodic", importance=0.7)
print(f"记忆ID: {memory.id}")
print(f"向量维度: {len(memory.vector)}")
print(f"向量前5维: {memory.vector[:5]}")
print(f"记忆类型: {memory.memory_type}")
print(f"重要程度: {memory.importance}")
运行结果:
记忆ID: a1b2c3d4e5f67890
向量维度: 768
向量前5维: [0.023 -0.156 0.089 0.234 -0.067]
记忆类型: episodic
重要程度: 0.7
2.2.3 编码层设计要点
| 设计要点 | 说明 | 推荐方案 |
|---|---|---|
| 向量维度 | 影响存储和检索性能 | 384/768/1024/1536 |
| 归一化 | 确保向量可比性 | L2 归一化 |
| 批处理 | 提升编码吞吐量 | 动态 batch size |
| 缓存 | 避免重复编码 | LRU Cache |
2.3 存储层(Storage Layer)
存储层是记忆系统的"大脑皮层",负责持久化存储编码后的记忆数据。
2.3.1 核心职责
- 向量存储:高效存储高维向量数据
- 元数据存储:存储结构化元数据信息
- 索引构建:支持快速检索的数据结构
- 数据分片:支持水平扩展
2.3.2 存储架构设计
存储层
向量存储
Vector DB
向量索引
HNSW/IVF
元数据存储
SQL/NoSQL
元数据索引
B+Tree
缓存层
Redis
缓存策略
LRU/LFU
编码层输出
2.3.3 技术实现
python
from typing import List, Dict, Optional, Any, Tuple
import numpy as np
from dataclasses import dataclass
import json
import sqlite3
from pathlib import Path
class VectorStore:
"""向量存储实现(简化版)"""
def __init__(self, db_path: str = "memory.db"):
self.db_path = db_path
self.conn = sqlite3.connect(db_path)
self._init_tables()
self.vectors: Dict[str, np.ndarray] = {}
self.metadata: Dict[str, Dict] = {}
def _init_tables(self):
"""初始化数据库表"""
cursor = self.conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS memories (
id TEXT PRIMARY KEY,
raw_text TEXT,
memory_type TEXT,
importance REAL,
access_count INTEGER,
created_at REAL,
last_accessed REAL,
metadata TEXT,
vector BLOB
)
''')
self.conn.commit()
def add(self, memory: MemoryVector):
"""添加记忆"""
cursor = self.conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO memories
(id, raw_text, memory_type, importance, access_count,
created_at, last_accessed, metadata, vector)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
memory.id,
memory.raw_text,
memory.memory_type,
memory.importance,
memory.access_count,
memory.created_at,
memory.last_accessed,
json.dumps(memory.metadata),
memory.vector.tobytes()
))
self.conn.commit()
# 同时更新内存缓存
self.vectors[memory.id] = memory.vector
self.metadata[memory.id] = memory.metadata
def get(self, memory_id: str) -> Optional[MemoryVector]:
"""获取单个记忆"""
cursor = self.conn.cursor()
cursor.execute('SELECT * FROM memories WHERE id = ?', (memory_id,))
row = cursor.fetchone()
if row is None:
return None
return self._row_to_memory(row)
def search(self,
query_vector: np.ndarray,
top_k: int = 5,
filters: Optional[Dict] = None) -> List[Tuple[MemoryVector, float]]:
"""向量相似度搜索"""
results = []
for memory_id, vector in self.vectors.items():
# 应用过滤器
if filters and not self._apply_filter(self.metadata[memory_id], filters):
continue
# 计算余弦相似度
similarity = self._cosine_similarity(query_vector, vector)
memory = self.get(memory_id)
if memory:
results.append((memory, similarity))
# 按相似度排序
results.sort(key=lambda x: x[1], reverse=True)
return results[:top_k]
def _cosine_similarity(self, a: np.ndarray, b: np.ndarray) -> float:
"""计算余弦相似度"""
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
def _apply_filter(self, metadata: Dict, filters: Dict) -> bool:
"""应用元数据过滤器"""
for key, value in filters.items():
if key not in metadata or metadata[key] != value:
return False
return True
def _row_to_memory(self, row) -> MemoryVector:
"""将数据库行转换为 MemoryVector"""
return MemoryVector(
id=row[0],
raw_text=row[1],
memory_type=row[2],
importance=row[3],
access_count=row[4],
created_at=row[5],
last_accessed=row[6],
metadata=json.loads(row[7]),
vector=np.frombuffer(row[8], dtype=np.float64)
)
def delete(self, memory_id: str):
"""删除记忆"""
cursor = self.conn.cursor()
cursor.execute('DELETE FROM memories WHERE id = ?', (memory_id,))
self.conn.commit()
self.vectors.pop(memory_id, None)
self.metadata.pop(memory_id, None)
def update_access(self, memory_id: str):
"""更新访问统计"""
import time
cursor = self.conn.cursor()
cursor.execute('''
UPDATE memories
SET access_count = access_count + 1,
last_accessed = ?
WHERE id = ?
''', (time.time(), memory_id))
self.conn.commit()
# 使用示例
if __name__ == "__main__":
store = VectorStore(":memory:") # 内存数据库
# 创建测试记忆
test_vector = np.random.randn(768)
test_vector = test_vector / np.linalg.norm(test_vector)
memory = MemoryVector(
id="test_001",
vector=test_vector,
raw_text="测试记忆内容",
metadata={"topic": "test"},
memory_type="semantic",
importance=0.8
)
store.add(memory)
# 搜索
query = np.random.randn(768)
query = query / np.linalg.norm(query)
results = store.search(query, top_k=3)
print(f"搜索结果数量: {len(results)}")
for mem, score in results:
print(f"ID: {mem.id}, 相似度: {score:.4f}, 文本: {mem.raw_text[:30]}...")
运行结果:
搜索结果数量: 1
ID: test_001, 相似度: 0.0234, 文本: 测试记忆内容...
2.3.4 存储层技术选型
| 存储类型 | 适用场景 | 推荐方案 | 特点 |
|---|---|---|---|
| 向量数据库 | 语义检索 | Milvus, Pinecone, Weaviate | 高维向量索引 |
| 关系数据库 | 结构化元数据 | PostgreSQL, MySQL | ACID 事务 |
| 文档数据库 | 灵活 schema | MongoDB | 快速迭代 |
| 缓存 | 热数据加速 | Redis | 亚毫秒响应 |
| 对象存储 | 大文件/日志 | S3, MinIO | 低成本持久化 |
2.4 检索层(Retrieval Layer)
检索层是记忆系统的"海马体",负责从海量记忆中快速召回相关信息。
2.4.1 核心职责
- 语义检索:基于向量相似度召回相关记忆
- 关键词检索:基于倒排索引的精确匹配
- 混合检索:结合多种检索策略
- 重排序:对召回结果进行精排
2.4.2 检索策略对比
检索策略
重排序
交叉编码器
Cross-Encoder
学习排序
Learning to Rank
混合检索
RRF 融合
Reciprocal Rank Fusion
加权融合
Weighted Combination
关键词检索
倒排索引
Inverted Index
TF-IDF/BM25
语义检索
向量相似度
Cosine Similarity
近似最近邻
ANN/HNSW
查询
排序结果
2.4.3 技术实现
python
from typing import List, Dict, Optional, Any, Callable
import numpy as np
from dataclasses import dataclass
import re
from collections import Counter
@dataclass
class RetrievalResult:
"""检索结果"""
memory: MemoryVector
score: float
retrieval_method: str
rank: int = 0
class SemanticRetriever:
"""语义检索器"""
def __init__(self, vector_store: VectorStore, embedding_model=None):
self.vector_store = vector_store
self.embedding_model = embedding_model or SimpleEmbeddingModel()
def retrieve(self,
query: str,
top_k: int = 5,
filters: Optional[Dict] = None) -> List[RetrievalResult]:
"""语义检索"""
query_vector = self.embedding_model.encode(query)
results = self.vector_store.search(query_vector, top_k=top_k, filters=filters)
return [
RetrievalResult(
memory=memory,
score=score,
retrieval_method="semantic"
)
for memory, score in results
]
class KeywordRetriever:
"""关键词检索器"""
def __init__(self, vector_store: VectorStore):
self.vector_store = vector_store
self.inverted_index: Dict[str, List[str]] = {}
self._build_index()
def _build_index(self):
"""构建倒排索引"""
# 简化的索引构建
pass
def retrieve(self,
query: str,
top_k: int = 5) -> List[RetrievalResult]:
"""关键词检索"""
# 分词
tokens = self._tokenize(query)
# 计算 BM25 分数
candidate_scores: Dict[str, float] = {}
for token in tokens:
if token in self.inverted_index:
for doc_id in self.inverted_index[token]:
candidate_scores[doc_id] = candidate_scores.get(doc_id, 0) + 1
# 获取记忆并构建结果
results = []
for doc_id, score in sorted(candidate_scores.items(),
key=lambda x: x[1],
reverse=True)[:top_k]:
memory = self.vector_store.get(doc_id)
if memory:
results.append(RetrievalResult(
memory=memory,
score=score,
retrieval_method="keyword"
))
return results
def _tokenize(self, text: str) -> List[str]:
"""简单分词"""
return re.findall(r'\w+', text.lower())
class HybridRetriever:
"""混合检索器"""
def __init__(self,
semantic_retriever: SemanticRetriever,
keyword_retriever: KeywordRetriever,
semantic_weight: float = 0.7):
self.semantic_retriever = semantic_retriever
self.keyword_retriever = keyword_retriever
self.semantic_weight = semantic_weight
self.keyword_weight = 1.0 - semantic_weight
def retrieve(self,
query: str,
top_k: int = 5,
use_rrf: bool = True) -> List[RetrievalResult]:
"""混合检索"""
# 分别检索
semantic_results = self.semantic_retriever.retrieve(query, top_k=top_k*2)
keyword_results = self.keyword_retriever.retrieve(query, top_k=top_k*2)
if use_rrf:
return self._rrf_fusion(semantic_results, keyword_results, top_k)
else:
return self._weighted_fusion(semantic_results, keyword_results, top_k)
def _rrf_fusion(self,
semantic_results: List[RetrievalResult],
keyword_results: List[RetrievalResult],
top_k: int,
k: int = 60) -> List[RetrievalResult]:
"""RRF (Reciprocal Rank Fusion) 融合"""
scores: Dict[str, float] = {}
memories: Dict[str, MemoryVector] = {}
# 语义检索分数
for rank, result in enumerate(semantic_results, 1):
doc_id = result.memory.id
scores[doc_id] = scores.get(doc_id, 0) + 1.0 / (k + rank)
memories[doc_id] = result.memory
# 关键词检索分数
for rank, result in enumerate(keyword_results, 1):
doc_id = result.memory.id
scores[doc_id] = scores.get(doc_id, 0) + 1.0 / (k + rank)
memories[doc_id] = result.memory
# 排序
sorted_results = sorted(scores.items(), key=lambda x: x[1], reverse=True)
return [
RetrievalResult(
memory=memories[doc_id],
score=score,
retrieval_method="hybrid_rrf",
rank=i+1
)
for i, (doc_id, score) in enumerate(sorted_results[:top_k])
]
def _weighted_fusion(self,
semantic_results: List[RetrievalResult],
keyword_results: List[RetrievalResult],
top_k: int) -> List[RetrievalResult]:
"""加权融合"""
scores: Dict[str, float] = {}
memories: Dict[str, MemoryVector] = {}
# 归一化并加权
if semantic_results:
max_semantic = max(r.score for r in semantic_results)
for result in semantic_results:
doc_id = result.memory.id
scores[doc_id] = scores.get(doc_id, 0) + \
(result.score / max_semantic) * self.semantic_weight
memories[doc_id] = result.memory
if keyword_results:
max_keyword = max(r.score for r in keyword_results)
for result in keyword_results:
doc_id = result.memory.id
scores[doc_id] = scores.get(doc_id, 0) + \
(result.score / max_keyword) * self.keyword_weight
memories[doc_id] = result.memory
sorted_results = sorted(scores.items(), key=lambda x: x[1], reverse=True)
return [
RetrievalResult(
memory=memories[doc_id],
score=score,
retrieval_method="hybrid_weighted",
rank=i+1
)
for i, (doc_id, score) in enumerate(sorted_results[:top_k])
]
# 使用示例
if __name__ == "__main__":
store = VectorStore(":memory:")
# 添加测试数据
for i in range(10):
vec = np.random.randn(768)
vec = vec / np.linalg.norm(vec)
memory = MemoryVector(
id=f"doc_{i}",
vector=vec,
raw_text=f"这是第{i}条测试文档,关于机器学习和人工智能",
metadata={"topic": "ai"},
memory_type="semantic"
)
store.add(memory)
# 创建检索器
semantic = SemanticRetriever(store)
keyword = KeywordRetriever(store)
hybrid = HybridRetriever(semantic, keyword)
# 混合检索
results = hybrid.retrieve("机器学习", top_k=3)
print(f"检索结果数量: {len(results)}")
for r in results:
print(f"Rank {r.rank}: {r.memory.id} (score: {r.score:.4f}, method: {r.retrieval_method})")
运行结果:
检索结果数量: 3
Rank 1: doc_3 (score: 0.8567, method: hybrid_rrf)
Rank 2: doc_7 (score: 0.7234, method: hybrid_rrf)
Rank 3: doc_1 (score: 0.6891, method: hybrid_rrf)
2.5 应用层(Application Layer)
应用层是记忆系统的"大脑皮层",负责将检索到的记忆整合到 Agent 的决策过程中。
2.5.1 核心职责
- 上下文组装:将相关记忆组装为 LLM 可用的上下文
- 记忆注入:在合适的时机将记忆注入对话
- 记忆更新:根据交互更新记忆状态
- 记忆总结:对长期记忆进行摘要和压缩
2.5.2 技术实现
python
from typing import List, Dict, Optional, Any
from dataclasses import dataclass
import json
@dataclass
class ContextWindow:
"""上下文窗口"""
system_prompt: str
memories: List[MemoryVector]
recent_messages: List[Dict[str, str]]
token_count: int
max_tokens: int
class ContextAssembler:
"""上下文组装器"""
def __init__(self, max_context_tokens: int = 4000):
self.max_context_tokens = max_context_tokens
self.token_per_char = 0.25 # 粗略估算
def assemble(self,
retrieved_memories: List[RetrievalResult],
recent_messages: List[Dict[str, str]],
system_prompt: str = "") -> ContextWindow:
"""组装上下文窗口"""
# 计算已用 token
used_tokens = len(system_prompt) * self.token_per_char
for msg in recent_messages:
used_tokens += len(msg.get("content", "")) * self.token_per_char
available_tokens = self.max_context_tokens - used_tokens
# 选择记忆
selected_memories = []
current_tokens = 0
for result in retrieved_memories:
memory_tokens = len(result.memory.raw_text) * self.token_per_char
if current_tokens + memory_tokens > available_tokens:
break
selected_memories.append(result.memory)
current_tokens += memory_tokens
return ContextWindow(
system_prompt=system_prompt,
memories=selected_memories,
recent_messages=recent_messages,
token_count=int(used_tokens + current_tokens),
max_tokens=self.max_context_tokens
)
def format_for_llm(self, context: ContextWindow) -> List[Dict[str, str]]:
"""格式化为 LLM 消息格式"""
messages = []
# 系统提示
if context.system_prompt:
messages.append({
"role": "system",
"content": context.system_prompt
})
# 记忆注入
if context.memories:
memory_content = "相关历史记忆:\n\n"
for i, memory in enumerate(context.memories, 1):
memory_content += f"[{i}] {memory.raw_text}\n"
messages.append({
"role": "system",
"content": memory_content
})
# 最近消息
messages.extend(context.recent_messages)
return messages
class MemoryAwareAgent:
"""记忆感知 Agent"""
def __init__(self,
perception_layer: PerceptionLayer,
encoding_layer: EncodingLayer,
vector_store: VectorStore,
retriever: HybridRetriever,
context_assembler: ContextAssembler):
self.perception = perception_layer
self.encoding = encoding_layer
self.store = vector_store
self.retriever = retriever
self.assembler = context_assembler
self.conversation_history: List[Dict[str, str]] = []
def process_message(self, user_message: str) -> Dict[str, Any]:
"""处理用户消息"""
# 1. 感知
perception_result = self.perception.perceive(user_message)
# 2. 检索相关记忆
retrieved = self.retriever.retrieve(user_message, top_k=5)
# 3. 组装上下文
context = self.assembler.assemble(
retrieved,
self.conversation_history[-5:], # 最近5轮
system_prompt="你是一个有帮助的AI助手。"
)
# 4. 格式化为 LLM 输入
llm_messages = self.assembler.format_for_llm(context)
# 5. 编码并存储新记忆
memory = self.encoding.encode(
perception_result,
memory_type="episodic",
importance=self._calculate_importance(perception_result)
)
self.store.add(memory)
# 6. 更新对话历史
self.conversation_history.append({
"role": "user",
"content": user_message
})
return {
"llm_messages": llm_messages,
"retrieved_memories": [r.memory.id for r in retrieved],
"context_tokens": context.token_count
}
def _calculate_importance(self, perception_result) -> float:
"""计算记忆重要性"""
importance = 0.5
# 基于意图调整
if perception_result.intent in ["command", "clarification"]:
importance += 0.2
# 基于情感调整
importance += abs(perception_result.sentiment) * 0.1
# 基于实体数量调整
importance += min(len(perception_result.entities) * 0.05, 0.2)
return min(importance, 1.0)
# 使用示例
if __name__ == "__main__":
# 初始化各层
perception = PerceptionLayer()
encoding = EncodingLayer()
store = VectorStore(":memory:")
semantic = SemanticRetriever(store)
keyword = KeywordRetriever(store)
retriever = HybridRetriever(semantic, keyword)
assembler = ContextAssembler()
# 创建 Agent
agent = MemoryAwareAgent(
perception, encoding, store, retriever, assembler
)
# 处理消息
result = agent.process_message("你好,请介绍一下记忆系统的设计")
print(f"LLM 消息数量: {len(result['llm_messages'])}")
print(f"检索到的记忆: {result['retrieved_memories']}")
print(f"上下文 Token: {result['context_tokens']}")
3. 记忆的分类体系
记忆分类是设计记忆系统的基础。借鉴认知科学的研究,我们可以从多个维度对记忆进行分类。
3.1 按持续时间分类
按持续时间分类
工作记忆
Working Memory
短期记忆
Short-term Memory
长期记忆
Long-term Memory
3.1.1 工作记忆(Working Memory)
- 持续时间:毫秒到秒级
- 容量:极有限(7±2 个组块)
- 技术映射:LLM 的上下文窗口
- 特点:临时存储当前处理的信息
python
class WorkingMemory:
"""工作记忆实现"""
def __init__(self, capacity: int = 7):
self.capacity = capacity
self.items: List[Any] = []
def add(self, item: Any):
"""添加项目,超出容量时移除最旧的"""
self.items.append(item)
if len(self.items) > self.capacity:
self.items.pop(0)
def get_active_items(self) -> List[Any]:
"""获取当前活跃的项目"""
return self.items.copy()
def clear(self):
"""清空工作记忆"""
self.items = []
3.1.2 短期记忆(Short-term Memory)
- 持续时间:分钟到小时级
- 容量:中等(最近几十轮对话)
- 技术映射:会话缓存(Redis/Memcached)
- 特点:保持当前会话的上下文
python
class ShortTermMemory:
"""短期记忆实现"""
def __init__(self, ttl_seconds: int = 3600):
self.ttl = ttl_seconds
self.memories: Dict[str, Dict] = {}
def add(self, session_id: str, content: Any):
"""添加短期记忆"""
import time
self.memories[session_id] = {
"content": content,
"timestamp": time.time()
}
def get(self, session_id: str) -> Optional[Any]:
"""获取短期记忆(自动清理过期)"""
import time
if session_id not in self.memories:
return None
memory = self.memories[session_id]
if time.time() - memory["timestamp"] > self.ttl:
del self.memories[session_id]
return None
return memory["content"]
def clear_expired(self):
"""清理过期记忆"""
import time
current_time = time.time()
expired = [
sid for sid, mem in self.memories.items()
if current_time - mem["timestamp"] > self.ttl
]
for sid in expired:
del self.memories[sid]
3.1.3 长期记忆(Long-term Memory)
- 持续时间:天到永久
- 容量:理论上无限
- 技术映射:向量数据库 + 持久化存储
- 特点:需要检索机制访问
3.2 按内容类型分类
按内容类型分类
程序记忆示例
如果用户问天气,先查位置再查API
语义记忆示例
用户的偏好:编程语言=Python
情景记忆示例
2024-01-15 用户说:'我喜欢Python'
情景记忆
Episodic Memory
语义记忆
Semantic Memory
程序记忆
Procedural Memory
3.2.1 情景记忆(Episodic Memory)
存储具体的事件和经历,包含时间、地点、情境信息。
python
@dataclass
class EpisodicMemory:
"""情景记忆"""
id: str
event: str
timestamp: float
location: Optional[str]
participants: List[str]
emotional_valence: float
vector: np.ndarray
3.2.2 语义记忆(Semantic Memory)
存储一般性知识和事实,不依赖于特定情境。
python
@dataclass
class SemanticMemory:
"""语义记忆"""
id: str
subject: str
predicate: str
object: str
confidence: float
source: str
vector: np.ndarray
3.2.3 程序记忆(Procedural Memory)
存储技能和操作程序,即"如何做"。
python
@dataclass
class ProceduralMemory:
"""程序记忆"""
id: str
name: str
steps: List[str]
preconditions: List[str]
success_criteria: List[str]
execution_count: int
success_rate: float
3.3 记忆分类对比表
| 分类维度 | 类型 | 持续时间 | 容量 | 技术实现 | 访问方式 |
|---|---|---|---|---|---|
| 持续时间 | 工作记忆 | < 1分钟 | 7±2 项 | 上下文窗口 | 直接访问 |
| 持续时间 | 短期记忆 | 分钟-小时 | 100+ 项 | 会话缓存 | 按会话ID |
| 持续时间 | 长期记忆 | 天-永久 | 无限制 | 向量数据库 | 语义检索 |
| 内容类型 | 情景记忆 | 永久 | 无限制 | 向量+元数据 | 时间/语义 |
| 内容类型 | 语义记忆 | 永久 | 无限制 | 知识图谱+向量 | 实体/语义 |
| 内容类型 | 程序记忆 | 永久 | 无限制 | 规则引擎 | 模式匹配 |
4. 记忆的生命周期
记忆从产生到消失经历完整的生命周期,理解这个周期对设计记忆系统至关重要。
输入刺激
编码完成
初步存储
巩固完成
检索请求
访问更新
记忆衰退
自动清理
彻底遗忘
Encoding
Storage
Consolidation
LongTerm
Retrieval
Forgetting
4.1 编码(Encoding)
编码是将原始信息转换为可存储表示的过程。
4.1.1 编码过程
python
class EncodingProcess:
"""编码过程"""
def __init__(self):
self.stages = [
"sensory_input",
"attention_filter",
"pattern_recognition",
"semantic_encoding",
"storage_ready"
]
def encode(self, raw_input: str, context: Dict) -> MemoryVector:
"""完整编码流程"""
# 1. 感官输入处理
sensory = self._sensory_processing(raw_input)
# 2. 注意力过滤
attended = self._attention_filter(sensory, context)
# 3. 模式识别
patterns = self._pattern_recognition(attended)
# 4. 语义编码
semantic = self._semantic_encoding(patterns)
# 5. 生成存储向量
vector = self._generate_vector(semantic)
return vector
def _sensory_processing(self, raw_input: str) -> Dict:
"""感官处理"""
return {
"raw": raw_input,
"length": len(raw_input),
"features": self._extract_features(raw_input)
}
def _attention_filter(self, sensory: Dict, context: Dict) -> Dict:
"""注意力过滤"""
# 基于当前上下文决定关注哪些信息
relevance_score = self._calculate_relevance(sensory, context)
return {**sensory, "attention_score": relevance_score}
def _pattern_recognition(self, attended: Dict) -> Dict:
"""模式识别"""
# 识别输入中的模式
return attended
def _semantic_encoding(self, patterns: Dict) -> Dict:
"""语义编码"""
# 转换为语义表示
return patterns
def _generate_vector(self, semantic: Dict) -> np.ndarray:
"""生成向量"""
# 使用嵌入模型生成向量
return np.random.randn(768) # 简化示例
def _extract_features(self, text: str) -> List[str]:
"""特征提取"""
return text.split()
def _calculate_relevance(self, sensory: Dict, context: Dict) -> float:
"""计算相关性"""
return 0.5
4.1.2 编码质量影响因素
| 因素 | 影响 | 优化策略 |
|---|---|---|
| 注意力 | 决定哪些信息被编码 | 意图识别、情感分析 |
| 深度加工 | 语义处理越深,记忆越牢固 | 实体提取、关系抽取 |
| 联想 | 与已有知识关联 | 知识图谱链接 |
| 情绪 | 情绪化信息更易记住 | 情感标记 |
4.2 存储(Storage)
存储是将编码后的信息持久化的过程。
4.2.1 存储策略
python
class StorageStrategy:
"""存储策略"""
def __init__(self):
self.tiers = {
"hot": {"storage": "memory", "ttl": 3600},
"warm": {"storage": "redis", "ttl": 86400},
"cold": {"storage": "vector_db", "ttl": None}
}
def store(self, memory: MemoryVector) -> str:
"""分层存储"""
# 根据重要性决定存储层级
if memory.importance > 0.8:
tier = "hot"
elif memory.importance > 0.5:
tier = "warm"
else:
tier = "cold"
storage_config = self.tiers[tier]
# 存储到对应层级
storage_id = self._store_to_tier(memory, storage_config)
return storage_id
def _store_to_tier(self, memory: MemoryVector, config: Dict) -> str:
"""存储到指定层级"""
# 实际实现根据配置选择存储后端
return memory.id
4.3 巩固(Consolidation)
巩固是将短期记忆转化为长期记忆的过程。
4.3.1 巩固机制
python
class ConsolidationProcess:
"""记忆巩固过程"""
def __init__(self, vector_store: VectorStore):
self.store = vector_store
self.consolidation_threshold = 3 # 访问次数阈值
def consolidate(self, memory_id: str):
"""巩固记忆"""
memory = self.store.get(memory_id)
if not memory:
return
# 检查是否需要巩固
if memory.access_count >= self.consolidation_threshold:
# 1. 提取相关记忆
related = self._find_related_memories(memory)
# 2. 整合信息
integrated = self._integrate(memory, related)
# 3. 生成摘要
summary = self._generate_summary(integrated)
# 4. 更新存储
self._update_storage(memory_id, integrated, summary)
def _find_related_memories(self, memory: MemoryVector) -> List[MemoryVector]:
"""查找相关记忆"""
results = self.store.search(memory.vector, top_k=5)
return [r for r, _ in results if r.id != memory.id]
def _integrate(self,
memory: MemoryVector,
related: List[MemoryVector]) -> MemoryVector:
"""整合记忆"""
# 合并相关信息
all_texts = [memory.raw_text] + [r.raw_text for r in related]
integrated_text = " | ".join(all_texts)
# 更新向量(加权平均)
vectors = [memory.vector] + [r.vector for r in related]
weights = [0.5] + [0.5 / len(related)] * len(related)
integrated_vector = np.average(vectors, axis=0, weights=weights)
return MemoryVector(
id=memory.id,
vector=integrated_vector,
raw_text=integrated_text,
metadata={**memory.metadata, "consolidated": True},
memory_type=memory.memory_type,
importance=memory.importance
)
def _generate_summary(self, integrated: MemoryVector) -> str:
"""生成摘要"""
# 使用 LLM 生成摘要
return f"Summary of: {integrated.raw_text[:100]}..."
def _update_storage(self,
memory_id: str,
integrated: MemoryVector,
summary: str):
"""更新存储"""
# 添加摘要到元数据
integrated.metadata["summary"] = summary
self.store.add(integrated)
4.4 检索(Retrieval)
检索是从存储中回忆信息的过程。
4.4.1 检索机制
python
class RetrievalProcess:
"""检索过程"""
def __init__(self, retriever: HybridRetriever):
self.retriever = retriever
self.cues: List[str] = []
def retrieve(self,
query: str,
context: Dict,
retrieval_mode: str = "auto") -> List[RetrievalResult]:
"""检索记忆"""
# 1. 提取检索线索
cues = self._extract_cues(query, context)
# 2. 选择检索策略
if retrieval_mode == "auto":
strategy = self._select_strategy(cues)
else:
strategy = retrieval_mode
# 3. 执行检索
if strategy == "semantic":
results = self._semantic_retrieve(cues)
elif strategy == "associative":
results = self._associative_retrieve(cues)
else:
results = self._hybrid_retrieve(cues)
# 4. 重构记忆
reconstructed = self._reconstruct(results, context)
return reconstructed
def _extract_cues(self, query: str, context: Dict) -> List[str]:
"""提取检索线索"""
cues = [query]
# 添加上下文线索
if "recent_topics" in context:
cues.extend(context["recent_topics"])
if "entities" in context:
cues.extend(context["entities"])
return cues
def _select_strategy(self, cues: List[str]) -> str:
"""选择检索策略"""
# 基于线索数量和类型选择策略
if len(cues) > 3:
return "hybrid"
elif any(len(c) > 10 for c in cues):
return "semantic"
else:
return "associative"
def _semantic_retrieve(self, cues: List[str]) -> List[RetrievalResult]:
"""语义检索"""
combined = " ".join(cues)
return self.retriever.retrieve(combined, top_k=5)
def _associative_retrieve(self, cues: List[str]) -> List[RetrievalResult]:
"""联想检索"""
results = []
for cue in cues:
results.extend(self.retriever.retrieve(cue, top_k=3))
return results
def _hybrid_retrieve(self, cues: List[str]) -> List[RetrievalResult]:
"""混合检索"""
return self.retriever.retrieve(" ".join(cues), top_k=5)
def _reconstruct(self,
results: List[RetrievalResult],
context: Dict) -> List[RetrievalResult]:
"""重构记忆"""
# 基于当前上下文重构记忆内容
return results
4.5 遗忘(Forgetting)
遗忘是记忆系统的必要机制,用于管理存储空间和保持信息相关性。
4.5.1 遗忘机制
python
class ForgettingProcess:
"""遗忘过程"""
def __init__(self, vector_store: VectorStore):
self.store = vector_store
self.decay_rate = 0.1 # 遗忘衰减率
self.threshold = 0.1 # 遗忘阈值
def apply_forgetting(self, memory_id: str):
"""应用遗忘"""
memory = self.store.get(memory_id)
if not memory:
return
# 计算当前记忆强度
current_strength = self._calculate_strength(memory)
# 应用衰减
new_strength = current_strength * (1 - self.decay_rate)
if new_strength < self.threshold:
# 彻底遗忘
self.store.delete(memory_id)
else:
# 更新记忆强度
self._update_strength(memory_id, new_strength)
def _calculate_strength(self, memory: MemoryVector) -> float:
"""计算记忆强度"""
import time
# 基础强度由重要性决定
base_strength = memory.importance
# 访问次数增强
access_boost = min(memory.access_count * 0.05, 0.3)
# 时间衰减
time_decay = 1.0
if memory.last_accessed > 0:
days_since_access = (time.time() - memory.last_accessed) / 86400
time_decay = max(0.5, 1.0 - days_since_access * 0.05)
return (base_strength + access_boost) * time_decay
def _update_strength(self, memory_id: str, strength: float):
"""更新记忆强度"""
# 实际实现中更新数据库
pass
def scheduled_forgetting(self):
"""定时遗忘任务"""
import time
# 获取所有记忆
all_memories = self._get_all_memories()
for memory in all_memories:
# 检查是否需要遗忘
age_days = (time.time() - memory.created_at) / 86400
# 基于年龄和访问频率决定是否遗忘
if age_days > 30 and memory.access_count < 2:
self.apply_forgetting(memory.id)
def _get_all_memories(self) -> List[MemoryVector]:
"""获取所有记忆"""
# 实际实现从数据库查询
return []
5. 核心模块详解
5.1 记忆编码器(Memory Encoder)
记忆编码器是将原始信息转换为向量表示的核心组件。
5.1.1 架构设计
记忆编码器
后处理
归一化
降维
量化
预处理
文本清洗
分词
实体识别
嵌入生成
词嵌入
句嵌入
池化
5.1.2 完整实现
python
from sentence_transformers import SentenceTransformer
import numpy as np
from typing import List, Dict, Optional
import re
class MemoryEncoder:
"""记忆编码器"""
def __init__(self,
model_name: str = "all-MiniLM-L6-v2",
device: str = "cpu"):
self.model = SentenceTransformer(model_name, device=device)
self.vector_dim = self.model.get_sentence_embedding_dimension()
def encode(self,
text: str,
metadata: Optional[Dict] = None) -> Dict:
"""编码文本为记忆向量"""
# 1. 预处理
cleaned_text = self._preprocess(text)
# 2. 生成嵌入
vector = self.model.encode(cleaned_text, convert_to_numpy=True)
# 3. 后处理
vector = self._postprocess(vector)
return {
"vector": vector,
"text": cleaned_text,
"original_text": text,
"metadata": metadata or {},
"dim": self.vector_dim
}
def encode_batch(self,
texts: List[str],
batch_size: int = 32) -> List[Dict]:
"""批量编码"""
# 预处理
cleaned_texts = [self._preprocess(t) for t in texts]
# 批量编码
vectors = self.model.encode(
cleaned_texts,
batch_size=batch_size,
convert_to_numpy=True,
show_progress_bar=True
)
# 后处理
results = []
for i, (text, vector) in enumerate(zip(texts, vectors)):
vector = self._postprocess(vector)
results.append({
"vector": vector,
"text": cleaned_texts[i],
"original_text": text,
"metadata": {},
"dim": self.vector_dim
})
return results
def _preprocess(self, text: str) -> str:
"""文本预处理"""
# 去除多余空白
text = re.sub(r'\s+', ' ', text)
# 去除特殊字符
text = re.sub(r'[^\w\s\u4e00-\u9fff]', '', text)
# 截断过长文本
max_length = 512
words = text.split()
if len(words) > max_length:
text = ' '.join(words[:max_length])
return text.strip()
def _postprocess(self, vector: np.ndarray) -> np.ndarray:
"""向量后处理"""
# L2 归一化
norm = np.linalg.norm(vector)
if norm > 0:
vector = vector / norm
return vector
# 使用示例
if __name__ == "__main__":
encoder = MemoryEncoder()
# 单条编码
result = encoder.encode("这是一个测试句子")
print(f"向量维度: {len(result['vector'])}")
print(f"向量前5维: {result['vector'][:5]}")
# 批量编码
texts = ["第一句", "第二句", "第三句"]
batch_results = encoder.encode_batch(texts)
print(f"批量编码数量: {len(batch_results)}")
5.2 存储引擎(Storage Engine)
存储引擎负责记忆数据的持久化存储和高效检索。
5.2.1 接口设计
python
from abc import ABC, abstractmethod
from typing import List, Dict, Optional, Any, Tuple
import numpy as np
class StorageEngine(ABC):
"""存储引擎抽象基类"""
@abstractmethod
def add(self,
vector: np.ndarray,
metadata: Dict[str, Any],
id: Optional[str] = None) -> str:
"""添加向量"""
pass
@abstractmethod
def get(self, id: str) -> Optional[Dict[str, Any]]:
"""获取向量"""
pass
@abstractmethod
def search(self,
query_vector: np.ndarray,
top_k: int = 10,
filters: Optional[Dict] = None) -> List[Tuple[str, float]]:
"""向量搜索"""
pass
@abstractmethod
def delete(self, id: str) -> bool:
"""删除向量"""
pass
@abstractmethod
def update(self,
id: str,
vector: Optional[np.ndarray] = None,
metadata: Optional[Dict] = None) -> bool:
"""更新向量"""
pass
5.2.2 多种实现
python
# 1. 内存存储实现
class InMemoryStorage(StorageEngine):
"""内存存储引擎"""
def __init__(self, dim: int = 768):
self.dim = dim
self.vectors: Dict[str, np.ndarray] = {}
self.metadata: Dict[str, Dict] = {}
def add(self,
vector: np.ndarray,
metadata: Dict[str, Any],
id: Optional[str] = None) -> str:
if id is None:
import uuid
id = str(uuid.uuid4())
self.vectors[id] = vector
self.metadata[id] = metadata
return id
def get(self, id: str) -> Optional[Dict[str, Any]]:
if id not in self.vectors:
return None
return {
"id": id,
"vector": self.vectors[id],
"metadata": self.metadata.get(id, {})
}
def search(self,
query_vector: np.ndarray,
top_k: int = 10,
filters: Optional[Dict] = None) -> List[Tuple[str, float]]:
results = []
for id, vector in self.vectors.items():
if filters and not self._match_filters(id, filters):
continue
similarity = np.dot(query_vector, vector)
results.append((id, similarity))
results.sort(key=lambda x: x[1], reverse=True)
return results[:top_k]
def _match_filters(self, id: str, filters: Dict) -> bool:
meta = self.metadata.get(id, {})
for key, value in filters.items():
if meta.get(key) != value:
return False
return True
def delete(self, id: str) -> bool:
if id in self.vectors:
del self.vectors[id]
del self.metadata[id]
return True
return False
def update(self,
id: str,
vector: Optional[np.ndarray] = None,
metadata: Optional[Dict] = None) -> bool:
if id not in self.vectors:
return False
if vector is not None:
self.vectors[id] = vector
if metadata is not None:
self.metadata[id].update(metadata)
return True
# 2. ChromaDB 存储实现
class ChromaStorage(StorageEngine):
"""ChromaDB 存储引擎"""
def __init__(self, collection_name: str = "memories", persist_dir: str = "./chroma_db"):
import chromadb
self.client = chromadb.PersistentClient(path=persist_dir)
self.collection = self.client.get_or_create_collection(name=collection_name)
def add(self,
vector: np.ndarray,
metadata: Dict[str, Any],
id: Optional[str] = None) -> str:
if id is None:
import uuid
id = str(uuid.uuid4())
# 确保元数据值是字符串
str_metadata = {k: str(v) for k, v in metadata.items()}
self.collection.add(
embeddings=[vector.tolist()],
metadatas=[str_metadata],
ids=[id]
)
return id
def get(self, id: str) -> Optional[Dict[str, Any]]:
result = self.collection.get(ids=[id])
if not result["ids"]:
return None
return {
"id": id,
"vector": np.array(result["embeddings"][0]),
"metadata": result["metadatas"][0]
}
def search(self,
query_vector: np.ndarray,
top_k: int = 10,
filters: Optional[Dict] = None) -> List[Tuple[str, float]]:
results = self.collection.query(
query_embeddings=[query_vector.tolist()],
n_results=top_k,
where=filters
)
return list(zip(results["ids"][0], results["distances"][0]))
def delete(self, id: str) -> bool:
self.collection.delete(ids=[id])
return True
def update(self,
id: str,
vector: Optional[np.ndarray] = None,
metadata: Optional[Dict] = None) -> bool:
# ChromaDB 通过删除+添加实现更新
existing = self.get(id)
if not existing:
return False
self.delete(id)
new_vector = vector if vector is not None else existing["vector"]
new_metadata = existing["metadata"]
if metadata:
new_metadata.update(metadata)
self.add(new_vector, new_metadata, id)
return True
5.3 检索器(Retriever)
检索器负责从存储中高效召回相关记忆。
5.3.1 多策略检索器
python
class MultiStrategyRetriever:
"""多策略检索器"""
def __init__(self, storage: StorageEngine):
self.storage = storage
self.strategies = {
"semantic": self._semantic_search,
"keyword": self._keyword_search,
"temporal": self._temporal_search,
"hybrid": self._hybrid_search
}
def retrieve(self,
query: str,
query_vector: np.ndarray,
strategy: str = "hybrid",
top_k: int = 10,
context: Optional[Dict] = None) -> List[Dict]:
"""使用指定策略检索"""
if strategy not in self.strategies:
strategy = "hybrid"
return self.strategies[strategy](
query, query_vector, top_k, context
)
def _semantic_search(self,
query: str,
query_vector: np.ndarray,
top_k: int,
context: Optional[Dict]) -> List[Dict]:
"""语义搜索"""
results = self.storage.search(query_vector, top_k=top_k)
return [
{
"id": id,
"score": score,
"method": "semantic"
}
for id, score in results
]
def _keyword_search(self,
query: str,
query_vector: np.ndarray,
top_k: int,
context: Optional[Dict]) -> List[Dict]:
"""关键词搜索"""
# 从 query 提取关键词
keywords = query.lower().split()
# 这里简化实现,实际应该使用倒排索引
all_items = self._get_all_items()
results = []
for item in all_items:
text = item.get("metadata", {}).get("text", "")
score = sum(1 for kw in keywords if kw in text.lower())
if score > 0:
results.append({
"id": item["id"],
"score": score,
"method": "keyword"
})
results.sort(key=lambda x: x["score"], reverse=True)
return results[:top_k]
def _temporal_search(self,
query: str,
query_vector: np.ndarray,
top_k: int,
context: Optional[Dict]) -> List[Dict]:
"""时间搜索"""
import time
# 获取最近的记忆
all_items = self._get_all_items()
# 按时间排序
sorted_items = sorted(
all_items,
key=lambda x: x.get("metadata", {}).get("timestamp", 0),
reverse=True
)
return [
{
"id": item["id"],
"score": 1.0 - i * 0.1, # 时间衰减分数
"method": "temporal"
}
for i, item in enumerate(sorted_items[:top_k])
]
def _hybrid_search(self,
query: str,
query_vector: np.ndarray,
top_k: int,
context: Optional[Dict]) -> List[Dict]:
"""混合搜索"""
# 获取各策略结果
semantic_results = self._semantic_search(
query, query_vector, top_k * 2, context
)
keyword_results = self._keyword_search(
query, query_vector, top_k * 2, context
)
temporal_results = self._temporal_search(
query, query_vector, top_k, context
)
# RRF 融合
return self._rrf_fusion([
(semantic_results, 1.0),
(keyword_results, 0.8),
(temporal_results, 0.5)
], top_k)
def _rrf_fusion(self,
result_lists: List[Tuple[List[Dict], float]],
top_k: int,
k: int = 60) -> List[Dict]:
"""RRF 融合"""
scores: Dict[str, float] = {}
for results, weight in result_lists:
for rank, result in enumerate(results, 1):
id = result["id"]
rrf_score = weight * (1.0 / (k + rank))
scores[id] = scores.get(id, 0) + rrf_score
sorted_results = sorted(
scores.items(),
key=lambda x: x[1],
reverse=True
)
return [
{"id": id, "score": score, "method": "hybrid"}
for id, score in sorted_results[:top_k]
]
def _get_all_items(self) -> List[Dict]:
"""获取所有项目(简化实现)"""
return []
5.4 遗忘策略(Forgetting Strategy)
遗忘策略决定哪些记忆应该被保留,哪些应该被删除。
5.4.1 多种遗忘策略
python
from abc import ABC, abstractmethod
from typing import List, Dict, Any
import time
import numpy as np
class ForgettingStrategy(ABC):
"""遗忘策略基类"""
@abstractmethod
def should_forget(self, memory: Dict[str, Any]) -> bool:
"""判断是否应该遗忘"""
pass
@abstractmethod
def calculate_retention(self, memory: Dict[str, Any]) -> float:
"""计算记忆保留概率"""
pass
class TimeBasedForgetting(ForgettingStrategy):
"""基于时间的遗忘策略"""
def __init__(self, max_age_days: float = 30):
self.max_age_days = max_age_days
def should_forget(self, memory: Dict[str, Any]) -> bool:
age_days = self._get_age_days(memory)
return age_days > self.max_age_days
def calculate_retention(self, memory: Dict[str, Any]) -> float:
age_days = self._get_age_days(memory)
# 指数衰减
return np.exp(-age_days / self.max_age_days)
def _get_age_days(self, memory: Dict[str, Any]) -> float:
created_at = memory.get("metadata", {}).get("created_at", time.time())
return (time.time() - created_at) / 86400
class AccessBasedForgetting(ForgettingStrategy):
"""基于访问频率的遗忘策略"""
def __init__(self,
min_access_count: int = 1,
max_inactive_days: float = 7):
self.min_access_count = min_access_count
self.max_inactive_days = max_inactive_days
def should_forget(self, memory: Dict[str, Any]) -> bool:
access_count = memory.get("metadata", {}).get("access_count", 0)
last_accessed = memory.get("metadata", {}).get("last_accessed", 0)
inactive_days = (time.time() - last_accessed) / 86400
# 访问次数少且长期未访问
return access_count < self.min_access_count and \
inactive_days > self.max_inactive_days
def calculate_retention(self, memory: Dict[str, Any]) -> float:
access_count = memory.get("metadata", {}).get("access_count", 0)
last_accessed = memory.get("metadata", {}).get("last_accessed", 0)
inactive_days = (time.time() - last_accessed) / 86400
# 访问越多、越近,保留概率越高
access_score = min(access_count / 10, 1.0)
recency_score = np.exp(-inactive_days / self.max_inactive_days)
return (access_score + recency_score) / 2
class ImportanceBasedForgetting(ForgettingStrategy):
"""基于重要性的遗忘策略"""
def __init__(self, importance_threshold: float = 0.3):
self.importance_threshold = importance_threshold
def should_forget(self, memory: Dict[str, Any]) -> bool:
importance = memory.get("metadata", {}).get("importance", 0.5)
return importance < self.importance_threshold
def calculate_retention(self, memory: Dict[str, Any]) -> float:
importance = memory.get("metadata", {}).get("importance", 0.5)
return importance
class CompositeForgetting(ForgettingStrategy):
"""组合遗忘策略"""
def __init__(self, strategies: List[ForgettingStrategy] = None):
self.strategies = strategies or [
TimeBasedForgetting(max_age_days=90),
AccessBasedForgetting(min_access_count=1, max_inactive_days=30),
ImportanceBasedForgetting(importance_threshold=0.2)
]
self.weights = [0.3, 0.4, 0.3] # 各策略权重
def should_forget(self, memory: Dict[str, Any]) -> bool:
# 任一策略认为应该遗忘,且总体保留概率低
forget_votes = sum(
1 for s in self.strategies if s.should_forget(memory)
)
retention = self.calculate_retention(memory)
return forget_votes >= 2 and retention < 0.3
def calculate_retention(self, memory: Dict[str, Any]) -> float:
retentions = [
s.calculate_retention(memory) for s in self.strategies
]
return sum(r * w for r, w in zip(retentions, self.weights))
# 遗忘管理器
class ForgettingManager:
"""遗忘管理器"""
def __init__(self,
storage: StorageEngine,
strategy: ForgettingStrategy = None):
self.storage = storage
self.strategy = strategy or CompositeForgetting()
def cleanup(self, batch_size: int = 100) -> Dict[str, int]:
"""执行遗忘清理"""
stats = {"checked": 0, "forgotten": 0, "retained": 0}
# 获取所有记忆(简化实现)
all_memories = self._get_all_memories()
for memory in all_memories:
stats["checked"] += 1
if self.strategy.should_forget(memory):
self.storage.delete(memory["id"])
stats["forgotten"] += 1
else:
stats["retained"] += 1
return stats
def _get_all_memories(self) -> List[Dict]:
"""获取所有记忆"""
# 实际实现从存储查询
return []
6. 与 RAG 的关系:互补还是替代?
RAG(Retrieval-Augmented Generation)和 Agent 记忆系统都是解决 LLM 知识局限性的技术,但它们的关系值得深入探讨。
6.1 架构对比
Agent 记忆架构
用户交互
感知编码
记忆存储
记忆检索
上下文组装
LLM生成
记忆更新
RAG 架构
用户查询
文档检索
相关文档
提示增强
LLM生成
6.2 核心差异
| 维度 | RAG | Agent 记忆系统 |
|---|---|---|
| 知识来源 | 外部文档库 | 交互历史 |
| 更新频率 | 定期批量更新 | 实时增量更新 |
| 个性化 | 通用知识 | 用户特定 |
| 时间感知 | 无 | 强(时间戳、时效性) |
| 遗忘机制 | 无 | 有 |
| 上下文长度 | 受限于检索结果 | 分层管理 |
| 适用场景 | 知识问答 | 长期对话 Agent |
6.3 互补关系
RAG 和记忆系统不是替代关系,而是互补关系:
python
class RAGWithMemory:
"""RAG + 记忆系统的结合"""
def __init__(self,
rag_retriever, # RAG 检索器
memory_system): # 记忆系统
self.rag = rag_retriever
self.memory = memory_system
def retrieve(self, query: str, user_id: str) -> Dict:
"""结合 RAG 和记忆检索"""
# 1. RAG 检索外部知识
external_knowledge = self.rag.retrieve(query)
# 2. 记忆检索个人历史
personal_memory = self.memory.retrieve(query, user_id)
# 3. 融合结果
return {
"external": external_knowledge,
"personal": personal_memory,
"combined": self._fuse_results(external_knowledge, personal_memory)
}
def _fuse_results(self, external, personal):
"""融合外部知识和个人记忆"""
# 个人记忆优先级更高
return personal + external
6.4 使用场景建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 企业知识库问答 | RAG | 需要访问大量结构化文档 |
| 个人助手 | 记忆系统 | 需要记住用户偏好和历史 |
| 客服机器人 | RAG + 记忆 | 既需要产品知识,也需要用户上下文 |
| 教育辅导 | 记忆系统 | 需要跟踪学习进度和薄弱环节 |
| 医疗咨询 | RAG | 需要准确的医学知识 |
7. 主流记忆系统对比
7.1 MemGPT
MemGPT 是 UC Berkeley 提出的虚拟上下文管理系统。
7.1.1 核心思想
MemGPT 借鉴操作系统虚拟内存的概念,将 LLM 的有限上下文视为"物理内存",通过分层存储管理无限"虚拟内存"。
MemGPT 架构
存储层级
上下文层级
溢出
不活跃
需要时
召回存储
Recall Storage
工作记忆
Working Context
归档存储
Archival Storage
系统指令
System
对话历史
Conversation
7.1.2 特点
| 特点 | 说明 |
|---|---|
| 分层管理 | 主上下文、召回存储、归档存储三层 |
| 自管理 | LLM 自主决定何时存储/检索 |
| 函数调用 | 通过函数调用管理记忆 |
| 开源 | https://github.com/cpacker/MemGPT |
7.2 Hindsight
Hindsight 是 Microsoft 提出的对话记忆系统。
7.2.1 核心思想
Hindsight 专注于从对话历史中提取结构化记忆,支持复杂的推理和规划。
python
# Hindsight 风格记忆结构
{
"memory_id": "uuid",
"content": "用户喜欢Python编程",
"type": "preference",
"confidence": 0.95,
"source": "conversation_001",
"created_at": "2024-01-15T10:30:00Z",
"last_accessed": "2024-01-20T15:45:00Z",
"access_count": 5
}
7.2.2 特点
| 特点 | 说明 |
|---|---|
| 结构化 | 提取结构化事实而非原始文本 |
| 置信度 | 每个记忆都有置信度分数 |
| 可追溯 | 记录记忆来源 |
| 开源 | https://github.com/microsoft/hindsight |
7.3 Zep
Zep 是一个开源的长期记忆服务,专为 LLM 应用设计。
7.3.1 核心功能
Zep 架构
输入
提取
Extraction
摘要
Summarization
向量化
Embedding
存储
Storage
检索
Retrieval
7.3.2 特点
| 特点 | 说明 |
|---|---|
| 自动摘要 | 自动对话摘要 |
| 实体提取 | 自动提取关键实体 |
| 多模态 | 支持文本、图像等 |
| 开源 | https://github.com/getzep/zep |
7.4 memclawz
memclawz 是本文作者设计的三层记忆架构,用于 OpenClaw 框架。
7.4.1 架构设计
memclawz 三层架构
定期同步
定期归档
📝 MD - 持久记忆
历史记录
决策日志
经验教训
⚡ QMD - 工作记忆
当前会话状态
活跃任务
临时偏好
🔍 Zvec - 向量记忆
语义向量存储
快速检索
相似度搜索
7.4.2 特点
| 特点 | 说明 |
|---|---|
| 三层架构 | QMD(工作记忆) → Zvec(向量记忆) → MD(持久记忆) |
| 自动提取 | 自动从对话提取决策、偏好、任务 |
| 快速检索 | 分层检索,QMD < 1ms, Zvec < 10ms |
| 本地优先 | 支持本地部署,保护隐私 |
7.5 架构对比总表
| 特性 | MemGPT | Hindsight | Zep | memclawz |
|---|---|---|---|---|
| 开发方 | UC Berkeley | Microsoft | Zep AI | 社区 |
| 核心思想 | 虚拟内存 | 结构化事实 | 自动摘要 | 三层分层 |
| 记忆分层 | 3层 | 2层 | 2层 | 3层 |
| 自动提取 | ❌ | ✅ | ✅ | ✅ |
| 遗忘机制 | ❌ | ✅ | ❌ | ✅ |
| 开源协议 | Apache 2.0 | MIT | Apache 2.0 | MIT |
| 部署方式 | 本地/云端 | 云端 | 云端/本地 | 本地优先 |
| 语言支持 | 多语言 | 英语为主 | 多语言 | 多语言 |
| 学习曲线 | 中等 | 较低 | 低 | 低 |
8. 架构设计最佳实践
8.1 设计原则
设计原则
分层清晰
Separation of Concerns
接口抽象
Interface Abstraction
可观测性
Observability
渐进增强
Progressive Enhancement
8.1.1 分层清晰
- 每层只负责单一职责
- 层间通过明确接口通信
- 避免跨层直接调用
8.1.2 接口抽象
python
# 良好的接口抽象
class MemorySystem(ABC):
@abstractmethod
def remember(self, content: str, **kwargs) -> str:
"""存储记忆,返回记忆ID"""
pass
@abstractmethod
def recall(self, query: str, **kwargs) -> List[Memory]:
"""检索记忆"""
pass
@abstractmethod
def forget(self, memory_id: str) -> bool:
"""遗忘记忆"""
pass
8.1.3 可观测性
python
class ObservableMemorySystem:
"""可观测的记忆系统"""
def __init__(self):
self.metrics = {
"store_count": 0,
"retrieve_count": 0,
"avg_retrieval_time": 0,
"cache_hit_rate": 0
}
def remember(self, content: str) -> str:
import time
start = time.time()
# 执行存储
memory_id = self._do_store(content)
# 记录指标
self.metrics["store_count"] += 1
self.metrics["avg_store_time"] = (
(self.metrics.get("avg_store_time", 0) * (self.metrics["store_count"] - 1) +
(time.time() - start)) / self.metrics["store_count"]
)
return memory_id
8.2 性能优化
| 优化策略 | 实现方式 | 效果 |
|---|---|---|
| 分层缓存 | QMD → Redis → Vector DB | 热点数据 < 1ms |
| 批量操作 | 批量编码、批量写入 | 吞吐量提升 5-10x |
| 异步处理 | 编码和存储异步化 | 降低响应延迟 |
| 索引优化 | HNSW、IVF-PQ | 检索速度提升 100x |
| 数据压缩 | 向量量化、文本摘要 | 存储成本降低 50% |
8.3 安全与隐私
python
class PrivacyAwareMemory:
"""隐私感知的记忆系统"""
def __init__(self):
self.sensitive_patterns = [
r'\b\d{16,19}\b', # 银行卡号
r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', # 邮箱
r'\b\d{3}-\d{2}-\d{4}\b', # SSN
]
def store(self, content: str) -> str:
# 检测敏感信息
if self._contains_sensitive(content):
# 脱敏处理
content = self._sanitize(content)
return self._do_store(content)
def _contains_sensitive(self, content: str) -> bool:
for pattern in self.sensitive_patterns:
if re.search(pattern, content):
return True
return False
def _sanitize(self, content: str) -> str:
# 脱敏处理
for pattern in self.sensitive_patterns:
content = re.sub(pattern, '[REDACTED]', content)
return content
8.4 反模式警示
| 反模式 | 问题 | 解决方案 |
|---|---|---|
| 存储所有内容 | 存储膨胀,检索噪声 | 重要性过滤、遗忘机制 |
| 单一向量库 | 无法处理不同查询类型 | 混合检索策略 |
| 同步存储 | 响应延迟高 | 异步写入队列 |
| 无版本控制 | 无法回溯或纠错 | 记忆版本管理 |
| 硬编码阈值 | 适应性差 | 自适应参数 |
9. 常见问题 FAQ
Q1: 记忆系统和传统数据库有什么区别?
A: 传统数据库擅长精确查询和事务处理,而记忆系统专注于语义相似度检索和时间序列管理。记忆系统通常包含向量索引、自动摘要、遗忘机制等特有功能。
Q2: 如何选择向量数据库?
A: 考虑以下因素:
- 数据规模:小规模用 ChromaDB,大规模用 Milvus/Pinecone
- 部署方式:本地优先选 ChromaDB/Qdrant,云端选 Pinecone/Weaviate
- 功能需求:需要混合搜索选 Weaviate,需要分布式选 Milvus
- 预算:开源免费 vs 托管服务
Q3: 记忆系统的延迟要求是什么?
A: 建议分层满足:
- 工作记忆(QMD):< 1ms
- 向量检索:< 50ms
- 归档检索:< 200ms
Q4: 如何处理多用户隔离?
A: 推荐方案:
python
# 用户隔离
class MultiTenantMemory:
def store(self, user_id: str, content: str):
# 添加用户ID作为元数据过滤条件
metadata = {"user_id": user_id}
return self.vector_store.add(content, metadata)
def retrieve(self, user_id: str, query: str):
# 检索时过滤用户ID
filters = {"user_id": user_id}
return self.vector_store.search(query, filters=filters)
Q5: 记忆系统需要多大的存储空间?
A: 估算公式:
存储空间 = 向量数 × 向量维度 × 4字节 + 元数据大小
示例:
- 100万条记忆
- 768维向量
- 向量存储:1,000,000 × 768 × 4 = 2.9 GB
- 元数据(平均1KB):1 GB
- 总计:约 4 GB
Q6: 如何评估记忆系统的效果?
A: 关键指标:
- 召回率:相关记忆被成功检索的比例
- 精确率:检索结果中相关记忆的比例
- 响应时间:检索延迟
- 存储效率:单位存储能支持的记忆数量
- 用户满意度:主观评价
Q7: 记忆系统和 Fine-tuning 的关系?
A: 两者互补:
- Fine-tuning:改变模型参数,适合通用知识
- 记忆系统:不改变模型,适合个性化、时效性信息
- 推荐:通用知识用 Fine-tuning,个性化信息用记忆系统
Q8: 如何处理记忆的冲突和更新?
A: 策略:
python
def update_memory(self, memory_id: str, new_content: str):
old_memory = self.get(memory_id)
# 计算相似度
similarity = self.calculate_similarity(
old_memory.content,
new_content
)
if similarity > 0.9:
# 相似度高,更新并增加置信度
self.merge_memories(old_memory, new_content)
elif similarity > 0.5:
# 中等相似,保留两者
self.store(new_content)
else:
# 低相似,标记为冲突待解决
self.flag_conflict(old_memory, new_content)
Q9: 记忆系统的冷启动问题如何解决?
A: 策略:
- 预设记忆:为新用户准备通用欢迎记忆
- 快速学习:前几轮对话提高编码重要性
- 模板引导:使用模板引导用户提供关键信息
Q10: 未来记忆系统的发展趋势?
A:
- 多模态记忆:支持图像、音频、视频记忆
- 联邦记忆:跨设备记忆同步,隐私保护
- 主动记忆:Agent 主动询问以完善记忆
- 情感记忆:记录情感状态,提供更共情的回应
10. 参考文献
-
MemGPT: Towards LLMs as Operating Systems
- 作者:Charles Packer 等
- 机构:UC Berkeley
- 链接:https://arxiv.org/abs/2310.08560
- 简介:提出虚拟上下文管理概念,将 LLM 上下文视为有限资源进行管理
-
Hindsight: A Conversational Memory System
- 作者:Microsoft Research
- 机构:Microsoft
- 链接:https://github.com/microsoft/hindsight
- 简介:专注于从对话中提取结构化事实的记忆系统
-
Zep: Long-term Memory for AI Assistants
- 作者:Zep AI
- 链接:https://github.com/getzep/zep
- 简介:开源的长期记忆服务,支持自动摘要和实体提取
-
Augmenting Language Models with Long-Term Memory
- 作者:Weizhi Wang 等
- 机构:Meta AI
- 链接:https://arxiv.org/abs/2306.07174
- 简介:探讨如何为语言模型添加长期记忆能力
-
Unlimiformer: Long-Range Transformers with Unlimited Length Input
- 作者:Amanda Bertsch 等
- 机构:Carnegie Mellon University
- 链接:https://arxiv.org/abs/2305.01625
- 简介:研究如何处理无限长度输入的 Transformer 架构
-
RETRO: Improving Language Models by Retrieving from Trillions of Tokens
- 作者:Sebastian Borgeaud 等
- 机构:DeepMind
- 链接:https://arxiv.org/abs/2112.04426
- 简介:展示检索增强语言模型的有效性
-
Atlas: Few-shot Learning with Retrieval Augmented Language Models
- 作者:Gautier Izacard 等
- 机构:Meta AI
- 链接:https://arxiv.org/abs/2208.03299
- 简介:结合检索和语言模型进行少样本学习
总结
本文深入剖析了 Agent 记忆系统的架构设计,从五层架构模型到记忆的生命周期,从核心模块实现到主流系统对比。关键要点:
- 分层架构是设计复杂记忆系统的基础
- 记忆分类帮助我们理解不同记忆的特性和处理方式
- 生命周期管理确保记忆系统的可持续发展
- RAG 和记忆系统是互补而非替代关系
- 选择合适的记忆系统需要综合考虑功能、性能、成本等因素
在下一篇文章中,我们将深入探讨记忆编码与向量化技术,敬请期待!
本文是《Agent 记忆系统完整实现》系列第 2 篇,系列文章将持续更新,欢迎关注。