🧩 第2章 看门道:理解技能运行的核心逻辑
📄 一句话概括

上下文是一笔预算:窗口有多大、常驻占多少、历史每轮涨多少,都是能算的数。 按需加载是这笔预算的核心算法——清单常驻、正文按需、参考文件用到才读。 再加三个立刻能用的省法:压摘要、换会话、交给脚本。

📝 本章和前面几章的关系

上一篇说「按需加载是四条区别里最要紧的」,这一篇把那句话拆成账本。 这一篇的数都能自己算一遍。算完你对「为什么对话越长越笨」会有具体的感受,不再是个说法。 第 3 章讲分工时会再回来用这里的结论:确定性的活不该占用模型的时间,也不该占用它的台面。

一、对话越长,可用空间越少

上下文窗口是一个固定大小的容器。装进去的东西包括五类,全都是只增不减的。 系统提示、技能清单、你的任务、你们的对话历史、工具返回的结果。 前三样是起手成本,后两样随着轮次往上累。 关键在于:模型不会因为空间不够就变慢,它会悄悄丢东西。 丢的通常是最早的那部分——也就是你最开始交代的要求。 这就是为什么长对话到后面它开始「忘事」,而你明明说过。 按一个常见的用量估:系统提示 800、技能清单 900、任务 120,起手 1820。 之后每轮对话加 420,每三次工具调用再加 620。二十轮下来是一万四千多。 8k 的窗口撑到第十轮就满了,32k 能撑满二十轮还余一半。 所以「换个更大的窗口」确实是解法之一,但它只是把问题往后推,不是消除。

二、按需加载的三级台阶

既然窗口有限,最直接的办法就是别把不用的东西放进去。 技能天然适合这个做法,因为它本来就分三层。 第一级,清单。每个技能的名字和 description 常驻,几十个字。 这一级不能省:不列出来,模型根本不知道有这个技能。 第二级,正文。只有被选中的那个技能的 SKILL.md 正文读进来。 第三级,参考文件。正文里点名的文档、模板、脚本,执行到那一步才读。 三级的分界很清楚:不知道有哪些 → 知道有但不知道怎么干 → 知道怎么干但还缺材料。 这个分层不是设计出来的巧合,是被窗口逼出来的必然。 十个技能全量预载九千多 token,三级加载只要三百常驻加九百临时。差七倍。

三、省法一:把前文压成摘要

历史是涨得最快的那一项。但历史里的绝大部分是过程,不是结论。 「我查了 A 文件、又查了 B 文件、发现 C 不对、改成 D」——四句话,真正要留的只有「结论是 D」。 压缩的规则:留结论、留下一步、留约束条件;删过程、删失败的尝试、删工具原始输出。 十轮原文两百多 token,压成一句三十几 token。省下来的空间能装十轮新的。 但摘要是有损的。压完要问一句:删掉的那些,后面还会不会用到。 会用到,就别压那么狠;不会用到,压到一句也行。

四、省法二:换话题就换会话

这一招一分钱不花,效果往往比前一条更好。 同一个会话里做三件不相干的事,三份历史互相挤占,谁都装不满。 开三个会话,每份只有自己那份历史——这是最省的做法,也是最少人做的。 判断标准很朴素:换了一件事,就换一个会话。 技能的设计也是同一个道理:一个技能只干一件事,被选中时读进来的正文才短。 一个「什么都能干」的技能,正文一定长,一定会挤占上下文。

五、省法三:确定性的活交给脚本

前两条是省,这一条是根本不进去。 五千行日志,塞进上下文是五万多 token,一次就爆。 但你要的其实只是「有多少条 ERROR、最慢的是哪条」——这是十几行脚本的活。 脚本跑完只回一句摘要,二十几个 token。差三个数量级。 这不是「省了 2000 倍」,是两种做法根本不在一个量级:一个搬数据,一个搬结论。 判断标准:这件事有没有唯一正确答案。有,就交给脚本;没有,才交给模型。 数 ERROR 有唯一答案,写复盘没有。前者用脚本,后者用模型。

六、动手 Demo:上下文是一笔预算,花了就没了

这一段不靠比喻,全部算成数:窗口里装了些什么、二十轮之后还剩多少、三种省法各能省多少。 最后一条会真造一份五千行的日志,对比「整份读进去」和「脚本跑完只回摘要」。

# 上下文预算的一行算术
used = 800 + 900 + 120          # 系统提示 + 技能清单 + 任务
for r in range(1, 21):
    used += 420                  # 每轮对话
    if r % 3 == 1:
        used += 620              # 每三次工具调用
left = window - used

实跑输出:

--------------------------------------------------------------------
上下文是一笔预算,花了就没了
--------------------------------------------------------------------


  ① 先看窗口里都装了些什么
  --------------------------------------------------------------------
| 占了什么 | 量级(token) | 什么时候占 |
|---|---|---|
| 系统提示 | 800 | 每次都占 |
| 技能清单(30 个) | 900 | 每次都占 |
| 用户任务 | 120 | 每次都占 |
| 对话历史 | 每轮 +420 | 只增不减 |
| 工具返回 | 每次 +300 到 +800 | 只增不减 |
| 留给回答的空间 | 剩下多少算多少 | 被挤掉就答不完 |

  常驻的三样加起来 1820。剩下的是历史与工具返回在吃。
  所以「对话越长越笨」不是错觉,是历史把回答的空间挤掉了。

  ② 二十轮对话,算一遍还剩多少
  --------------------------------------------------------------------
| 窗口 | 20 轮后已用 | 什么时候撑满 | 20 轮时余量 |
|---:|---:|---:|---:|
| 8k | 14560 | 第 10 轮 | 超 6560 |
| 32k | 14560 | 撑得住 | 17440 |
| 128k | 14560 | 撑得住 | 113440 |

  按这个用量,8k 的窗口撑到第 10 轮就满了,后面每问一句都得丢一点历史。
  32k 能撑满 20 轮还余一半,128k 全程宽裕——但价格跟窗口一起上去。
  ! 这些数是按「每轮 420、每三次工具调用加 620」估的,量级对,绝对值看你的活。

  ③ 技巧一:把前文压成摘要
  --------------------------------------------------------------------
  十轮原文 280 token,压成一句 37 token,省 243。
  压掉的是过程,留下的是结论与下一步。这两样后面还要用。
  ! 摘要不是无损的。压完要问自己一句:删掉的那些,后面会不会用到?

  ④ 技巧二:换话题就换会话
  --------------------------------------------------------------------
  同一个会话里做三件不相干的事,三份历史互相挤。
  开三个会话,每份只有自己那份历史——这是最省钱的一招,一分钱不花。
  ! 技能也是同理:一个技能只干一件事,被选中时读进来的正文才短。

  ⑤ 技巧三:确定性的活交给脚本
  --------------------------------------------------------------------
| 做法 | 处理量 | 进上下文的 token | 结果 |
|---|---:|---:|---|
| 整份读进上下文 | 5000 行 | 55871 | 一次就爆 |
| 脚本跑完只回摘要 | 5000 行 | 26 | 省 2149 倍 |

  同一份日志,整份塞进去 55871 token,脚本跑完只回 26 token。
  这个差不是「快了 2000 倍」,是两种做法根本不在一个量级:
  前者把整份数据搬进上下文,后者只把结论搬进来。
  「数一数有多少条 ERROR」这种事,本来就不该让模型去数。
  ! 这就是第 3 章要讲的分工:确定性的交给脚本,判断性的交给模型。

第一张表把窗口里的六类内容列清楚了,前三样是起手成本,后两样只增不减。 第二段算三档窗口:8k 到第十轮就满,32k 撑满二十轮余一半,128k 全程宽裕。 注意「已用」那一列三档都是 14560——因为用量一样,差别只在窗口。 第三段是摘要:十轮原文 280 token 压成 37,省 243。 第四段没有输出,只有一句判断:换话题就换会话,一分钱不花。 第五段是真造了一份 5000 行日志:整份读进去 55871 token,脚本跑完只回 26。 这两个数不是「快慢」的差别,是「搬数据」和「搬结论」的差别。

30 秒实验

  1. 按你这周的用法估一下:每天几轮对话、每轮多少字、工具返回多长。算出来的数会让你改习惯。
  2. 把你上一次的长对话,用一句话重写成摘要,看丢了什么。丢的都是过程,就说明该压。
  3. 找一件你最近让模型「数一数」的事,改成写脚本。这一条能立刻见效。

常见误区

  1. 以为窗口大就可以随便塞。窗口再大也有上限,而且塞得越满,留给回答的空间越小。
  2. 把整份日志或整张表丢给模型让它自己找。找得到,但代价是把数据全搬进了台面。 先过一遍脚本,只把结论搬进来。
  3. 一个会话干到底。三件不相干的事挤在同一个会话里,三份历史互相挤,最后每一件都装不满。 换事就换会话。
自测三问(点开对答案) 1. 技能的三级加载分别是什么? —— 清单常驻(名字与描述)、正文按需(选中才读)、参考文件用到才读。 2. 为什么说「换个更大的窗口」不是根治? —— 它只是把问题往后推。用量也在涨,塞得越满,回答空间越小,机制没变。 3. 什么活该交给脚本,而不是模型? —— 有唯一正确答案的活。数 ERROR、算合计、校验格式都属于这一类。

下一篇讲技能清单里那一行字:description。它是整份技能里最容易被写坏、又最决定成败的一行。

相关笔记