← 返回技能笔记

MemPalace 学习笔记

🔗 GitHub 项目地址

一、项目概述

1.1 定位与目标

MemPalace 是一个本地优先(Local-first)的AI记忆系统,旨在解决AI对话中"记忆消失"的核心问题。项目名称取自古希腊记忆术"记忆宫殿"(Method of Loci),将古罗马演说家西塞罗使用的记忆方法应用到AI记忆存储领域。

核心理念

  • 存储一切,然后让它可查找 — 不做摘要、不做提取、原文存储
  • 零API调用 — 完全本地运行,数据永不离开用户机器
  • 结构化索引 — 通过wing(翼)、room(房间)、hall(走廊)等概念组织记忆

1.2 核心功能

功能描述
原文存储将对话历史以原文形式存储在ChromaDB中,不做摘要或提取
语义搜索支持按wing/room/hall多维度过滤的语义检索
知识图谱SQLite本地知识图谱,支持时序有效性和关系查询
AAAK压缩实验性压缩格式,用于上下文加载
MCP服务29个MCP工具,集成Claude Code等AI助手
自动保存钩子Claude Code的自动保存机制

1.3 技术栈

核心存储:
├── ChromaDB(默认向量数据库)
├── SQLite(知识图谱)
└── 可插拔后端接口(BaseCollection抽象)

语言与框架:
├── Python 3.9+
├── uv(包管理器)
├── PyPI分发
└── MCP协议(Model Context Protocol)

嵌入模型:
└── ~300MB(默认模型)

二、架构设计

2.1 整体架构

┌─────────────────────────────────────────────────────────────────┐
│                        MemPalace 架构                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────┐     ┌─────────────────┐     ┌──────────────┐ │
│  │   Miners   │────▶│   Palace Layer  │◀────│  MCP Server  │ │
│  │  (数据采集)  │     │   (存储抽象层)    │     │  (29工具)    │ │
│  └─────────────┘     └─────────────────┘     └──────────────┘ │
│         │                   │                       │          │
│         ▼                   ▼                       ▼          │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                    Backends(可插拔)                    │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐ │   │
│  │  │  ChromaDB   │  │  (Future)   │  │   BaseCollection │ │   │
│  │  │  (默认)     │  │  Qdrant     │  │    (接口定义)    │ │   │
│  │  └─────────────┘  └─────────────┘  └─────────────────┘ │   │
│  └─────────────────────────────────────────────────────────┘   │
│                            │                                   │
│                            ▼                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │              Knowledge Graph (SQLite)                   │   │
│  │  Entities ◀───────▶ Triples (时序关系)                  │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

2.2 核心模块关系

mempalace/
├── backends/
│   ├── base.py           # BaseCollection 抽象接口
│   └── chroma.py         # ChromaDB 后端实现
├── palace.py             # 共享的Palace操作(锁、closet构建)
├── miner.py              # 数据采集(项目文件、会话)
├── searcher.py           # 混合搜索(向量+BM25)
├── knowledge_graph.py    # 知识图谱(实体-关系)
├── mcp_server.py         # MCP协议服务(29工具)
├── palace_graph.py       # 图遍历(tunnel、tunnels)
├── config.py             # 配置管理
└── query_sanitizer.py    # 查询清理

2.3 数据流

┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  文件/   │───▶│  Miner   │───▶│ Chunking │───▶│ Drawer   │
│  对话    │    │  采集器   │    │  切分    │    │  抽屉存储  │
└──────────┘    └──────────┘    └──────────┘    └──────────┘
                                                      │
                                                      ▼
┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  查询    │◀───│ Searcher │◀───│ Metadata │◀───│ ChromaDB │
│  用户    │    │  搜索器   │    │  过滤    │    │  向量库   │
└──────────┘    └──────────┘    └──────────┘    └──────────┘

三、关键技术

3.1 Palace记忆宫殿结构

这是MemPalace的核心创新——将记忆组织成宫殿结构:

+------------------------------------------------------------+
|  WING: Project/Person                                      |
|                                                            |
|    +----------+            +----------+                    |
|    |  Room A  |  --hall--  |  Room B  |                    |
|    +----------+            +----------+                    |
|         │                                                  |
|         v                                                  |
|    +----------+      +----------+                          |
|    |  Closet  | ---> |  Drawer  |  # 原文抽屉              |
|    +----------+      +----------+                          |
+------------------------------------------------------------+
            │
          tunnel
            │
+------------------------------------------------------------+
|  WING: Another Project/Person                               |
+------------------------------------------------------------+

核心概念详解

概念作用示例
Wing项目/人员隔离wing_orion, wing_kai
Room主题分类auth-migration, graphql-switch
Hall记忆类型hall_facts, hall_events, hall_advice
Closet摘要索引指向原文的可搜索摘要
Drawer原文抽屉原始内容,精确存储
TunnelWing间连接跨项目的同一主题连接

3.2 混合搜索算法

searcher.py 实现了向量搜索 + BM25关键词的混合排序:

# 核心混合排序逻辑
def _hybrid_rank(
    results: list,
    query: str,
    vector_weight: float = 0.6,
    bm25_weight: float = 0.4,
) -> list:
    """
    1. 向量相似度使用绝对cosine相似度:max(0, 1 - distance)
    2. BM25使用Okapi-BM25公式,IDF基于候选集计算
    3. BM25结果min-max归一化后与向量相似度加权组合
    """

搜索流程

def search_memories(query, palace_path, wing=None, room=None, n_results=5):
    # Step 1: 直接搜索抽屉(底层保证)
    drawer_results = drawers_col.query(
        query_texts=[query],
        n_results=n_results * 3,  # 过采样用于重排
        ...
    )
    
    # Step 2: 搜索closet获取排名信号
    closet_boost_by_source = {}
    
    # Step 3: 基于closet排名应用boost
    CLOSET_RANK_BOOSTS = [0.40, 0.25, 0.15, 0.08, 0.04]
    
    # Step 4: Drawer-grep上下文扩展
    # 对于closet-boosted结果,用关键词匹配找到更好的chunk
    
    # Step 5: BM25混合重排
    hits = _hybrid_rank(hits, query)

设计亮点:抽屉搜索是地板(floor),永远不会被closet结果隐藏。Closet只是排名信号,不是门控。

3.3 知识图谱实现

knowledge_graph.py 实现了时序实体关系图:

class KnowledgeGraph:
    """
    SQLite-backed temporal entity-relationship graph
    特点:
    - 实体节点 + 类型化关系边
    - 时序有效性(valid_from → valid_to)
    - 源引用(关联到原始记忆)
    """
    
    def add_triple(self, subject, predicate, obj, valid_from=None, valid_to=None):
        """添加关系三元组"""
        
    def invalidate(self, subject, predicate, obj, ended=None):
        """标记关系失效"""
        
    def query_entity(self, name, as_of=None, direction="outgoing"):
        """查询实体在某时间点的状态"""

数据库模式

CREATE TABLE entities (
    id TEXT PRIMARY KEY,
    name TEXT NOT NULL,
    type TEXT DEFAULT 'unknown',
    properties TEXT DEFAULT '{}',
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE triples (
    id TEXT PRIMARY KEY,
    subject TEXT NOT NULL,
    predicate TEXT NOT NULL,
    object TEXT NOT NULL,
    valid_from TEXT,           -- 时序:开始时间
    valid_to TEXT,             -- 时序:结束时间(NULL=当前有效)
    confidence REAL DEFAULT 1.0,
    source_closet TEXT,        -- 指向原文
    source_file TEXT,
    extracted_at TEXT DEFAULT CURRENT_TIMESTAMP
);

3.4 可插拔后端架构

backends/base.py 定义了后端接口:

class BaseCollection(ABC):
    """最小集合接口,MemPalace其余部分依赖此接口"""
    
    @abstractmethod
    def add(self, *, documents, ids, metadatas=None):
        raise NotImplementedError
    
    @abstractmethod
    def upsert(self, *, documents, ids, metadatas=None):
        raise NotImplementedError
    
    @abstractmethod
    def query(self, **kwargs) -> Dict[str, Any]:
        raise NotImplementedError
    
    @abstractmethod
    def get(self, **kwargs) -> Dict[str, Any]:
        raise NotImplementedError
    
    @abstractmethod
    def delete(self, **kwargs) -> None:
        raise NotImplementedError
    
    @abstractmethod
    def count(self) -> int:
        raise NotImplementedError

这种设计允许替换ChromaDB为其他向量数据库(如Qdrant、Pinecone),无需修改上层代码。

3.5 并发安全机制

palace.py 实现了跨平台文件锁:

@contextlib.contextmanager
def mine_lock(source_file: str):
    """跨平台文件锁,防止多agent并发写入同一文件"""
    lock_path = f".../{hashlib.sha256(source_file.encode()).hexdigest()[:16]}.lock"
    
    if os.name == "nt":  # Windows
        import msvcrt
        msvcrt.locking(lf.fileno(), msvcrt.LK_LOCK, 1)
    else:  # Unix
        import fcntl
        fcntl.flock(lf, fcntl.LOCK_EX)
    
    yield

四、核心代码分析

4.1 Miner数据采集

miner.py 的核心是文件路由和chunking:

# 文件路由到房间的优先级
def detect_room(filepath, content, rooms, project_path):
    """
    1. 文件夹路径匹配房间名/关键词
    2. 文件名匹配房间名
    3. 内容关键词评分
    4. 默认fallback: "general"
    """

# 文本分块(Drawer创建)
CHUNK_SIZE = 800      # 每块字符数
CHUNK_OVERLAP = 100   # 重叠区域

def chunk_text(content, source_file):
    """按段落边界切分文本,保留语义完整性"""

4.2 Closet构建逻辑

palace.py 中的build_closet_lines

def build_closet_lines(source_file, drawer_ids, content, wing, room):
    """
    从原文中提取可搜索的索引行
    格式: topic|entities|→drawer_ids
    """
    
    # 1. 提取实名词(大小写敏感,≥2次出现)
    words = re.findall(r"\b[A-Z][a-z]{2,}\b", window)
    # 过滤停用词:The, This, When, Where...
    
    # 2. 提取关键短语(动词+上下文)
    patterns = [r"(?:built|fixed|wrote|added|pushed|...)\s+[\w\s]{3,40}"]
    
    # 3. 提取Markdown标题
    # 4. 提取引用

4.3 MCP Server架构

mcp_server.py 实现了完整的MCP协议:

# 工具注册表
TOOLS = {
    # 读取工具
    "mempalace_status": {...},
    "mempalace_search": {...},
    "mempalace_kg_query": {...},
    "mempalace_traverse": {...},
    
    # 写入工具
    "mempalace_add_drawer": {...},
    "mempalace_delete_drawer": {...},
    "mempalace_kg_add": {...},
    
    # 导航工具
    "mempalace_follow_tunnels": {...},
    "mempalace_create_tunnel": {...},
}

五、创新亮点

5.1 vs 其他AI记忆系统

特性MemPalaceMem0ZepSupermemory
存储方式原文verbatim摘要提取摘要+图混合
检索模式向量+BM25混合向量向量+图向量
知识图谱SQLite本地云端Neo4j云端-
API依赖需要需要需要
LongMemEval R@596.6%~85%~85%~99%
成本免费$19-249/mo$25/mo+-

5.2 核心创新点

  1. 原文优先策略:不做摘要,存储一切,通过结构化索引让搜索更精准
  2. Palace记忆宫殿:Wing-Room-Hall-Drawer的多层组织,比扁平索引提升34%召回率
  3. 混合搜索Floor机制:抽屉搜索是地板,closet只是排名信号,永不隐藏结果
  4. Drawer-grep上下文:向量搜索可能选错chunk,用关键词在源文件中找到更好的
  5. AAAK压缩格式:实验性的人类和LLM可读的压缩语言
  6. 时序知识图谱:SQLite实现,支持时间旅行查询

5.3 基准测试表现

LongMemEval R@5 (500题):
├── Raw模式(纯向量): 96.6% ★ 无API调用
├── Hybrid v4 (held-out): 98.4% ★ 可复现
└── Hybrid + LLM rerank: ≥99% (使用Haiku等轻量模型)

LoCoMo R@10 (1986题):
├── Raw模式: 60.3%
└── Hybrid v5: 88.9%

ConvoMem (250项): 92.9%
MemBench (8500项): 80.3%

六、实践应用

6.1 快速开始

# 安装
pip install mempalace

# 初始化
mempalace init ~/projects/myapp

# 采集数据
mempalace mine ~/projects/myapp           # 项目文件
mempalace mine ~/chats/ --mode convos    # 对话导出

# 搜索
mempalace search "why did we switch to GraphQL"

# Claude Code集成
claude mcp add mempalace -- python -m mempalace.mcp_server

6.2 Python API使用

from mempalace.searcher import search_memories
from mempalace.knowledge_graph import KnowledgeGraph

# 语义搜索
results = search_memories(
    "auth decisions",
    palace_path="~/.mempalace/palace"
)

# 知识图谱查询
kg = KnowledgeGraph()
kg.add_triple("Kai", "works_on", "Orion", valid_from="2025-06-01")

# 查询实体的历史状态
facts = kg.query_entity("Maya", as_of="2026-01-20")

# 时间线
timeline = kg.timeline("Orion")

6.3 扩展方向建议

  1. 支持更多后端:实现Pinecone、Qdrant等后端适配器
  2. LLM重排优化:当前是可选步骤,可以集成更轻量的重排模型
  3. AAAK改进:当前实验性质,可研究更好的压缩算法
  4. 多模态支持:扩展到图像、音频记忆
  5. 协作功能:多人共享的分布式Palace

七、总结与思考

7.1 学习收获

  1. 架构设计:可插拔后端、多层抽象、接口驱动的设计值得学习
  2. 搜索工程:混合搜索的floor机制、drawer-grep上下文扩展是精妙的工程决策
  3. 本地优先:完全不依赖外部API的设计在隐私敏感场景很有价值
  4. 时序数据:知识图谱的时序有效性设计优雅而实用

7.2 可借鉴之处

场景借鉴点
构建AI应用记忆层Palace结构的多层组织
设计向量搜索系统混合搜索 + floor机制
实现知识图谱SQLite + 时序有效性
MCP工具开发完整的工具注册和参数白名单
审计日志WAL机制保护数据安全

7.3 潜在改进方向

  1. Benchmarks透明化:文档中已承认早期宣传数据有误,这种诚实态度值得肯定
  2. AAAK实验状态:README中明确标注了实验性质,避免误导用户
  3. 安全考虑:WAL脱敏、文件锁、权限控制等安全措施完整

相关链接


本笔记基于 v3.3.0 版本分析,代码细节可能随版本更新而变化。