claude-mem实战:用SQLite+向量检索为AI助手构建长期记忆层

发布时间:2026/10/12 0:14:22

claude-mem实战:用SQLite+向量检索为AI助手构建长期记忆层 先说一个让人抓狂的场景你在对话框里花二十分钟描述一个模块的重构思路AI 给出了相当具体的实现方案还帮你理清了依赖关系。第二天你打开同一个会话发现它已经忘了你是谁、昨天讨论的接口叫 lark-core 还是 core-lark。你只能把关键背景重新粘贴一遍然后对方又从“你好有什么可以帮你”开始。这我不是第一次遇到后来才决定认真做一个叫 claude-mem 的小项目专门解决“对话一关就全忘”的问题。claude-mem 是一个典型的“AI 助手长期记忆”工具。它的核心功能是把每一次对话中值得留存的信息自动提取出来存进本地数据库下一次新会话开始时按需检索并注入回上下文。你可以把它理解成给 AI 装了一个“外部记事本”它不用记住所有流水账只需要记住决策、偏好、待办和关键背景。这样每次开新会话都像续接昨天的话题而不是从零开始。这篇文章我会从设计思路讲到具体实现把 claude-mem 的存储结构、检索逻辑、注入策略、踩坑和调试方法完整过一遍适合那些重度使用 AI 辅助开发或写作、又不想反复解释背景的人。当然想学点本地知识库和向量检索实践的读者也能直接抄作业。1. 这个项目到底在解决什么问题1.1 先把痛点说清楚AI 不是记忆力差而是“上下文窗口只有那么一点”大模型本身不是没有记忆它只是把“记忆”限制在了当前上下文中。浏览器一刷新、进程一重启这段上下文就像被橡皮擦掉了一样。更微妙的是即使上下文窗口还没超限如果聊到一半切到另一个会话模型就完全无法引用上一个会话的内容。这就带来几个很实际的麻烦你需要反复自我介绍包括职业背景、项目约束、技术栈偏好。一个跨三天的复杂需求每天都要重新复述一遍“业务背景是什么”“昨天已确认哪些方案”。一旦项目涉及十几个文件你根本没法把所有信息塞进一次对话只能人为拆碎拆完之后轮廓又丢了。最要命的是AI 会基于缺失前提“脑补”给出一份看起来合理但方向跑偏的方案你还要花时间解释为什么不对。这些问题并不是模型能力不够而是缺少一个“记忆层”。上下文窗口是工作台记忆层是货架。工作台不够大没关系货架够大、取货够快就行。claude-mem 就是去做这个货架。1.2 claude-mem 的定位不是聊天记录备份是“结构化记忆”从一开始我就想清楚一件事记忆工具不能做成历史记录导出器。聊天记录虽然信息全但检索效率极低而且多数内容是寒暄、试探、重复问问题属于过期垃圾。真正有价值的是从对话里提炼出来的“稳定事实”。举个例子你和 AI 聊“帮我把支付模块改成工厂模式”。原始消息里有大量过程性描述但真正值得记住的是需求支付模块切换为工厂模式。目的后续增加新的支付渠道时不用改核心逻辑。约束不能影响现有微信、支付宝两个渠道灰度上线。偏好代码中不使用反射擅长“每类一个分支函数”的风格。claude-mem 要做的就是从原始对话里提取这些“结论型信息”打上分类标签存进本地向量库。下次你再开一个新会话它可以自动把与该主题相关的一条或多条记忆找出来插进你发出去的提示词里。1.3 设计目标排序有用、轻量、可遗忘正式动手前我给自己定了几个原则防止项目失控。第一本地优先。所有记忆默认存在本机 SQLite 文件里数据不出内网。不是不信任云端而是“记忆”这种东西太私密里面往往带着代码路径、业务命名和未公开想法哪怕是托管给第三方也有心理负担。第二安装和使用必须简单。我不希望为实现记忆功能再搭一个服务端、再引入一套消息队列。一个 Python 脚本、一个 SQLite 文件、一条命令启动足够了。第三记忆必须可查、可删、可改。人都会记错程序提炼的信息也可能出错。如果记忆模型没有遗忘接口错误记忆就会反复注入每次对话误导性比没记忆还要强。所以 claude-mem 从一开始就设计了forget、edit、list这类命令把控制权留在使用者手里。2. 方案选型为什么是 SQLite 向量检索2.1 先盘一圈市面上的“记忆方案”做之前我也去了解过一些现成的思路大致分为三类。第一类是“全量拼接”。把历史消息全部塞进上下文靠模型自己回忆。这种方式实现最简单但几乎不可用。上下文窗口有限聊一个星期之后光历史就有几十万字模型还没回答就先看背景了速度慢、费用高、关键信息被淹没。第二类是“数据库标记关联”。把每一段对话关联一个项目 ID下次同一项目启动时拉取全部相关消息做个简单截断。这种方式解决了“跨会话”的问题但没解决“检索质量”的问题。同一个项目下可能有三万条消息你打开新会话时根本不知道该带哪几条。第三类是“向量检索记忆”。把值得记忆的句子转成向量查询时把当前问题也转成向量语义找最相似的旧记忆。这是最接近人脑的做法不是每次都把所有书都摊在桌上而是根据当前问题想起最相关的几段。claude-mem 最终也选了这条路。2.2 存储引擎对比向量库真不一定要用重型武器提到向量检索很多人第一反应是上 Milvus、Chroma、Weaviate 这类专用数据库。我在最开始也差点这么干后来做了一个小实验往 SQLite 里塞了五万条记忆向量用暴力余弦相似度做检索单次查询耗时 30 毫秒左右。对我这种个人使用规模来说完全够用。我整理了一下当时的对比思路方案部署成本查询性能十万级维护复杂度合适场景内存直接算最低中等最低数据量小于 10 万条SQLite 应用层向量计算低中上低个人工具、团队小工具Chroma 等嵌入式向量库中中上中需要集合管理、过滤查询Milvus 等独立服务高高高百万级以上、高并发对于 claude-mem 的使用频率单机一天能新增几百条记忆已经算很高了SQLite 完全不构成瓶颈。更关键的是SQLite 生态成熟备份就是一个文件同步可以用网盘或 Git崩溃恢复也简单。如果我选了重型向量库那我需要维护的服务就从一个 Python 脚本变成了一个数据库集群这跟项目定位完全相悖。最终选型是SQLite 存原始记忆和元数据应用启动时把所有 embedding 加载到内存用 numpy 做向量点积求相似度。这听起来很“原始”但对一个轻量工具来说简单和可靠才是第一优先。2.3 向量从哪来本地小模型还是云端 APIembedding 模型的选择我踩过一点坑。最开始图省事直接用一款远程 embedding API每次新增记忆都发一条请求。结果有两个问题一是网络抖动会让批量写入速度变得不可控二是对话中需要现场注入记忆时还要等一次 API 往返响应延迟明显变大。后来我改成本地运行一个开源的小型中文 embedding 模型大概三百 MB 左右单机 CPU 就能跑单条文本向量化耗时 50 到 200 毫秒。对 claude-mem 这种非实时嵌入的场景完全没压力。这里给大家一个关键建议不要盲目追求高维向量。向量维度越高存储占用越大中小规模数据上精度提升却很有限。我实测在个人语料上从一百多跳到三百多维度检索准确率提升肉眼可见再从三百多跳到上千维度几乎没有变化空间却翻了三倍。选一个两三百维的中文优化模型是最划算的。3. 核心实现记忆的写入、检索与注入3.1 什么样的内容才值得被记住这是 claude-mem 最核心的问题。如果什么东西都存很快存储就会爆炸而且大量低质量记忆会污染检索结果。我把值得提取的信息归纳成四类事实类“用户所在团队叫服务端组”“项目的数据库是 PostgreSQL 15”决策类“上个月确定使用消息队列解耦下单流程”“以前试过同步调用太慢所以放弃”偏好类“代码风格偏好类型提示”“喜欢先写测试再写实现”任务状态类“用户正在进行订单模块的重构”“已完成表结构设计下一步是写接口”提取逻辑用提示词工程实现。我每轮对话结束后把完整的消息列表发给一个专门做“记忆提炼”的调用让它输出 JSON 结构格式大概是这样[ {type: fact, content: 支付模块即将从策略模式改为工厂模式}, {type: preference, content: 新代码需要保留原有微信和支付宝渠道}, {type: todo, content: 下一步编写工厂类的接口定义} ]注意我刻意要求模型“只提取稳定的、对后续任务有影响的结论”过滤掉“我觉得”“可能”这类不确定表述。如果一句本来该被记住的话同时带着明确条件和场景那么我会让它加上场景标签比如“仅在部署新支付渠道时适用”。这样后续检索时即使关键词相同也能避免把不同场景下的结论混淆。3.2 数据库表怎么设计数据库结构一开始设计得挺复杂后来不断做减法。最终的核心表只有四张CREATE TABLE conversations ( id INTEGER PRIMARY KEY AUTOINCREMENT, started_at TEXT NOT NULL, source TEXT, summary TEXT ); CREATE TABLE memories ( id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id INTEGER REFERENCES conversations(id), memory_type TEXT NOT NULL, content TEXT NOT NULL, category TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, access_count INTEGER DEFAULT 0, embedding BLOB ); CREATE TABLE memory_similarity ( memory_id INTEGER REFERENCES memories(id), similar_id INTEGER REFERENCES memories(id), score REAL ); CREATE TABLE settings ( key TEXT PRIMARY KEY, value TEXT );其中memories表的embedding字段是一个二进制数组存的是浮点向量转换成的 bytes。conversations表保留会话摘要方便倒查某条记忆是从哪段对话来的。memory_similarity表用来做相邻记忆去重后文会讲。真实使用中我还加了一个很简单的索引标记memory_type。当检索命中某一条记忆后如果它的类型是fact或decision那么在注入上下文时我会给予更高优先级如果是todo或临时状态会放在更靠后的位置避免它干扰当前问题的主线。3.3 检索与注入如何让“往事”正好出现在该出现的位置每次发起新对话之前claude-mem 做的事情可以拆成五步拿到用户当前输入。将当前输入向量化。与历史上所有记忆向量做余弦相似度排序。筛选出分数超过阈值的 top-k 条。组装成一段“参考记忆”文本拼接到 system 提示或用户消息之前。检索这部分有个非常容易被忽略的坑不要只拿“用户当前提问”作为查询向量而要把“当前工程上下文”也拼进去。因为很多时候用户输入很短比如“继续”若不带上历史中的项目关键词向量检索只能搜出一堆低相关度内容。我的做法是把最近一次会话摘要、当前打开的文件路径、项目名全部拼成一个“查询前缀”再向量化去检索。实测比只查原始问题准确率高很多。注入格式我固定为[From memory] (1) [fact] 支付模块计划从策略模式改为工厂模式 (2) [preference] 必须兼容现有微信和支付宝渠道 (3) [todo] 下一步编写工厂类接口定义 [End of memory]这样模型能清晰区分“这是外部注入的记忆”和“这是用户当前说的话”。如果直接混在用户消息里模型偶尔会把这些记忆当成用户本次真正想表达的意图造成莫名奇妙的回复。3.4 遗忘与去重做减法比做加法难我一度以为把记忆存进去就万事大吉结果跑了一周后出现一个明显问题同一件事被反复写入内容高度相似检索时一次性把七八条“旧版本”都翻出来模型反而困惑了。后来我加入去重逻辑每写入一条新记忆先拿它的向量与已有记忆计算相似度如果相似度超过 0.92就把新内容当作旧记忆的“更新”直接进行合并。合并规则也很简单如果两条内容存在明显的时间先后顺序以新的覆盖旧的如果内容互为补充就把它们拼接合并为一条并更新updated_at。遗忘这件事就更直接了。我在命令行里提供了claude-mem forget --memory-id 123 claude-mem forget --category preference删除不只是删数据库里一行还要把该条记忆的向量从内存索引中同步移除。我一开始因为惯性只在数据库标记deleted1结果向量检索还是会把已删除内容找出来返工过一次。4. 实操过程把 claude-mem 接到我的日常工作中4.1 环境准备和安装我这里以本地 Python 环境为例。整个项目依赖非常少核心就这几项python -m venv .venv source .venv/bin/activate pip install numpy pip install click # 用来做命令行参数解析 pip install sentence-transformers # 本地 embedding 模型运行框架如果你对模型大小敏感也可以直接用更轻量的 fastembed 或 llamafile。我选 sentence-transformers 主要是因为它生态最稳、API 简洁遇到问题社区方案多。安装后先初始化claude-mem init --db ~/.claude-mem/memory.db这个命令会创建数据库文件、建表、写入默认配置同时把本地 embedding 模型下载到本地缓存目录。模型首次下载比较慢后面完全离线工作不会因为网络波动影响记忆写入。4.2 命令行工具的几个常用操作我陆续给 claude-mem 加了一组命令实际使用频率从高到低排序如下命令作用典型场景claude-mem add --text ... --type decision手动写入一条记忆对话没自动抓到但你自己觉得应该保留claude-mem ingest --file chat_history.json从导出的历史对话批量提取记忆迁移旧会话claude-mem query 支付模块重构命令行测试检索效果验证某条记忆能否被召回claude-mem recall --topk 5生成下一轮对话需要注入的上下文接入工作流前调试claude-mem list --category preference查看某类记忆检查有没有存坏的记忆claude-mem forget --memory-id 123删除指定记忆记忆过时或错误时claude-mem stats查看总条数、分类分布、每日新增量判断记忆库健康程度其中最常用的是recall因为它直接对接我接下来要说的工作流。4.3 集成到 Claude 会话流程实际工作里我用 claude-mem 的方式有两种。一种是在启动新会话时手动把claude-mem recall的结果复制到对话开头。这种方式适合偶尔使用。第二种是做了一个小的命令行包装器类似这样claude-mem recall --compose-into-prompt 我正在做支付模块工厂模式改造 context.txt # 然后把 context.txt 的内容与我的消息一起交给模型短期用下来我其实更推荐“包装器 后台服务”的方式。我写了一段简单脚本每次调用模型前先执行 recall将输出拼进 system 消息再发起接口请求。整个过程大约增加一两百毫秒延迟但换来的是对话连续感。关键是这段逻辑极其简单不用侵入模型接口内部因此无论你用官方客户端、本地大模型框架还是自写的调用脚本都能接得上。这里有一个接入手感上的细节不要把 claude-mem 的结果当成“必读的权威事实”。更好的做法是在注入文本里明确标注“以下内容来自记忆提取可能存在偏差如果与当前用户描述冲突以当前用户描述为准”。这样能大幅降低模型因为旧记忆而坚持错误信息的概率。4.4 用一段真实对话演示完整效果我实际跑了一遍模拟情境是“准备把支付模块从策略模式改造为工厂模式”。第一步上一轮对话结束时claude-mem 自动提取并存入记忆。提取出的内容有两个decision: 支付模块改造为工厂模式保留微信和支付宝渠道。todo: 下一步为工厂类设计接口定义。第二步第二天我新开一个会话输入只有一句话“继续昨天的改造”。这时 claude-mem 的查询拼接会把“继续昨天的改造”和项目摘要拼一起向量检索出上面两条记忆并注入。我拿到的模型回复开头是“根据之前的结论支付模块要改为工厂模式并且必须保留现有微信和支付宝渠道。接下来我们先定义工厂类接口你看看下面这个设计是否符合预期。”这就省去了我重新花十分钟描述背景。整个体验和“不是同一个模型在聊天”完全不同更像是同一个助理中途出去喝了杯咖啡又回来继续干活。4.5 参数调优实测记录跑了一段时间后我留下两组比较满意的参数可以直接抄参数我的取值说明相似度阈值0.68低于这个分数的记忆基本不注入top_k5单次最多携带五条记忆单条记忆最大长度120 中文字符超长记忆先自动压缩成摘要注入总 token 预算600约合 400 个中文字占上下文的 5% 到 10%我在多轮对话里做了对比测试top_k 从 3 调到 5 时相关性提升比较明显调到 8 之后开始出现冗余信息偶尔会把模型带偏。阈值如果设在 0.8会漏掉很多语义相关但表面用词不同的记忆并不推荐。5. 常见问题与排查技巧实录5.1 高频问题速查表用了一段时间我总结出下面这些容易踩的坑做成一个速查表遇到问题照着查就行。现象大概率原因解决办法检索经常漏掉关键记忆查询向量只用了用户一句话把项目名、会话摘要拼进查询前缀中文同义句匹配不上embedding 模型对中文支持不佳换成中文语料优化的模型或加关键词过滤注入记忆后回复跑偏相似度阈值太低带了无关记忆提高阈值降低 top_k同一件事反复写入缺少去重合并逻辑增加写入前相似度检测超过阈值就合并删除记忆后仍然被检索出来删除时只改标记没移除向量索引删除时同步从内存索引和数据库共同清理一段旧记忆反复干扰新决策缺少时间衰减机制对超过 90 天未访问的记忆降低优先级本地模型加载太慢每次启动都重新加载 embedding 模型做常驻后台进程或把向量导出成缓存文件第一项是最常见的很多人做完基础版都会发现“明明存了却搜不到”。其实不是没存到是你拿一条只有几个关键词的查询向量去打一个内容密度很高的记忆库相似度自然很难超过阈值。5.2 翻车现场我踩过的三个大坑第一个坑是把清洗前的敏感内容直接存进了记忆库。有一阵我拿真实项目的完整日志跑批量 ingest结果记忆库里存满了内部服务地址、数据库表名、临时凭证。谁看到都有点慌。后来我给 ingest 命令加了一条强制规则所有记忆在写入前先经过一次敏感信息扫描包含疑似密钥或内部域名的直接打上敏感标签不参与自动注入。个人工具更要想清楚“量”的问题越多的数据不代表越强。第二个坑是以为“提取一次就一劳永逸”。记忆是会过期的。项目重构完成后当初的“支付模块计划改为工厂模式”就已经从 plan 变成了历史事实如果还把它当成todo注入就会让模型一直以为改造尚未开始。我现在会在每次对话结束时顺带做一次“记忆状态刷新”让模型根据最新对话更新同一主题下记忆的状态。具体到实现上就是查一遍 top-k 相关记忆若有状态变化就重写memory_type。第三个坑是没有考虑多会话并发时的写入覆盖问题。我有一次同时打开三个会话处理同一个需求结果三个会话都在向记忆库写入“下一步是写接口”后写的覆盖了先写的导致其中一个会话丢失了更早更完整的上下文。后来我在写入路径里加了“乐观锁式时间戳比较”只有新记忆的时间比旧条目晚时才允许覆盖解决了并发下互相踩踏的问题。5.3 几条独家避坑经验想在实际项目里用起来我有几条普通文档里不会写的建议。第一条给记忆加“可信度分数”。我建议在每条记忆入库时让提取模型输出一个 0 到 1 的可信度值。当两条记忆互相矛盾时检索阶段直接忽略低可信度条目。这个分数在我实际测试中把错误注入率降低了接近一半。第二条对高频检索的记忆做“热度加权”。我在检索排序公式里加了一个加成系数访问次数越多的记忆在下一次排序中略微上浮。这样那些反复使用的背景信息会被自然固定在 top-k 队列中不需要人工反复置顶。第三条记忆库也要定期“断舍离”。每过两周跑一次claude-mem prune --max-age 90把超过九十天且访问次数低于两次的记忆归档或删除。表面看是丢了一些数据实际上是保住了检索质量。没有修剪的记忆库和你聊了一年没整理的聊天记录文件没什么区别。结尾一点个人体会我在实际使用 claude-mem 之前也怀疑过一个“外挂记忆”会不会让 AI 表现得越来越僵化甚至把旧经验当成包袱。但跑了两个多月后我发现真正的问题不是“记忆太多”而是“记忆没有分层”。把该记住的事实记牢、把过期的决策及时遗忘、把临时状态和稳定偏好分开这个工具才算是合格。最后再分享一个小技巧。如果你也和一样经常需要跨项目工作建议每个项目单独建一个记忆库而不是所有项目混成一个。我在一个全局库里放了三个项目的内容后检索时经常出现“项目 A 的结论干扰项目 B 的方案”切分开之后基本不再发生。配置文件里指定一下--db ~/.claude-mem/projects/{project}.db就行成本极低收益明显。claude-mem 这条路目前还不算成熟但方向我越走越确定与其指望模型的上下文窗口变得无限大不如在窗口之外帮它搭一个可靠的外部记忆层。只要提取够准确、检索够相关、遗忘够及时这个组合就能一直保持“记得住又不被旧账拖累”的状态。
延伸阅读

更多相关文章

2026/10/12 1:24:28

MP-DQN深度强化学习无人机避障与目标追踪:Python从零复现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 1:24:28

《单片机原理与应用》期末速成:一周拿下51单片机核心考点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/11 0:02:13

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/11 0:02:13

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/12 0:04:22

绝缘子缺陷检测数据集清洗与工业级训练实战指南

简介:本资源是面向电力AI研发人员、工业视觉工程师及智能巡检系统开发者的绝缘子缺陷检测专用YOLO格式数据集,解决无人机航拍场景下绝缘子破损、污闪、积雪等9类典型缺陷的精准识别与定位难题。数据集共2139张真实巡检图像(含训练/验证/测试集…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑