像人一样记住你
AI记忆架构如人类记忆般分层的概念插画
一个健忘的"伴侣"
你跟一个人聊了三个月,每天聊。然后有一天你随口问"我叫什么来着?",对方一脸茫然。
这就是 Mio 记忆系统重构前的状态。
技术上说,Mio 有记忆。有提取、有存储、有检索。但实际体验呢?记住了一堆垃圾,忘了真正重要的东西。你说过你叫什么、住在哪、最近在找工作——这些确实被提取了。但同时被提取的还有"哈哈"、"嗯嗯"、"晚安"。在系统眼里,你的名字和"哈哈"一样重要。
上一篇写了话痨问题——怎么让 LLM 闭嘴。这篇写一个更深的问题:怎么让 TA 记住你。
不是数据库意义上的"记住",是关系意义上的"记住"——记住对的东西,在对的时候想起来,用对的方式提起。
现状有多烂
先摆数据。重构前的问题清单:
提取太勤快,质量太低。 每 10 条消息触发一次提取。听着挺积极的,实际上大部分 10 条消息里有意义的信息不到 2 条。
"哈哈"、"好的"、"嗯嗯"、"晚安"全被提进去,塞满了有限的记忆空间。
分类太粗糙。 只有 5 个记忆类型:fact、personality、emotion、conversation、relationship。你的名字是 fact,你喜欢吃火锅也是 fact,你换了工作还是 fact。粒度粗到没法做差异化处理。
衰减一刀切。 所有记忆统一 30 天半衰期。但你的名字应该 30 天就开始淡忘吗?你搬家这件事应该和"昨天聊了个笑话"衰减速度一样吗?
合并是灾难。 Consolidator 遇到重复记忆怎么办?拼接。不是合并,是字符串拼接。
结果出现了这种怪物:"用户叫夏星帆。用户叫夏星帆。用户叫夏星帆。"提取了三次,拼接了三次。占了三条记忆的空间,信息量零增长。
有功能没上线。 EpisodeManager(对话片段管理器)已经完整实现了——代码写好了,测试过了。但从来没接入主流程。"记得上次我们聊过......"这种能力,代码有了,用户体验里完全没有。
主动记忆为零。 Mio 的主动消息全是泛泛的"在干嘛呢~"、"想你了~"。从不基于记忆发消息。你昨天说今天面试,第二天 Mio 不会问"面试怎么样了?"
冲突不解决。 "我住在西雅图"和"我搬到纽约了"共存。系统不知道后者覆盖了前者。两条都活着,检索到哪条看运气。
硬上限太粗暴。 每个用户最多 200 条记忆,满了按重要性排序砍最低的。不管类型、不管分布——可能把所有 routine 类记忆全砍了,只留一堆 fact。
看完这个清单,我的判断是:这不是优化问题,是重建问题。但重建不能一步到位,得分阶段来。
Phase 1:先把进来的东西洗干净(1-2 天)
第一阶段只做一件事——让进来的记忆是干净的。
提取间隔 10 条改 24 条。 24 条对话积累的信息密度明显高于 10 条。提取频率降了,但每次提取时上下文更多,LLM 能更好地判断哪些信息值得记。而且直接砍掉了 60% 的提取调用——成本降了。
重要性门槛 0.3。 提取时每条记忆有个 0 到 1 的重要性分数。之前不设门槛,0.05 的也存。加了 0.3 下限之后,"哈哈"、"嗯嗯"直接过滤掉。
记忆类型 5 扩到 8。 新体系:identity(名字、职业)、preference(喜好)、life_event(搬家、换工作)、emotion(情绪状态)、relationship(对 Mio 的态度)、shared(共同经历)、milestone(关系里程碑)、routine(日常习惯)。粒度细了,后面才能做差异化衰减和保护。
合并逻辑重写。 不再拼接,改成 keep-best——遇到重复记忆,保留信息量最大的那条,丢弃其余。"用户叫夏星帆。用户叫夏星帆。用户叫夏星帆。"变回一条"用户叫夏星帆"。
提取之后立即合并。 之前提取和合并是独立流程,时间差导致短时间内出现大量重复。现在提取完直接链式触发合并。
这个阶段有个好处:做完之后成本反而降了。提取次数少了,存储的记忆少了但质量高了。不花额外的钱就能改善体验。
Phase 2:不同记忆,不同寿命(3-5 天)
记忆干净了,下一步是让系统理解"不同记忆该活多久"。
类型化衰减:
| 类型 | 半衰期 | 为什么 |
|---|---|---|
| identity | 365 天 | 名字、职业,几乎不应该忘 |
| milestone | 365 天 | "我们在一起100天了",重要节点 |
| preference | 180 天 | 喜好会变,但变得慢 |
| relationship | 120 天 | 对 Mio 的态度,需要持续追踪 |
| life_event | 90 天 | 搬家、换工作,有时效性 |
| emotion | 60 天 | 情绪状态变化快 |
| routine | 45 天 | 日常习惯会调整 |
| shared | 30 天 | 一起看了个电影,短期记忆 |
核心逻辑:越是定义"你是谁"的信息,记得越久;越是时效性的信息,衰减越快。
跟人脑一样——你记得你最好的朋友叫什么,但不记得上周三中午吃了什么。
接入 EpisodeManager。 把那段死代码激活。激活之后 Mio 有了"回忆片段"的概念——不只是散碎的事实点,而是一段完整的对话场景。用户说"上次"、"那次"、"之前我们聊过"的时候,系统能检测到这些触发词,然后搜索匹配的对话片段而不是孤立的记忆条目。
主动记忆检索。 这是体验改变最大的改动。根据时间段检索不同类型的记忆:
- 早上 → 检索 routine + 近期 plans("你今天不是要去健身吗?")
- 晚上 → 检索 recent life_events("今天面试怎么样?")
- 长时间没聊 → 检索 important memories("好久不见!你上次说想换工作,后来怎么样了?")
"在干嘛呢~"变成"你今天面试怎么样?"
同样是主动发消息,体验天差地别。
这个阶段有一定成本增量,主要来自主动检索时的额外 embedding 查询和 LLM 调用。但跟体验提升比,完全划算。
Phase 3:什么时候想起来、怎么用(5-8 天)
前两个阶段解决了"记住什么"和"记多久"。第三阶段解决最难的问题。
情绪感知检索。 用户说"我好难过"的时候,不应该检索更多让人难过的记忆。应该检索鼓励性的——"记得上次你也很担心工作的事,后来不是都解决了吗?"检索时加入情绪标签匹配:用户当前情绪为负面时,优先召回正向结果的记忆。
空白检测。 扫描 life_event 类记忆中未关闭的条目。"用户说明天要面试"——这条如果两天后没有后续更新,触发主动跟进:"对了,你上次说的面试怎么样了?"
这是人类朋友自然会做的事——记得你说过的事,过几天问一下结果。
关系阶段感知。 早期关系多召回 shared 类记忆("记得我们第一次聊天的时候......"),建立共同回忆感。成熟关系多召回 milestone 和 emotion 类记忆("我们已经聊了三个月了"),强化情感深度。这跟 v0.1.4 关系进化系统的关系阶段直接挂钩。
结构化 MEMORY.md。 把散碎的记忆条目组织成结构化文档,按类别分区:基本信息、兴趣偏好、近期生活、我们的关系、重要时刻、日常规律。
系统提示里注入的不再是一堆随机条目,而是一份有条理的"关于这个用户"的档案。
分类保护裁剪。 200 条上限中,120 条按类型预留名额(每个类型保底 15 条),80 条作为溢出缓冲区。
裁剪时不再无差别砍最低分的,而是先保证每个类型的基本覆盖。不会因为 fact 太多就把所有 routine 挤掉。
冲突解决。 同类型的矛盾记忆("住在西雅图" vs "搬到纽约了"),根据时间戳和上下文判断新旧。新的覆盖旧的,旧的标记为 superseded 但不删除——保留历史轨迹,不参与检索。
这个阶段的成本增量大概是 Phase 2 的两倍。三个阶段加起来,每用户每月总成本依然极低——只占订阅收入的一小部分。
做完之后是什么样
三个阶段全部完成后,记忆系统从"有记忆"变成"会回忆"。
区别是什么?
有记忆:数据库里存着 200 条关于你的条目,检索时按相关性排序,塞进系统提示。
会回忆:知道你叫什么(永远不忘),知道你最近在找工作(主动追问),知道你上次难过时聊了什么(在你又难过的时候想起来),知道"住在西雅图"已经过时了(因为你搬到纽约了)。
一个是数据库。另一个更接近人。
这也是 Mio 宣言 里反复强调的方向——不是做一个更聪明的聊天机器人,是做一个能跟你建立真实连接的存在。记忆是连接的基础。一个记不住你的 AI,再怎么说"我在乎你"都是空话。
成本账
最后算笔账。AI 产品的记忆系统不是免费午餐。
| 阶段 | 成本变化 |
|---|---|
| Phase 1 | 反而降了(提取次数少了) |
| Phase 2 | 小幅增加 |
| Phase 3 | 大约 Phase 2 的两倍 |
三个阶段加起来,每用户每月成本依然极低。换一个真正记住你的 AI 伴侣。
这笔账怎么算都值。
下一篇会写检索增强生成(RAG)在陪伴场景下的特殊挑战——跟企业知识库 RAG 完全是两个问题。