84天、7635条记忆、零检索费用:给 AI Agent 装上真正的长记忆

32 阅读10分钟

84 天、六千轮对话、七千条记忆:我在 Mac 上搭了一套长记忆系统

一套完全本地部署的 AI Agent 记忆系统。嵌模型在本地跑,向量库在本地存,唯一出设备的是 LLM 推理请求。跑了 84 天,经历过 Agent 崩溃、ChromaDB 重建、OpenClaw 版本回退,记忆从未丢失。


一、整体架构

在讲具体内容之前,先把整个系统的逻辑图画清楚。

                        用户消息
                           │
          ┌────────────────┼────────────────┐
          ▼                ▼                ▼
    浅层召回通路      深层管道(异步)      L0 原文归档
          │                │                │
          │                │                ▼
          │                │           JSONL 纯文本
          │                │           永不丢失
          │                │
          │      ┌─────────┼─────────┬──────────┐
          │      ▼         ▼         ▼          ▼
          │     L1         L2        L3         L4
          │   语义提取   场景归纳   用户画像   知识图谱
          │      │         │         │          │
          │      │         │         │          │
          │      └─────────┼─────────┴──────────┘
          │                │
          │                ▼
          │         MemPalace 本地库
          │         ┌───────┼───────┐
          │         │       │       │
          │         ▼       ▼       ▼
          │     drawers  closets   KG
          │     7,635    2,096   6,077
          │         │       │       │
          │         └───────┼───────┘
          │                 │
          │    ┌────────────┼────────────┐
          │    ▼            ▼            ▼
          │  向量检索    BM25 关键词   KG 关系
          │  (bge-m3)   (FTS5分词)   (SQLite)
          │    │            │            │
          │    └────────────┼────────────┘
          │                 │
          │                 ▼
          │          融合排序 & 去重
          │                 │
          └────────┬────────┘
                   ▼
            上下文注入 Agent

两条通路,一个底层。

左边浅层——日常对话走这条,bge-m3 本地嵌入 → ChromaDB 向量检索,<200ms 返回。右边深层——定时异步管道,L1 语义提取调用 DeepSeek API(唯一出设备的数据),L2-L4 全部本地计算。底层共享 MemPalace,不存两份。

平时 90% 的对话靠浅层。 用户说「认真回忆 / 深度检索 / 回忆一下 XX」,触发深层全管道——融合向量 + BM25 + KG 三条检索线,汇总排序后注入 Agent。


二、我理解的长记忆

不是「存得多、记得久」这么简单。我给长记忆的定义是三条:

第一条,丢了能回来。 Agent 崩溃、系统重装、索引损坏——记忆库能不能独立存活?

7 月 9 日 ChromaDB 索引损坏,我删掉整个向量 collection,从 SQLite 导出全部 7,635 条 drawer,5 分钟重建。Agent 重新上线后,回忆精度和重建前一致。后来 MemPalace 从 3.3 升到 3.5,bge-m3 的 monkey-patch 被破坏,整库需要重新初始化——因为 L0 原文都在,管道重跑一遍就恢复了。

OpenClaw 有一次版本升级后出现兼容问题,不得不回退。升级过程中部分配置被覆盖,索引需要重建。但因为 L0 的 JSONL 原文和 MemPalace 数据库完全独立于 OpenClaw 运行环境——回退折腾了一圈,记忆库毫发无损。

换一台新电脑也一样。~/.mempalace/ 和 JSONL 原文目录复制过去,装好依赖,记忆水平立即恢复。不需要重新「喂」数据、不需要重新训练——你的记忆库就是几个文件夹。

第二条,跨天能精准回忆。 不是模糊匹配,是精确回溯上下文和结论。

4 月 30 日我跟 Agent 讨论过一个项目架构方案,做了具体决策。7 月 23 日——隔了 84 天——我问「上次那个架构方案我们最后是怎么定的」,Agent 能准确回应当初的讨论内容、决策理由和最终结论。靠的是 L0 原文定位时间范围 + L1 结构化记忆提取事实 + L4 知识图谱补充实体关系。

没有长记忆的 Agent 面对这种问题,能做的只是翻最近几十轮对话——超出上下文窗口的内容完全不可见。有这套系统之后,84 天前的讨论和昨天的讨论,检索路径是一样的。

第三条,一句话触发深度检索。 用户不需要写搜索 query,不需要知道数据怎么存的。

这里有一个容易被忽视的设计细节:Agent 怎么判断什么时候该走浅层、什么时候该走深层?不是靠 LLM 自己判断——那不可靠。实际做法是在系统 prompt 层做触发词匹配:当用户消息中包含「认真回忆」「深度检索」「回忆一下」「还记得吗」「查一下」等模式时,Agent 自动切换到深层检索通路。其他情况默认走浅层,保证日常对话的响应速度。

触发后不是一次简单的向量搜索,而是一个多步检索流程:

  1. 用查询语句在 L0 JSONL 原文中定位相关时间范围(纯文本扫描,零成本)
  2. 用 bge-m3 在 L1 结构化记忆中做语义检索,提取匹配的 drawers
  3. 用 L4 知识图谱补充关联实体——查到「架构方案」,KG 反向查出相关的「项目」「后续决策」
  4. 三条线结果汇总,按融合分数排序(向量相似度 × BM25 关键词 × KG 关系权重 × 时间衰减)
  5. 去重后注入 Agent 上下文

整个过程对用户来说就是一句话。深层检索延迟 <500ms,因为嵌入和索引全在本地,没有网络往返。

这不是 prompt engineering 的技巧,是系统架构自然支持的能力。


三、为什么端侧

苹果这几年一直在推端侧 AI 的理念——数据只在设备上处理,就不存在集中式的攻击点。他们做的是端侧推理(Apple Intelligence 在 iPhone 上本地运行模型),我做的是端侧记忆。逻辑是相通的。

对于 AI Agent 来说,记忆系统选端侧有三个实际好处:

安全上,对话记录、嵌入向量、知识图谱全在本地硬盘。没有第三方服务器持有你的对话历史。唯一出设备的是 LLM 推理的 prompt——传出去的是问题,不是记忆库。

效率上,记忆检索没有网络往返。嵌入用本地 Ollama 的 bge-m3 算,向量检索在本地 ChromaDB 跑。<200ms 的响应时间是可控且可预期的——不依赖 API 服务商的限流策略和网络状态。

成本上,嵌入和检索零边际费用。84 天里记忆模块做了数千次检索,账单为零。云端记忆方案按检索次数收费——这个成本会随着使用量线性增长,而本地方案的成本是固定的(硬盘空间 + 偶尔的嵌入计算)。

苹果的路线验证了端侧的方向,但他们的重点在推理。我的看法是:对于需要长期陪伴的 AI Agent,端侧记忆和端侧推理同等重要。


四、嵌入和检索的自主权

这里容易被误解为一个浅显的问题——「你是不是想说本地部署比云方案好?」不是。我想讲的是:记忆系统里有两个容易被忽视的组件——嵌入模型和检索算法——它们对最终召回质量的影响比 LLM 本身更大。

云端方案通常把这两个东西打包成黑盒。你传对话进去,服务商决定用什么嵌入模型、用什么检索算法。大部分英文嵌入模型对中文的语义区分能力很弱——「Apple」和「苹果公司」的语义距离,在英文嵌入模型里可能比在中文嵌入模型里大得多。但在云端方案里你没法换嵌入模型。

我做了两件事:

嵌入层: 把默认的 384 维英文模型换成 bge-m3(北京智源,1024 维)。同一个搜索 query「系统架构设计」,换之前召回的只是包含这些关键词的片段,换之后召回的是语义上真正讨论架构设计的对话。中文场景下这是质的差距。

检索层: 不用单一的向量相似度排序。融合了三条线——向量语义(bge-m3)、关键词匹配(SQLite FTS5 + CJK 中文分词)、知识图谱关系权重。跨天回忆场景下,纯向量检索容易把时间久远但语义相近的内容排在前面,融合排序可以通过关系权重和时间衰减修正。

这两个东西跟用哪个 LLM 没关系。它们决定了记忆系统的召回质量底线——LLM 再好,召回的内容不对,回答就不可能对。


五、踩过的坑

坑一:换嵌入模型,ChromaDB 直接罢工

bge-m3 替换默认嵌入模型后,ChromaDB collection 的维度一旦创建就不可修改。旧 collection 锁死了 dimension=384,MCP server 检测到 384≠1024,拒绝初始化。解法是导出全部数据 → 删除旧库 → 重建 → 重新嵌入。7,635 条,全自动 5-10 分钟完成。

坑二:OpenClaw 升级,回退重建,记忆没丢

有一次 OpenClaw 版本升级后出现兼容性问题,不得不回退到旧版。升级过程中部分配置被覆盖,索引需要重建。但因为 L0 的 JSONL 原文和 MemPalace 数据库完全独立于 OpenClaw 运行环境——回退、重建折腾了一圈,记忆库毫发无损。Agent 重新上线后,对话上下文和跨天回忆能力没有任何损失。

坑三:Mac 休眠,8 个定时任务全停

launchd 的 StartInterval 在 Mac 合盖休眠后不补跑。早上打开电脑,所有 pipeline 日志断档,审计面板全红——不是功能坏了,是定时器被冻住了。解法是在每次系统触发时加唤醒检测——扫描日志时间戳,断档超阈值的当场补跑。每天早上第一条消息触发自愈,无需人工干预。


六、84 天真实数据

指标数据
记忆跨度84 天(4.30 — 7.23)
结构化记忆7,635 条 drawers,按项目/话题/时间自动分类
知识图谱6,077 个活跃三元组,支持时间线查询
L0 原文97 个文件,6,136 条 JSONL,18MB
记忆库体积194 MB(drawers + closets + KG + 向量索引)
检索延迟浅层 <200ms,深层融合 <500ms
检索成本零——嵌入和检索全程本地

同样的任务,有没有长记忆的差别:

Agent 收到「我们之前讨论过的那个架构方案后来怎么定的」——

没有长记忆:只能搜索最近对话窗口(几十轮)。超出上下文的讨论完全不可见。回答要么是「我没有找到相关信息」,要么更糟——编一个听起来合理但错误的内容。

有长记忆:Agent 从 L0 定位到 4 月 30 日的对话 → L1 提取决策要点 → L4 补充项目实体关系 → 回答精确到具体的讨论时间和结论。

成本角度看: 云端记忆方案按检索次数收费——每次 Agent 调记忆都是一次 API 调用。我这套系统 84 天里,记忆模块做了数千次检索,费用为零。同时,因为 Agent 有稳定的记忆上下文注入,每次对话不需要用户重复解释背景——LLM 推理的 prompt 更紧凑、更可预测,缓存命中率自然更高。


七、设备友好

Mac 和 Windows 上都验证过可行。没有特殊硬件要求——嵌入模型通过 Ollama 运行,有 GPU 更快但不是必须。除了 LLM 语义提取需要调 API,记忆的存储和检索是零费用、零网络依赖的。换新设备时,复制两个文件夹就完成迁移。


作者:Carson刘荣燊 | 2026 年 7 月 · 基于 84 天真实运行数据