跳到主要内容

它记得住什么、记不住什么 — 四种「记忆」是四件不同的事

这一章讲三件事: 「记忆」这个词在这本书里指的四件事各是什么; 为什么第一种查不出出处;以及天天在用的那一种到底要花多少钱。

它在全书链条里的位置: 第 02 章说过「模型什么都不记得」, 第 03 章说过「记事本只增不减」。这一章把这两句话合起来算一次总账, 顺便解释第 01 章第 1 节那个「张口就编」的现象到底是哪一层出的问题。

1. 「记忆」在这本书里是四件不同的事

这一节先立一张表,免得你把四件事混成一件。

书用了一整节来数「记忆」有几种形成方式,一口气数出四种1它们的差别不在程度,而在东西存在哪儿:

第几种东西存在哪改一次要多久查得出出处吗
① 训练时压进去的模型内部那一大堆数里重训一遍,以月计查不出
② 这一轮重发给它的你发过去的那段文字里下一次调用就变查得出(你自己写的)
③ 焊进去的同样在那堆数里,但只动一小部分重训一小段,以天计查不出
④ 外挂一个库你自己的数据库里随时改查得出,而且能显示给用户看

这张表是本章的地图。 下面五节分别走一遍,最后两节讲书里没讲的那一半。

注意第 2 列:只有第②④两种在模型外面。 这一条决定了后面所有的取舍—— 凡是要「说出这句话是从哪来的」的场合,只有第②④两种能办到。

2. 第一种:压进一大堆数里,查不出出处

这一节回答第 01 章第 1 节那个悬案:它为什么敢编一个花价。

书对这一种的描述,里面有一个词得先讲清:权重—— 模型内部那一大堆可以调的数,一个数管一点点「什么跟什么有多大关系」

有了这个词,原话就好读了:模型在大量包含世界知识的数据上做训练, 通过调整神经元的权重来学习理解和生成人类语言, 这可以被视为其「记忆」的形成过程2。 (这里的「神经元」不是脑细胞,是模型内部一个个做加权求和的小零件。)

换成大白话:训练就是把那一大堆数一点点挪到位,挪完就固定了。 这一步的正式名字叫预训练——书里和外面的文档都这么写, 「预」是相对后面那种针对具体任务的小幅调整(本章第 6 节那一种)说的。

书在另一处把这件事说得更透:训练时获得的这些知识, 都属于大模型这个 Agent 的大脑的记忆的一部分3。 换句话说——在作者的框架里,「模型知道的东西」和「Agent 的记忆」是同一件事。

现在把第 01 章那个现象接上来。

第 01 章第 1 节里,作者跟一个聊天机器人聊《浮生六记》,对方讲得头头是道、 而作者自己在旁边注明它被带歪了。为什么它不说「我不确定」?

因为这一种记忆的存法本身就不保留出处: 一句话是从哪本书学来的、被多少条相互矛盾的资料同时影响过, 在那堆数里已经彻底混在一起了。 它没有一个「出处」字段可查—— 它连「这一条我记得不牢」都判断不出来。

所以它敢编一个花价,不是因为它想骗你,是因为它区分不了「我记得」和「我在编」。 第 01 章那趟走查为什么非要挂一个搜索工具?答案就在这一节。

3. 第二种:这一轮你重发给它的那一段

这一节讲全书唯一一种你天天在用的记忆。

书对这一种的说法是上下文互动:模型执行任务时,会把长期记忆和 你提供的上下文(也就是那段交代)结合起来用;并且理想情况下, 如果上下文里的信息和它记住的知识冲突,模型应优先考虑上下文4

「应优先」这三个字要划重点:这是个期待,不是保证。 书自己也承认这一点, 说要靠一些额外的手段,才能让它更听话、更经得住折腾。

这一种就是第 02 章第 3 节那个消息数组,和第 03 章第 5 节那个记事本。 把它们并排放,你会发现是同一件事的两副面孔:

第 02 章那套第 03 章那套
长什么样一排消息,每条带角色一段纯文字,接在模板后面
谁往里加你的代码,每轮加一条执行器,每轮加三行
一轮结束后整个重发整个重发

结论:两套写法不同,机制完全一样——重发。 下一节把这笔账算清楚。

4. 主走查:四条消息,逐条问「这一句是从哪来的」

这一节是本章的主走查。用的是第 02 章那次调用——书里唯一一次给全了用量数字的调用。

输入: 四条消息(和第 02 章同一份),模型面前摆着的全部东西就是这四条。 已知的账单:输入 89、输出 254、合计 3435

第 1 步 · 逐条认领。 四条消息各自属于哪一种记忆:

[0] system "您是一个帮助用户了解鲜花信息的智能助手,并能够输出JSON格式的内容。"
└─ 第②种。你写的。每轮都要重发。

[1] user "生日送什么花最好?"
└─ 第②种。用户上一轮说的。每轮都要重发。

[2] assistant "玫瑰花是生日礼物的热门选择。"
└─ 第②种,而且是你自己编进去的 —— 这一轮之前它从没说过这句话。

[3] user "送货需要多长时间?"
└─ 第②种。用户这一轮说的。

── 那么第①种在哪? ──
它不在这四行里。「玫瑰是常见的生日花」「送货时间受节日影响」这类常识,
全部来自模型内部那堆数 —— 你在这个数组里一个字都看不到它。

图说:你能读到的全是第②种,而回答里真正的内容主要来自看不见的第①种。
**这就是「查不出出处」在一次真实调用里的样子。**

第 2 步 · 算这一轮的账。 那四条消息一共 89 个 token, 模型写了 254 个 token 的回答5这一轮的记忆成本就是那 89。

第 3 步 · 算下一轮要重发多少。 假设用户接着问第三个问题。 按第 02 章第 3 节那条规矩,你要发过去的是:

原来的四条(89)
+ 上一轮它写的那段回答(254) ← 变成第 [4] 条 assistant
+ 用户的新问题(设为 20) ← 这个数是我们假设的,不是书里的
─────────────────────────────
下一轮的输入 ≈ 363 个 token

给这个数配参照:上一轮输入是 89,这一轮变成 363,涨了三倍多。 而涨的那一大截几乎全是它自己上一轮说的话。

第 4 步 · 看趋势。 再往下问第四个问题,输入还要加上这一轮的输出。 每一轮的输入 = 上一轮的输入 + 上一轮的输出 + 新问题。 这个式子只加不减——这就是第 02 章那句「对话越长越贵越慢」的算式形式。

5. 另起一处:记事本里那一大段

这一节走第二处,因为那一圈里的重发比对话更凶。

回看第 05 章那趟鲜花定价。第 2 轮时,记事本里塞进去的是什么? 是第 1 轮那三行,加上搜索工具返回的十条新闻摘要—— 书把那十条原样印了出来,是密密麻麻的一大段6

请把这一段和上一节那 89 个 token 比一比。 那十条摘要里光是中文正文就有六七百字,折成 token 至少是那四条消息的好几倍。 而它们每一轮都要跟着重发一遍

这就是「工具产出的东西比对话贵得多」的原因,而书里一个字都没提。 第 09 章那一整章的起因,就是这件事:作者自己在原书第 7 章开头承认, 为了让程序既盯着目标又记得住之前的步骤,人们不得不把提示词越写越大, 结果模型「往往不堪重负」7

6. 第三种:微调,把知识焊进去

这一节讲一种这本书提了、但一次都没用过的做法。

这种做法叫微调——拿一组你自己的例子再训练一小段, 把这些例子的规律固定进模型内部那堆数里

书对它的描述很短:模型可以在更具体的数据上进一步调整, 以适应特定行为或提高特定任务的表现;举的例子是拿某类问题的数据集调一遍, 模型答这类问题就更熟练8

它和第一种的差别只有一个:动的范围小、花的时间短。 东西存在哪、查不查得出出处,两者完全一样——都在那堆数里,都查不出。

这本书没有任何一处用到它。 七个实战案例、七个现成的框架与开源项目,一个微调都没有。 第 10 章第 2 节会解释为什么:书自己把它排在了「难且贵」那一端。

7. 第四种:外挂一个库

这一节讲书里最看重、也留给后面整整两章的那一种。

书的说法是:模型可以和外部记忆系统整合,通过提供长期记忆来增强表现, 使它能够记住和回忆过去的互动、理解用户的个性并提供更个性化的互动9

书还提了这套东西涉及的三块:动态理解用户个性、用一种双塔结构做记忆检索、 以及受艾宾浩斯遗忘曲线理论启发的记忆更新机制9这三块书里都没有展开,只列了名字。

但书把它和一件事挂上了钩,而且给了一个很好的比喻: 原书第 8 章讲的那套检索做法也可以视为和外部知识系统整合的过程, 这相当于给大模型提供了一个「外挂第二大脑」10

为什么这一种是四种里唯一「查得出出处」的? 因为东西存在你自己的库里。 你从库里取了哪一段贴进去,你自己一清二楚——所以你可以把那一段原文显示给用户看。 第 10 章第 2 节会把这条列成检索这条路的三大好处之一。

书里那个框架的记忆模块,给的例子也很朴素:记忆可以是短期的 (比如最近 5 次工具使用过程的列表),也可以是长期的(过去与当前情况最相似的那些)11注意「最近 5 次」这个说法——它已经是一种压缩策略了,只是书没有点破。

8. 书里没讲的那一半:只增不减怎么办

这一节把书的缺口摆出来,它是第 09 章那些麻烦的直接来源。

第 4、5 两节算出来的那个式子——每一轮的输入 = 上一轮的输入 + 上一轮的输出 + 新东西—— 只加不减。 而第 02 章说过,模型一次能读进的长度是有上限的。

两件事撞在一起,必然出事。书里对此的处理是:

书在哪里碰到了这个问题书是怎么处理的
原书第 3 章:那个记事本一轮比一轮长没提
原书第 4 章:托管接口自己会压一句「会用相关的手段压一压」带过,并承认你控制不了成本
原书第 7 章:提示词越写越大、模型不堪重负承认了,并把它作为换一种做法的理由
原书第 9 章:任务表越滚越长没提

三处碰到、一处承认、零处给解法。 这是这本书在记忆这一块最大的空白。

书唯一给过的一条线索,是第 7 节那个「最近 5 次」。 但它是一个例子,不是一个方案——只带最近几次,意味着更早的东西直接丢掉, 而「哪些该丢、哪些该留」这件事书里没有任何讨论。

9. 今天这一层长成了什么样

这一节补上今天的做法。两条,正好对应上一节那个空白的两半。

第一半:长了怎么办。 今天有一种做法是把「模型面前那一段」和「一个外部库」 明确分成两层,并且让模型自己在两层之间搬东西:

补充(不在书里,依据我们的前沿框架书架): 一种做法是把常驻在模型面前的那一段当「内存」、把数据库当「硬盘」, 并且给模型两件工具,让它自己往硬盘里写、自己搜回来。 依据: shelf=ai-frontier-reference/letta#01-memory-tiers.md @6d8cb7fd48938b629aad5770faa051a8d42e1e9f 事实=该框架把记忆分成三层:常驻在模型面前且可被它自己改写的一块、 存在数据库里的全部历史消息、以及一个按意思检索的长期知识库; 模型用 archival_memory_insert 主动写入一条条能独立读懂的事实, 用 archival_memory_search 按「意思有多接近」把它们取回来。12

第二半:什么该留、什么该丢。 另一种做法是不存原始对话,只存从对话里抽出来的事实:

补充(不在书里,依据我们的前沿框架书架): 写入端只做一件事:把对话提炼成一句句能独立读懂的事实,去重之后存库。 依据: shelf=ai-frontier-reference/mem0#01-add-pipeline.md @001c235229be8795e3834520467bd0d661ed8f34 事实=一次写入是一条直线流程——先用一次模型调用抽出事实, 再按文本内容比对去重(和已有的撞了就丢、和这一组里已见的撞了也丢), 然后一次性建好可搜的目录、一次性入库; 判断「要不要改旧记忆」这件难事被从写入端整个拿掉了,留给取回那一端的排序去自然处理。13

这两条合起来,正好回答了书里没答的那个问题:

  1. 模型面前那一段要有上限,超了就得往外搬;
  2. 搬出去的东西不是原文,是提炼出来的一条条事实,这样才压得动;
  3. 要用的时候按意思搜回来,而不是把全部历史重发一遍。

注意第 3 条:它就是第 7 节那个「外挂第二大脑」,只是对象从「资料」换成了「对话历史」。 第 10 章讲的检索做法,和这里说的是同一套机制。

10. 可带走的

  1. 「记忆」在这本书里是四件不同的事,差别不在程度,在东西存在哪儿;
  2. 只有第②④两种在模型外面——所以只有它们能「说出这句话是从哪来的」;
  3. 第①种(训练时压进去的)不保留出处,它连「这一条我记不牢」都判断不出来——这就是它敢编的原因;
  4. 第②种就是你每轮重发的那段文字,书里那个消息数组和那个记事本是它的两副面孔;
  5. 每一轮的输入 = 上一轮的输入 + 上一轮的输出 + 新东西,只加不减; 书里那次调用从 89 涨到约 363,一轮涨三倍多;
  6. 工具产出比对话贵得多: 那十条新闻摘要每轮都要跟着重发一遍;
  7. **第③种(微调)和第①种存在同一个地方,**只是动的范围小;这本书一次都没用过它;
  8. 第④种(外挂一个库)是唯一能把出处显示给用户看的——第 10 章整章讲它;
  9. 「只增不减怎么办」这个问题,书碰到三次、承认一次、零次给解法;
  10. 今天的两条做法是:给模型面前那一段设上限并让它自己往外搬;搬出去的存提炼出来的一条条事实而不是原文,用的时候按意思搜回来。

11. 原文地图

主题原书章原文位置
四种记忆的总纲2.3 Agent的各种记忆机制text/19-ch02-03-2-3-agent.txt:5(搜「大模型形成记忆的机制可以总结为以下几种」)
第一种:训练时压进去2.3 Agent的各种记忆机制text/19-ch02-03-2-3-agent.txt:9(搜「通过预训练形成记忆」) · text/19-ch02-03-2-3-agent.txt:11(搜「调整神经元的权重」)
训练得到的知识就是它的记忆1.3 Agent的大脑:大模型的通用推理能力text/10-ch01-03-1-3-agent.txt:143(搜「这些预训练时获得的知识」)
第二种:上下文互动、优先考虑上下文2.3 Agent的各种记忆机制text/19-ch02-03-2-3-agent.txt:15(搜「上下文互动」) · text/19-ch02-03-2-3-agent.txt:17(搜「优先考虑上下文」)
短期记忆与长期记忆的分法2.1 Agent的四大要素text/17-ch02-01-2-1-agent.txt:17(搜「短期记忆与上下文学习有关」)
主走查:四条消息与用量3.1 何谓OpenAI APItext/25-ch03-01-3-1-openai-api.txt:148(搜「您是一个帮助用户了解鲜花信息的智能助手」) · text/25-ch03-01-3-1-openai-api.txt:222(搜「prompt_tokens=89」) · text/25-ch03-01-3-1-openai-api.txt:221(搜「completion_tokens=254」)
另起一处:记事本里那十条摘要6.5 深挖AgentExecutor的运行机制text/46-ch06-05-6-5-agentexecutor.txt:189(搜「今年基本上进货价都在25~30元」)
提示词越写越大、模型不堪重负7.1 Plan-and-Solve策略的提出text/49-ch07-01-7-1-plan-and-solve.txt:62(搜「增加提示词的规模」)
第三种:微调2.3 Agent的各种记忆机制text/19-ch02-03-2-3-agent.txt:21(搜「针对特定任务的微调进行增强」)
第四种:外部记忆系统、外挂第二大脑2.3 Agent的各种记忆机制text/19-ch02-03-2-3-agent.txt:25(搜「艾宾浩斯遗忘曲线」) · text/19-ch02-03-2-3-agent.txt:27(搜「外挂第二」)
最近 5 次工具使用的列表3.2 何谓LangChaintext/26-ch03-02-3-2-langchain.txt:171(搜「最近5次工具使用过程的列表」)
托管接口会自己压、但你控制不了成本4.3 Assistants API的简单示例text/32-ch04-03-4-3-assistants-api.txt:225(搜「无法有效控制运行助手的成本」)

Footnotes

  1. 出处:「2.3 Agent的各种记忆机制」第 5 段(text/19-ch02-03-2-3-agent.txt:5,搜「大模型形成记忆的机制可以总结为以下几种」)。「东西存在哪」这个切法是我们加的,书里只是把四种依次列出来,没有做过对比。

  2. 出处:「2.3 Agent的各种记忆机制」第 11 段(text/19-ch02-03-2-3-agent.txt:11,搜「调整神经元的权重」)。原文还提到具体的做法是深度学习神经网络加梯度下降,但这本书没有展开讲这两样是什么——想懂那一层要另外找书。

  3. 出处:「1.3 Agent的大脑:大模型的通用推理能力」第 143 段(text/10-ch01-03-1-3-agent.txt:143,搜「这些预训练时获得的知识」)。这句话把「模型知道的」和「Agent 的记忆」划了等号,是理解这本书用词习惯的关键一句。

  4. 出处:「2.3 Agent的各种记忆机制」第 17 段(text/19-ch02-03-2-3-agent.txt:17,搜「优先考虑上下文」)。原文用的是「理想情况下……应优先考虑上下文」这样的措辞,并提到可以用一种叫「知识意识型微调」的方法来增强这方面的可控性。

  5. 出处:「3.1 何谓OpenAI API」第 222 段(text/25-ch03-01-3-1-openai-api.txt:222,搜「prompt_tokens=89」)与第 221 段(text/25-ch03-01-3-1-openai-api.txt:221,搜「completion_tokens=254」)。第 3 步里那个「新问题设为 20」是我们假设的数,不是书里的;89 + 254 + 20 ≈ 363 这个算式也是我们算的。 2

  6. 出处:「6.5 深挖AgentExecutor的运行机制」第 189 段(text/46-ch06-05-6-5-agentexecutor.txt:189,搜「今年基本上进货价都在25~30元」)。「六七百字」是我们数的,书里没有给这一段的长度或用量。

  7. 出处:「7.1 Plan-and-Solve策略的提出」第 62 段(text/49-ch07-01-7-1-plan-and-solve.txt:62,搜「增加提示词的规模」)。原文的完整说法是:为了让程序专注最终目标的同时也记住之前的步骤,提示词里要纳入越来越多的历史信息;加上为了可靠性又塞进更多用法说明,结果模型「往往不堪重负,在几个轮次之后会出现各种各样的问题」

  8. 出处:「2.3 Agent的各种记忆机制」第 21 段(text/19-ch02-03-2-3-agent.txt:21,搜「针对特定任务的微调进行增强」)。原文举的例子是拿某类可满足性问题的数据集调一遍,模型回答这类问题会更熟练。

  9. 出处:「2.3 Agent的各种记忆机制」第 25 段(text/19-ch02-03-2-3-agent.txt:25,搜「艾宾浩斯遗忘曲线」)。那三块(动态个性理解、双塔检索、受遗忘曲线启发的更新机制)书里只列了名字,一个都没展开。 2

  10. 出处:「2.3 Agent的各种记忆机制」第 27 段(text/19-ch02-03-2-3-agent.txt:27,搜「外挂第二」)。这句话被排版拆成了三行,完整读法是「这相当于给大模型提供了一个『外挂第二大脑』」。

  11. 出处:「3.2 何谓LangChain」第 171 段(text/26-ch03-02-3-2-langchain.txt:171,搜「最近5次工具使用过程的列表」)。原文把互动对象分成两类:和人或其他程序的互动、和工具的互动;这个「5」是书里给的唯一一个和记忆长度有关的具体数字。

  12. 补充(不在书里,依据我们的前沿框架书架):把模型面前那一段当内存、把库当硬盘,并让模型自己搬。依据: shelf=ai-frontier-reference/letta#01-memory-tiers.md @6d8cb7fd48938b629aad5770faa051a8d42e1e9f 事实=该框架的记忆分三层——常驻在模型面前且可被它自己改写的一块、数据库里的全部历史消息、一个按意思检索的长期知识库;模型通过两个工具主动写入一条条能独立读懂的事实、并按「意思有多接近」加上标签把它们搜回来,系统还会把该库里所有可用标签列进它每次看到的那段交代里。

  13. 补充(不在书里,依据我们的前沿框架书架):写入端只抽事实、去重、落库。依据: shelf=ai-frontier-reference/mem0#01-add-pipeline.md @001c235229be8795e3834520467bd0d661ed8f34 事实=一次写入是一条直线流程:先捞出已有的相关记忆当参照、用一次模型调用把对话提炼成一句句能独立读懂的事实、按文本内容比对做两道去重(和已有的撞了丢、和这一组里已见的撞了也丢)、最后一次性建好可搜的目录并入库;「判断要不要改旧记忆」被从写入端整个拿掉,交给取回那一端的排序处理。