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

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

🎯 博主简介

CSDN 「新星创作者」 人工智能技术领域博主,码龄5年 ,累计发布 180+篇原创 文章,博客总访问量 24万+浏览!

🚀 持续更新AI前沿实战知识,专注于 AI 技术实战,多个专栏详细解析,包括:

同时也涉猎计算机视觉、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. 参考文献

  1. MemGPT: Towards LLMs as Operating Systems

    • 作者:Charles Packer 等
    • 机构:UC Berkeley
    • 链接:https://arxiv.org/abs/2310.08560
    • 简介:提出虚拟上下文管理概念,将 LLM 上下文视为有限资源进行管理
  2. Hindsight: A Conversational Memory System

  3. Zep: Long-term Memory for AI Assistants

  4. Augmenting Language Models with Long-Term Memory

  5. Unlimiformer: Long-Range Transformers with Unlimited Length Input

    • 作者:Amanda Bertsch 等
    • 机构:Carnegie Mellon University
    • 链接:https://arxiv.org/abs/2305.01625
    • 简介:研究如何处理无限长度输入的 Transformer 架构
  6. RETRO: Improving Language Models by Retrieving from Trillions of Tokens

  7. Atlas: Few-shot Learning with Retrieval Augmented Language Models


总结

本文深入剖析了 Agent 记忆系统的架构设计,从五层架构模型到记忆的生命周期,从核心模块实现到主流系统对比。关键要点:

  1. 分层架构是设计复杂记忆系统的基础
  2. 记忆分类帮助我们理解不同记忆的特性和处理方式
  3. 生命周期管理确保记忆系统的可持续发展
  4. RAG 和记忆系统是互补而非替代关系
  5. 选择合适的记忆系统需要综合考虑功能、性能、成本等因素

在下一篇文章中,我们将深入探讨记忆编码与向量化技术,敬请期待!


本文是《Agent 记忆系统完整实现》系列第 2 篇,系列文章将持续更新,欢迎关注。

相关推荐
智算菩萨2 小时前
【How Far Are We From AGI】6 AGI的进化论——从胚胎到终极的三级跃迁与发展路线图
论文阅读·人工智能·深度学习·ai·agi
胡少侠72 小时前
LangGraph 多步推理:State + Node + 条件路由,手写 StateGraph
ai·重构·langchain·agent·rag·langgraph
范特西林2 小时前
AI OS 已来:OpenClaw与第三次操作系统革命
操作系统·agent
天青色等烟雨092 小时前
Skill的终局:不是被生成,而是能进化
人工智能·agent
尼尼爱睡觉2 小时前
Harness Engineering 笔记(二):Agent 运行时核心机制——循环、路由与上下文
aigc
智算菩萨2 小时前
【How Far Are We From AGI】7 AGI的七重奏——从实验室到现实世界的应用图景与文明展望
论文阅读·人工智能·ai·agi·感知
进击的野人2 小时前
深入浅出 Spring AI Advisor:自定义你的智能助手拦截器
spring·agent·ai编程
胡少侠74 小时前
RAG 向量持久化:用 ChromaDB 替换内存存储,支持 Metadata 溯源
ai·agent·rag·chromadb
深蓝电商API4 小时前
缓存策略在海淘代购系统中的应用
缓存·系统架构·跨境电商·代购系统·反向海淘·代购平台