上下文不是越多越好,而是一道排序题
写 Agent 的人都会踩同一个坑:把对话历史一股脑塞进 prompt,然后期待模型自己理清重点。前三轮表现尚可,到第五轮开始胡言乱语——工具调用参数填错、重复调用同一个接口、甚至把用户早就纠正过的错误再犯一遍。
很多人以为这是模型能力问题,其实是上下文工程(Context Engineering)的问题。
一、根因:上下文窗口里塞满了噪音
上下文窗口是一个固定容量的资源池。你把 10 轮对话、3 个工具返回结果、2 段检索文档全放进去,看起来信息很全,实际上模型拿到的是一份没有优先级的物料清单。
打个比方,这就像给新来的实习生一箱没有分类的文档,让他「先熟悉一下项目」。他能记住的只有最上面几页,而不是最关键的那份架构图。上下文窗口的注意力分布是类似的——开头和结尾的信息权重高,中间的容易被忽略。这就是「中间迷失」(Lost in the Middle)现象。
真实场景中,一个典型的 Agent 请求里 60% 以上的 token 消耗在低价值内容上:过期的工具返回、已经被回答过的历史轮次、大段的原始日志。
二、机制:三段式上下文组装
有效的做法是把上下文拆成三块,各自承担不同职责:
固定区(System + 核心指令):始终放在最前面且保持稳定。它定义角色、约束和输出格式。这部分不要动态改,否则模型的行为会漂移。
检索区(相关事实):把当前这一步真正需要的信息放进来,通过向量检索或关键词匹配获取。这一区的内容应该「少而准」,检索到 3 条相关文档,胜过塞 30 条模糊的。
执行区(最近交互):保留最近 N 轮对话和本轮的工具调用结果。这区最容易膨胀,需要主动裁剪。
关键动作是裁剪策略:工具返回超过阈值时不做截断,而是做摘要压缩;同一工具连续失败两次就折叠成一条诊断记录;历史轮次中已被解决的追问直接丢弃。
三、落地:给 Agent 加上上下文预算
假设你给一个 32K 的窗口定下这样的预算:固定区 2K,检索区 8K,执行区 4K,预留 18K 给模型输出和多轮工具循环。超预算时按优先级回收——先砍执行区的历史轮次,再砍检索区的低分文档,固定区绝不动。
落地效果可以直接测量。给同一个任务集打上「上下文构造」和「上下文构造 + 预算裁剪」两个版本,对比工具调用准确率和平均 token 消耗。多数真实任务上,后者能省掉 30% 到 50% 的 token,而准确率不降反升——因为噪音被清掉了。
四、边界:不是所有任务都值得做
如果你的 Agent 只做单轮问答,没有多轮工具调用,上下文工程的收益很小,徒增复杂度。判断标准很简单:当单次请求的上下文超过 4K token,且存在多步工具循环时,才值得投入。
另外,长上下文模型出现后这套工程并没有过时,只是把「怎么压缩」换成了「压缩多少」——你仍然需要决定检索区放什么、放多少,模型不会替你做这个决定。
收束
上下文工程的核心不是把更多东西塞进窗口,而是把对的东西按对的位置放进去。今天就可以做的一个动作:打开你的 Agent 项目,统计最近 10 次请求的 token 构成,看看有多少比例花在了你根本不看的工具返回上——那个数字通常比想象的更难看。
延伸阅读可以关注检索增强(RAG)的排序策略,以及长上下文模型在真实业务里的性价比拐点。