别再把“AI 记忆”理解成向量库了MemPalace 源码级架构深拆
引言
很多人一提到“AI 记忆系统”,第一反应就是:把历史对话存进向量库,等需要的时候再检索出来。
这个思路当然没错,但它只碰到了问题表面。
当我真正把 MemPalace 的核心源码一路读下来之后,我越来越强烈地意识到:AI 的长期记忆,根本不是“存一下文本”这么简单。 这个项目当前以 Python 为主,核心依赖很少,默认使用 ChromaDB 作为 palace 存储,使用 SQLite 作为知识图谱存储,并通过 MCP Server 把能力暴露给 Claude Code 一类客户端。它在包元数据里把自己描述为“给 AI 一套记忆系统”,而核心包说明也把模块分工写得非常完整。
真正让我觉得这个项目值得认真研究的,不是某个 benchmark 数字有多高,而是它在认真回答一个更难的问题:
如果不依赖云端,不依赖外部 API,也不把所有上下文一股脑塞进 prompt,AI 要怎样拥有一套可持续、可组织、可维护、可被代理主动使用的长期记忆? README、核心模块说明和 MCP Server 的协议设计,几乎都在围绕这个问题展开。
这篇文章,我不准备只讲“怎么安装、怎么运行”,而是想从源码层面,把 MemPalace 真正拆开,看看它到底是怎样把“长期记忆”这件事一步步落地的。
一、MemPalace 到底是什么
从表面上看,MemPalace 像一个“本地 AI 记忆工具”。但如果你顺着它的核心模块往下看,会发现它其实更接近一套 Memory Runtime。
它有明确的分层:
cli.py负责命令入口与调度miner.py负责项目文件入库convo_miner.py负责会话入库normalize.py负责多平台聊天导出归一化searcher.py负责语义检索layers.py负责四层记忆栈knowledge_graph.py负责时序知识图谱palace_graph.py负责主题导航图mcp_server.py负责把整套系统变成 MCP 工具服务
这意味着,MemPalace 想做的根本不只是“本地存聊天记录”。
它在尝试构建的是一套完整链路:
输入进入系统 → 内容被组织成统一记忆单元 → 检索层把相关内容找回来 → 调度层控制哪些记忆先进入上下文 → 结构化层维护事实与主题关系 → 服务层把这些能力交给 AI 代理持续调用。 这就是它和普通本地 RAG 工具最大的区别。
二、这个项目最关键的一句话
在 mcp_server.py 里,有一句非常有代表性的话:
Storage is not memory — but storage + this protocol = memory.
如果你真的做过 AI Agent 或长期上下文系统,就会知道这句话有多准确。
因为很多人误以为:
只要把内容放进数据库,AI 就“有记忆”了。
但 MemPalace 的做法不是这样。
它真正强调的是三件事必须同时成立:
第一,内容要被合理组织。
第二,系统要能在需要时把相关内容找回来。
第三,代理本身要形成一套稳定行为:回答前先查、会话后会写、事实变化时会更新。 mcp_server.py 里通过 PALACE_PROTOCOL 把这种行为约束直接写进了系统协议。
所以 MemPalace 的核心,不是“存储本身”,而是:
存储 + 检索 + 行为协议 = 记忆系统。
这就是它比很多“向量库封装器”更值得研究的地方。
三、项目资料是怎么被放进记忆宫殿的
在项目资料这条链路上,核心文件是 miner.py。
它不是简单地遍历目录、读文件、做 embedding,然后完事。
它走的是一条明显带工程思维的路径:
先读项目根目录的 mempalace.yaml 配置;
然后扫描目录,尊重 .gitignore;
过滤掉 .git、node_modules、__pycache__、dist、build 等常见噪声目录;
只保留可读扩展名;
再根据目录结构、文件名和内容关键词,把文件路由到某个 room;
最后按字符和换行边界切成 chunk,写入 palace。每个 chunk 都会成为一个 drawer,并带上 wing、room、source_file、chunk_index、added_by、filed_at、source_mtime 等 metadata。
这里最值得注意的,不是“它会切 chunk”,而是它的整体思路:
优先相信项目本身已有的结构,而不是一开始就把所有理解都交给模型。
这是非常成熟的工程判断。
因为真实项目里的知识并不是平铺的,它天然带着目录、模块、文件名、文档分区、约定俗成的结构信号。MemPalace 在这一层做的事情,本质上是在说:
先用最稳定、最便宜、最可解释的方式把内容初步归位,再用语义检索去补足规则无法覆盖的模糊区。
这种路线并不炫技,但非常适合做长期记忆系统。
四、聊天记录又是怎么进入系统的
另一条核心链路是会话入库,也就是 normalize.py 和 convo_miner.py。
normalize.py 做的第一件事不是理解内容,而是做协议兼容。它支持:
- Claude.ai JSON
- ChatGPT
conversations.json - Claude Code JSONL
- OpenAI Codex CLI JSONL
- Slack JSON
- 普通文本 transcript
它的目标很明确:
把这些不同来源、不同结构的聊天导出,统一转成一种内部 transcript 表示。
更有意思的是,它并没有只保留“用户说了什么、AI 回了什么”。
对于 Claude Code 这类会话,它还会保留 tool_use 和 tool_result 的痕迹,只不过不会原样保留完整 JSON,而是做了轻量格式化和裁剪,比如:
[Bash] ...[Read path][Grep] pattern in target
同时会对 Bash 输出、Grep 结果做限量保留,避免工具输出过长,把记忆库变成日志仓库。
这一点特别关键。
因为在真正的 Agent 场景里,最有价值的往往不是最后一句答案,而是:
- 它读了哪些文件
- 它执行了哪些命令
- 它 grep 了什么
- 它遇到了什么错误
- 它是通过什么路径定位到问题的
换句话说,MemPalace 不只是保存“对话结果”,它还在尽量保存解决过程的痕迹。
接下来 convo_miner.py 会把这些归一化后的 transcript 进一步切成 drawer。默认模式下,它按“一个用户问题 + 后续 AI 响应”作为一个 exchange chunk;如果不是标准 transcript,就退化到按段落或行组切块。它还支持一个 general 模式,把会话直接抽取成 decision、preference、milestone、problem、emotional 这几类记忆。写入时,还会额外打上 ingest_mode=convos 和 extract_mode=exchange/general 的 metadata。
这说明 MemPalace 的会话处理,并不是“简单存档”,而是在尝试把会话真正变成可组织、可检索、可继续加工的记忆对象。
五、理解 MemPalace,必须先理解 drawer
无论是项目资料,还是聊天记录,最终都会被收敛成一种统一对象:drawer。
这是整个系统最重要的抽象。
drawer 不是一段普通文本,它是:
- 某段原文或半结构化内容
- 归属于某个 wing
- 落在某个 room
- 来自某个 source file
- 具有写入时间、来源、切片序号等 metadata 的最小记忆单元
一旦你理解了 drawer,整个系统的设计就会突然变得很清晰:
miner.py负责生产 drawerconvo_miner.py负责生产 drawersearcher.py负责回收 drawerlayers.py负责选择 drawermcp_server.py负责暴露 drawer 的增删改查和检索能力
换句话说,MemPalace 的本质,不是“文件库”也不是“聊天库”,而是:
一个以 drawer 为核心对象的本地记忆系统。
这就是它统一异构输入的方式。
六、它的检索为什么比普通“向量搜索”更像记忆系统
searcher.py 的定位很克制:
它做 semantic search,但明确强调返回的是 verbatim text,不是摘要。
它的典型路径是:
- 获取 collection
- 根据
wing/room构造 where filter - 调用 Chroma
query() - 返回 drawer 原文、metadata 和 distance
- 展示相似度与来源信息
这看起来像是普通向量搜索,但它有两个重要差异。
第一,它并不是只靠向量。
它先做 wing/room 收窄,再做 embedding query。也就是说,它天然就是:
metadata filter + 向量检索
这种方式虽然不算花哨,却极其实用。很多检索效果提升,本质上就来自正确的检索范围约束,而不是某个神奇模型。
第二,它明确把自己的职责限制在“找回原文”,而不是提前替你总结答案。
这非常重要。
因为长期记忆系统最怕的一件事,就是在检索阶段就把原始上下文损耗掉。
MemPalace 在这一层非常克制:尽量只负责“把过去的东西找回来”。
当然,它当前还不是完美检索系统。路线图已经明确提到 hybrid search、time-decay scoring 等增强能力,说明作者也很清楚:目前这套检索体系的主轴还是“向量 + metadata”,对精确术语、错误码、代码符号、路径这类内容,仍有进一步升级空间。
七、四层记忆栈,才是这个项目真正的灵魂
如果说 drawer 是存储抽象,
那 layers.py 就是 MemPalace 的上下文调度抽象。
它把记忆分成四层:
- L0:Identity
- L1:Essential Story
- L2:On-Demand Recall
- L3:Deep Search
L0 很简单,从 ~/.mempalace/identity.txt 读取“我是谁”;
L1 会从 palace 里抽出一批高权重 drawer,按 room 组织成较短的 wake-up text;
L2 用于按 wing / room 快速召回局部内容;
L3 则是真正的深度语义搜索。
这里真正厉害的地方,不在于“分了四层”,而在于它承认了一个现实:
上下文窗口是稀缺资源。
真正的长期记忆系统,不可能每次都把几年历史、所有文档、全部对话塞进 prompt。
它必须学会按成本逐层装载:
- 先用很少的 token 让模型“醒过来”
- 再按当前话题召回局部记忆
- 真要查证时,再做深搜
这其实比“能不能搜到”更重要。
因为长期记忆系统一旦无法控制装载成本,再好的存储和检索也会在真实使用中失去意义。
从这个角度看,layers.py 才是 MemPalace 最接近“产品思想”的部分。
八、为什么它还要做知识图谱和主题图
如果 MemPalace 只做 drawer + 向量检索,其实已经能跑起来了。
但它没有停在这里。
它还做了两套额外的结构化层:
1. 时序知识图谱
knowledge_graph.py 用 SQLite 存实体、关系三元组、valid_from、valid_to,支持:
- 查询某个实体当前或某个时间点的事实
- 标记事实失效
- 查看时间线
- 查看图谱统计信息
这层的意义在于:
有些记忆不是“找文本”,而是“确认某个事实在什么时间成立”。
比如项目负责人变了、偏好变了、关系变了、状态变了,这些都更适合进 KG,而不是只靠向量库模糊搜索。
2. Palace Graph 主题导航图
palace_graph.py 做的不是实体图,而是 room 图。
它把 room 当节点,把跨 wing 共享的 room 当连接通道,允许从一个主题出发,找到与之相邻的房间,或者发现连接不同领域的“隧道”。
这层非常有意思,因为它表达的是:
记忆不只是“能不能搜到”,还包括“能不能顺着主题走过去”。
很多系统只能回答“给我找相关文本”,但 MemPalace 在尝试更进一步地支持“这个主题还能连到哪些领域”。
这条路线未必已经打磨到最强,但方向非常有辨识度。
九、MCP Server 为什么像一个“记忆中台”
mcp_server.py 是整个系统最像“中台服务”的部分。
它做的事情很多:
- 解析 MCP 请求
- 协商协议版本
- 暴露工具列表
- 按 schema 分发
tools/call - 对输入参数做白名单过滤和类型转换
- 管理 Chroma client / collection 缓存
- 维护 metadata cache
- 做 WAL 写前审计
- 在搜索前做 query sanitize
- 对外统一暴露 palace、KG、graph、diary、hook 等能力
这里有两个点特别值得强调。
第一个点:它对脏查询并不天真
query_sanitizer.py 的存在非常说明问题。
源码里明确提到,AI 代理有时会把大段 system prompt 或杂乱上下文一起塞进搜索 query,导致 embedding 被前缀污染,检索效果可能从 89.8% 掉到 1.0%。sanitize 的目的,就是尽可能从长 query 里提取真正的检索意图,至少避免“悬崖式失败”。
这说明 MemPalace 不是默认上层 agent 总会“正确调用工具”,而是在服务层主动做了抗脏输入缓冲。
第二个点:它对写入风险有审计意识
mcp_server.py 会把所有写操作先记进 WAL:
写 drawer、删 drawer、改 drawer、写 diary、加 KG 事实、使 KG 事实失效,都会先记录 JSONL 日志。目录和文件权限也会尽可能收紧。源码注释还直接提到 memory poisoning 风险。
这一点特别像真正要长期运行的系统,而不是“写完就算”的 demo。
十、它最有野心的一块,其实是 diary 和 hook
很多人第一次看 MemPalace,注意力都会被 palace、KG、graph 吸引。
但如果你往后看,会发现它最有想象力的一块,可能反而是:
让 agent 自己也形成连续经验。
mcp_server.py 里提供了 mempalace_diary_write 和 mempalace_diary_read。每个 agent 都可以拥有自己的 diary wing,记录工作、观察、判断和重要发现。
与此同时,hooks_cli.py 实现了 session-start、stop、precompact 三类 hook,支持在会话进行到一定长度时自动提醒保存,在上下文即将 compaction 时强制提醒“把重要内容沉淀进记忆系统”,还支持通过 MEMPAL_DIR 自动触发本地 mempalace mine。
这说明 MemPalace 想解决的已经不只是“记住过去”,而是:
让代理能够持续维护自己的长期记忆状态。
这一步非常难,但也非常值钱。
因为真正长期使用 Agent 的人都知道,最痛的并不是“有没有存储能力”,而是:
- 我会不会忘了保存
- 上下文压缩前能不能及时沉淀
- 学到的新信息能不能进入长期记忆
- 旧事实变了之后有没有地方维护
MemPalace 已经开始碰这些问题了。
十一、这个项目现在最强的地方
如果我要总结它最强的地方,我会说有三点。
第一,它抓住了“长期记忆系统”真正难的部分
真正难的从来不是“接一个向量库”,而是:
- 异构输入怎么统一
- 内容怎么组织
- 检索怎么控制成本
- 代理怎样形成先查后说的习惯
- 事实如何随时间维护
- 自动写入怎样防污染、可审计、可回溯
MemPalace 在这些点上都已经有了明确实现。
第二,它不是概念先行,而是代码跟得上概念
很多项目包装很好,但落地后本质上仍是“向量库 + 搜索接口”。
MemPalace 不一样。
它的 palace、wing、room、drawer、L0~L3、KG、graph、protocol、diary,这些概念在代码里都有对应实现。
第三,它已经开始为平台化演进做准备
palace.py 已经不是把 Chroma 写死在所有模块里,而是通过 backend seam 统一收口;路线图也明确写了 PostgreSQL backend、LanceDB backend、PalaceStore 等方向。
这意味着它不满足于永远做一个“本地脚本工具”,而是在为未来的多后端、多场景演进留空间。
十二、它现在最大的短板也很明确
当然,MemPalace 绝不是没有问题。
1. 检索层还不够 hybrid
当前主干仍是“向量 + metadata filter”,对精确术语、错误码、路径、代码符号这类关键词检索,理论上还有提升空间。路线图已经把 hybrid search 写进去了,说明作者自己也认同这一点。
2. room 模型偏单标签
无论项目文件还是会话,当前都更接近“主归属到一个 room”,这对复杂多主题内容不够友好。
3. chunking 还不够结构感知
项目文件主要按字符和换行切,会话在 exchange 模式下甚至只保留 AI 回答前 8 行,这对某些长回答和代码型内容并不理想。
4. 有些设计理念已经成熟,但实现还没完全追平
比如 L1 注释里说会兼顾近期性与重要性,但当前实现主要还是按 importance 系列字段排序;KG 虽然有时序建模,但自动抽取与冲突治理闭环仍不完整。
所以它现在更像一套:
方向非常正确、核心骨架已经搭起来、但仍在快速打磨中的强原型。
十三、最后的判断
如果你只是想找一个“本地存聊天”的工具,MemPalace 可能显得有点重。
但如果你真正关心的是:
AI 如何拥有可持续、可组织、可维护、可服务化、可被代理主动使用的长期记忆,
那 MemPalace 绝对值得认真读一遍。
它最厉害的地方,不是它已经完美,而是它几乎把这件事里最难、最关键、最容易被忽略的环节都碰到了:
- 原文保留
- drawer 抽象
- 项目与会话统一入库
- 分层上下文装载
- 时序知识图谱
- 主题导航图
- MCP 工具体系
- hook 自动沉淀
- 查询污染防护
- 写入审计与风险意识
很多项目停留在“本地向量库工具”这一步,
而 MemPalace 已经开始认真回答一个更本质的问题:
AI 的长期记忆,到底该如何工作。
这,才是它真正值得被研究的原因。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)