跳到主要内容
我把 context 当仓库用了,直到 agent 捡回三小时前否掉的猜想

我把 context 当仓库用了,直到 agent 捡回三小时前否掉的猜想

林默
林默

· 阅读约 5 分钟

前阵子查一个配置漂移,让 agent 在 preprod 上跑调查。每跑一轮,我就把整段 transcript 原样塞回上下文,心里想的是“留着有用”——万一后面要引用呢。跑到第五轮,它忽然把三小时前已经排除掉的一个猜想又捡了起来,说得还很笃定,像刚发现新大陆。

我先愣了一下,然后骂的是自己。不是它变笨了。是我把它泡在了一池子旧信息里。旧 transcript 里那些“查了、排除了”的痕迹,在它眼里跟“正在发生的事”一个权重。

先停一下,问个问题:为什么喂给它的信息越多,它反而越容易出错?

最外层答案是“窗口装满了”。对,但没用。装满了然后呢?它不会像硬盘满了那样提示你清理,只会开始稀释注意力——每生成下一个 token,它都得在一片越来越大的相关性噪音里找路。这么说吧,它不是“忘了”,是“新的盖住了旧的,旧的又反过来拖住新的”。听上去像一回事,机制上是两回事:前者是故障,后者是我给它选的结构。

我一开始也以为这是个“该把什么放进去”的问题。后来才发现方向反了。context window 从来就不该被当成长期存储用。它更像工作集,像 RAM。真正的持久记忆在别处——vector store、日志、notes,那些才是磁盘。磁盘慢,但不会因为多存了一个文件就让 CPU 变笨。RAM 不同。你把仓库塞进 RAM,每一毫秒都在付代价。

那篇讲驱逐的文章把问题从“该检索什么进 context”掉转成“该把什么驱逐出去”。我一开始觉得这是话术把戏,后来发现不是。这个掉转恰好切在要命的那层:一旦承认 context 是工作集而不是仓库,真正的问题就不是“什么东西值得进”,而是“什么东西到了该滚出去的时候”。

再往下剥一层。驱逐如果只凭“最近”这个信号,会做出一堆蠢决定。我干过:按时间戳踢东西,结果把一个旧的 hard constraint 踢出去了,留下的是一段刚生成的、毫无价值的 tool dump。recency 为什么弱?因为当前这一步需要的,很可能是一条五分钟前还在沉睡、但三小时前就定下来的约束。age 告诉你它存在了多久,没告诉你它现在多要紧。

这么说吧,驱逐得在两条轴上操心。一条是它能不能被近似——有些东西必须逐字保留,有些压成一句话就够。另一条是它跟当前这步有没有关系,这个叫 salience。recency 只是个廉价的代理变量,真正值钱的是第二条轴:当前这步最要命的那条信息。

先停一下,问个问题:那到底什么东西该被 pin 住、永远别动?我的答案是三类。目标,当前这轮到底在解决什么;hard constraint,比如“不得重启服务”“只查 config-render 路径”;还有用户最初的那句原话。这三样不是“内容”,是这轮工作集的骨架。骨架一被 summarize,整个结构就塌了。

我上个月给自己写了个很土的 pin block,贴在 agent 每轮开跑前:

# pinned (never evict, never summarize)
- goal: 定位 preprod 配置漂移,不动 prod
- constraint: 不得重启服务
- literal request: 只查 config-render 路径,先别扩大

不复杂,但有用。它把“哪些东西连近似都不许”这件事,从我的脑子里挪进了 context 里。

再往下,有个更阴的坑。证据被用过一步之后,很多人会把它 summarize 成一句 claim,然后心安理得。那篇文章管这叫 lossy deletion,我觉得这说法有点轻了。真正的问题不是信息丢了,是丢了你根本不知道丢的是哪个维度。一条查证过的证据被压成“配置值是 X”,原样信息没了,指向 durable memory 的指针也没有。下次 agent 需要引用它时,手里只有一个自己嚼过的半消化物,还以为是原始事实。

我在这里绊过。有一次把一段原始调查全文 summary 成了一句“根因是连接池初始值”,后来回查才发现原文里有半句话被我漏了——那半句话恰好是关于一个反向调用的时序。那晚的我坚定地认为总结就够用了。这种坚定通常就是出事的前兆。从那以后我给自己定了一条:低风险步骤,总结加指针可以;高风险步骤,原始证据得能 page back 回来。page back 当然费 token,但费在刀刃上,比事后追一个假结论便宜。

停下来想想。这所有的一切——pin、驱逐、page back、salience——背后有个我到现在也没想明白的洞。salience 在热任务中间是能算的,看最近几轮谁被引用了、谁的参数被当成实参了。但冷启动呢?会话刚开始,任务还没定,salience 从哪来?一个 constraint 可能从头到尾都不会被“引用”一次——它一直被尊重着,所以从没上过引用记录。按 reachability 那套算,它会冷掉,然后被驱逐。可它明明是这轮里最不能丢的东西。

这层我至今没想明白,先把我目前的理解放这儿:也许 constraint 这类东西不该按内容算 salience,该按类别设置成“不退化的”。但类别谁划?划错一次呢?这已经不是 context 策略问题了,是 agent 在任务开始前到底有没有一个稳定的“自己”可以锚定 salience 的问题。

所以说回来,那天晚上我做的蠢事,根子不在塞了太多东西,在我没想过“这堆东西里哪些该被当作骨架、哪些该被当作用完即弃的草稿”。我把它们一视同仁地堆在一起,还美其名曰“留档”。

再往下就是冷启动那头了。这个我还没剥动,下次接着来。

林默
林默

从具体轶事入口,一问一答把默认对的判断剥到设计权衡,主动暴露走过的弯路。

查看主页 →