应用层 · Context 工程
学习舱 / 应用层 / Context 工程

Context 工程

整理中 深度 · 应用 更新 2026-09-09

Context 工程

一句话定位:Context 工程管 Agent 循环里「喂什么、留什么、扔什么」——上下文是稀缺且会衰减的资源,把它当预算来花,长任务才不跑偏。前置:Agent:循环、工具调用与 harness——知道了循环怎么转,这篇管循环每圈吃进去的东西。

Agent 干得越久,越不像它自己

Agent 跑长任务的头几步,又快又准:目标清晰、材料新鲜、每一步有的放矢。

几十圈之后画风突变:开始忘事(最初的约束早被挤出了视野)、开始重复劳动(刚查过的东西再查一遍)、开始拿不相干的旧材料当依据。模型没换、指令没改,表现却一路下滑。

问题出在哪?不在模型,在喂给它的东西——上下文窗口是有限的,每转一圈都往里塞新内容,早期的关键信息被稀释、被挤出,注意力跟着失焦。业界给这种现象起了名字:上下文腐烂(context rot)。

怎么让长任务的第 50 步和第 1 步一样清醒?答案是把上下文当预算来花——这就是 Context 工程。

每圈循环的上下文组装流水线 素材池(全部可得) 系统提示 消息历史 工具返回 检索材料 三条流水线 ① 过滤:跟本次有关吗 ② 组装:排序 + 按预算装窗 ③ 迭代:每圈重新装一遍 上下文窗口 容量有限 注意力会稀释 塞越满越迟钝 Token 预算条(示意) 常驻区 本任务区(历史+工具返回) 机动区 读法:素材池里的东西尽量多,右边的窗口装不下——①②③决定谁能进、怎么摆、何时重装

图:上下文流水线——素材池里大部分东西进不了窗口;①②③决定谁能进、怎么摆、何时重装

渐进拆解:一只容量固定的行李箱

类比:收拾一只容量固定的行李箱

Context 工程就是收拾一只容量固定的行李箱——箱子就那么大(上下文窗口),旅程却在变长(循环圈数)。

  • 身份证件放外袋(系统提示):常驻、固定位置、每次过安检都要第一时间拿出来。
  • 衣服按天卷着放(工具返回与检索材料):今天的必带,三天后的大概率不用带。
  • 纪念品最占地方(消息历史):每一件都有意义,但全塞进去箱子就关不上——得挑、得压、得扔。
  • 装箱单(Token 预算):每类东西配额多少,出发前定好,超了就淘汰——外袋(常驻)、主仓(本任务)、侧袋(机动)各划各的线。

不会收拾箱子的旅行者有两种:什么都带的(超重,翻东西翻半天——对应注意力稀释)和什么都不带的(到目的地两眼一抹黑——对应信息不足瞎编)。收拾箱子的手艺,就是在「带够」和「装得下」之间找平衡。

例子:30 圈长任务的上下文账

把前一篇的运维助手放进一个 30 圈的长任务里,算一笔上下文账:系统提示 800 token 纹丝不动;用户最初那句「服务响应变慢了」早就被挤到视野边缘;30 条工具返回里,只有最近 3 条还有用,其余 27 条是几千 token 的日志原文,静静躺在上下文里稀释注意力。第 31 圈模型开始重复查询第 5 圈查过的东西——不是它忘了怎么干活,是干活需要的线索被淹了。

大白话

模型的注意力像手电筒的光,上下文越长,同一束光照到的地方越多、每处越暗。Context 工程的全部工作,就是让这束光永远只照现在重要的东西。

技术定义

Context 工程是提示词工程的演进——后者关注「一条指令怎么写」,前者关注「推理时的整个上下文状态怎么策划」,包括系统提示、工具、消息历史、外部检索材料的持续取舍。业界权威表述把上下文看作注意力预算:token 是稀缺资源,且模型召回信息的准确度会随上下文总量增加而衰减,目标是「找到能最大程度实现预期结果的最小高信号 token 集合」。这套策划落地为三条流水线,见下节。

三条流水线各干各的

过滤:进门先问「跟这步有关吗」

工具返回原样回填是腐烂素材的大头——一次 grep 几千行日志,有用就几十行。工具相关性过滤让「和当前任务无关的工具」压根不进候选:查数据库的活,别让模型看见发邮件的工具;消息相关性过滤淘汰与当前目标无关的旧对话;检索材料按相似度掐尖。

过滤的标准只有一条:这一段如果删掉,下一步的判断会变差吗? 不会就删。

组装:位置也是信息

一般经验是窗口开头与结尾的内容更受关注,中段容易被「扫过」。所以常驻约束(角色、边界、输出格式)放系统区;关键材料靠近当前任务放;历史长尾压缩成摘要垫底。Token 预算按「常驻区 / 本任务区 / 机动区」切分配额,超区的素材先过滤再进窗。

迭代:每圈重新装一次箱

上下文不是一次性打包——每圈循环结束,都要重新过一遍流水线:新工具返回进来了、旧材料过期了、目标推进到新阶段了。节奏上不必每圈都大动干戈:常规圈只做增量检查(新素材够不够格进窗),每隔几圈做一次全量重组(历史压缩、预算复核)。这也是它与一次性提示词写作的本质区别:写 prompt 是一次动作,管 context 是持续职责。

失败重试与降级也要配合这套节奏:

  • 重试时,回填的错误信息要精炼:错误类型 + 关键参数,而不是整个报错堆栈——「上游超时 30s,重试第 2 次」比 200 行堆栈有用且便宜。
  • 降级到备用模型时,上下文要按新模型的窗口重新适配:预算表跟着换,别拿大模型的行李塞小模型的箱子。

动手:一张上下文预算表

伪代码:每圈循环跑一次预算检查,超区先压缩再进窗:

BUDGET = {"reserved": 2000, "task": 24000, "flex": 8000}   # 三区配额(token)

def pack(system, history, tool_results, query):
    ctx = system[:BUDGET["reserved"]]              # 常驻区:角色与约束
    task_zone = history + tool_results             # 本任务区:历史与返回
    while size(task_zone) > BUDGET["task"]:        # 超预算 → 压最旧的
        task_zone = summarize_oldest(task_zone)    # 旧记录压成摘要
    flex = retrieve(query, top_k=3)[:BUDGET["flex"]]  # 机动区:检索掐尖
    return ctx + task_zone + flex

# 每圈循环调用一次 pack——上下文是每圈重新装的行李,不是一次装箱

配合一张 Debug 记录(见下节),每一次打包都可以复查:谁进了、谁被压了、各区实际占用多少。

三区的配额给个可感的量级:一个 2 万 token 的窗口,常驻区给 2000(角色与约束,反复被读不嫌多)、本任务区给 14000(历史与工具返回的主战场)、机动区留 4000(检索材料按需进出)。数字随模型与任务浮动,比例感比绝对值重要:常驻要小而硬,机动要留余量。

边界与取舍:污染与检测

上下文污染:长任务最常见的翻车原因

一段被注入的错误信息、一次失败工具的噪音返回、一段过时的旧结论——只要留在窗口里,就会持续影响后续判断,而且模型往往言之凿凿地引用它。污染的麻烦在于不可见:窗口里几万 token,人眼扫不出那一段是毒。

所以检测要靠报表而不是靠眼睛。每次打包时顺手记录一份上下文调试报告:本圈进了哪些素材(来源、token 数)、压掉了哪些、各区占用与配额的偏差、与上圈相比的增量。长这样:

上下文调试报告(第 31 圈,节选) 圈数 素材(来源) token 动作 31 工具返回 · grep 日志 3,200 进窗 31 消息历史 · 第 5–28 圈 8,400 压成摘要 31 检索材料 · top1(来源可疑) 2,100 进窗 ⚠ 复查 30 旧检索材料 · 已过期 900 降级留档 模型第 31 圈开始胡来时,翻表发现可疑检索材料恰在本圈进窗——定位完成

图:调试报告样例——逐圈记录谁进窗、谁被压、token 多少;出问题翻表即可定位污染源

别把过滤做成误杀

过滤的标准是「删了不影响下一步」——但「下一步」会变:此刻没用的材料,三圈后可能就是关键证据。最典型的懊悔场面:第 3 圈丢掉的报错码,第 30 圈才发现正是破案钥匙。保守做法是把被过滤的素材降级留档(移出窗口、留在仓库),需要时可以捞回,而不是物理删除。

方法与实现的分工

本篇讲的是「喂什么、留什么」的方法论;工程上还有一整套源码级的压缩实现——按什么时机触发、对哪些内容折叠、怎么保留骨架——那是上下文压缩体系专篇的主题。两篇合起来才是完整拼图:这里定策略,那里看机器。

自测

合上文章先自己答,再展开对照:

「上下文污染」是什么、怎么检测?

污染指错误信息混进上下文并持续影响后续判断:被注入的错误指令、失败工具的噪音返回、过时的旧结论,都会被模型当作依据反复引用,且引用得言之凿凿。麻烦在于不可见——几万 token 里人眼扫不出那一段是毒。检测靠报表:每次打包记录一份上下文调试报告(本圈进了哪些素材及来源与 token 数、压掉了哪些、各区占用与配额偏差、逐圈增量),出问题时翻到异常素材进入的那一圈,即可定位污染源。预防手段是把被过滤素材降级留档而非物理删除,随时可回捞。

这篇的方法论与上下文压缩体系的源码级实现,分工在哪?

分工是「策略层」与「实现层」。本篇(Context 工程)回答策略问题:喂什么、留什么、扔什么——过滤标准、三区预算怎么切、位置怎么摆、每圈怎么迭代,这些决策先于任何实现。上下文压缩体系专篇回答实现问题:压缩在什么时机触发(阈值、定时)、对哪些内容怎么折叠(工具结果占位、历史摘要)、多级压缩体系怎么用源码组织。先有策略再有实现——不知道该扔什么,再精巧的压缩算法也只是在错误的取舍上跑得飞快。

参考与延伸

下一站:Embedding 与向量化——机器怎么把「语义」变成可计算的距离:检索靠它排序,Agent 记忆靠它去重,是两大机制共同的地基。

本节点大纲与自测题(4 个子点 · 2 问)

大纲

  • Prompt 工程 vs Context 工程的本质区别
  • 上下文组装:Packing / Prioritization / Token 预算
  • 工具相关性过滤、消息过滤、聊天记录压缩
  • 失败重试与降级的上下文配合

自测——答不上来就是缺口

  • 「上下文污染」是什么、怎么检测?Context Debug Report 长什么样?
  • 这里的方法论与上下文压缩体系的源码级实现(microcompact 等)分工在哪?