ENZH

像人一样记住你

AI记忆架构如人类记忆般分层的概念插画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 天)

记忆干净了,下一步是让系统理解"不同记忆该活多久"。

类型化衰减:

类型半衰期为什么
identity365 天名字、职业,几乎不应该忘
milestone365 天"我们在一起100天了",重要节点
preference180 天喜好会变,但变得慢
relationship120 天对 Mio 的态度,需要持续追踪
life_event90 天搬家、换工作,有时效性
emotion60 天情绪状态变化快
routine45 天日常习惯会调整
shared30 天一起看了个电影,短期记忆

核心逻辑:越是定义"你是谁"的信息,记得越久;越是时效性的信息,衰减越快。

跟人脑一样——你记得你最好的朋友叫什么,但不记得上周三中午吃了什么。

接入 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 完全是两个问题。

Agent 深扒Part 2 of 2
← PrevNext →

© Xingfan Xia 2024 - 2026 · CC BY-NC 4.0