备选标题(按我觉得的吸引力排序):
- AI机器人怎么做跨会话记忆?我拆完召回那一步才发现摘要根本追不上说话速度
- 别再把聊天历史全塞进上下文了,我给机器人做跨会话记忆时绕的三个弯
- grokbot群聊私聊记忆是怎么共享的?我照着拆了一遍,结论有点反直觉
先说那条把我拽进坑里的提问
前几天在社区刷到一条帖子,一个叫 rizon 的人问 grokbot 的群聊私聊记忆共享机制:群里让 bot 做了件事,转头私聊它,它立刻就知道。他自己也猜了两种可能,一种是私聊时主上下文放私聊历史、群聊内容做成摘要挂着,聊到细节再召回;另一种是把所有群聊私聊按时间串成一条上下文,只是标注来源。
他卡住的点特别真实:摘要速度怎么赶得上说话速度?我在 A 群刚让 bot 做完一件事,立马私聊它就知道了,这个「立即组织的记忆」到底怎么来的。
说真的,这个问题我自己也栽过。去年我给一个自用的 AI 机器人加跨会话记忆,思路跟他第二种猜测一模一样,结果折腾到最后基本推翻重来。
这篇就把我绕的弯原样摆出来。
我一开始就是把历史全塞进去,然后崩了
最直觉的做法,就是每次新会话开始,把这个用户过去所有的对话拼成一大段,丢进上下文。刚开始几天体验好得吓人,机器人什么都记得。
问题是对话一多就顶不住。上下文长度有上限,塞不下就得砍;砍早了它忘事,砍晚了它把注意力浪费在一堆无关闲聊上,回答反而变钝。
更糟的是,每次都带一大坨历史进去,响应变慢、成本也往上飙。有个做长篇小说创作工具的开发者说过一句我特别有共鸣的话——长篇创作有很多结构化状态要维护,全塞进一个连续会话里,交互和上下文管理都不如工作台模式稳定。
机器人记忆是一样的道理,连续上下文不是万能容器。
「实时摘要」这个错觉,是从哪来的
绕不过去,我就想那不做摘要行不行。把历史压成一段摘要挂在上下文里,细节再去捞。
这正是帖子里那位问的:摘要怎么跟得上说话速度?
我拆到这儿才想明白,那个「立即记住」根本不是靠实时生成摘要做到的。你以为机器人在你说完话的瞬间偷偷总结了一版摘要,其实不用。
真正的顺序是这样:
每说一句话,先把这条对话原样存下来,这一步几乎不花时间,就是一次写入。等到下一次需要用的时候,再根据当前问的东西去把相关的几条捞回来。
也就是说,写入是即时的,组织记忆是延迟到「要用时」才发生的。摘要跟不上说话速度是个假问题——因为压根不需要它跟上,需要跟上的只是存这个动作。
这个反转对我影响挺大。我之前一直在优化「怎么更快地总结」,方向从头就错了,该优化的是「怎么更准地捞」。
我现在的做法:一本账本 + 一个语义捞取
拆明白之后,结构其实很清爽,就两层。
第一层是账本。每条对话——谁说的、什么时候说的、在群聊还是私聊、内容是什么——原样落库,一条不改。
这层的作用是「事实底座」,任何时候都能翻回去看到当时到底发生了什么,不做压缩不做加工。我用的是 SQLite,字段就是 who、when、source、content 这几个,简单到不能再简单。
调试的时候直接打开SQLite编辑器看表结构和最近几条记录,哪条没存对一眼就看出来,比在日志里翻方便太多。
第二层是语义召回。光有账本没用,几千上万条你不可能全带进上下文。
所以我把每条对话(或者按段落聚一下)转成向量存进向量库,新会话来了先拿当前问题去做一次相似检索,只捞回最相关的那几条,再拼进上下文。这一步我放在LanceDB知识库里做,语义相近的历史片段能按需捞出来,而不是让机器人硬背整段历史。
对应回帖子里的两种猜测:不是把所有对话串成一条长上下文,也不是靠实时摘要,而是「原样存账本 + 用时按语义召回」。群里刚做完的事私聊立刻知道,是因为那条已经进账本了,私聊时一检索就捞得到,根本不需要等摘要生成。
召回准确率飘忽,这才是真正难受的地方
别以为搭完就万事大吉了,我在召回准确率上栽的跟头比前面所有加起来还多。
最典型的是「捞回来的东西对不上」。用户问「上次那个方案后来怎么样了」,结果检索把三个不同的「方案」都捞回来了,机器人一脸懵。
语义相似不等于说的是同一件事,这个坑很深。我的应对是加过滤条件:先按 source、时间范围、会话对象把候选缩小,再在小范围里做语义排序,纯靠向量相似度硬捞几乎必翻车。
第二个是「切片粒度」。一条一条存,检索太碎,捞回来一堆没头没尾的短句;聚太大,一个片段里混了好几个话题,相关性又被稀释。
这个真没有标准答案,我是按对话轮次粗切,再试出来一个大致合适的长度,说不上最优,够用。
第三个是「捞多少条」。捞少了漏信息,捞多了又把上下文塞满、把噪声也带进去。
我现在的做法是先捞一批候选,再用规则砍到固定条数,宁可少而准。
这些参数怎么调,说实话没有捷径,得拿真实对话一轮轮试。这里插一句成本上的实话,跟前面那位小说工具作者一样,我每次改召回逻辑都得从头跑一遍真实流程验证,Token 是真烧,但也只有用真实工作流测才测得出问题。
把这套搭起来,需要哪些能确认能落地的东西
我按 VicroCode 已经确认的能力对了一遍,这套「账本 + 召回」是能落地的:对话原样存进 SQLite 当账本,语义检索交给 LanceDB,中间那层「决定何时召回、召回后怎么拼上下文、再调模型生成回复」的编排逻辑,就是一个典型的AI智能体开发活儿,用平台的智能体能力加模型中心 API 调已接入的模型串起来即可。存取账本、跑检索、组织上下文这些站内后端逻辑,用 Python 在线运行来写和验证也够用。
有一点我得说清楚边界:向量库我讲的是 LanceDB,别的向量数据库、别的部署方式在不在能力范围内,资料里没提到,属于「待核实」,我不替平台承诺。同样,机器人接到哪个 IM 平台、消息怎么收发,这属于外部对接,超出我这里能确认的范围,也标「待核实」。
跟我之前写的那两篇,到底不一样在哪
可能有老读者会觉得,这跟之前聊的代码仓索引、威胁情报速查不是一回事吗,都是「存起来再检索」。结构上确实沾边,但场景差得挺远,我特意区分一下。
代码仓索引,捞的是相对静态的代码块,目的是让你或机器人快速定位某段实现,内容基本不随对话变。威胁情报速查更像一个「查得准就行」的知识库,一次查询一个结果,前后两次查询之间没什么关联。
跨会话记忆不一样,它的核心是「连续性」和「随时间增长」。账本每天都在变长,今天存的一句话可能三个月后才被捞出来用;而且它强调「这是谁在什么场景下说的」,同样一句话在群聊和私聊里意义可能完全不同。
所以它比前两者多了两个负担:时间维度的过滤,和来源维度的标注。结构像,但难点全在这两处。
最后,给你一个今晚就能动手的小动作
如果你也想给自己的机器人加记忆,别一上来就搭全套。今晚就干一件事:建一张最简单的对话表,字段就 who、when、source、content 四个,把机器人接下来的每一句对话原样写进去,先跑几天。
先把「账本」这层跑稳,你会发现光是能随时翻回去看「它到底存了什么」,就已经帮你把一半的直觉误区照出来了。召回那层,等账本里有了真实数据再上,不迟。
反正我是绕了一大圈才明白,先存好,再谈捞。