好记性不如烂笔头。

这句老话,搁在大模型身上再贴切不过——因为模型压根没有记性。

它的"脑子"在训练完那天就冻住了。之后你聊得再多,它也不会往里面存一个字节;每个请求对它都是初见——你是谁、聊过什么、上次定过什么,不知道,也不记得。

可"它记得我"又是真的:记得你的名字、你的项目、你不吃香菜。

秘密不在它脑子里,在它身外。每次请求发出之前,应用层都在做同一件事:把该带的材料翻出来、拼进去——历史、偏好、相关记录。"睁眼"那一刻,材料已经摆在它面前了。所谓多轮对话,就是这么"装"出来的。

所以这篇要讲的"记忆",没有玄学:模型没有记忆,所有记忆都是外置的。

前两篇,压缩讲装不下时怎么舍,缓存讲同一段话别付两次钱。这篇讲怎么留下来——短期的怎么撑,长期的怎么存,存到哪儿,攒多了又怎么用。

一、短期记忆:这一轮别忘事

先说短期。

它不神秘,就是上下文窗口里的一切:这轮对话、刚跑完的工具、手头的任务。框架自动带着,不用你操心。

两个边界:会话一关,它就没了;装着装着会满——满了怎么办,第二篇整篇都在讲,这里不重复。

补一个和记忆有关的玩法:卸载。

卸到别处

工具调用经常产出巨长的东西:一次日志回显、一次网页抓取,动辄几万字符。

有的系统不压它,而是挪它——把完整结果写进文件,窗口里只留一行"结果在某某文件里"。模型以后真要用细节,再去读回来。

像不像操作系统?内存不够用,把冷数据换出到磁盘。窗口就是内存,文件就是磁盘,那一行指针就是页表。

妙处在于:信息没丢,只是换了个地方待着——窗口保持轻快,细节随时取回。

二、长期记忆:下次还认得你

短期管这一轮,长期管"下次"。

它要跨过会话存下来——你下次再来,它还记得上次的事。这件事听着简单,做起来有三个问题:记什么、放哪儿、怎么找回来。

不是录音机

先说记什么。

最常见的误区,是把记忆当录音机——对话全存,句句不落。那样得到的不是记忆,是流水账:一半是废话,另一半是重复,真到用的时候,捞出来的全是噪音。

记忆的第一原则是选择性。值得记的其实就那几类:

  • 偏好——"不吃香菜""回复喜欢简洁";
  • 事实——"项目用 Go""公司在北京";
  • 约定——"下周一验收""先做登录再做支付"。

共同点:以后还用得上。当时热闹、事后无用的,都不该进记忆。

提炼这步通常交给模型自己做:把一段对话喂进去,让它挑出值得记的条目。所以它挑得准不准,直接决定记忆的质量。宁少一点,别多。

各有各的活法

挑出来的记忆,命运并不一样。

  • "项目用 Go"——稳定,但项目一换就得更新;
  • "昨天部署失败"——三天后基本就没用了;
  • "不吃辣"——长期有效,但也可能只是随口一提,用的时候要谨慎。

事实、经历、偏好。如果全按一套办法管,必然拧巴:要么把该留的清了,要么把该扔的留着占地方、搅浑水。

所以成熟的记忆系统都会给记忆分类。一条记忆被标成什么类型,它的下半辈子就定了:怎么写、怎么改、什么时候扔。

有位工程师的说法更到位:分类的本质,是契约——类型一确定,处理策略就同时约定了。

从碎片到画像

再看存放,有个不太起眼、但很关键的设计:分层。

假设记忆全是碎片:"用过 Python""问过 goroutine""在读 Go 文档"……几百条。

麻烦在哪?下次用户一来,系统得从几百条碎片里现场拼出"这人是谁"——又慢又费钱,还容易拼歪。

更好的做法,是在碎片之上加一层汇总:把几十条碎片凝成一句画像——"Python 后端工程师,关注高并发"。

召回时先看画像,一百来个 token,人物状态立刻清楚;要细节,再顺着往下钻到碎片。

人脑就是分层干的,工程上也给了它一个形象的叫法:在线快写,离线慢想。聊天时只管快速记小本本,整理归纳放后台慢慢做——就像人白天经历事情,晚上睡觉时大脑再做整理。

还有个细节:画像属于推断,不是观测。它是从碎片里总结出来的,可能错。所以系统会把它标成推断、带上证据链——较真的时候,能回到碎片原话对质。

三、外置记忆:到底存哪儿

短期靠窗口,长期……写在哪儿?

这道题的答案,这几年翻了个面。

文件回来了

前几年的默认答案是向量数据库。万物皆可嵌入:把记忆转成向量,找的时候算相似度。

但这两年,最前沿的实践反而退回了最朴素的地方——文件。

Claude Code 的记忆,就是项目目录里一个 markdown 文件,你随手能打开,看它记了你什么;Anthropic 把托管记忆也做成了可导出、可版本化的文件;做记忆系统出名的 Letta,博客标题直接问:"一个文件系统就够了吗?"——他们的测试结果:够,成绩甚至压过专门做记忆的产品。

为什么是文件

朴素为什么赢了花哨?四个原因,从浅到深。

一是量不大。记忆就几十到几百条,向量数据库是为海量语料设计的——上百万条切块,才用得上它那套索引。给几百条记忆配 embedding 管线、调相似度参数,是杀鸡用牛刀。

二是要得准。记忆里全是"差一个字就全错"的东西:版本号、日期、路径。向量检索的本事是"意思相近就算命中"——"Go 1.22"和"Go 1.21"在它眼里几乎一样。可"差不多",在记忆场景里就等于"错"。

三是要能管。记忆是用户的资产:要看得到、改得动、删得掉、审计得了。文件随手打开就能看,git 管着版本;向量库是个黑盒——里面是几百维浮点数,改一条得先找到它在哪,删没删干净你都不知道。

四是最根本的:模型自己会翻。以前的逻辑是"模型不会找,我们替它算好"——embedding 在写入时就算完了,等于把"什么相关"提前猜掉。现在的模型会用工具了:ls、cat、grep,这些是它预训练里最熟的东西。把目录树交给它,它自己会翻——什么相关,用的那一刻再判断,比提前猜准。

有工程师一句话点破:文件系统和 bash,大概是模型预训练里关于"计算"最大的知识来源之一——对它来说,这就是母语。

原文与目录

顺着这层思路,还能得出一个更底层的定位:文件是原文,向量库只是目录。

想想书架怎么整理:书按房间摆好,再单独抄一张索引卡方便找。卡片丢了、乱了,照着书架重抄一份就行;书架要是没了,卡片什么都不是。

向量库对记忆,就是这张卡片。

想清楚这层关系,"文件还是向量库"就不再是信仰之争:目录随时可以重做——今天用 grep,明天建向量索引,后天换更好的检索方式;原文一直在,换什么都不心疼。

反过来,如果记忆只活在向量库里,它就碎了、卷了、打不开了——改不动,也删不干净。

四、知识库:存多了怎么用起来

记忆是"关于你"的:你的偏好、你的项目、你们的约定。它少而精。

但还有一种是"关于事"的:公司的规章、产品的文档、项目的资料。它多而杂——这类东西,叫知识库。

笔记本与图书馆

记忆像笔记本:就几页,随手翻,写错了划掉重写。

知识库像图书馆:书架上成千上万册,你不能每本都背下来,只能需要的时候去检索。

两者的要求正好相反:记忆要准——错一条,后面全歪;知识库要全——少一本问题不大,能找到就行。

把它们混在一起管,是常见的翻车:个人数据污染公共知识,每轮都拖着无关上下文,token 花得肉疼。

开卷考试

知识库怎么用起来?主流答案是 RAG(检索增强生成)。

一句话说清它的本质:开卷考试。答题之前,先把相关的几页翻出来摆在桌上,然后照着答题——而不是把整座图书馆背进脑子。

(把知识背进脑子,那是微调干的事——成本高、更新难,另一个话题了。)

所以知识库的功夫,不在"存了多少",在"要用的那几页,翻不翻得到"。

五、绕不开的几件事

最后,几件怎么都绕不开的事。

遗忘是功能

记忆系统最容易犯的错,是只进不出。

陈旧的事件该过期就过期;前后矛盾的要做裁决——用户"搬到上海了","住在北京"这条就得下架。别舍不得:只增不删的系统,错误会越积越多,最后把整个记忆污染掉。

能删、会删、按时删——这和第二篇聊的是一回事:遗忘,不是记忆的对立面,而是记忆的一部分。

记错的代价

还有一条分寸:记错,比不记更糟。

记忆会被注入到之后的每一轮对话里。一条记错的偏好、一个过期的约定,污染的不是一次回答,是后面每一次。

所以高质量的用法是宁缺毋滥:不确定的标上"可能",推断来的带回证据、随时可撤。

隐私

最后是隐私。

记忆存住的往往是私人的东西——喜好、习惯、日程。放哪儿、谁能看、用户能不能一键删干净——这些问题不会自己消失。

文件方案的好处在这里也顺手续上了:人能打开文件,就能审查、就能删除——看得见的记忆,才好管理。

模型还是那个没记性的模型。

每个请求,它都崭新、空白、不认识你。但短期的窗口、长期的文件、规模大了配的检索——一支支"烂笔头"插好之后,它看起来记性好得很。

它"记得"你,是因为每次睁眼之前,我们已经把材料摆在了它面前。

好记性不如烂笔头——对人是这样,对模型,更是这样。