资讯动态

给Claude装上长期记忆:从零构建AI记忆中间件claude-mem

发布时间:2026/10/26 11:51:33 来源:尧图企业网站定制
1. 从每次都要重新自我介绍说起如果你经常用 AI 助手做点正经事大概率遇到过同一个尴尬上午刚让它记住你负责的项目背景、代码风格偏好、常用的技术栈下午开启新会话它又是一副我们认识吗的表情。上下文窗口再大关掉对话就是清零重来。这个问题我忍了很久最后决定自己动手写一个叫 claude-mem 的小工具专门给 Claude 补一块长期记忆。claude-mem 做的事情很纯粹在会话之外维护一个独立的记忆存储层自动从每轮对话中提取值得记住的信息在后续会话中按需检索并注入系统提示词让 Claude 表现得像是还记得上次聊了什么。它不是一个全新的 AI 应用而是一个介于应用层与模型之间的记忆中间件。适合谁用如果你是重度 AI 用户每天靠 AI 管项目资料、记技术决策、维护个人知识库或者你在开发基于 Claude API 的自动化工具这块记忆层基本是刚需。整个项目从数据格式、存储选型到检索策略都经历过好几轮推翻重做。这篇文章把我的设计思路、核心实现和踩坑过程完整梳理一遍代码不算复杂但每个决策背后的理由比代码本身更有价值。我会尽量讲清楚为什么这么做而不只是怎么做。2. 动手之前必须想清楚的三件事写代码之前先花了两天想架构。记忆系统看起来简单无非就是存下来、查出来、塞回去但一旦开始细化三个问题立刻横在面前。2.1 记忆存哪轻量优先的选型逻辑第一版把方案铺得很大想直接用向量数据库。理由很充分记忆检索本质是语义相似度问题向量检索天然合适。但落地时发现向量数据库会引入额外的部署维护成本对一个个人工具来说太重了。纠结之后我退了一步用 SQLite 做基础存储把向量降级为可选增强。为什么这样也能跑因为记忆检索的精度并不完全依赖向量关键词全文索引配合一些结构化字段已经能解决八成召回问题。核心存储表只需要四个字段记忆 ID、内容文本、类型标签、时间戳。类型标签用来区分用户偏好项目事实临时任务等类别时间戳是后续做遗忘衰减的依据。表结构足够简单备份就是复制一个文件迁移成本几乎为零。等到规模确实大了再在 SQLite 外面挂一层向量索引也不迟。CREATE TABLE memories ( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT NOT NULL, category TEXT DEFAULT fact, importance REAL DEFAULT 0.5, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, last_access_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_memories_category ON memories(category);这个设计的核心逻辑是记忆系统的瓶颈通常不在存储而在提取质量和检索精度。存储先做轻把精力放在前面两个环节上收益更大。2.2 记忆记什么不是所有对话都值得记一开始我试图把所有对话原封不动存下来结果跑了三天就发现这条路走不通。原始对话噪声太大大量寒暄、临时提问、反复修改的过程性内容堆在一起检索时全是不相关命中。后来换了个思路让 Claude 自己在每轮对话结束后提炼出一条或多条值得长期保留的事实。相当于把记忆的提炼工作交给模型本身而不是靠规则硬切。提取的标准我总结成三条缺一不可事实性有明确的内容可以陈述不是感受也不是临时指令。长期性对后续会话有潜在价值而不是一次性任务。独立性脱离当前对话上下文后仍然可理解。满足这三条的内容才写入记忆库。比如用户负责某电商平台的后端重构是长期事实今天帮我查一下某个函数报错是临时任务两者要分开处理。临时任务单独放短期队列会话结束或任务完成后自动清理。2.3 记忆何时用注入时机决定体验上限存储和提取都定了还有一个更关键的问题记忆应该什么时候、以什么方式回到对话里一开始想简单了每次请求都把记忆库全量塞进系统提示词。这样做有两个问题一是 token 消耗不可控二是无关记忆会严重干扰模型判断。实际的做法是按需检索、动态注入。用户每次发消息时先用当前消息作为查询条件去记忆库召回再结合一定的随机性保证覆盖面最后把命中结果按相关度排序插入到系统提示词的一个固定位置。这样做不仅省 token还避免了记忆轰炸对模型注意力的干扰。我后来实际测过全量注入和按需检索的效果差距非常明显按需注入的任务完成质量明显更高。3. 从对话到记忆一条完整的数据流水线记忆系统的核心是一条流水线采集对话、切分处理、提取记忆、写入存储。每一环看起来都不复杂但串联起来有很多细节。3.1 采集端把对话切成可处理的块如果直接对整段超长对话做提取既费 token 又容易丢失细节。我选择按用户发言的语义边界切块当助手回答完毕且用户开启新话题时把前一段完整对话打包送去提取。切块时保留最基本的角色标识因为用户说过什么比助手总结过什么更值得记忆。采集端还有一个容易被忽略的点不要抓取中间态。用户和模型经常会来回修改同一个问题如果每一轮都提取记忆库里很快堆满互相矛盾的内容。我的做法是引入一个简单的合并机制——提取前先看当前话题是否与之前某段对话高度相似相似度超过阈值就只更新旧记忆的时间戳不新建记录。3.2 提取端让模型自己提炼关键信息提取环节我设计了一个专门的提示词模板要求模型输出结构化的 JSON。模板里明确指定三类输出用户偏好、持续事实、待办事项。每一类都要有一个置信度字段置信度低于 0.6 的丢弃。{ preferences: [ {content: 用户更喜欢使用Python写数据处理脚本, confidence: 0.92} ], facts: [ {content: 用户正在负责一个跨平台桌面应用的UI重构, confidence: 0.85} ], todos: [] }这个模板跑了一段时间后我发现了两个值得优化的点。第一个是置信度阈值不能一刀切偏好类的置信度普遍偏低但偏好恰恰是最值得长期记忆的内容所以偏好类的阈值我降到了 0.5。第二个是提取频率不能太高建议每十轮对话或用户明确说记住这个时触发一次否则又回到记忆爆炸的老路上。整个提取过程其实就是在提取成本和记忆覆盖度之间找平衡。每次提取都要调用一次模型接口频繁调用既花钱又拖慢响应所以必须克制。3.3 存储层写库之前先过一次去重提取出一批新记忆后不能直接写入。我先用关键词匹配对候选记忆做一轮去重提取内容的摘要词和已有记忆做比对相似度超过 0.8 的视为重复只更新原记忆的最后访问时间。这样做的目的是防止同一个事实在库里有七八个版本。去重之外还有一个重要的步骤重要性评分。这个分数决定记忆被检索时的权重。默认规则很简单——包含用户偏好关键词的记忆重要性 0.2包含时间敏感词的重要性 -0.1被连续访问超过三次的记忆重要性逐步提升。重要性分是后续做遗忘清理时的头号参考分太低的记忆会被自动压缩成摘要腾出空间给新记忆。4. 检索阶段如何在合适的时候想起该想起来的事存储做得再好检索拉胯整个系统还是废的。这一部分我花的时间最多也是 claude-mem 体验好坏的分水岭。4.1 粗排召回与精排过滤检索分为两步。第一步是粗排召回用当前用户消息的文本同时走两条路——SQLite 的 FTS5 全文索引做关键词匹配再加一个轻量的向量相似度计算做语义匹配。两条路的召回结果做并集至少保证了关键词命中和语义相近两条腿走路。第二步是精排对召回结果按三个维度打分——文本相似度、重要性分、时间衰减系数。最后取综合分 Top 5 注入对话。时间衰减系数是这里的关键。记忆库里可能同时存在三个月前和昨天的相似内容如果不做时间加权旧记忆会频繁压过新记忆。我的衰减公式很简单距今天数每翻一倍权重乘 0.8。这样既不会让记忆瞬间失效也能让近期信息自然占据更大比重。4.2 记忆冲突旧记忆和新事实打架怎么办这是记忆系统普遍会遇到的问题。用户三个月前说我在用 React 写前端现在说已经切到 Vue 了。两条记忆同时在库模型注入时可能同时读到导致回答自相矛盾。我处理冲突的方式是给每条记忆加一个状态位。当新记忆与旧记忆的核心实体相同、内容语义相反时系统不只写新记录还会把旧记录标记为已过时。检索时优先返回状态为有效的记忆过时记录只保留用于追溯不再注入系统提示词。这个机制听起来简单但解决了一个很实际的大麻烦。没做之前模型经常被这种自相矛盾的记忆带偏要么回避问题要么给出模棱两可的回答。4.3 上下文预算给记忆分配 token 额度Claude 的上下文窗口有限记忆不能无限占用。我给 claude-mem 定了一个预算规则记忆内容最多占系统提示词 token 的 15%超出部分宁可截断也不挤占用户消息和工具调用的空间。同时每次注入前会检测当前上下文的剩余空间如果空间紧张就只注入与当前话题直接相关的 Top 3而不是 Top 5。这个预算比例不是拍脑袋定的。我试过 5%、10%、15%、20% 四档5% 时模型经常忘记之前的关键背景20% 时模型回答开始变得啰嗦、频频引用无关记忆。15% 是稳定区间大多数情况下既够用又不喧宾夺主。不同任务类型可以调这个参数但建议给一个硬上限防住极端场景。5. 实测中的那些坑跑了近两个月claude-mem 从能用到好用中间踩了不少坑。挑几个印象最深的说说。5.1 记忆污染的滚雪球最严重的一个问题是记忆一旦被错误提取就会被反复检索、反复加强形成自我实现的错误。有一次我在调试代码时随口说这个函数有问题可能是缓存导致的模型把用户认为缓存导致函数问题记成了长期事实。之后每次聊到类似函数这条错误记忆都被召回模型给出的分析全都带着这个错误前提。修复办法是双管齐下一是提取端提高对猜测性陈述的识别要求提示词里明确要求模型区分确定性陈述和推测性陈述只有前者才能写入二是增加手动删除入口我在命令行里留了一个交互式管理命令可以查看记忆列表、一键删除指定条目。自动化工具永远需要一个人为纠偏的出口别把系统做成闭环。5.2 重复写入产生的膨胀去重模块上线之前记忆库一周就涨到了三千多条其中至少一半是重复的。最典型的情况是用户每周都说一次这个项目下周要上线但每次措辞略有不同关键词匹配的相似度只有 0.6没触发去重阈值于是每周新增一条。后来我把去重逻辑从提取前比对改成写入前比对 每周批量清理双层机制。批量清理会用嵌入模型对整个库做一遍两两相似度计算把相似度超过 0.85 的合并成一条内容取最近一次版本。阈值不能调太高否则误合并会把语义相近但不同的记忆糊在一起。5.3 过度注入导致的幻觉如果注入的记忆足够多模型的回复质量反而会下降。这是我一开始完全没预料到的。有一次我连续塞了十条记忆进系统提示词模型的回答变得异常自信开始把记忆里的细节当成事实强加在答案里甚至主动编造记忆里没有的关联信息。这其实是注意力稀释的典型表现上下文太长模型分不清哪些是直接的当前信息、哪些是背景参考。后来我强制要求记忆注入的格式一致每个条目都以参考背景开头并在系统提示词末尾写明参考背景仅供参考若与用户当前描述冲突以用户描述为准。这句话的约束效果超出了预期模型不再拿记忆去压用户。6. 持续优化的一些做法功能稳定之后我陆续做了一些优化这里挑三个方向记录一下。6.1 基于重要性的记忆衰减记忆库不可能无限增长必须有一套淘汰机制。我的做法是定期对低重要性记忆做摘要合并把一个月前的、重要性低于 0.4 的同类记忆合并成一条高密度摘要原记录清入归档表。这样既保留了信息的大致脉络又避免了库体膨胀。衰减规则的另一个好处是倒逼提取质量。我已经发现一条记忆如果存了一个月都没被访问过它对当前工作的价值基本趋近于零。与其留着占空间不如压缩成一句话放进旧知识存档需要时还能翻出来。6.2 用评测集把记忆效果量化记忆系统的好坏不能靠感觉判断。我搭了一个简单的评测集二十个模拟用户场景每个场景包含三段连续对话和对应的五道追问。跑 claude-mem 时检查追问的答对率不跑时作为对照组两个数值的差值就是记忆层的净增益。实测下来带上记忆层后追问答对率提升了大约四成但在涉及临时任务切换的场景中提升不明显说明记忆对持续型任务的帮助远大于即时型任务。这个结论反过来指导我调整了提取策略临时任务的提取频率被调低提取资源集中到长期型任务上。6.3 实际使用的个人体会最后分享一点自己的使用感受。claude-mem 这种工具技术难度谈不上多高真正难的是对记忆这件事的理解。人的记忆本来就是会遗忘、会扭曲、会重建的给 AI 做的记忆系统反而不能太忠实——什么都记等于没记什么都信等于被骗。最好的状态是记住真正重要的遗忘大部分噪声并且给错误留一个修改的入口。如果你也在做类似的项目我的建议是先跑通最小可用版本再把精力花在提取和检索的质量上。存储选型、表结构这些东西撑到几千条记忆都绰绰有余不值得反复折腾。真正决定系统好用与否的永远是你提炼了什么、又在哪里学会了放手。

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

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

免费获取报价 →
↑