会“做梦”的 Agent 记忆:Claude、ChatGPT 的梦在云端,河蟹的梦在你本机
前几天我翻河蟹的记忆文件,看到这么一行:
- 我在西湖区 <!--m:subj=所在地; vf=2026-06-20;conf=0.90;hc=2-->
行尾那段 HTML 注释,markdown 渲染时是隐形的。再往下翻,我发现"西湖区"这条还在,只是被标了个失效时间(上周去过那一趟);当前有效的,是后面新写的"我在余杭区"(我常待的地方)。它没把西湖区删掉——只是给它盖了个时间戳。
这阵子 Claude 和 ChatGPT 都给记忆加了"做梦"——后台自动把你说过的话整理成一份画像(Anthropic 5 月发的叫 Claude Dreaming,OpenAI 6 月发的叫 Dreaming V3,都拿人睡觉时大脑固化记忆来打比方)。我也想给河蟹一套这样的记忆。但真动手时,有两个地方我特意做得不一样:
-
它整理记忆的每一步,都落在你能
cat、能git diff的纯文本上——不是某个你看不见的云端。 -
"做梦"里真正会幻觉的那部分(让 LLM 改写你的记忆),我把它关进一个有边界的笼子,而且默认锁着,开关留给你。
这两条不是什么功能卖点,是我自己用得安心的底线。下面就跟着开头这条"所在地"记忆,看它在河蟹里怎么过完一生。
先看一眼整座楼:三层 + 六类
在跟着那条记忆往下走之前,先把整座楼看一眼。河蟹的记忆不是一个大池子,而是三层楼(这套三层借的是操作系统管内存的思路——Letta / MemGPT 把它叫 core / recall / archival,本质是拿管虚拟内存的办法管记忆):
- 常驻层(楼顶)
——你是谁、你定的硬规则、你的长期偏好。会话一开始就冻结成快照注入,每轮都在,保证带。
- 检索层(中间)
——一条条离散事实("在余杭区""上周在改一个 RAG 的 bug""技术栈是 Go")。不每轮都带,按当前问题三维打分、挑最相关的几条召回。
- 原始层(地下室)
——你所有对话的全文留底,平时不动,需要时全文检索翻出来。
一条记忆落在哪层,由它的类型自动决定,不用你手填:规则 / 身份 / 指令 / 偏好归常驻,普通事实 / 上下文归检索。而且每条记忆都带 (用户, 角色) 的归属——你接了飞书、几个人共用一个 Agent,各人的记忆不串场。
这座楼里发生的所有改动——你随口说的、AI 主动记的、半夜做梦整理的、你自己手动改文件的——全走同一个"单写器"排队落盘,原子写、不互相覆盖,连你手改过的条目它都会先比对、不盲覆盖。下面挨层看(也可以先对着这张图建个全局):

一条记忆的一生:① 写入(去重 → 取代留史)· ② 读取(三层组装注入)· ③ 做梦(机械轻相 + LLM 深相,整理后写回)
存:一行人话,行尾藏着批注
你随口跟它说一句"我在余杭区",河蟹把它记了下来。存哪儿这事,业界两条路:ChatGPT 存进云端、你只能在设置里翻列表;Claude Code 存进本地文件。河蟹走后者,但多做了一件事——在你看不见的地方,给每条记忆缝了一张隐藏批注(structured_entry.go)。
就是开头那段行尾注释:subj 是这条事实的"主语"(所在地),vf 生效时间,conf 置信度,hc 被召回过几次。一个字段都不靠数据库,全藏在 markdown 行尾的注释里。文件还是那个你能 cat、能改、能 git diff 的纯文本,但记忆从此有了结构——能排序、能比对、能标记失效。旧条目没这段注释?解析时字段全取零值,照常工作。
你可能会问:元数据为什么不进数据库、不进向量库?——因为一进库,你就 cat 不了、git diff 不了、手改不了了。河蟹宁可用"纯文本 + 行内注释 + 单写器串行落盘"硬扛结构化,也要把"你能看见、能改、能回滚"这条护城河留住。这是个清醒的取舍:拿一点写入吞吐,换全程透明——对一个跑在你自己机器上、还会半夜自己改自己的记忆,这买卖划算。
改主意:旧的不删,只盖个失效戳
先说这套为什么长成这样。最早它就是个 append-only 流水账——往文件里一条条追加、从不回头。用久了两个病就冒出来:矛盾打架(同一件事先后说了两个值,它到底信哪条)、越积越脏。后面的 supersede 留史、和半夜的做梦整理,都是被这两个病逼出来的。
你平时常在余杭区,过些天去了趟西湖区,随口跟它说一声。这时候多数记忆系统会做一件我不太放心的事:把"余杭区"那条直接改写成"西湖区"。ChatGPT 的 Dreaming 就是这一类——后台改写,旧值没了,它到底动了什么,你也很难回看。
河蟹不覆盖。它先做一次去重判定(upsert.go):新说的话和库里哪条,字符二元组相似度超过 0.65,就算同一件事的改写;可"所在地"这个主语下,余杭区 ≠ 西湖区,是矛盾——于是走 supersede(时序取代),而不是覆盖。每条事实带一个"有效窗口",矛盾即取代、不是抹除——这套 Zep / Graphiti 管它叫 bi-temporal(双时间轴):
// 召回默认只取"当前有效"的条目func IsCurrentlyValid(e, now) bool { if e.ValidTo != nil && !now.Before(*e.ValidTo) { return false // 已被取代,失效 } return true}
"余杭区"那条不删,只在隐藏批注里补一个 vt(失效时刻);"西湖区"新写进去,带上 sup 指回旧条。往后召回默认只取"当前有效"的——你人在西湖区时它就答西湖区;等你回了余杭区,它再 supersede 一次、把所在地切回来。这一趟来回——你哪天在余杭、哪天去了趟西湖——都原原本本躺在文件里,git log 一翻清清楚楚。
覆盖,是把历史擦掉;取代,是给历史盖个时间戳。前者你只能信它,后者你能查它。
想起来:常驻冻结 + 三维打分 + 主动召回
该用记忆的时候,三层楼各出各的力。
楼顶(常驻层)每轮都带。会话一开始,引擎就把常驻层冻结成一张快照,按一个 token 预算挑进来——pinned 优先、然后按重要度、再按新近度(resident.go)。硬规则、你的身份,保证每轮都在,不靠"碰运气检索"。
中间(检索层)按需挑。记忆多了塞不下,得挑。最朴素的做法是按向量相似度挑——谁跟当前问题最像就召谁。但我很快撞上这条路的坑:纯相似度会埋掉"重要但旧"的事。比如你两个月前踩过一个坑,特意叮嘱过它"那个老接口偶尔抽风,千万记得加超时兜底";过些天你问的东西跟这句八竿子打不着、语义上根本不沾边——可它要是没把这条捞出来,你很可能又栽在同一个地方。所以河蟹的打分是三维的——这套 recency × importance × relevance,正是斯坦福 Generative Agents 那篇论文的打分法(recall/entry.go):
// 三维加权,确定性,零 LLMScore = 新近度 + 重要度 + 相关度// 重要度 = 类型先验 + 显著性 + 召回频次// 规则/身份 1.0 · 指令 0.8// 偏好 0.6 · 普通事实 0.4
- 相关度
——配了向量模型就用 cosine 0.7 + 关键词 BM25 0.3 的加权混合;没配就软降级成纯关键词,不崩。
- 新近度
——指数衰减,半衰期 30 天。
- 重要度
——不靠 LLM 现打分,而是"类型先验 + 显著性 + 被召回次数"算的。"过敏""务必""千万"这类词命中会加分(重要的新事实第一次就够分被想起);每被成功召回一次再涨一点、封顶。
"千万记得加超时兜底"是条要紧的旧叮嘱——"千万"这种词会触发显著性加成,把它的重要度顶上去;就算旧、就算今天语义不最像,三维一加权照样浮得上来。这里还藏着个刻意的设计:三维不是一个量纲——重要度上限能到 2.0(类型先验 + 显著性 + 召回叠起来),新近度、相关度却各自封顶 1.0。换句话说,够要紧的事,在分数里天生就压得过够相似的事。纯相似度只问"像不像",河蟹还问"要不要紧"——而且这"要不要紧"是算出来的,不是嘴上说的。
地下室(原始层)需要时才翻。这里走两条独立通道,不混在一起:高信任的策展事实每轮自动注入,而原始会话全文是按需的。除了模型自己想搜,河蟹还会在回复之前主动翻一次历史对话(active_recall.go,默认开),把"该想起来"的旧片段先浮上来。但它很克制——最多浮 3 条、1.5 秒超时、纯本地全文检索零 LLM、连续失败 3 次熔断冷却 60 秒、只在一对一聊天时跑,失败就静默退回,绝不卡你回复。
做梦:它会整理,但会幻觉的那半我上了锁
前面这些够日常用了。但记忆会越积越碎:你这周提了三次同一个项目、五条零散偏好,总得定期把它们整理成一句干净的话、一份稳定的画像。这就是"做梦"——也是这篇标题的来历。河蟹的做梦分两相,区别就在"哪部分让 LLM 碰"。
轻相:机械整理,一行 LLM 都不碰
轻相(reflect.go)只做搬运和标记:近重复的删并、矛盾的标失效、高频的晋升常驻、陈旧的归档。它背后是一台确定性的生命周期状态机(lifecycle.go),阈值都写死、零 LLM:
被取代/失效 → 归档(可恢复,非删)检索条召回 ≥ 3 次 → 晋升常驻又旧又不重要 → 归档常驻偏好长期零召回 → 降级回检索pinned / 硬规则 → 永远不动
关键是:这一相根本没有"改写正文"的能力,它只搬运、只标记,碰不到你记忆的字面内容——所以它不可能幻觉。你被召回多了的事实会自动浮成常驻、长期没人问的会沉下去归档,全程不需要、也用不上一次模型调用。
深相:让 LLM 合成,但锁进笼子
深相(dreaming.go)才请 LLM 出场:把一簇相关、冗余的零碎记忆合成成一条连贯的。这是做梦里真正像做梦的部分,也是唯一允许生成新文字的地方。正因为它会幻觉,我给它上了一圈硬边界:
- 只碰检索层、不碰常驻层
——规则、身份、你 pin 住的、高频召回的(≥ 3 次)、很新的(约 4.5 天内),一律不折叠。还在演化的、最要紧的,做梦时不动。
- 有界
——一轮最多整合 4 簇、一簇最多 8 条进 prompt。不让它一晚上把你整个记忆库重写一遍。
- 合成也不覆盖
——整合出的新条仍走 supersede 留史:旧的标失效、不硬删,新的指回去。做梦改了什么,照样
git diff得出来。 - prompt 钉死不臆造
——整合指令写明:保留全部关键信息、不丢事实、不臆造未提及的内容。
还有回放相,和把零碎捏成一个"你"
深相之外还有两步。一是回放相(engine 级,思路上对标 Claude Dreaming 的"回放历史会话"):低频地把你以前的老对话翻出来,补上当时在线没顺手记下的事实。二是画像蒸馏(profile.go):把你零散提过的偏好、习惯——深夜才冒泡、动不动喊累、张口就是 Go——蒸馏成一句稳定的用户画像置顶常驻,比如"一个常熬到凌晨 5 点的疲惫工程师"。这就是标题说的"整理成画像"。轻相跑得勤、深相和回放跑得稀。
做梦到底帮 Agent 解决了什么
讲了半天机制,说点实在的——一个会做梦的 Agent,和不会做梦的,差在哪:
- 记忆不变成"杂物抽屉"。
用得越久零碎越堆越多,不收拾就全是噪音、召回越来越不准。做梦定期去重、归档、合并,把常驻预算和检索池保持精炼。(OpenAI 自己也用 "junk drawer" 形容没做梦的记忆。)
- 从零碎长出一个"你"。
你今天提一句爱用深色、明天嫌某框架啰嗦——单看都是碎片,做梦把它们蒸馏成一条稳定画像,Agent 下次开口就更像懂你的人,而不是每次从零认识你。
- 不拿过期信息答你。
你换了城市、换了技术栈、戒了某样东西——矛盾的旧事实被标失效,Agent 只认当前有效的那条。
- 跨会话把教训记住。
回放相把老对话翻出来、提炼"这类活我老在哪栽跟头"的模式。Harvey 报告打开 Claude Dreaming 后,反复失败的法律起草任务完成率涨了约 6 倍——Agent 不再每次重复踩同一个坑。
- 补回当时漏记的。
在线聊时关了记忆、用的弱模型没顺手存、或你导入了一批旧会话——这些漏网的事实,回放相事后补回来。
一句话:做梦是 Agent 长期记忆的"维护进程"。没有它,记忆只增不减、矛盾累积、画像涣散,Agent 越用越乱;有了它,记忆越用越精、画像越用越准、还能跨会话学——Agent 才谈得上"越用越懂你"。
说清楚它什么时候跑、要不要你管:默认就帮你开着,低频在后台跑、不频繁打扰你机器。会幻觉的那一相(让 LLM 合成)多一道守卫:得你自己配了模型才启,没配就只跑零幻觉的机械整理,LLM 根本碰不到你的记忆。还有一条专为桌面做的:关了机也不丢——下次开机离上次够久,它会先把欠的那觉补上,再接着低频跑。不想要随时能关;但"让模型改记忆"这一步,我卡在"你得主动配模型"上——默认就是安全的。
你说了算,还有安全
随手管(manage_memory.go):一句"记住我喜欢深色主题""忘掉刚才那条""以后都用中文回我",模型就去增 / 改 / 删 / 置顶;它也会在聊天里主动判断该不该记。但有两条线焊死:凭证绝不入记忆,内容一旦疑似密码 / 密钥直接拒记、让你走加密的连接中心;所有写入都经同一个单写器、同一套去重和留史纪律——AI 主动记的、你手动改的、半夜做梦整理的,谁都绕不过前面那些规矩。
那条"所在地"记忆的一生到这就走完了:它被存进一行带隐藏批注的 markdown,改主意时被标记失效而不是抹掉,被三维打分想起来,半夜被两相做梦整理进画像——而自始至终,你都能 cat 它、git diff 它、一句话改掉它。
我也得说句公道话:标题那句"它们的梦在云端",不全对——Claude Code 的 Auto Dream 整理的也是你本地的文件。所以河蟹真正不一样的,其实是三条叠一起:做梦的逻辑开源、你能读;算力可以全本地跑(接 Ollama,记忆连整理都不必喂给别人);全程纯文本、git 可回滚。单拎一条都不算独一份,叠起来才是。(还有:这篇我没给河蟹报任何跑分——上面 ChatGPT 的 82.8%、Harvey 的 6 倍都是人家公开的;河蟹这套我只摊机制和常量,没做对标评测,就不编实测数字。)
它趁你睡着,把你白天说的零碎,整理成一份更懂你的画像——只是这场"梦"不在云端,就摊在你本机的纸上,一行行都翻得到。
这篇只讲了记忆——它自己学到、自己整理的那半个"第二大脑"。还有另半个:你主动喂给它的资料、文档、源码,也就是知识库。这两半共享同一套本地检索底座,却长成了完全不同的两种"记得"——记忆会做梦,知识库不做梦。那是下一篇的事。
更多推荐


所有评论(0)