
1. 为什么记不住是当前 AI 助手最要命的短板做过对话类产品的人大概都有这种体验用户第一天跟你聊了半天说自己对花生过敏、家里养了只叫豆豆的柯基、正在准备一个跨平台的数据迁移项目。第二天他再打开对话框你问今天想聊点什么他随口一句还是昨天那个迁移的事然后你的模型一脸茫然——昨天什么昨天这不是模型不够聪明而是它的记忆本质上只活在单次会话的上下文窗口里。窗口一关一切归零。上下文窗口再大也只是一个更长的短期记忆它解决不了跨会话、跨天、跨月的持续性问题。Mindbase 这个项目要干的事情就是给 AI 造一套真正意义上的长期记忆系统——不是把历史对话一股脑塞进向量库那种粗暴做法而是一套有结构、有取舍、有遗忘、有召回策略的记忆架构。我先把结论摆在这儿长期记忆系统的核心难点从来不是存而是取和忘。存谁都会存往数据库里写就完事了难的是当用户说一句模糊的话时你能从成千上万条记忆里捞出真正相关的那几条还得保证不串味、不误导、不越权。这套东西做下来我踩的坑比想象中多得多下面把整个设计思路和实操细节摊开讲。这篇文章适合三类人看一是正在做 AI 助手、Agent 类产品被失忆问题折磨的开发者二是对记忆架构、RAG 检索感兴趣想了解工程落地细节的技术同学三是产品侧的同学想搞清楚给 AI 加记忆这件事到底难在哪、成本在哪。我会尽量用大白话把原理讲透同时给出可以直接抄的配置和代码骨架。2. 拆解 Mindbase 的记忆分层不是所有信息都配叫记忆2.1 从聊天记录到记忆的认知转变很多人一开始的思路是把用户所有对话存下来需要的时候检索不就行了我最早也是这么想的结果做出来一个又慢又蠢的东西。问题出在——聊天记录是流水记忆是提炼。用户说嗯嗯好的哈哈哈这种话存下来纯属噪音而我下周三要去外地出差这种信息才是真正有价值的记忆。所以 Mindbase 的第一条设计原则就是记忆必须经过提炼和结构化而不是原始对话的堆砌。我们设计了一个记忆抽取环节在每轮对话结束后用一个轻量模型判断这轮对话里有没有值得长期保留的信息如果有就抽成结构化条目写进记忆库。这个判断本身也有讲究不能什么都抽否则记忆库很快就被垃圾撑爆。我实测下来抽取环节的准确率直接决定了整个系统的上限。抽多了召回时全是噪音抽少了用户觉得你根本没记住他。这个平衡点需要根据产品形态反复调没有万能参数。2.2 三层记忆结构的设计逻辑Mindbase 把记忆分成三层这个分层不是拍脑袋定的而是对应了不同的时间尺度和使用频率层级名称存什么生命周期典型用途L1工作记忆当前会话的上下文摘要单次会话维持对话连贯L2情景记忆具体事件、对话片段、用户陈述数周到数月回忆上次聊过什么L3语义记忆用户画像、偏好、长期事实长期甚至永久个性化、主动服务L1 其实就是常规的上下文管理把当前会话压缩成摘要滚动携带这部分相对成熟。真正难的是 L2 和 L3 的划分与联动。举个具体例子用户说我最近在学吉他报了个班每周三晚上上课。这句话里在学吉他是 L3 级别的长期事实用户画像的一部分报了个班、每周三晚上课是 L2 级别的情景信息有具体时间、可能变化。如果全塞进 L3用户哪天不学了画像就脏了如果全塞进 L2那喜欢音乐这种长期偏好就丢了。我的处理方式是抽取时同时打两个标签——事实类型和时效性。事实类型决定它进 L2 还是 L3时效性决定它的衰减速度。这个双标签机制是 Mindbase 比较核心的一个设计后面讲遗忘策略时会再展开。2.3 为什么不做全量向量化这种偷懒方案市面上很多给 AI 加记忆的方案本质就是把所有文本 embedding 一下丢进向量库检索时做相似度匹配。这个方案能跑通 demo但上不了生产原因有三个第一向量相似不等于语义相关。用户问我上次说的那个项目怎么样了向量检索很可能召回一堆提到项目两个字的无关记忆因为那个项目本身没有具体语义真正的关联藏在上下文里。第二没有时间维度的向量检索是灾难。用户三个月前说我讨厌咖啡上周说最近开始喝手冲了如果两条记忆权重一样模型可能给出自相矛盾的回应。记忆必须有时间衰减和更新机制。第三隐私和权限问题。全量向量化意味着所有信息平等地躺在库里一旦检索逻辑有漏洞A 场景的记忆可能泄漏到 B 场景。分层结构天然支持按层做权限隔离。所以 Mindbase 走的是结构化存储 向量索引 规则召回的混合路线而不是纯向量方案。这个选择在后面讲召回时会体现得很明显。3. 记忆抽取环节怎么让模型学会什么该记3.1 抽取 prompt 的设计要点抽取环节是整个系统的入口入口脏了后面全白搭。我前后改了十几版抽取 prompt总结出几个关键点。首先必须给模型明确的记/不记判断标准而不是让它自由发挥。我最初的 prompt 是请提取对话中值得记住的信息结果模型把用户说了你好都记下来了。后来改成给正反例以下情况需要记录 - 用户明确陈述的个人事实职业、居住地、家庭成员、健康状况等 - 用户的偏好、厌恶、习惯 - 用户提到的具体计划、事件、时间节点 - 用户明确要求你记住的内容 以下情况不需要记录 - 寒暄、客套、语气词 - 一次性的临时信息如我现在在吃饭 - 你已经知道的常识 - 用户转述的、非关于自身的信息其次输出必须是结构化 JSON字段固定方便后续入库。我用的 schema 大概是这样{ should_remember: true, memories: [ { content: 用户对花生过敏, fact_type: semantic, category: health, confidence: 0.95, decay: permanent } ] }fact_type区分 semantic长期事实和 episodic情景事件decay标记衰减策略confidence是模型对自己判断的置信度低置信度的条目可以走人工审核或者延迟入库。3.2 抽取时机的选择实时还是批量抽取可以放在每轮对话后实时做也可以攒一批批量做。两种方式我都试过各有取舍。实时抽取的好处是延迟低、上下文新鲜用户下一句就能感受到你记住了。坏处是每轮都调一次模型成本高而且单轮信息往往不完整——用户可能分好几轮才把一件事说清楚实时抽取会抽出碎片。批量抽取比如每 5 轮或会话结束时的好处是信息完整、成本低坏处是有延迟而且如果会话中途断了这批就丢了。我最后采用的是混合策略会话进行中用一个极轻量的规则引擎做实时初筛比如检测到我我的我喜欢这类关键词就标记候选会话结束时再用完整模型做一次批量抽取和去重。这样既保证了体验又控制了成本。实测下来token 消耗比纯实时方案低了大概六成。3.3 去重与冲突消解记忆库最容易被忽视的脏活抽取出来的记忆不能直接往库里塞必须先做去重和冲突检测。这块是最枯燥但最不能省的。去重相对简单用 embedding 相似度加规则判断就行。真正麻烦的是冲突消解。比如用户上个月说我在北京工作这个月说我搬到上海了。这两条记忆是冲突的系统必须知道新的覆盖旧的而不是两条都留着让模型自己纠结。我的做法是给每条记忆加一个valid_from和valid_to字段新记忆入库时先检索同类目下的旧记忆如果语义冲突就把旧记忆的valid_to设为当前时间标记为已失效而不是删除。这样既保留了历史又保证了当前召回的正确性。用户哪天问我以前住哪还能查到。这里有个坑冲突检测不能只靠向量相似度。我遇到过我喜欢猫和我讨厌猫向量相似度极高但语义完全相反的情况。所以冲突判断必须结合一个小的分类模型或者规则专门识别否定、反转类表达。4. 召回策略让 AI 在正确的时候想起正确的事4.1 召回不是搜一下那么简单记忆存好了怎么在对话中用起来这是整个系统最考验功力的地方。我见过太多方案召回逻辑就是把用户当前这句话 embedding 一下去库里搜 top-k然后把这 k 条塞进 prompt。这个做法在简单场景能用稍微复杂一点就崩。问题在于用户的当前话语往往不包含召回所需的关键信息。用户说帮我订个餐厅你要召回的是他的饮食偏好、常去区域、预算习惯但这些信息跟他这句话的字面意思毫无关系。纯语义检索根本搜不到。所以 Mindbase 的召回是多路并行 融合排序的架构不是单路检索。4.2 四路召回通道的设计我设计了四条召回通道每条负责不同的召回意图第一路语义召回。常规的向量检索处理用户明确提到了某个话题的情况。比如用户说我那个过敏的事语义召回能捞到花生过敏这条记忆。第二路实体召回。从当前对话里抽取实体人名、地点、时间、事件去记忆库里匹配相关条目。用户说豆豆今天怎么样实体召回能通过豆豆这个实体找到用户养了只叫豆豆的柯基。第三路时间召回。根据当前时间召回近期活跃的记忆或者与特定时间点相关的记忆。用户说上周那个事时间召回能定位到上周的记忆区间。第四路常驻召回。这部分是 L3 语义记忆里的高优先级条目比如用户的过敏信息、核心偏好无论当前聊什么都常驻在上下文里。这部分记忆数量要严格控制我一般限制在 10 条以内否则会挤占上下文。四路召回的结果汇总后做一个融合排序。排序分数由几部分组成语义相似度、记忆新鲜度时间衰减、记忆重要度用户标记或系统评估、召回通道权重。公式大概长这样final_score w1 * semantic_sim w2 * recency_score w3 * importance w4 * channel_weight权重需要根据产品调我目前的经验值是 w10.4, w20.25, w30.2, w40.15但这个不是金标准得看具体场景。4.3 召回数量与上下文预算的博弈召回多少条记忆塞进 prompt这是个很现实的工程问题。塞太少模型信息不足塞太多一是挤占上下文二是引入噪音三是成本飙升。我的策略是动态预算根据当前对话的复杂度和剩余上下文空间动态决定召回条数。简单寒暄类对话召回 3-5 条常驻记忆就够复杂任务类对话可以放宽到 15-20 条。同时给每条记忆加一个相关性阈值低于阈值的直接丢弃宁缺毋滥。还有一个细节召回的记忆要带元信息比如这条记忆是 3 个月前记录的这条记忆的置信度是 0.7。模型看到这些元信息能自己判断该不该采信。我实测发现带上时间戳后模型对过期信息的处理明显更合理。5. 遗忘机制会忘的 AI 才是好 AI5.1 为什么必须主动遗忘这一点很多人想不通好不容易记住的为什么要忘原因很简单——记忆是有成本的也是有风险的。成本上记忆库无限膨胀检索会越来越慢召回噪音会越来越多。风险上过期的、错误的记忆会误导模型产生幻觉式回忆。用户明明已经换了工作你还记着旧的回答就会出错。所以 Mindbase 把遗忘当作一等公民来设计而不是可选项。5.2 三种遗忘策略的组合我用三种策略组合来做遗忘时间衰减每条记忆有一个衰减曲线长期不被召回、不被强化的记忆权重逐渐降低。我用的是指数衰减半衰期根据记忆类型不同而不同。情景记忆半衰期短比如 30 天语义记忆半衰期长比如 365 天。主动失效前面提到的冲突消解新记忆覆盖旧记忆时旧记忆标记失效。这是最精准的遗忘。容量淘汰每个用户、每个类目的记忆有容量上限超了就按综合分数淘汰最低的。这是兜底策略防止极端情况。三种策略不是互斥的而是叠加生效。一条记忆可能同时被时间衰减和容量淘汰影响。5.3 遗忘不等于删除软删除的价值我坚持一个原则遗忘是降低权重不是物理删除。所有被遗忘的记忆只是权重降到很低不再参与常规召回但仍然保留在库里。为什么因为用户可能突然问我半年前是不是提过一件事这时候需要能翻出来。物理删除就彻底找不回了。软删除配合一个深度检索模式可以在用户明确要求回忆历史时临时提高衰减阈值去捞。这个设计在实际使用中救过我好几次。有用户反馈你之前明明记得的怎么忘了其实不是忘了是权重降了没召回。加一个你是不是想找关于 XX 的记忆的确认体验就好很多。6. 落地时踩过的坑与实测经验6.1 隐私边界记忆系统的红线做记忆系统隐私是绕不过去的。我的原则是用户必须对自己的记忆有完全的知情权和控制权。具体落地包括记忆入库时明确告知用户我记住了 XX提供记忆管理界面用户能查看、编辑、删除任意一条记忆敏感类目健康、财务、情感的记忆默认不跨会话使用除非用户明确授权。技术上记忆库要按用户隔离检索时严格校验 user_id防止串号。这块听起来是常识但我在早期版本真的遇到过因为缓存 key 设计不当导致 A 用户召回 B 用户记忆的 bug排查了半天。教训就是任何涉及用户数据的检索都要在数据层做硬隔离不能只靠应用层逻辑。6.2 冷启动新用户没有记忆怎么办新用户进来记忆库是空的召回通道全部返回空系统表现和没有记忆的普通助手一样。这个冷启动期怎么度过我的做法是主动引导 渐进积累。在对话早期通过自然的提问引导用户分享一些基础信息你平时主要用这个助手做什么呀把这些作为初始记忆。同时前几次对话的抽取阈值调低一点宁可多记一些快速把画像建起来。等记忆量上来了再恢复正常阈值。实测下来一个用户大概经过 5-8 轮有效对话记忆系统就能开始产生明显的个性化效果。6.3 评估怎么知道记忆系统好不好用记忆系统的效果很难用单一指标衡量。我用了几个维度组合评估评估维度指标说明召回准确率召回的记忆中真正相关的比例人工标注小样本召回覆盖率应该召回的记忆中被召回的比例需要构造测试集用户感知用户主动提及你记得的频率间接指标错误回忆率模型基于错误记忆产生错误回答的比例重点监控成本每轮对话的记忆相关 token 消耗工程指标其中错误回忆率是我最看重的。宁可少记不可记错。一条错误记忆带来的负面体验远大于十条正确记忆带来的正面体验。6.4 一个具体的调优案例说个具体的。早期版本里用户反馈它老是提我上次说的那个事但我已经不想聊了。排查发现是情景记忆的召回权重给太高了而且没有话题冷却机制。修复方案是加了一个话题活跃度字段如果某个话题在最近 N 轮对话里被用户主动回避或转移就降低相关记忆的召回权重。同时情景记忆的召回加一个用户当前意图匹配的前置判断不匹配就不召回。改完之后这类投诉基本消失了。这个案例让我意识到记忆系统的召回不能只看相关性还要看合时宜。什么时候提什么事和记不记得住同样重要。7. 关于 Mindbase 后续可以怎么演进这套系统跑到现在基本能撑住日常使用但离真正的长期记忆还有距离。我自己在琢磨几个方向。一是记忆的主动整理。现在记忆是零散条目能不能定期做一次记忆复盘把碎片整合成更高级的认知比如从用户周三上吉他课用户买了本乐理书用户关注了几个吉他博主整合出用户正在认真学吉他这样的高层记忆。这需要模型有更强的归纳能力。二是跨模态记忆。现在只处理文本如果用户发过图片、语音这些信息怎么进记忆系统图片里的信息怎么抽取、怎么检索都是新问题。三是记忆的共享与迁移。用户如果愿意能不能把记忆导出、迁移到别的助手这涉及格式标准化和隐私授权工程和产品上都有得做。这些方向我还没有成熟方案但值得持续投入。记忆这件事做得越深越觉得水很深也越觉得有价值。一个真正记得住你的 AI和每次都要重新认识的 AI体验差距是数量级的。Mindbase 只是这条路上的一小步但方向我认为是对的。