本地优先的 AI 记忆系统 MemPalace:从零构建语义记忆层,让 AI 记住你的一切
背景介绍:AI 为何总像失忆的金鱼
用过 Claude Code、Cursor 或 GitHub Copilot 的同学应该都有一个共同的痛点:每次开启新对话,AI 就是一张白纸。你上周在这项目里做过什么技术选型决策、踩过什么坑、为什么放弃 GraphQL 改用 REST——AI 统统不知道,只能靠你反复唠叨。
现有的解决方案有几条路:
- Mem0:云端记忆系统,效果不错但数据得上传到第三方,隐私敏感项目直接 pass
- Supermemory:书签式的记忆管理,太偏信息收藏而非代码上下文
- 手动写 CLAUDE.md:最朴素但最可靠,缺点是完全靠人肉维护
MemPalace 走的是第四条路:本地优先、语义检索、零 API 调用。它的核心设计理念是:不压缩、不摘要,直接原文存储,用向量检索来找到相关内容。听起来简单,但背后的工程实现相当有技术含量——96.6% 的 R@5 召回率(不需要 LLM 参与)已经超过了大多数闭源商业方案。
这篇长文会从架构设计、核心概念、代码实现、实战使用、性能优化等维度,把 MemPalace 拆解透。
一、核心架构:宫殿式记忆的隐喻
MemPalace 的名字来自「记忆宫殿」(Method of Loci)——这是一种古老的记忆术,通过在脑海中构建一个熟悉的空间,把要记住的信息「放」在不同的位置,回忆时按位置走一遍即可。
MemPalace 把这个隐喻搬进了代码世界:
项目 (Palace)
├── wing(侧翼)= 按人/项目分的记忆空间
│ ├── room(房间)= 话题/主题
│ │ └── drawer(抽屉)= 具体的原始内容
└── knowledge-graph = 时间线感知的实体关系图
三层嵌套结构解决了两个核心问题:
1. 搜索范围的可控性
传统方案把所有记忆塞进一个向量数据库,检索时是全量搜索。MemPalace 的 wing/room/drawer 结构让你可以按「只查这个项目的记忆」或「只查这个话题的讨论」,避免上下文污染。Claude Code 的集成就是按 project wing 来组织的,每次 mempalace wake-up 只加载当前项目的上下文。
2. 原文保留而非摘要
很多记忆系统会自动摘要压缩内容,代价是丢失细节。MemPalace 直接存原文(verbatim),检索靠向量相似度,召回的是完整原始记忆,交给 LLM 自己判断哪些有用。
架构分层:
┌─────────────────────────────────────────────────────────┐
│ CLI / MCP Server │
│ (mempalace mine / wake-up / search) │
├─────────────────────────────────────────────────────────┤
│ Agents Layer │
│ (specialist agents, diaries, MCP tool access) │
├─────────────────────────────────────────────────────────┤
│ Knowledge Graph │
│ (SQLite-backed temporal entity graph) │
├─────────────────────────────────────────────────────────┤
│ Retrieval Engine │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │
│ │ ChromaDB │ │ Temporal │ │ Preference │ │
│ │ (semantic) │ │ Boosting │ │ Patterns │ │
│ └─────────────┘ └─────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Storage Layer │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Drawers │ │ Wings │ │
│ │ (raw text) │ │ (metadata) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
二、核心概念详解
2.1 Palace(宫殿)
一个 Palace 对应一个顶层存储单元,通常是一个机器上的所有记忆集合,或者一个组织的多人记忆共享空间。mempalace init ~/projects/myapp 初始化的就是当前用户视角下的一个 Palace。
Palace 的存储结构:
~/projects/myapp/.mempalace/
├── index/
│ ├── chroma/
│ └── metadata.json
├── drawers/ # 原始记忆文本
│ ├── d_abc123.txt
│ └── d_def456.txt
├── wings/ # wing 配置
│ └── wing_project_1.json
└── knowledge-graph.db # SQLite 时序图谱
2.2 Wing(侧翼)
Wing 是记忆的第一级分区。最典型的用法是「按项目」或「按人」分 wing。
# mine 时指定 wing
mempalace mine ~/projects/myapp --wing myproject
# mine Claude Code 会话时按项目自动分 wing
mempalace mine ~/.claude/projects/ --mode convos --wing per-project
Wing 的 metadata 里存储了创建时间、最近访问时间、标签等信息。检索时可以限定 wing:
mempalace search "为什么用 Postgres" --wing myproject
2.3 Room(房间)
Room 是 wing 下的二级组织,对应话题或主题。自动根据内容聚类生成,也支持手动指定。
2.4 Drawer(抽屉)
Drawer 是最小的存储单元,一条原始记忆。可能是:
- 一段对话记录(Claude Code session 的一个 chunk)
- 一个项目的 README 或设计文档
- 一段代码注释
- 一个决策记录
Drawer 的设计哲学是不可变:存入后不修改,只在知识图谱层维护引用关系。
2.5 Knowledge Graph(知识图谱)
MemPalace 不只是向量检索,还维护了一个 SQLite-backed 的时序实体关系图谱:
# 知识图谱操作示例
from mempalace import KnowledgeGraph
kg = KnowledgeGraph("path/to/knowledge-graph.db")
# 添加实体关系
kg.add_entity("决策", "使用 Postgres 而非 MySQL", timestamp=1700000000)
kg.add_relation("使用 Postgres 而非 MySQL", "原因", "MySQL 8.x 的 JSON 支持不够成熟")
kg.add_relation("使用 Postgres 而非 MySQL", "时间", "2024-01-15 技术评审会")
# 查询时间线
results = kg.query_timeline(entity="Postgres", start=1698000000, end=1710000000)
# 使失效(比如某决策被推翻)
kg.invalidate("使用 Postgres 而非 MySQL", reason="新版本 MySQL 9.0 JSON 性能已追平")
这个图谱的价值在于:向量检索擅长「相似性」,但知识图谱擅长「因果链」。两者结合才能回答「我们为什么在 3 月份做了这个决定」这类时间敏感的推理问题。
三、检索引擎深度解析
这是 MemPalace 最硬核的部分。核心数字:
- Raw(纯语义检索,无 LLM):R@5 = 96.6%
- Hybrid v5(加入关键词提升 + 时间近邻 + 偏好模式):R@10 = 88.9%(LoCoMo 数据集)
- Rerank 管道(+ LLM 重排):≥99%
3.1 Raw 检索管道
用户 query
↓
Embedding(本地模型,默认 bge-m3 或类似)
↓
向量相似度检索 (ChromaDB, top-K=50)
↓
候选重排 → top-5 返回
关键设计点:
1. 零 LLM 调用
纯向量检索,不依赖任何 API key。这是 benchmark 能到 96.6% 的核心——没有中间商(LLM)赚差价,直接拿向量相似度说话。
2. Chunking 策略
对话记忆被切分成合理的 chunk。MemPalace 没有固定 chunk size,而是根据语义边界(消息边界、主题切换)动态切分,避免一句话被切成两半。
3. 混合索引
支持 ChromaDB 作为默认后端,同时也支持 Qdrant、Pinecone 等替代后端。接口定义在 mempalace/backends/base.py:
from abc import ABC, abstractmethod
class MemoryBackend(ABC):
@abstractmethod
def add(self, texts: list[str], metadata: list[dict]) -> list[str]:
"""添加记忆片段,返回 IDs"""
pass
@abstractmethod
def search(self, query: str, top_k: int = 10, filter_metadata: dict = None) -> list[dict]:
"""语义检索"""
pass
@abstractmethod
def delete(self, ids: list[str]) -> None:
"""删除记忆"""
pass
@abstractmethod
def update(self, id: str, text: str, metadata: dict = None) -> None:
"""更新记忆"""
pass
换后端只需实现这几个方法,不用动上层代码。
3.2 Hybrid v5 增强
Raw 检索只靠语义相似度,但有些场景语义相似度不够:
- 查询「上次数据库迁移是什么时候」,时间信息很关键
- 查询「项目里用到的 Python 库」,关键词「Python」比语义重要
- 查询「张三关于 API 设计的讨论」,偏好特定人
Hybrid v5 加入了三个增强层:
# 伪代码展示混合检索逻辑
def hybrid_search(query: str, wing: str = None):
# 1. 语义检索
semantic_results = vector_index.search(query, top_k=50)
# 2. 关键词提升
keyword_matches = keyword_index.search(query)
for result in semantic_results:
if result['text'] in keyword_matches:
result['score'] += BOOST_WEIGHT['keyword']
# 3. 时间近邻提升(查询涉及的时间窗口内的记忆得分更高)
temporal_context = extract_temporal_context(query) # "上周"、"3月份"
if temporal_context:
for result in semantic_results:
time_distance = abs(result['timestamp'] - temporal_context['center'])
result['score'] += BOOST_WEIGHT['temporal'] / (time_distance + 1)
# 4. 偏好模式(根据用户历史查询习惯加权)
preference_pattern = get_user_preference(query)
for result in semantic_results:
if matches_preference(result, preference_pattern):
result['score'] += BOOST_WEIGHT['preference']
# 排序返回
return sorted(semantic_results, key=lambda x: x['score'], reverse=True)[:10]
这些增强让 R@10 从 60.3% 提升到 88.9%(LoCoMo 数据集),提升幅度非常显著。
3.3 LLM Rerank(可选层)
如果对召回质量要求极高,可以加一层 LLM 重排:
# rerank 示例
from mempalace.rerank import LLMReranker
reranker = LLMReranker(model="claude-haiku") # 小模型即可,无需 Sonnet
top_20 = vector_index.search(query, top_k=20)
top_5 = reranker.rerank(query, top_20)
# 返回最相关的 5 条
Reranker 的 prompt 大概是:「给定用户查询,从以下候选记忆中选出最相关的 5 条,解释为什么」,模型输出排序。配合任何 capable 的本地模型(实测 Claude Haiku 就够用),最终召回率可达 ≥99%。
四、Claude Code 集成:真正的上下文连续性
MemPalace 最实用的场景是给 Claude Code 注入记忆。下面看几个核心集成点。
4.1 自动保存钩子(Auto-save Hooks)
MemPalace 提供了两个 Claude Code hooks:
# ~/.claude/hooks/mempalace_save.py
# post-context-compaction hook:上下文压缩前自动保存
# periodic-save hook:定期保存当前会话状态
import subprocess
import sys
def on_context_compaction(context_before: str, context_after: str):
"""上下文被压缩前,把即将丢失的内容存到 MemPalace"""
# context_before 是压缩前的完整上下文
# 提取有价值的信息存入 palace
subprocess.run([
"mempalace", "add",
"--content", context_before,
"--wing", "current-project",
"--room", "claude-sessions"
], check=True)
def on_periodic_save(session_context: str):
"""每 N 分钟自动保存"""
subprocess.run([
"mempalace", "add",
"--content", session_context,
"--wing", "current-project",
"--room", "claude-sessions"
], check=True)
配置方式是在 Claude Code 的 hooks 配置文件中引用:
// ~/.claude/settings.json
{
"hooks": {
"post-context-compaction": "python3 ~/.claude/hooks/mempalace_save.py --event post-context-compaction",
"periodic-save": "python3 ~/.claude/hooks/mempalace_save.py --event periodic-save"
}
}
4.2 启动恢复(wake-up)
新会话开始时,用 mempalace wake-up 把相关记忆注入上下文:
# 自动加载当前目录相关记忆
mempalace wake-up
# 指定项目 wing
mempalace wake-up --wing myproject
# 只加载最近 30 天的记忆(避免太旧的上下文)
mempalace wake-up --max-age 30d
wake-up 输出的格式可以直接粘贴到 Claude Code 的输入框,或者通过 MCP 接口自动注入。
4.3 MCP Server
MemPalace 内置了 29 个 MCP 工具,覆盖 palace 的读写、图谱操作、wing 导航、agent diary 等:
{
"tools": [
{ "name": "mempalace_search", "description": "搜索记忆" },
{ "name": "mempalace_add", "description": "添加记忆" },
{ "name": "mempalace_list_wings", "description": "列出所有 wing" },
{ "name": "mempalace_wake_up", "description": "加载当前上下文相关记忆" },
{ "name": "mempalace_query_graph", "description": "查询知识图谱" },
{ "name": "mempalace_add_entity", "description": "添加图谱实体" },
{ "name": "mempalace_add_relation", "description": "添加图谱关系" },
{ "name": "mempalace_list_agents", "description": "列出所有 agent diaries" },
// ... 共 29 个
]
}
这意味着在支持 MCP 的工具(Claude Code、Cursor、OpenClaw 等)里,可以直接用 tool 调用 MemPalace,无需 shell 命令。
五、Python API 与自定义集成
除了 CLI,MemPalace 也提供了完整的 Python API,适合集成到现有工具中:
5.1 基础使用
from mempalace import Palace, Wing, Drawer
# 初始化
palace = Palace("~/my-palace")
# 添加记忆
palace.add(
content="""技术决策记录:
- 2026-01-15:选型评审决定使用 Postgres 而非 MySQL
- 原因:Postgres 的 JSONB 列式存储更适合我们的半结构化数据
- 参与人:张三、李四
- 结论:MySQL 候选,等 Postgres 验证后再评估
""",
wing="backend-api",
room="architecture",
metadata={
"type": "decision",
"date": "2026-01-15",
"participants": ["张三", "李四"]
}
)
# 语义搜索
results = palace.search("Postgres 选型", wing="backend-api", top_k=5)
for r in results:
print(f"[{r['score']:.3f}] {r['text'][:200]}...")
5.2 时间线查询
from mempalace import KnowledgeGraph
kg = KnowledgeGraph("~/my-palace/knowledge-graph.db")
# 查询某个实体的完整时间线
timeline = kg.get_timeline("API Gateway")
for event in timeline:
print(f"{event['timestamp']}: {event['event']} → {event['outcome']}")
# 查询两个实体之间的路径(类似 "A 和 B 之间有什么关联")
path = kg.find_path("Postgres", "JSONB")
print("关联路径:", " → ".join(path))
5.3 Agent 记忆共享
每个 specialist agent 可以在 palace 里拥有自己的 wing 和 diary:
from mempalace import AgentDiary
# 给一个 agent 创建专属 diary
diary = AgentDiary(palace, agent_name="code-review-agent")
# agent 执行任务后写日记
diary.write(f"""任务:审查 PR #234 的安全性
发现:
- SQL 注入风险:user_id 参数未做参数化查询
- 修复:已要求 PR 作者使用 prepared statement
时间:{datetime.now()}
""")
# agent 下次启动时读自己的日记
yesterday_notes = diary.read(since=datetime.now() - timedelta(days=1))
六、性能优化与生产配置
6.1 Embedding 模型选择
默认使用 bge-m3( multilingual),支持 100+ 语言,embedding 维度 1024。如果追求更快的检索速度,可以换轻量模型:
from mempalace import Palace
from mempalace.embedders import FastEmbedder
palace = Palace("~/my-palace")
palace.configure_embedder(FastEmbedder(model="all-MiniLM-L6-v2"))
| 模型 | 维度 | 速度 | 质量 |
|---|---|---|---|
| bge-m3 | 1024 | 中 | 最高(多语言) |
| all-MiniLM-L6-v2 | 384 | 快 | 良好 |
| bge-small | 384 | 最快 | 一般 |
6.2 向量数据库后端
from mempalace import Palace
from mempalace.backends import QdrantBackend
# 切换到 Qdrant(支持分布式)
palace = Palace("~/my-palace")
palace.configure_backend(QdrantBackend(
url="http://localhost:6333",
collection="mempalace"
))
6.3 存储空间估算
| 内容类型 | 平均大小 | 10000 条存储 |
|---|---|---|
| 短对话 chunk | ~500 bytes | ~5 MB |
| 长代码块 | ~5 KB | ~50 MB |
| 设计文档 | ~50 KB | ~500 MB |
| 向量索引 | ~2 KB/条 | ~20 MB |
总开销:约 300MB base(embedding 模型)+ 存储内容 + 向量索引。10000 条对话记忆大约 75MB 整体。
6.4 多机器同步
MemPalace 默认本地存储,但通过 wing 的 export/import 可以实现有限的多端同步:
# 导出 wing
palace.export_wing("work-laptop", output="/tmp/work-wing.tar.gz")
# 导入 wing(另一台机器)
palace.import_wing("/tmp/work-wing.tar.gz", merge_strategy="prefer-newer")
七、与 Mem0/Mastra/Hindsight 的横向对比
MemPalace 的优势在哪里?按实际测试数据说话:
| 维度 | MemPalace | Mem0 | Mastra | Hindsight |
|---|---|---|---|---|
| 存储位置 | 本地 | 云 | 云 | 本地 |
| API 依赖 | 无 | 需要 | 需要 | 部分需要 |
| R@5(无 LLM) | 96.6% | N/A | N/A | N/A |
| 知识图谱 | ✅ SQLite | ❌ | ❌ | ❌ |
| MCP Server | ✅ 29 tools | ❌ | ✅ | ❌ |
| Claude Code 钩子 | ✅ | ❌ | ❌ | ❌ |
| 多后端支持 | ✅ ChromaDB/Qdrant | ❌ | ❌ | ❌ |
| Rerank 支持 | ✅ Haiku 即可 | 需要大模型 | 需要 | 需要 |
核心差异:MemPalace 是唯一一个在「零 API + 本地存储」约束下做到 96%+ R@5 的方案。 这对于隐私敏感项目(医疗、金融、内部代码)和成本敏感场景(有大量长期会话但不想付 API 费用)特别有价值。
八、安装与快速上手
8.1 安装
pip install mempalace
Python 3.9+,无需其他依赖。
8.2 初始化
mempalace init ~/projects/myapp
8.3 挖矿(Mine)
把内容注入 palace:
# 挖掘项目文件
mempalace mine ~/projects/myapp
# 挖掘 Claude Code 会话(按项目分 wing)
mempalace mine ~/.claude/projects/ --mode convos --wing per-project
# 挖掘指定项目并加标签
mempalace mine ~/projects/myapp --wing api-server --tags "backend,python"
8.4 搜索
mempalace search "为什么弃用 GraphQL"
# 限定 wing
mempalace search "JWT token 刷新" --wing api-server
# 带时间过滤
mempalace search "性能优化" --after 2026-01-01 --before 2026-03-31
8.5 启动恢复
mempalace wake-up
九、总结与展望
MemPalace 解决了一个很具体但很痛的问题:AI 的会话级失忆。
它没有走「云端大统一记忆平台」的老路,而是选择了本地优先、语义检索、知识图谱增强的工程路线。几个值得关注的点:
- 96.6% R@5 靠纯向量检索实现——这说明在记忆检索这个场景,semantic search 已经足够好了,LLM 重排是锦上添花而非必须
- wing/room/drawer 的层级设计——解决了全量搜索的上下文污染问题,让记忆真正可复用
- 零 API 依赖——对于企业内网项目和隐私敏感代码,这点比什么都重要
- 知识图谱 + 向量检索的双引擎——时间敏感和因果链类查询靠图谱,模糊相似性查询靠向量,两者互补
展望未来,MemPalace 的几个演进方向值得关注:
- 多端同步协议:目前 export/import 是手动的,未来可能支持 CRDT 类的自动冲突合并
- 更强的图谱推理:当前是关系存储 + 时间线查询,未来可能加入规则引擎做自动推理
- 多人协作模式:目前的 wing 是单用户视角,多人共享记忆的权限管理还是个空白
GitHub 上 49K stars 的热度说明社区对这个方向是认可的。如果你也在被 AI 失忆困扰,强烈建议跑一遍 Quickstart 试试——整个安装过程不超过 5 分钟,但从此 Claude Code 就有了真正的记忆。
相关资源:
- GitHub:https://github.com/MemPalace/mempalace
- PyPI:
pip install mempalace - 官方文档:https://mempalaceofficial.com
- Discord:https://discord.gg/ycTQQCu6kn
- Benchmark 方法论:https://github.com/MemPalace/mempalace/blob/main/benchmarks/BENCHMARKS.md
本文所有 benchmark 数据均来自 MemPalace 官方仓库可复现的测试结果,详见 benchmarks/BENCHMARKS.md。