
1. 从零认识 claude-mem它到底解决什么问题第一次看到claude-mem这个名字我的直觉是这应该是一个给 Claude 做“记忆管理”的工具。事实也确实如此。简单来说claude-mem 是一套面向 Claude 会话的上下文记忆持久化方案它要解决的核心痛点非常明确——大模型在长对话、跨会话场景下“记不住事”。如果你用过 Claude 做长期项目一定遇到过这种尴尬昨天聊了三个小时的架构设计今天开新窗口它完全不记得你是谁、在做什么、之前定了哪些约定。每次都要重新贴一遍背景资料token 烧得心疼效率还低。claude-mem 就是冲着这个来的它把对话中值得留存的信息抽取出来结构化存储在需要的时候再注入回上下文。这套东西适合谁我梳理了三类人第一类是重度依赖 Claude 做长期开发或写作的从业者比如独立开发者、技术博主、产品经理第二类是想自建 AI 工作流的技术玩家喜欢折腾本地存储、向量检索这类东西第三类是团队协作场景下需要共享“AI 记忆”的小团队希望多个成员调用同一个知识底座。它解决的问题可以拆成三层记忆的写入怎么判断哪些信息值得存、记忆的存储存成什么结构、放哪里、记忆的召回下次对话怎么精准捞出来。这三层每一层都有坑后面我会逐个拆。需要先说明一点claude-mem 并不是官方产品而是社区围绕 Claude 的上下文机制衍生出来的一类实践方案的统称。不同人实现细节不一样但核心思路高度一致。我下面讲的是基于这类方案最常见的工程实践做的合理还原具体参数你可以按自己的场景调整。2. 整体设计思路为什么是“抽取存储召回”三段式2.1 直接塞全文为什么行不通很多人第一反应是那我干脆把历史对话全部拼起来每次请求都带上不就行了我早期也这么干过结果很快撞墙。第一个问题是token 成本。Claude 的上下文窗口虽然不小但你把几万字的历史全塞进去每次请求的输入 token 都是实打实的开销聊得越久越贵而且是线性增长。第二个问题是注意力稀释。上下文里塞太多无关内容模型对关键信息的抓取能力反而下降这就是所谓的“lost in the middle”现象——中间部分的信息最容易被忽略。第三个问题是窗口上限。再大的窗口也有天花板长期项目迟早撑爆。所以“全量拼接”这条路短期能用长期必崩。claude-mem 的思路是反过来的不存原文存提炼后的结构化记忆。2.2 三段式架构的取舍逻辑我把这套架构拆成三个环节每个环节的选型都有讲究。写入环节核心问题是“什么值得记”。我的做法是设定触发条件比如对话轮次达到阈值、或者检测到特定关键词“记住”“以后都按这个来”“我的偏好是”。触发后调用一次 Claude 做信息抽取让它输出结构化的 JSON而不是自由文本。为什么强调结构化因为后面检索和注入都依赖字段自由文本没法精准召回。存储环节核心问题是“存哪里、存成什么”。常见选择有两类一类是本地文件 向量库比如 SQLite 存结构化字段配合一个轻量向量库存语义嵌入另一类是纯文件方案用 Markdown 或 JSON 按主题分文件管理。前者适合记忆量大、需要语义检索的场景后者适合记忆量小、追求简单可控的场景。我个人偏向混合结构化字段进 SQLite语义向量进本地向量库原文摘要存 Markdown 方便人工审阅。召回环节核心问题是“怎么捞得准”。这里有个关键设计不能只靠语义相似度。纯向量检索容易召回“语义相近但实际无关”的记忆。我的做法是双路召回——语义检索一路基于时间、标签、项目名的结构化过滤一路两路结果合并去重后再排序。排序时给“最近使用过的记忆”加权因为长期项目里近期上下文的相关性通常更高。2.3 为什么不做成“全自动黑盒”市面上有些方案追求全自动对话一结束就自动抽取、自动存储、自动注入用户完全无感。我试过结论是全自动在长期项目里会失控。原因是模型抽取会犯错。它可能把一句玩笑话当成你的真实偏好存下来也可能把临时决定当成长期约定。这些错误记忆一旦注入后续对话会持续污染输出而且你很难察觉是哪一条出了问题。所以 claude-mem 这类方案里我强烈建议保留人工审阅环节——抽取出来的记忆先落到一个待确认队列你扫一眼确认或删除再正式入库。多花这十秒钟能省掉后面一堆莫名其妙的“AI 抽风”。3. 核心细节拆解记忆抽取、存储与召回的实操要点3.1 记忆抽取提示词怎么写才不跑偏抽取环节的成败八成取决于提示词。我踩过的坑是提示词太宽松模型什么都往里塞太严格又漏掉关键信息。我的提示词模板大致是这样的结构先定义记忆的分类体系再给输出格式约束最后给几个正反例。分类体系我一般分四类——用户偏好“我喜欢简洁的回答”、项目事实“这个项目用 PostgreSQL 不用 MySQL”、决策记录“上周决定放弃方案 A”、待办事项“下次要补单元测试”。这四类覆盖了长期项目里 90% 需要记住的东西。输出格式我强制要求 JSON字段包括type、content、confidence、source_turn。confidence是模型自评的置信度低于 0.6 的我直接丢进待确认队列不自动入库。source_turn记录来源轮次方便回溯。提示抽取提示词里一定要加一句“如果本轮对话没有值得长期记忆的信息返回空数组”。不加这句模型会硬凑把寒暄都存下来。3.2 存储结构字段设计决定召回上限存储这块我见过太多人只存一个content字段结果召回时只能靠语义相似度硬扛。正确的做法是把可过滤的维度都拆成独立字段。我的表结构核心字段包括id、type记忆类型、content记忆正文、embedding语义向量、tags标签数组、project所属项目、created_at、last_used_at、use_count。别小看last_used_at和use_count这两个字段在排序时极其有用——高频使用、近期使用的记忆权重应该更高。向量维度方面我用的嵌入模型输出 768 维存成二进制 blob 比存 JSON 数组省一半空间。如果记忆量在几千条以内其实用不上专业向量库SQLite 配合简单的余弦相似度计算就够了省去一堆依赖。3.3 召回策略双路合并的具体实现召回是整套方案里最考验工程能力的地方。我的实现分三步。第一步结构化预过滤。根据当前对话的project字段先把不相关项目的记忆全部排除。这一步能砍掉一大半候选大幅降低后续计算量。第二步语义检索。把当前用户输入做嵌入和候选记忆的向量算余弦相似度取 Top-K我一般取 20。第三步重排序。对 Top-K 结果做加权打分公式大致是score 0.6 * 语义相似度 0.2 * 时间衰减因子 0.2 * 使用频率因子。时间衰减因子用exp(-days_since_used / 30)使用频率因子用log(1 use_count) / log(1 max_use_count)归一化。最后取 Top-5 注入上下文。这套权重是我反复调出来的0.6/0.2/0.2 这个比例在多数场景下表现稳定。如果你的项目对“最新决策”特别敏感可以把时间权重提到 0.3。4. 完整实操流程从环境搭建到跑通第一条记忆4.1 环境准备与依赖选型先说技术栈。我用的是 Python 3.11主要依赖三个库anthropic调用 Claude API、sqlite3内置存结构化数据、numpy向量计算。嵌入模型我用的是本地部署的轻量模型避免额外 API 开销如果你图省事也可以直接用 Claude 或其它嵌入服务。目录结构我建议这样组织claude-mem/ ├── data/ │ ├── memory.db # SQLite 主库 │ └── summaries/ # Markdown 摘要按项目分目录 ├── src/ │ ├── extractor.py # 记忆抽取 │ ├── store.py # 存储与检索 │ └── injector.py # 上下文注入 └── config.yaml # 配置阈值、权重、模型名为什么把摘要单独存 Markdown因为数据库里的记录是给程序读的Markdown 是给人读的。你定期翻一翻summaries/目录能快速发现哪些记忆存歪了。4.2 数据库初始化与字段定义建表语句我贴一下核心部分CREATE TABLE memories ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL, content TEXT NOT NULL, embedding BLOB, tags TEXT, project TEXT, confidence REAL DEFAULT 1.0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_used_at TIMESTAMP, use_count INTEGER DEFAULT 0 ); CREATE INDEX idx_project ON memories(project); CREATE INDEX idx_type ON memories(type);embedding存 BLOB写入时用numpy.array(vec, dtypenp.float32).tobytes()读取时反向还原。索引建在project和type上因为这两个字段是预过滤的主力。4.3 抽取函数的实现细节抽取函数的核心逻辑接收一段对话文本调用 Claude解析返回的 JSON过滤低置信度项写入待确认队列。def extract_memories(conversation: str, project: str) - list: prompt EXTRACT_PROMPT.format(conversationconversation) resp client.messages.create( modelclaude-sonnet-4-20250514, max_tokens1024, messages[{role: user, content: prompt}] ) raw resp.content[0].text items json.loads(raw) return [it for it in items if it.get(confidence, 0) 0.6]这里有个细节max_tokens别设太大1024 足够。设太大模型容易啰嗦输出一堆解释性文字反而干扰 JSON 解析。另外解析前最好做一次清洗去掉可能的 Markdown 代码块标记。4.4 召回与注入的完整链路召回函数接收当前用户输入和项目名返回要注入的记忆列表。注入时我建议用固定格式包裹比如[历史记忆] - (偏好) 用户喜欢简洁回答 - (决策) 项目采用 PostgreSQL [/历史记忆]用标签包裹的好处是模型能清楚区分“这是记忆”和“这是当前问题”减少混淆。注入位置放在系统提示之后、用户输入之前实测这个位置模型利用率最高。注意注入的记忆条数别贪多5 条是甜点区。超过 8 条模型开始忽略部分内容而且 token 成本上升明显。5. 常见问题与排查技巧实录5.1 记忆污染错误记忆怎么清理最常见的坑就是错误记忆。表现是模型突然说出你从没定过的“约定”。排查方法是查memories表按created_at倒序看最近入库的记录找到可疑项直接删除同时把summaries/里对应的 Markdown 也删掉。预防手段有两个一是前面说的置信度阈值二是定期审计。我习惯每周花十分钟扫一遍本周新增记忆删掉明显不对的。这个习惯养成后记忆库的“信噪比”能维持在很高水平。5.2 召回不准语义相似但实际无关这个问题的典型症状是你问 A 项目的事它把 B 项目的记忆捞出来了。根因通常是project字段没填对或者预过滤没生效。检查两点写入时project是否准确赋值召回时预过滤条件是否真的执行了。如果预过滤没问题还是不准那就是语义检索的锅。解决办法是加标签。给记忆打上更细的标签比如“数据库”“部署”“UI”召回时先按标签粗筛再做语义精排。标签相当于给语义检索加了一层护栏。5.3 性能问题记忆多了变慢记忆量到几千条后全量算余弦相似度会明显变慢。我的优化顺序是先加预过滤按项目、类型通常能砍掉 70% 候选还不够就上向量索引比如用hnswlib建近似最近邻索引查询从 O(n) 降到 O(log n)。另一个容易忽略的点是嵌入计算。如果每次召回都实时算当前输入的嵌入会有延迟。我的做法是加一层缓存相同输入 5 分钟内直接复用嵌入结果。5.4 常见问题速查表问题现象可能原因排查方向解决手段模型说出没定过的约定错误记忆入库查最近入库记录删除可疑项提高置信度阈值召回跨项目记忆project 字段错误检查写入赋值修正字段强化预过滤召回语义相近但无关缺标签护栏检查标签覆盖补充标签粗筛后再精排记忆多了查询变慢全量向量计算看候选集大小加预过滤上向量索引抽取结果解析失败输出含多余文本看原始返回清洗 Markdown 标记限制 max_tokens5.5 几个我踩过的独家坑第一个坑时间戳时区。SQLite 的CURRENT_TIMESTAMP默认 UTC如果你本地是东八区时间衰减计算会差 8 小时导致“刚用过的记忆”被算成“8 小时前”。解决办法是统一用 UTC 存储展示时再转本地。第二个坑嵌入模型换版本。换了嵌入模型后旧记忆的向量和新查询的向量不在同一空间相似度计算完全失效。换模型必须全量重算嵌入别偷懒。第三个坑并发写入。如果你多个进程同时写 SQLite会遇到锁表。我的做法是写入走单进程队列或者干脆换成支持并发的存储。6. 进阶扩展让 claude-mem 更贴合你的工作流6.1 按项目隔离记忆空间长期下来你会有多个项目记忆混在一起必然互相干扰。我的做法是每个项目一个独立的project值召回时强制过滤。更进一步可以给每个项目配独立的配置文件定义该项目特有的记忆类型和权重。比如代码项目重视“决策记录”写作项目重视“风格偏好”。6.2 记忆的版本管理有些记忆会更新比如“项目用 MySQL”后来改成“项目用 PostgreSQL”。直接覆盖会丢失历史我的做法是加一个superseded_by字段旧记忆标记为被取代召回时默认排除被取代项但保留可追溯性。这样你能看到决策的演变过程对复盘很有价值。6.3 与工作流的集成点claude-mem 最好用的集成方式是做成一个中间层你的所有 Claude 请求都先过这一层它负责注入记忆、记录对话、触发抽取。这样你不需要改任何现有调用代码只改一个 base_url 或包一层函数就行。我自己的集成方式是在请求封装函数里加三个钩子请求前注入记忆响应后记录对话对话结束触发抽取。三个钩子加起来不到 50 行代码但对体验的提升是质变的。6.4 记忆的可视化审阅纯命令行审阅记忆效率低。我后来写了个简单的本地页面把记忆按类型、项目、时间分组展示支持一键删除和编辑。工具不复杂但让“定期审计”这件事从负担变成了顺手的事。如果你不想写页面用 Obsidian 直接打开summaries/目录也是个不错的替代方案Markdown 天然适合人工阅读。6.5 关于隐私与数据边界最后提醒一点记忆库里存的是你的项目细节、偏好、决策这些数据敏感度不低。如果走云端嵌入服务等于把内容传出去了。我的建议是嵌入本地算存储本地放只把最终注入的少量记忆发给 Claude。这样数据边界清晰心里也踏实。这套方案我从最初的全量拼接一路迭代到现在的三段式架构中间推翻重来过两次。最大的体会是记忆系统的价值不在于记得多而在于记得准、取得对。与其追求全自动不如老老实实做好抽取质量、存储结构和召回策略这三件事。我现在这套跑了大半年记忆库稳定在两千条左右召回准确率目测在八成以上日常用起来已经感觉不到“AI 失忆”这件事了。