首页
/ MemPalace 架构与开发规范:从逐字记忆、AAAK 索引到 L0-L3 记忆唤醒栈

MemPalace 架构与开发规范:从逐字记忆、AAAK 索引到 L0-L3 记忆唤醒栈

2026-09-06 15:38:49作者:毕习沙Eudora

MemPalace 是一个以"逐字存储、100% 召回"为设计目标的本地优先 AI 记忆系统,其名字源自古老的"记忆宫殿"(method of loci)技术,并借鉴了 Zettelkasten 卡片盒的交叉引用思想。本文基于仓库中的 AGENTS.md 完整梳理 MemPalace 的设计使命、七条不可妥协的设计原则、Wing/Room/Drawer 宫殿结构与 AAAK 索引层架构、核心模块地图,以及本地开发环境搭建、测试与代码规范,并结合 mempalace/dialect.pymempalace/layers.pymempalace/backends/base.py 等源码印证关键设计,帮助读者快速理解该系统"为什么这样设计"以及如何在其之上开发。

设计使命:记忆即身份,而非搜索或 RAG

AGENTS.md 开篇即给出 MemPalace 的立场声明:它不是搜索引擎、不是 RAG 流水线、也不是向量数据库的包装器,而是一个记忆系统。其核心承诺可以归纳为三点:

  • 逐字(Verbatim)存储:用户说过的每一句话都原样保存,系统"搜索索引、返回原文",从不做摘要或改写;
  • 100% 召回是设计硬性要求:所有搜索路径都以"完整召回"为测量目标,低于它就意味着"遗忘",遗忘意味着一切推倒重来;
  • 数据永不离开本机:所有提取、分块、嵌入与 LLM 辅助精炼默认在用户机器上完成。

这一使命直接体现在其"宫殿"组织结构上(详见 website/concepts/the-palace.md):

概念 作用 说明
Wing(翼) 大类 按人物、项目、主题划分,如"某个人""某个项目"
Room(房间) 时间分组 按天、按会话等时间维度组织
Drawer(抽屉) 逐字内容 存放用户原话的完整文本块,是整个系统的存储原子单位
AAAK 压缩 索引层 一种紧凑的符号化格式(由 dialect.py 实现),让 LLM 可以瞬间扫描数千条条目、精确判断该打开哪个抽屉

这套结构对应了 Zettelkasten 的"小卡片互相引用"与记忆宫殿的"把信息放进想象中的房间"两条思想脉络:抽屉是卡片本体,房间是房间,而 AAAK 索引层则是卡片背面的交叉引用标注。

值得特别指出 AAAK 的边界:从 mempalace/dialect.py 的模块文档可以看出,AAAK 不是无损压缩——它无法从 AAAK 输出还原原文。源码明确注释它是"结构化摘要层(closets),指向原始逐字内容(drawers)"。其格式在 mempalace/dialect.py 中有完整定义:

FORMAT:
  Header:   FILE_NUM|PRIMARY_ENTITY|DATE|TITLE
  Zettel:   ZID:ENTITIES|topic_keywords|"key_quote"|WEIGHT|EMOTIONS|FLAGS
  Tunnel:   T:ZID<->ZID|label
  Arc:      ARC:emotion->emotion->emotion

此外,dialect.py 还定义了通用情绪码表(vul=脆弱、joy=喜悦、fear=恐惧、trust=信任等二十余种,见 mempalace/dialect.pyEMOTION_CODES)与一组语义旗标(ORIGIN 起源时刻、CORE 核心信念、SENSITIVE 需谨慎处理、PIVOT 情绪转折点、DECISION 明确决策、TECHNICAL 技术细节等)。这一设计让"索引层"本身对任意 LLM 都是可直接阅读的纯文本——源码注释强调"任何 LLM 都能原生读懂,无需解码器",这与 AGENTS.md 中"AAAK 让 LLM 瞬间扫描数千条索引"的描述相互印证。

七条不可妥协的设计原则

AGENTS.md 将以下原则列为"non-negotiable"——每个 PR、每个功能、每次重构都必须遵守。理解它们是判断任何 MemPalace 变更是否合理的基准:

  1. Verbatim always(永远逐字):绝不摘要、改写或有损压缩用户数据。用户说了什么,就存什么。这是整个系统的基础承诺。
  2. Incremental only(只增量):初始构建之后采用 append-only 的摄取方式;绝不通过销毁现有数据来重建;操作中途崩溃时必须让既有宫殿保持原样。
  3. Entity-first(实体优先):一切以真实名称为键,并用出生日期、ID 或上下文消歧。"人比主题重要"。
  4. Local-first, zero external API by default(本地优先,默认零外部 API):提取、分块、嵌入、LLM 精炼默认全部在本机完成,使用 Ollama、LM Studio、llama.cpp、vLLM 等本地运行时。外部服务商(Anthropic、OpenAI、Google)仅通过 BYOK 支持,从不强制、从不静默启用;运行在 localhost 上的 Ollama 属于用户机器的一部分,不算外部 API;外部 BYOK 永远是用户的显式选择,既不是默认值,也绝不作为静默回退。
  5. Performance budgets(性能预算):Hook 执行小于 500ms,启动注入小于 100ms——"记忆应该感觉是瞬时的"。
  6. Privacy by architecture(架构即隐私):因为数据物理上从不离开用户机器,所以"不可能"被发送出去;无遥测、无回传、核心操作无外部服务依赖。
  7. Background everything(一切后台化):归档、索引、时间戳、流水线工作全部通过 hook 在后台完成,不打断用户对话,聊天窗口中不为记账工作消耗任何 token。

这些原则在贡献边界上有直接体现:项目不接受用户内容摘要、云存储/同步功能、遥测或分析、核心记忆依赖 API key 的功能,以及任何绕过逐字存储的捷径(AGENTS.md "Contributing" 一节)。

架构总览:数据流、宫殿结构与知识图谱

AGENTS.md 给出的架构蓝图如下,可直接作为理解整个代码库的地图:

User → CLI / MCP Server → Storage Backend (ChromaDB default, pluggable)
                        → SQLite (knowledge graph)

Palace structure:
  WING (person/project)
    └── ROOM (day/topic)
          └── DRAWER (verbatim text chunk)

Index layer (AAAK):
  Compressed pointers → DRAWER locations
  Scanned by LLM to find relevant drawers without reading all content

Knowledge Graph:
  ENTITY → PREDICATE → ENTITY (with valid_from / valid_to dates)

逐层拆解:

  • 入口层:用户通过 CLI(mempalace/cli.py)或 MCP Server(mempalace/mcp_server.py)访问系统。MCP Server 是全部读/写工具的宿主,源码中按 "READ TOOLS / WRITE TOOLS / SETTINGS TOOLS" 分区组织(mempalace/mcp_server.py 起)。
  • 存储层:可插拔的存储后端,默认 ChromaDB。后端契约定义在 mempalace/backends/base.py 中,模块 docstring 明确其对应 docs/rfcs/001-storage-backend-plugin-spec.md(RFC 001):BaseCollection 是每个 collection 的读写接口(仅接受 kwargs),BaseBackend 是按 PalaceRef 寻址的每宫殿工厂,QueryResult/GetResult 是取代 Chroma dict 形状的规范返回类型,并配有统一的错误体系(如 PalaceNotFoundError 同时是 FileNotFoundError 子类以保持旧调用方兼容,见 mempalace/backends/base.py)。仓库中已有 chromapgvectorqdrantmilvussqlite_exact 等后端实现(mempalace/backends/)。
  • 知识图谱层:SQLite 上的时序实体关系图(mempalace/knowledge_graph.py),以 ENTITY → PREDICATE → ENTITY 三元组存储,并带 valid_from / valid_to 时间戳,即关系本身也是随时间演化的。
  • 搜索路径:混合检索,BM25 + 向量。AGENTS.md 将 mempalace/searcher.py 标注为"Semantic search (hybrid BM25 + vector)";从源码看,其中 _bm25_scores() 负责 BM25 打分(mempalace/searcher.py),对外入口为 search()mempalace/searcher.py),还存在仅走 SQLite 的 BM25 降级路径 _bm25_only_via_sqlite()mempalace/searcher.py)。

L0-L3 记忆唤醒栈:性能预算如何落地

AGENTS.md 中"启动注入小于 100ms、记忆应该瞬时"的性能预算,对应实现就是 mempalace/layers.py 的四层记忆栈(详见 website/concepts/memory-stack.md)。模块头部注释给出了精确的 token 预算(mempalace/layers.py):

Layer 0: Identity       (~100 tokens)   — Always loaded. "Who am I?"
Layer 1: Essential Story (~500-800)      — Always loaded. Top moments from the palace.
Layer 2: On-Demand      (~200-500 each)  — Loaded when a topic/wing comes up.
Layer 3: Deep Search    (unlimited)      — Full ChromaDB semantic search.

Wake-up cost: ~600-900 tokens (L0+L1). Leaves 95%+ of context free.

从源码实现看各层的具体形态:

  • L0 IdentityLayer0 类读取用户手写的 ~/.mempalace/identity.txt 纯文本文件(约 100 token),文件不存在时返回占位提示而非报错(mempalace/layers.py);
  • L1 Essential StoryLayer1 类从 ChromaDB 中自动提取权重最高/最近的内容,常量约束非常具体——MAX_DRAWERS = 15(唤醒时最多 15 个片段)、MAX_CHARS = 3200(约 800 token 的硬上限)、MAX_SCAN = 2000(生成时最多扫描 2000 条,mempalace/layers.py)。正是这些硬上限保证了"启动注入"的耗时与 token 成本可控;
  • L2 On-Demand:当某个主题/翼被提及时才按需加载;
  • L3 Deep Search:完整的 ChromaDB 语义搜索,无上限,兜底"100% 召回"目标。

这套分层把 AGENTS.md 中"Background everything"与"瞬时召回"两个原则变成了可度量的工程参数。

核心模块地图

AGENTS.md 的 "Project Structure" 一节是理解代码库组织方式的骨架。下表在其基础上补充了各模块在源码中的定位(mempalace/ 包内路径):

模块 职责
mempalace/mcp_server.py MCP Server,承载全部读/写工具
mempalace/cli.py CLI 分发器
mempalace/config.py 配置 + 输入校验
mempalace/miner.py 项目文件挖掘器
mempalace/convo_miner.py 对话记录挖掘器
mempalace/searcher.py 混合语义搜索(BM25 + 向量)
mempalace/knowledge_graph.py 时序实体关系图谱(SQLite)
mempalace/palace.py 共享宫殿操作
mempalace/palace_graph.py 房间遍历 + 跨翼隧道
mempalace/backends/ 可插拔存储后端(默认 ChromaDB);新后端实现 mempalace/backends/base.py 抽象接口
mempalace/dialect.py AAAK 压缩方言
mempalace/normalize.py 转录格式检测 + 归一化
mempalace/entity_detector.py 从内容自动识别人物/项目
mempalace/entity_registry.py 实体存储与消歧
mempalace/layers.py L0-L3 记忆唤醒栈
mempalace/onboarding.py 交互式首跑设置
mempalace/repair.py 宫殿修复与一致性检查
mempalace/dedup.py 去重
mempalace/migrate.py ChromaDB 版本迁移
mempalace/spellcheck.py 用户消息自动纠错
mempalace/exporter.py 宫殿数据导出
mempalace/hooks_cli.py Hook 管理 CLI
mempalace/query_sanitizer.py 提示词污染防护
mempalace/split_mega_files.py 拆分拼接型大转录文件
mempalace/version.py 版本号的单一事实来源

Hook 脚本位于 hooks/ 目录,AGENTS.md 中特别点名了两个核心脚本:

这两条 hook 正是"Background everything"原则的执行点——在用户对话结束或即将被压缩的时机,后台完成归档,而对话窗口本身不为记账消耗 token。仓库中还提供 Cursor、Antigravity 等 IDE 的 hook 变体(hooks/cursor/hooks/antigravity/)。

本地开发流程:环境搭建、测试与命令

AGENTS.md "Setup" 与 "Commands" 两节给出了完整的开发者命令序列,原样如下(推荐 uv 工作流):

# 环境搭建(推荐)
uv sync --extra dev
# 或使用 pip
pip install -e ".[dev]"

# 运行测试
uv run pytest tests/ -v --ignore=tests/benchmarks

# 带覆盖率的测试
uv run pytest tests/ -v --ignore=tests/benchmarks --cov=mempalace --cov-report=term-missing

# Lint
uv run ruff check .

# 格式化
uv run ruff format .

# 格式检查(CI 模式)
uv run ruff format --check .

几个值得注意的细节:

  • 测试命令统一 --ignore=tests/benchmarks,基准测试(tests/benchmarks/)与单元/集成测试分离,避免 CI 被性能基准拖慢;
  • 依赖管理以 uv.lock 锁定版本(uv.lockpyproject.toml),与 uv sync 配套使用。

代码规范(Conventions)

AGENTS.md 的 "Conventions" 一节定义了所有贡献必须遵守的编码约定:

  • Python 风格:函数/变量用 snake_case,类用 PascalCase
  • Linter:ruff,启用 E/F/W 规则集;
  • Formatterruff format,双引号风格;
  • 提交信息:conventional commits(fix:feat:test:docs:ci:);
  • 测试组织tests/test_*.py,fixture 放在 tests/conftest.py
  • 覆盖率门槛:85%;Windows 上因 ChromaDB 文件锁清理差异放宽到 80%。

输入校验:Verbatim 原则的边界

"Verbatim always" 并不意味着"任何输入都原样入库"。AGENTS.md 将输入校验指向 mempalace/config.py 中的两个函数,源码确认了它们的签名:

  • sanitize_name()mempalace/config.py):校验名称类字段(如 wing/room 名);
  • sanitize_content()mempalace/config.py):校验内容,带 max_length: int = 100_000 的默认长度上限。

即:内容层面严格逐字,但字段层面做格式与长度约束——这与"prompt 污染防护"(mempalace/query_sanitizer.py)共同构成写入侧的安全边界。

面向常见任务的关键文件指引

AGENTS.md 最后给出了一张"按任务找文件"的速查表,这是对该仓库最实用的入口指南,逐条补充源码级说明:

总结

MemPalace 的 AGENTS.md 实质上是一份"架构宪法":它以"记忆即身份"为使命,用"永远逐字、只增量、实体优先、本地优先、性能预算、架构即隐私、一切后台化"七条原则划定了设计边界,再用 Wing/Room/Drawer 的宫殿结构 + AAAK 索引层 + SQLite 时序知识图谱 + L0-L3 唤醒栈给出了完整的技术落地路径。对贡献者而言,开发闭环是:uv sync --extra dev 建环境、uv run pytest tests/ --ignore=tests/benchmarks 跑测试、uv run ruff 保证风格、按"按任务找文件"速查表定位改动点、并以 85% 覆盖率门槛守住质量线。任何新功能在提交前,都应先对照七条原则自检——尤其是"是否绕过了逐字存储""是否引入了静默的外部 API 调用"这两条一票否决项。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388