资讯动态

claude-mem:为 Claude 打造跨会话持久记忆系统

发布时间:2026/10/26 8:50:42 来源:尧图企业网站定制
做 AI 工具这行久了会发现一个特别反直觉的事各家模型聊得越久越聪明可一旦你点上“新会话”它就全忘了像喝了孟婆汤。Claude 在各家模型里算上下文拉满的选手但这个“每次从零开始”的毛病一样躲不掉。claude-mem 这个项目就是我为了解决这个痛点折腾出来的简单来说它是一套给 Claude 使用的跨会话持久记忆系统核心任务是把对话里值得记住的信息沉淀到本地在合适的时机再塞回上下文里。它解决的是一类非常具体又很普遍的问题你上周刚和 Claude 敲定的架构方案这周它一个字都不记得你反复叮嘱过的代码风格换个会话它又按自己的习惯来。它适合重度用 Claude 写代码的开发者、正在搭 AI 工作流的工程师以及所有被“反复调教却反复失忆”折磨过的人。1. 选题动机Claude 最缺的从来不是上下文而是“上一周”1.1 一次会话的终点就是下一次会话的起点我最早意识到这个问题是在一个跨度接近两周的项目里。前一周我和 Claude 花了整整七个小时把一套缓存策略从设计到落地聊了个遍包括为什么不用 Redis 而用本地 LRU、哪些边界条件需要兜底、压测的预期指标是多少。第二周我打开新会话准备继续问它“上次说的缓存淘汰策略咱们讨论到哪一步了”它居然一本正经地给我介绍了 LRU 的基础概念。那一刻的挫败感很真实就像你和一个特别靠谱的同事配合默契结果隔天他失忆了你得把所有背景资料再讲一遍。这个体验让我彻底想明白一件事大语言模型的记忆只在上下文窗口里窗口一关什么都没留下。用户表面上在和一个“长期合作的 AI”协作实际上每次都在和一个“刚刚入职的新人”重头沟通。与其抱怨模型记性差不如从工程角度给它补一个外部记忆模块。claude-mem 的定位由此确定它不做上下文扩容而做上下文的“外置硬盘”。一方面把会话中产生的有用信息提炼成结构化记忆持久化到本地另一方面在新会话启动时根据当前任务自动筛选最相关的记忆回填给模型。这套思路听起来不复杂但真正落地要处理的细节远超预期。1.2 市面上的“记忆方案”为什么不够用立项之前我认真调研过现有的路线基本可以分成三类。第一类是最暴力的把所有历史聊天记录全部拼到系统提示词里。这种方案实现成本极低但效果差得离谱几百轮历史对话塞进去光 token 费用就能让人肉疼而且大量无关信息互相干扰Claude 反而抓不住重点。第二类是“用户备忘录”模式让用户手动维护一份项目说明文件每次开始前贴给 Claude。这个方法有一定效果但把记忆负担完全转嫁给了人绝大多数人根本坚持不下来写着写着就过期了。第三类只做搜索提供历史会话的关键词检索能查到但不够聪明用户得先想清楚“用什么词搜”而对话里大量关键信息根本没法通过关键词表达。claude-mem 走的是完全不同的路线先把原始对话离线蒸馏成结构化记忆再按相关性动态回填。听起来类似 RAG检索增强生成但又有本质区别。RAG 通常面向知识库针对的是文档、网页这种相对规范的内容而 claude-mem 处理的是对话流——里面既有用户偏好又有决策过程还有大量临时性讨论。对话场景下信息粒度小、噪声大、时效性强必须叠加会话状态管理否则一堆过期记忆会持续误导模型。1.3 产品边界什么该记什么不该记记忆系统要做的第一件事其实是学会拒绝。我们最初版本做了个“全记录”功能结果灾难性地出现了一批离谱记忆用户某次随口说了句“今天有点想吃火锅”被当成长期偏好存了一个月一次代码 review 里的临时吐槽也被升格成“项目原则”。这些垃圾记忆不仅占数据库空间还会在后续回填时干扰 Claude 的判断。claude-mem 后来把记忆分成四类用户偏好、项目状态、决策记录、临时任务。前三种进长期记忆池第四种只在 48 小时内有效到期自动清理。判断标准也很粗暴——能被一句话概括清楚且对后续项目推进有直接影响的才值得入库其余一概不记。这和我个人写代码的习惯一脉相承不重要的代码不写不重要的记忆不存。2. 记忆系统的整体设计与核心原理2.1 一条记忆是怎么产生的整个系统的核心链路可以压缩成三个词采集、提炼、回填。采集这一步最容易翻车我踩过一个特别丧的坑最初只监听 Claude 的回复忽略用户的提问。后来分析真实数据才发现用户偏好信息大量藏在提问方式里。比如用户说“能不能像上次那样先给我一份表格再逐条解释”这句话基本等于在明示记忆系统“我喜欢表格优先且分点解释”。如果只盯着 AI 的回复采集这类信号会全部漏掉。所以 claude-mem 的采集层是双向监听用户的设问、语气、命令式表达都是高价值输入。提炼阶段的任务是把采集到的原始消息转换成结构化记忆条目。我们采用“分块提取 二次复核”的管线先把一段长对话按语义切块每个块送给一个轻量的提炼模型让它输出包含主体、动作、对象、场景、置信度五个字段的 JSON 记录。再拿这批记录过一遍规则过滤器过滤掉包含脏词、个人隐私、纯闲聊的内容最后才写入存储层。提炼用的模型不追求大实测一个 7B 级别的本地小模型就够用毕竟提取任务比推理任务简单得多大模型在这个环节纯属浪费。2.2 存储层设计与数据结构存储层选 SQLite 而不是 MongoDB这在刚提方案时被同事质疑过。我的理由有两条第一claude-mem 是单机工具数据量撑死几十万条SQLite 完全扛得住还省掉了数据库运维第二SQLite 单文件备份转移极其方便换电脑直接拷一个文件走人。记忆条目表的结构如下字段类型作用idTEXT记忆唯一 IDUUIDcontentTEXT记忆正文纯文本memory_typeTEXT枚举值preference、decision、status、tasksource_conversationTEXT来源会话 ID用于追溯created_atINTEGER创建时间戳last_access_atINTEGER最近一次被回填的时间hit_countINTEGER历史命中次数参与权重计算vectorBLOB语义向量二进制可空光有表结构不够真正决定记忆质量的是检索。claude-mem 采用“关键词 语义向量”双通道召回。关键词通道用 SQLite 自带的 FTS5 全文索引查询毫秒级返回负责精确匹配语义通道用 Embedding 模型把记忆正文转成向量负责召回那些表达不同但意思相近的记忆。两条通道的结果做加权融合权重默认是 0.4 和 0.6因为纯关键词召回太容易漏掉近义改写语义通道优先级稍高。融合后还要过一次时间衰减排序把 last_access_at 超过 30 天的老记忆降权。这里分享一个个人观点不要一上来就上向量数据库单机场景 SQLite FTS5 覆盖了大部分需求向量检索是锦上添花不是雪中送炭。2.3 回填策略不是所有回忆都该出现记忆系统做崩通常不是因为“没记下”而是因为“回得太多”。我做第一版时给 Claude 注入了二十多条记忆结果它在关键问题上反而开始迷糊两条互相矛盾的记忆排在一起时它会反复横跳。后来我设计了一套三级注入策略。第一级叫常驻记忆严格控制在 5 条以内放的是项目目标、用户核心偏好这类影响全局的信息平时永远占用上下文。第二级叫场景记忆新会话建立后系统先从用户第一句消息里提取主题标签再按标签去检索最多注入 15 条覆盖当前任务相关的事项。第三级叫临时记忆默认不进上下文只有在用户主动发起“查找相关历史”之类的行为时才触发进去完再出来用完即走。这个三级策略最直接的价值是把稳定性和灵活性分开了。常驻记忆管“人设”场景记忆管“当下任务”临时记忆管“深挖历史”。哪一环节出问题只需要检查对应层级排查成本极低。有一次用户反馈说“Claude 对我的偏好置若罔闻”我第一反应就是查常驻记忆有没有被新写入的偏好挤出去果不其然一条只有 3 次命中的临时偏好因为时间靠新把用户坚持了两个月的主偏好顶掉了。修复方案也很简单常驻记忆的写入必须经过用户确认任何自动提炼的内容都只能进二级和三级。3. 项目结构与实操搭建3.1 技术选型与目录结构claude-mem 的整体框架选了 Python没有别的原因就是 AI 生态里 Python 的库最齐全能省掉不少从零造轮子的时间。不过我刻意把核心存储层写成了独立包只依赖 Python 标准库这样未来换成 Go 或者 Node 重写不至于被存储逻辑绑住。项目目录是按照功能边界拆的大致如下claude-mem/ ├── cli/ │ ├── main.py # 命令行入口 │ ├── watch.py # 会话监听模式 │ └── search.py # 历史记忆搜索命令 ├── core/ │ ├── capture.py # 采集层双向消息监听 │ ├── distill.py # 提炼层记忆抽取 │ ├── store.py # 存储层SQLite 封装 │ └── inject.py # 回填层记忆排序与注入 ├── models/ │ ├── extractor.py # 提炼模型调用 │ └── embedder.py # 向量编码器封装 ├── config/ │ └── defaults.yaml # 默认配置 └── data/ └── memory.db # SQLite 数据文件这个目录结构不是第一天就长这样的。最初我把采集和提炼写在一个文件里后来发现改一个模块的代码老是导致另一个模块莫名其妙出 bug逼着自己拆成现在的样子。如果你也想做类似工具我的建议是 core 层四个模块之间不要有任何循环依赖数据流向必须是单向的capture 到 distill再进 store最后被 inject 读取永远不走回头路。3.2 安装与初始化安装走的是标准流程用 pip 直接装就行。不过我做过一个比较重要的决定默认提供一个 offline 模式安装后不联网也能用基础功能只有做语义召回时才需要本地起一个 Embedding 模型服务。这样既照顾了隐私敏感用户也避免了一堆功能依赖一个在线的 API 导致整个工具离开网络就瘫痪。安装完成后第一次初始化会弹出交互式引导我建议你用下面三分钟把这几个参数确认清楚比事后改配置省心得多# 一键安装 pip install claude-mem # 初始化数据库和配置文件 claude-mem init # 启动监听模式开始采集 Claude 会话 claude-mem watchinit 命令会生成一个 defaults.yaml 配置文件里面有几项需要手工确认。第一个是 memory_scope决定那些目录下的会话被监听默认是你的工作目录建议改成实际存放 Claude 会话记录的目录。第二个是 retention_days控制临时记忆的保留时间默认 48 小时。第三个是 max_inject_count控制单次回填的记忆条数上限默认 20。别小看这个上限我见过有人拉到 100结果模型经常被历史信息带跑。3.3 配置参数与运行示例配置文件打开之后大概长这样scope: include_dirs: - ~/projects/my-app - ~/projects/notes exclude_dirs: - ~/projects/my-app/node_modules - ~/projects/my-app/build retention: temporary_days: 48 decision_forever: true injection: resident_max: 5 scene_max: 15 temporary_enabled: true storage: db_path: ~/claude-mem/data/memory.db enable_fts: true embed_model: local:all-MiniLM-L6-v2几个值得展开的参数。resident_max 就是上面说的常驻记忆上限写死 5 就行千万不要觉得越多越好。场景记忆的 scene_max 我设为 15这是在模型效果和 token 成本之间反复测试出来的经验值15 条语义相关记忆大概占据 2K 到 3K token对长上下文模型来说影响不大又能覆盖绝大多数任务需求。embed_model 可以选本地模型或云端 API本地模型推荐 all-MiniLM-L6-v2300M 大小单机跑很流畅语义效果对短文本记忆够用。初始化完成后可以直接搜索历史记忆验证# 查一下和缓存策略相关的历史记录 claude-mem search 缓存策略 # 输出示例 2025-01-12 14:32 decision #decision 决定放弃 Redis改用本地 LRU原因是访问量不足以支撑额外中间件运维。 2025-01-10 09:18 status #status 缓存模块进入压测阶段目标 TPS 8000。第一次跑通这条命令的时候说实话我有点兴奋那种“它真的记下来了”的感觉是写普通 CRUD 功能永远不可能带来的。4. 把 claude-mem 接入 Claude 工作流的三种方式4.1 系统提示词注入接入方式最直接的是系统提示词注入。在每次启动 Claude 会话前用脚本把 claude-mem 筛选出的记忆拼装成一段“项目背景与历史决策”塞进系统提示词里。这种方式的优势是简单粗暴不需要改任何模型侧的接口兼容所有版本的 Claude API。缺点是记忆只能静态生效会话过程中如果用户话题突然转向模型不会自动去查新的记忆只能靠启动时那一次性的注入。我对这个方案的定位是“零成本起步”。如果你只是想先试下水就用这种。具体实现也不复杂启动会话前调用 claude-mem snapshot 拿到当前会话的上下文快照然后再拉起 Claude 客户端。需要提醒的是注入的格式最好统一我习惯用 markdown 引用块包住记忆内容并在末尾加一句“以上是项目历史记录回答时优先参照”。实测下来模型对带引用的外部信息态度会明显更重视。4.2 工具调用方案第二种方式是把记忆检索做成 Claude 的工具调用function calling。这是一种更接近“主动回忆”的方案。模型在对话中如果觉得需要历史信息会主动调用一个名为 search_memory 的工具传入查询参数工具返回相关记忆列表模型再结合当前对话继续生成。好处很明显记忆只在需要的时候被拉取上下文占用降到最低也不会出现“塞了一堆记忆但当前根本用不上”的浪费。坏处是接入成本高需要在 API 层配置工具 schema并且模型有时候会犯懒明明该查记忆却直接用现有知识回答。为了解决“模型不主动查”的问题我在系统提示词里特意加了一条 soft constraint当用户提到“上次”“之前”“我们讨论过”这类词时必须调用 search_memory。这个约束的效果立竿见影但仍有 10% 左右的概率被模型忽略。这时我会在用户侧做兜底当检测到对话中出现上述关键词且工具未被调用判断为一次缺失检索我们会在那个位置自动补一次检索调用。4.3 MCP 服务方式推荐第三种方式也是我目前最推荐的方式是把 claude-mem 封装成 MCPModel Context Protocol服务。MCP 现在是 Claude 生态里标准化的上下文扩展协议客户端可以直接通过服务发现连接各种记忆、文件、数据库资源。我把 claude-mem 的检索能力暴露成 MCP tools模型端不需要任何额外配置Claude 这类支持 MCP 的客户端会自动发现并调用。这个方案的解释是它把记忆能力彻底产品化了用户可以像给 IDE 装插件一样给 Claude 装一个“记忆插件”不用折腾任何代码。从工程侧维护一个 MCP server 也只比写命令行多几步难点主要是对协议栈的理解。claude-mem 实现 MCP server 时用的是 Python 的 FastMCP 库十几行代码就能把现有 search、snapshot 方法暴露成服务。我还做了一个细节把所有 MCP 工具的 description 写得非常具体因为模型选择工具时主要读 description写得太泛它不知道什么时候该调。如果你在纠结选哪种接入方式我的建议是想快速验证就选 4.1想在生产环境精确控制上下文就选 4.2想长期维护、想让多个客户端共用一套记忆库就直接上 4.3。三者的关系不是互斥的我的生产环境就是 4.3 为主、4.1 兜底启动时注入常驻记忆会话中通过 MCP 按需检索场景记忆。5. 实际运营中的常见问题与排坑实录5.1 记忆重复与矛盾处理跑了三个月之后遇到的第一个麻烦是记忆重复和矛盾。同一个决策用户可能在不同会话里以不同措辞重申了三遍我的提炼流程会为这三句话生成三个不同的条目。重复问题还好办按语义相似度做合并就行矛盾问题才真头疼比如第一周说“数据库迁到 PostgreSQL”第二周又说“先不迁了保持 SQLite”。我的记忆库里会同时出现 direction 完全相反的决策条目而回填层不自知把这俩都塞给了 Claude模型给出的建议因此变得摇摆不定。解决方案分两层。字段层所有 decision 类型条目必须绑定 source_conversation没有源会话的不得入库。逻辑层新增一条“supersedes”链当新决策被写入时提炼流程根据语义相似度找到旧决策并标记为 superseded1。回填层只读取未被废弃的决策。这套机制上线后记忆中矛盾率从 9% 降到了 1% 以下。这个改进给我最大启发记忆系统不只是存储和检索它必须承担一部分“遗忘”的能力如果一个对象只会积累不会清理最后只会变成一堆相互矛盾的过期信息。5.2 上下文预算被记忆挤占第二个高频问题是上下文预算失衡。常驻记忆虽然只有 5 条但如果每条都写成长篇大论照样能吃掉四五千 token。场景记忆 15 条听起来不多但如果每条内容都包含了完整的上下文背景合起来就不是小数目。有一次我统计发现记忆注入占到了总上下文的 35%这个比例太高了因为 Claude 的任务本来就是代码生成不是文档理解。解决办法是给记忆条目做“摘要压缩 分层长度限制”。常驻记忆每条压缩到 100 个汉字以内只保留最核心的动作和结论场景记忆每条控制在 300 字左右详细背景保留在 SQLite 原始记录中回填时只注入摘要需要全文时再通过工具查询。压缩的过程不是简单截断而是专门写了一个短文本摘要 prompt硬性要求输出“主体 动作 结论 时间”四要素。这条规则上线后记忆注入的平均 token 占比降到了 10% 左右模型也明显更“专注”了。5.3 数据库膨胀与性能劣化SQLite 虽然轻量但长时间跑下来也会膨胀。最典型的是 FTS5 索引文件越来越大这是因为每次 merge 记忆时我都会新增一条记录而不是原地更新。膨胀带来的直接后果是检索速度从毫秒级掉到百毫秒级搜索关键词“缓存”要卡将近两秒。说实话这个感受很直观我在交互式终端里等两秒都受不了。后来写了一个维护命令每周定期做 VACUUM顺手把已经 superseded 的老决策彻底物理删除。改造后数据库大小从 380MB 降到 60MB检索速度回到毫秒级。我还把 SQLite 切到了 WAL 模式写和读并行时的锁等待问题也基本消失了。5.4 隐私边界与敏感信息过滤最后一个坑是隐私。记忆系统记的所有信息都落在本地理论上安全但提炼出来的内容有相当一部分涉及业务敏感信息比如项目内部代号、未公开的技术选型、甚至客户名称。如果用户把数据库文件打错发到社交平台这类泄露不是谁都能承担的。claude-mem 的应对方案是加了双层过滤器。提炼层规则黑名单 本地小模型识别扫描出手机号、邮箱、银行账号等直接丢弃。回填层如果识别出某条记忆包含敏感类别则只在用户手动确认的环境下注入不再自动回填。我还默认关闭了云端 Embedding 服务改用本地模型做向量化。隐私这件事宁可过度保护也不冒进一旦出问题用户就不会再信任这个工具了。5.5 其他小问题速查表现象原因解决方案Claude 对话里出现了三个月前的过期经验临时任务没有被及时清理检查 retention_days 配置确认是否调到 48 小时同一个偏好记了十几条提炼流程缺少语义合并升级到新版本开启语义去重开关启动会话非常慢回填层在做全量检索检查 scene_max 是否过大建议改成 10-15MCP 工具不生效description 写得太泛模型不知道该调用重写工具描述加上调用时机与示例记忆库文件丢失误删或换机没过文件设置 data 目录软链到云盘定期备份 memory.db我自己在真实使用中最常踩的还是第一条曾因为临时任务保留时间设置过长导致模型在写新功能时反复引用已经清除的旧方案浪费了半天排查时间。后来干脆加了一个 dashboard 命令每周扫一遍记忆库里的过期条目数量顺手清理掉这个习惯一直保持到现在。写到最后说点实际的体会。claude-mem 技术上不复杂真正难的是想清楚“记忆该长什么样”以及“什么时候该出现”。我搭完第一版后最大的收获不是那套检索链而是意识到给 AI 加记忆本质是在重做一遍人脑记忆系统的简化模型需要记录、需要遗忘、需要冲突消解、需要优先级调度。如果你也想折腾类似的东西我建议从最小闭环开始先只记住用户的偏好把它用最原始的方式写进系统提示词里试两周再一步步加检索、加压缩、加冲突处理。别一上来就堆基础设施记忆系统的瓶颈从来不在存储而在你对“什么值得记”这件事的判断。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑