第 6 章 AI AgentAgentic Patterns上下文压缩

第 6 章 上下文压缩与精选:装不下怎么办

把最值得的东西装进有限的口袋

上一章说上下文是一笔要管好的账。这一章要回答一个更直接的问题:装不下了怎么办?

上下文窗口是有限的——几万到几十万 token,看着不小,但真实世界很大:一个大型代码库动辄几十万行代码、一个 PDF 可能几 MB、一个网页塞满了导航和广告。全塞进去,要么爆掉,要么"注意力"被噪音稀释。

这一章讲四个模式,核心思路都是同一个:别把原始数据塞给模型,把"提炼后最值得的东西"塞进去

  1. Context Window Auto-Compaction(上下文自动压缩):溢出时自动压缩、自动重试,用户无感知。
  2. Curated Code/File Context Window(精选代码/文件窗口):只载入最相关的模块,而不是整个仓库。
  3. Semantic Context Filtering(语义过滤):把原始数据转成"语义抽象"再给模型。
  4. Progressive Disclosure(渐进披露):先给元数据,需要时再加载内容。

模式一:上下文自动压缩(Context Window Auto-Compaction)

问题

上下文溢出是 Agent 可靠性的"无声杀手"。对话历史累积到超过模型的窗口时:

  • 请求直接失败(context_length_exceeded 之类的错误)。
  • 运维要手动截断对话记录,宝贵的上下文被丢掉。
  • 检测溢出、压缩重试的过程又容易出错。

方案

让系统在溢出时自动压缩、自动重试,全程对用户透明。核心机制:

  • 溢出检测:捕获 "上下文超长" 类的 API 错误。
  • 自动压缩重试:检测到溢出后,压缩会话记录,然后自动重发请求。
  • 保留 token 下限:压缩后,确保至少留出一段可用空间(默认约 20k token),防止刚压缩完立刻又溢出。
  • 压缩后验证:压缩完估算 token 数,确认确实比压缩前少,防止压缩无效。
  • 按模型适配:不同模型对对话格式要求不同(比如 Anthropic 严格要求的 turn 顺序、Gemini 不同的记录要求),压缩逻辑要按模型调整。
async def 压缩会话(会话文件, 配置):
    # 1. 加载会话,配置保留token
    # 2. 检测到溢出 → 触发压缩
    # 3. 压缩到保留下限之内
    # 4. 验证压缩后token数 < 压缩前
    # 5. 重发请求

证据

  • 来自 Clawdbot、Pi Coding Agent、OpenAI Codex 等生产实现,状态是 validated-in-production(生产验证过)。
  • 压缩是几乎所有长会话 Agent 的标配能力。

怎么用

  • 任何可能长时间运行的 Agent 会话,都应该配上自动压缩。
  • 压缩指令要明确"什么必须留、什么可以丢"(见第 5 章的配套动作)。
  • 保留 token 下限按你的模型和任务调——太小容易反复溢出,太大等于没压。

取舍

  • 好处:会话永不因溢出而中断;用户无感知;保留关键信息。
  • 代价:压缩本身花 token 和延迟;压得不好会丢信息。
  • 注意:压缩是"保底",不是"不精选的借口"——最好在源头就少塞垃圾(见下面几个模式)。

模式二:精选代码/文件窗口(Curated Code/File Context Window)

问题

把整个代码仓库都丢进上下文,会出大问题:

  • 无关的代码会带偏模型——塞满了 test 工具和文档,模型在处理 UI 组件时就"失去连贯性"。
  • 大上下文让 token 用量暴涨,拖慢推理,也让多轮训练变慢。

方案

给主 Agent 维护一个最小、高信号的上下文——让上下文保持"无菌"(sterile)。

核心动作:用一个小 Agent 来找"该看哪些文件"

派一个轻量的 SearchSubagent(可以是小模型、向量检索,或普通的 grep/ripgrep),负责回答"哪几个文件定义了 UserModel"这类问题。它返回排序后的文件片段,只有排名最前的 3 个片段(每个 ≤150 token)被注入主 Agent 的上下文

典型的工作循环:

  1. 主 Agent:"我要重构 UserService。"
  2. SearchSubagent:"找到了 user_service.pymodels/user.pyutils/auth.py。"
  3. 上下文注入:只有这三个文件(或它们的摘要)进入主 Agent 的窗口。

配套技巧:渐进披露——先取文件摘要,真正需要时再加载全文(详见模式四)。

证据

  • 多个生产实践验证(validated-in-production),来源包括开源 Agent RL 的分享、Prime Intellect、Thorsten Ball 等一线实践者。

怎么用

  • 编码类 Agent 几乎都该用:它决定了"模型到底在看什么"。
  • 文件选择的标准要明确(函数/类名、相关模块),别让搜索 Agent 也"自由发挥"。
  • 和下一章的上下文最小化配合:选出来的文件要干净,别带污染。

取舍

  • 好处:推理更快、更准;token 大幅减少;模型不被无关代码带偏。
  • 代价:需要额外的检索逻辑;如果搜索漏了关键文件,Agent 会在错误的信息上工作。

模式三:语义过滤(Semantic Context Filtering)

问题

原始数据对模型来说太啰嗦、太吵了。举个惊人的数据:网页内容里 40%-80% 是导航、页脚、广告这类样板内容(boilerplate),在语义处理前就该被过滤掉。

这个问题到处都是:

  • 网页抓取:完整的 HTML DOM 塞满了脚本、样式、追踪 iframe。
  • API 响应:JSON 里全是嵌套的元数据、内部字段、调试信息。
  • 文档处理:页眉、页脚、导航、样板文字。
  • 代码分析:注释、空白、样板代码。

塞给模型的结果就是:token 爆炸、信噪比极差、推理变慢、噪音把推理带偏甚至产生幻觉。

方案

核心原则一句话:别把原始数据发给 LLM,发给它语义抽象(semantic abstraction)。

把原始数据里"有语义的、可交互的、相关的"元素提取出来,过滤掉噪音,给模型一份干净的表示。生产系统里到处是这个思路的验证:

  • 浏览器自动化工具用可访问性树(accessibility tree)而不是原始 DOM。
  • RAG 框架(LangChain、LlamaIndex)做语义分块
  • 代码分析工具(Aider)用 AST 生成 repo-map,而不是贴源码。

证据

  • 网页样板检测的研究(Kohlschütter 等人,SIGIR 2010)给出了 40%-80% 的数据。
  • 浏览器、RAG、代码分析三大领域都验证了"语义抽象"的路线。

怎么用

  • 凡是"要把外部数据给模型看"的地方,先问一句:这是原始数据,还是提炼后的抽象?
  • 网页 → 用可访问性树或正文提取;API → 只保留业务字段;文档 → 去样板;代码 → 用 AST 摘要。
  • 过滤要在进入上下文之前做,而不是让模型自己"忽略噪音"——模型做不到。

取舍

  • 好处:token 大减、推理更准、幻觉更少。
  • 代价:需要写提取/转换逻辑;过度过滤可能丢掉边缘信息。

模式四:渐进披露(Progressive Disclosure for Large Files)

问题

大文件(PDF、DOCX、图片)如果被"朴素地"整个塞进上下文,会瞬间撑爆窗口。一个 5-10MB 的 PDF,真正有用的文字/表格可能只有 10-20KB,但整个文件往往被一股脑塞进去,浪费 token、拖垮性能。

方案

渐进披露:先只加载文件的元数据,然后提供工具,需要时再按需加载内容。

第一步:永远把元数据放进提示词,而不是全文

文件:
  - id: f_a1
    名称: my_image.png
    大小: 500,000 字节
    类型: 图片

第二步:提供按需加载的工具,让 Agent 在真正需要时,用 读取(f_a1, 页码/区域/摘要模式) 去取具体内容。

这样,Agent 先"看到"有哪些文件、大概多大,然后精准地只加载它需要的部分——可能是第 3 页、可能是某个表格、可能是某个摘要。

证据

  • 来自 Will Larson(lethain.com)的工程实践总结。
  • 和"懒加载"(lazy loading)思想一脉相承,在数据库、前端、分布式系统里都是成熟模式。

怎么用

  • 任何 Agent 可能接触大文件(PDF、图片、大日志、大 CSV)的场景都适用。
  • 元数据要够用:名称、大小、类型、结构概览。
  • 加载工具要支持多种模式:按页、按区域、按摘要、按关键字。

取舍

  • 好处:大文件不再是上下文的负担;Agent 按需取用,精准高效。
  • 代价:需要设计加载工具和元数据格式;Agent 可能"不知道该加载哪部分",需要好的元数据引导。

四个模式怎么选

场景 推荐模式
会话太长,溢出报错 自动压缩(保底)
编码 Agent,仓库太大 精选代码窗口
网页/API/文档噪音太多 语义过滤
会接触 PDF/图片/大文件 渐进披露

四个模式可以组合成一条流水线:源头用语义过滤和精选窗口"少塞垃圾",中间用渐进披露"按需取用",兜底用自动压缩"装不下就提炼"。这就是完整的上下文管理链路。

实践清单

  • 长会话 Agent 配自动压缩,保留 token 下限约 20k
  • 压缩指令明确"什么必须留、什么可以丢"
  • 编码 Agent 用搜索子 Agent 精选文件,只注入 top-3 片段
  • 外部数据进上下文前,先转成语义抽象(可访问性树/AST/字段提取)
  • 大文件只给元数据,提供按需加载工具
  • 检查:模型看到的到底是原始数据,还是提炼后的东西?

本章小结

  • 自动压缩:溢出时自动提炼重试,会话永不中断。
  • 精选窗口:用小 Agent 找"该看哪些文件",只注入高信号内容。
  • 语义过滤:给模型语义抽象,而不是原始数据。
  • 渐进披露:先给元数据,需要时再加载内容。
  • 组合成流水线:源头少塞、按需取用、兜底提炼。

下一章,我们讲上下文管理的另一个角度——最小化:不仅要"装得下",还要"不装脏东西"。

📑 Agent 模式实战:生产级 AI Agent 的工程模式

1 第 1 章 什么是 Agent 模式 2 第 2 章 规划-执行-观察:先想清楚,再动手 3 第 3 章 反思闭环:让 Agent 学会检查自己的作业 4 第 4 章 委派:让主 Agent 学会把活分出去 5 第 5 章 上下文预算治理:把 token 当成钱来管 6 第 6 章 上下文压缩与精选:装不下怎么办 7 第 7 章 上下文最小化:别让脏东西留在脑子里 8 第 8 章 记忆体系:让 Agent 记得住过去 9 第 9 章 学习沉淀:让 Agent 和团队一起变聪明 10 第 10 章 工具接口哲学:让 Agent 能用、好用、用得起 11 第 11 章 工具发现:让 Agent 在几百个工具里找到对的 12 第 12 章 执行环境:Agent 在哪动手、怎么动手 13 第 13 章 代码执行与沙箱:先写码,再跑码 14 第 14 章 结构化输出与契约:让 Agent 的输出能接住 15 第 15 章 验证循环:Agent 怎么检查自己的作业 16 第 16 章 评测基建:怎么系统地检验 Agent 17 第 17 章 可观测性:看见 Agent 在想什么、在干嘛 18 第 18 章 韧性工程:扛得住部分失效 19 第 19 章 威胁模型:先看风险长什么样,再谈防御 20 第 20 章 控制流隔离:把"谁做决定"和"谁执行"分开 21 第 21 章 权限与审批:谁有权干什么、谁点头 22 第 22 章 凭据与出口:Agent 手里的钥匙和门 23 第 23 章 多智能体信任:多个 Agent 之间怎么互信、怎么审计 24 第 24 章 反馈信号设计:给 Agent 的是信号,不是更大的提示词 25 第 25 章 评测驱动的改进:让 Agent 在真实使用和对抗测试里变强 26 第 26 章 强化学习:把反馈变成训练信号 27 第 27 章 复合式进化:让 Agent 系统越用越值钱 28 第 28 章 多智能体协调:让一群 Agent 一起干活不掉链子 29 第 29 章 模型路由:谁用哪个模型,怎么用得起 30 第 30 章 推理搜索结构:让 Agent 多想想,而不是一条道走到黑 31 第 31 章 控制谱系:从自动补全到完全自主的滑动条 32 第 32 章 团队与产品:把 Agent 变成团队资产,而不是个人玩具
← 返回本书大纲