🐎 第4章 分而治之:子智能体与任务委派的艺术
📄 一句话概括

窗口装不下长任务,不是因为「记性差」,是因为任务要求同时看三十份,而窗口只装得下十七份。 更贵的是:每一轮都要把窗口里的全部内容重发一遍,所以读 n 个文件的成本是 n 的平方。

📝 本章和前面几章的关系

上一章讲技能,管的是「用到才读的知识」。这一章讲子智能体,管的是「在别处读完再回来」。 先要把「为什么非得到别处去」讲清楚,这一节算的就是这笔账。

一、先看一个真实的形状

任务:审三十个源文件,每个文件读进来约四百 token,最后汇总全部问题。 主窗口八千 token,其中系统提示和工具定义占一千二,留给内容的六千八。 六千八除以四百,正好十七个。也就是说,读到第十七个的时候窗口满了。

从第十八个开始,每读一个就挤掉最早的一个。三十个读完,窗口里还是十七个,前十三个已经出去了。 而任务要的是「汇总全部」。要汇总就得回去重读,重读又把后面挤掉。

二、这不是记性差,是装不下

很多人把这个现象理解成「模型忘性大」。不准确——它没有忘,是那些内容根本不在这一轮的输入里。 模型每次被调用都是一次独立计算,窗口里有什么它就看见什么,窗口里没有的它不知道存在。 所以「塞满就忘」的准确说法是「塞满就挤」:挤出去的内容不会留在任何地方,它只是不再被送进来了。

这个区别很要紧。如果理解成「记性差」,解法会是「让它多记一点」(提示它、强调它); 正确理解成「装不下」,解法才是「换个地方装」。 子智能体就是那个「换个地方」——这是本章所有内容的方向。

三、第二个问题:成本是平方的

每一轮都要把窗口里的全部内容重发一遍。读到第 i 个时,前面 i 个文件已经付过 i 次钱了。 演示里算了这个累计:第五个一万二、第十个三万四、第十七个八万一、第三十个十八万五。 三十个文件、每个四百 token,内容本身只有一万二;累计花了十八万五,多出来的十五倍全是重发。

这就是平方增长的实际形状。它不是说「有点浪费」,是「读得越多,单份越贵」。 而且这个账还没算重读。真要「读完了汇总」,前十七个至少再读一遍,累计还要再翻一倍。

四、窗口开大一点能救吗

从八千开到二十万,三十个文件当然装得下。但这条路走不远,两个原因。 第一个原因:装得下三十个,装不下三百个。而真实仓库的文件数恰恰是往几百走的。 第二个原因更实在:窗口里的每一份内容,每一轮都要重付一次钱。 窗口开大只是把「撞墙的位置」往后推,平方那条曲线一点没变。

还有一层隐性的:窗口里无关内容越多,真正相关的那句越容易被淹。 这不是玄学,是注意力机制要在所有内容之间分配权重。 所以窗口变大只是延后了问题,没有改变问题的性质。

五、三种「换个地方」的办法

第一种是写进文件(第 2 章的记忆层):把该记的搬出去,用的时候读回来。它解决「跨会话要记住」。 第二种是做成技能(第 3 章):把大块知识放到用到才读。它解决「知识太大不必每轮都在」。 第三种是派子智能体:把一段噪声很大的活整个搬到另一个窗口去做,只把结论带回来。 它解决的是「过程本身很脏」。

三者的分界线很清楚:跨会话记的用文件,知识按需的用技能,过程太脏的用子智能体。 这一章只讲第三种。前两种的前提都是「读进来之后主窗口还能用」; 第三种针对的是「读进来的过程本身就把主窗口占了」。

六、动手 Demo:三十个文件读进主窗口,第几个开始丢东西

模拟一个「审三十个文件、最后汇总」的任务:每个文件约四百 token,主窗口八千, 系统提示和工具定义占一千二。 先看窗口怎么涨、什么时候开始挤,再算累计成本——每一轮都要重发窗口里的全部内容。

win, used = [], SYS_TOK          # 窗口里现有内容、已占 token
for i in range(1, NFILE + 1):
    win.append((i, FILE_TOK))
    used += FILE_TOK
    while used > WIN and len(win) > 1:   # 满了就挤最早的
        _old, t = win.pop(0)
        used -= t

# 成本:每一轮都要重发窗口里的全部内容
cost = min(WIN, SYS_TOK + i * FILE_TOK)

实跑输出:

--------------------------------------------------------------------
三十个文件读进主窗口,第几个开始丢东西
--------------------------------------------------------------------

  任务:审三十个源文件,每个约 400 token,最后汇总全部问题。
  主窗口 8000 token,其中系统提示和工具定义占 1200,留给内容的是 6800。

  ① 窗口怎么涨、什么时候满
  --------------------------------------------------------------------
| 读到 | 窗口里剩几个 | 窗口 token | 状态 |
|---|---:|---:|---|
| 第 5 个 | 5 | 3200 | 没丢 |
| 第 10 个 | 10 | 5200 | 没丢 |
| 第 17 个 | 17 | 8000 | 没丢 |
| 第 25 个 | 17 | 8000 | 丢了 8 个 |
| 第 30 个 | 17 | 8000 | 丢了 13 个 |

  第 17 个之后窗口就满了,每多读一个就挤掉最早的一个。
  三十个读完,窗口里只剩 17 个,前 13 个全被挤出去。

  ② 挤掉的是「结论」还是「原文」
  --------------------------------------------------------------------
  挤掉的是原文。
  但结论也没留下——因为汇总要等三十个都读完才做,而那时候前十几个文件早就不在窗口里了。
  要汇总就得回去重读。重读又把后面挤掉。
  这就是「塞满就忘」的真实形状:不是记性差,是任务要求同时看三十份,而窗口只装得下十七份。

  ③ 越读越贵:成本是平方的
  --------------------------------------------------------------------
| 读到 | 本轮要重发多少 | 累计 token |
|---|---:|---:|
| 第 5 个 | 3200 | 12000 |
| 第 10 个 | 5200 | 34000 |
| 第 17 个 | 8000 | 81600 |
| 第 30 个 | 8000 | 185600 |

  每一轮都要把窗口里的全部内容重发一遍——模型无状态,不重发它看不见。
  所以读到第 i 个时,前面那 i 个文件已经付过 i 次钱了。
  三十个文件一轮读完,累计 185600 token。按每千 token 一分钱算,这一个任务光读文件就 1.86 元。
  ! 而且这个账还没算重读。真要「读完了汇总」,前十七个至少再读一遍,累计会再翻一倍。
  平方增长不是理论问题,它是这个任务的默认成本。

①窗口涨到八千就停住,之后每读一个挤掉最早的一个。 三十个读完,窗口里只剩十七个,前十三个全被挤出去。 这个「十七」不是巧合:八千减一千二的系统提示,除以四百,正好十七。 窗口容量和单份大小一除,就是能同时看几份。 ②挤掉的是原文,但结论也没留下——因为汇总要等三十个都读完才做。 而那时候前十几个文件已经不在窗口里了。 要汇总就得回去重读,重读又把后面挤掉。 这就是「塞满就忘」的真实形状:不是记性差,是任务要求同时看三十份而窗口只装得下十七份。 ③成本那一段是这一节的重点:第五个一万二、第十个三万四、第十七個八万一、第三十个十八万五。 内容本身只有一万二,累计花了十八万五,多出来的十五倍全是重发。 每一轮都要把窗口里的全部内容重发一遍——模型无状态,不重发它看不见。 所以「读 n 份材料」的成本是 n 的平方,不是 n。这个结论在任何窗口大小下都成立。 最后一句要记住:平方增长不是理论问题,它是这类任务的默认成本。 而且这个账还没算重读——真要做到「读完了汇总」,前十七个再读一遍,累计还要翻一倍。

30 秒实验

  1. 把窗口从八千改成两万,重跑第 ① 步。第几个开始挤?累计成本变成多少?平方那条曲线有变化吗?
  2. 把单份文件从四百改成八百,重跑第 ① 步。窗口能同时看几份?这说明「能看几份」由什么决定?
  3. 把任务改成「每读一个就写一条结论到文件」,重跑一遍。这样前十几个还会丢吗?代价是什么?

常见误区

  1. 把「塞满就忘」理解成模型记性差。它没有忘,那些内容只是不再被送进来了。 理解成记性差,解法就会变成「反复强调」,而不是「换个地方装」。
  2. 靠把窗口开大来解决问题。窗口再大也有上限,而且每轮都要为窗口里的全部内容付费,平方曲线没有变。
  3. 以为读三十个文件的成本是三十乘四百。实际是平方:每一轮都要重发已读的全部内容。
  4. 在窗口里堆过程细节(命令输出、代码片段),指望「反正它看得见」。 看得见的东西每一轮都要重付一次。
  5. 把「写到文件里」和「派出去做」当成一回事。前者解决跨会话记住,后者解决过程太脏。
自测三问(点开对答案) 1. 为什么说「塞满就忘」的准确说法是「塞满就挤」? —— 因为挤出去的内容不是被遗忘了,是根本不再被送进这一轮的输入。模型看不见它,也就不知道它存在。 2. 读 n 个文件的成本为什么是平方的? —— 因为每一轮都要把窗口里的全部内容重发一遍。 读到第 i 个时,前面 i 个文件已经付过 i 次钱,累计就是 1 加到 n。 3. 把窗口开大能解决问题吗? —— 只能延后。装得下三十个装不下三百个,而且窗口里的每份内容每轮都要重付,平方那条曲线没有变。

知道了「装不下」和「越读越贵」,下一节看子智能体到底改变了什么。

相关笔记