从0打造编码Agent 岔路 阅读 + 实验 ≈ 20 分钟 页内实验 ×1
A5 上下文:对话太长装不下怎么办? 岔路课

上下文越长,模型真的越差吗?

上下文越长越差吗
先在图上猜一条「准确率随输入长度」的曲线,再揭示 NoLiMa 的公开结果:标称 128K 窗口的模型,多数到 32K 时已跌到自己短输入成绩的一半以下。再看我们自己的 trace 里一个真实的「上下文中毒」:摘要编出的 timezone,被后面的摘要一份份继承下去。
❓

本课一问:第 1 课说「窗口迟早会满」。那没满之前呢?窗口标称 128K,塞到 100K 也照样好用吗?

这一课先不碰:怎么压缩(第 2 课)。这里只问:上下文变长这件事本身,会不会让模型变差。

从已有出发

从已有出发 · 累计数据流 点已学环节看它回答什么
每一轮循环都经过

第 1 课的账只回答了「装不装得下」。可装得下不等于用得好:同一个任务,把相关的那几行放在 1K 的上下文里,和埋在 30K 的上下文里,模型找得到的概率一样吗?换例子的原因:我们贯穿任务的上下文最长才两千多 token,测不出这个效应,所以这一课用公开的论文数据。

先猜,再看

先猜:一个标称 128K 窗口的模型,输入从 1K 涨到 32K,准确率会怎样?

数据:Modarressi 等,NoLiMa: Long-Context Evaluation Beyond Literal Matching(ICML 2025),arXiv:2502.05167v3 表 3(arXiv HTML 版,需联网;2026-09-26 转录)。数值从 arXiv HTML 版表格的文字转录(不是从图上估读);Base Score = 250/500/1K 三档里每题最高分的平均,×0.85 为阈值;有效长度 = 仍高于阈值的最大测试长度。58 组问题-针,5 组针,10 本开放版权书作干草堆。 任务是「针在干草堆里」的变体:问题和答案之间几乎没有字面重合,模型要靠语义联想找到那句话。它测的是长输入下的检索与联想,不是编码任务;迁移到 agent 场景时只能当方向性证据。

🎯

试三件事:① 先在每个长度上点出你的猜测,再点「揭示」;② 高亮 GPT-4o:它在 1K 时 98.1%,看它在哪一个长度第一次掉到黄线(基线 × 0.85)以下;③ 高亮 Llama 3.1 8B:它和我们录制用的 Qwen3-8B 同一个量级,注意它从 1K 就在往下走。

揭示之后能读出两件事:

  1. 长度本身就在伤害结果。这个测试里问题和答案之间几乎没有字面重合,模型得靠语义联想去找那一句;13 个模型里,到 32K 时有 11 个跌到了自己短输入成绩的一半以下。32K 只是它们标称窗口的零头。
  2. 「有效长度」远小于标称窗口。论文把「仍高于基线 × 0.85 的最大长度」叫有效长度:GPT-4o 是 8K,其余 12 个里有 12 个在 4K 及以下。LLM 课 C2·L5 从位置编码的角度讲过同一件事:窗口长度不等于有效长度。

Chroma 的《Context Rot》(2025-07-14)在更多设置下看到了同一个方向:18 个模型(含我们录制用的 Qwen3-8B),六类实验,包括把同一批问题分别放在约 300 token 的精简上下文和约 113k token 的完整对话里(LongMemEval,306 条)。它的各模型曲线只在报告的静态图里,本页没有转录,需联网看原文。

⚠
常见误解:「窗口标称多大,就能放心用多大。」

标称窗口是「放得下」,不是「用得好」。对 agent 的直接推论:能少放就少放——这正是第 2 课「先裁工具输出」、A7「让子 agent 去读、只把结论带回来」的动机。

另一个常被当成定律的说法是「上下文用到约 40% 就进入 dumb zone」(Dex Horthy 的演讲《No Vibes Allowed》)。那是讲者的个人经验断言,没有实验支撑;可以当提醒,不能当阈值。

我们自己的 trace 里:一次真实的「上下文中毒」

Anthropic 对 context rot 的官方表述是:上下文里的 token 越多,模型准确回忆其中信息的能力越下降(《Effective context engineering for AI agents》)。Drew Breunig 把长上下文的失败分成四种(《How Long Contexts Fail》,2025-06-22):中毒(poisoning,一个幻觉或错误进入上下文后被反复引用)、分心(distraction)、混淆(confusion)、冲突(clash)。

四种里,我们的短 trace 测得出的只有第一种,而且证据很完整。分层压缩那条运行(pd-v2-layered-s1)一共写了 17 份摘要,其中 16 份提到了 timezone(时区处理)——而这个任务从头到尾,任何工具输出、任务说明、system prompt 里都没有出现过这个词:

这些摘要里写的「可能是时区处理的问题」,把模型的注意力往一个根本不存在的方向引了十几轮。第 4 课会把这些摘要逐份拆开看。

🔍 另外三种失败,我们的数据为什么测不出来?

分心要足够长的上下文才出现(Breunig 转引的 Databricks 研究里,Llama 3.1 405B 在约 32K 开始变差,更小的模型更早);混淆与冲突需要多套工具或互相矛盾的信息源。我们的任务只有 6 个工具、上下文不到三千 token。本页不为它们编例子,想看例子请读原文(需联网)。

证据三问

问本课的回答
① 它解决什么问题?提醒「装得下」不等于「用得好」:上下文要尽量短、尽量相关
② 为什么可能这样?注意力要在越来越多的位置之间分配,相关的那几个位置更难被选中;位置编码在远距离上也没训练充分
③ 实验上呢?NoLiMa:13 个模型、6 个长度,多数在 32K 前明显下降 ;Chroma 18 个模型同方向 ;我们 trace 里的中毒是项目实测的单次运行

演进地图

这一课不在演进链上:它解释的是整条链的动机——为什么要把上下文压小,而不只是「不超窗口」就行。

上下文管理的演进:每一代都被上一代的某个真数字逼出来
  1. A1 的循环(所有 harness 的底层事实:模型 API 不记得上一轮)
    解决了实现最简单,模型每轮都看得到全部经过。
    卡在pd-v2-cap20-s1 从第 1 轮的 947 token 涨到第 11 轮的 2,618;第 1 轮里工具定义就占 72%,到最后一轮工具结果占 44%。只增不减,总有撞墙的一轮。
  2. 本课项目 miniagent 的 truncate(整轮丢,保留 system 与任务)、learn-claude-code s08 的 snip_compact(中段存档)
    解决了零成本,还能保证 tool 调用与结果不被拆散(按整轮丢)。
    卡在pd-v2-truncate-s1 截断 2 次共丢 3 轮,读文件那一轮也在其中;第 7 轮模型凭记忆改,那一行变成 + 1 + 1,验收测试退出码 1。
  3. CoreCoder Layer 1、learn-claude-code micro_compact、OpenCode prune(默认关)、Anthropic tool result clearing
    解决了工具结果是最占地方、也最可再生的一块;裁它不用调模型。
    卡在按位置裁,不懂内容:分层运行里被裁过的 0 份测试输出,0 份丢了唯一关键的 AssertionError 行。另一头,本任务最长的工具输出 1,302 字符,CoreCoder 的 1,500 字符门槛一次都没碰到。
  4. CoreCoder 50 / 70 / 90%、Pi 窗口 − 16,384、OpenCode 窗口 − min(20,000, 最大输出)、Codex 90%
    解决了阈值定在撞墙之前,给压缩本身和下一次回复留出余地。
    卡在本地估算在中文上偏低:一段真实中文 118 token(录制模型的 tokenizer),CoreCoder v0.4.0 估成 60,按「字符数 ÷ 4」估成 45。只靠本地估算触发,就会晚。
  5. CoreCoder Layer 2、本课项目 miniagent L2
    解决了比截断保留更多:旧轮次不是消失,而是被压成一段话。
    卡在pd-v2-layered-s1 的 17 份摘要里,写下确切报错的 0 份,编出不存在的「timezone」的 16 份;第 10 轮模型把改对的一处改了回去。21 轮、73,168 token(摘要另花 11,832)才完成,是同组不压缩成功运行最少的 4.3 倍。
  6. Codex(交接摘要 + 保留用户原话)、Pi(结构化模板 + 文件清单)、OpenCode(五节模板)
    解决了把「必须留下什么」写进模板:目标、约束、进度、确切报错、下一步、相关文件;完整历史留在磁盘上。
    卡在仍然有损。Codex 每次压缩后提醒用户:「Heads up: Long threads and multiple compactions can cause the model to be less accurate. Start a new thread when possible to keep threads small and targeted.」→ 下一章:会话存在哪、明天还记得吗。
旁支 context reset:清空上下文,换一个新 agent 接手 作者已弃用
Anthropic《Harness design for long-running application development》(2026-03-24)
为治「context anxiety」(模型以为快满了就草草收尾)而设;同一篇文章写明:换到 Opus 4.5 后这种行为基本消失,作者把 reset 整个拿掉了。

数字口径:本课项目 miniagent 用 Qwen/Qwen3-8B-MLX-4bit 本机录制的真实运行(2026-09-26),每轮发出的消息由重放得到并与录制的压缩事件、服务端 usage 逐轮核对一致;估算器的输出由 CoreCoder、Pi 的原实现在 pin 源码上跑出(a05-context.json,2026-09-26)。耗时不作比较(本机有其他任务同时占用)。

一句话

📌
窗口是上限,不是有效长度;能少放就少放。

回到主线

最省事的办法:截掉最早的消息,行不行? → 第 2 课

你可能会问