译:如何修复你的 Context

发布于 2025年7月11日

原文: https://www.dbreunig.com/2025/06/26/how-to-fix-your-context.html
作者: DB Reunig
译者: Gemini 2.5 Pro

减轻和避免 Context 故障

继我们之前的文章《长 Context 如何失效》之后,我们来探讨一下如何减轻甚至完全避免这些故障。

但在开始之前,我们先简单回顾一下长 Context 可能出现的几种故障:

  • Context Poisoning (上下文投毒): 当幻觉或其他错误进入 Context,并被反复引用时。
  • Context Distraction (上下文干扰): 当 Context 变得过长,导致模型过度关注 Context 内容,而忽略了它在训练中学到的知识时。
  • Context Confusion (上下文混淆): 当 Context 中的多余信息被模型用来生成低质量回应时。
  • Context Clash (上下文冲突): 当你在 Context 中积累的新信息和工具与 Prompt 中的其他信息发生冲突时。

这里所有的问题都关乎信息管理。Context 中的一切都会影响模型的响应。这又回到了那句古老的编程格言:“垃圾进,垃圾出”。幸运的是,我们有很多方法来处理上述问题。

Context 管理策略


一叠文件。

RAG

检索增强生成 (Retrieval-Augmented Generation, RAG) 是指选择性地添加相关信息,以帮助 LLM 生成更好的响应。

关于 RAG 的文章已经太多了,我们今天不打算深入探讨,只想说一句:它还远未过时。

每当有模型提高 Context 窗口的上限,新一轮“RAG 已死”的辩论就会出现。最近一次是 Llama 4 Scout 带着 1000 万 token 的窗口横空出世。面对这么大的容量,你真的很难不产生“去他的,把所有东西都扔进去”然后收工的想法。

但是,正如我们上次所说:如果你把 Context 当成一个杂物抽屉,那么里面的杂物就会影响你的响应。如果你想了解更多,这里有一个看起来很棒的新课程

电子游戏《命运》中的一系列枪支

Tool Loadout (工具装载)

Tool Loadout 是指只选择相关的工具定义添加到你的 Context 中。

“Loadout” 是一个游戏术语,指的是你在进入一个关卡、比赛或回合前选择的技能、武器和装备的特定组合。通常,你的 Loadout 是根据具体情况量身定制的——角色、关卡、团队其他成员的配置,以及你自己的技能。

在这里,我们借用这个词来描述为特定任务选择最相关的工具。

也许选择工具最简单的方法就是对你的工具描述应用 RAG。这正是 Tiantian Gan 和 Qiyao Sun 在他们的论文《RAG MCP》中所做的。通过将工具描述存储在向量数据库中,他们能够根据输入的 Prompt 选择最相关的工具。

在对 DeepSeek-v3 进行 Prompting 时,该团队发现,当你拥有超过 30 个工具时,选择正确的工具变得至关重要。超过 30 个,工具的描述开始重叠,造成混淆。一旦超过 100 个工具,模型几乎肯定会测试失败。而使用 RAG 技术来选择少于 30 个工具,不仅大大缩短了 Prompt,还使工具选择的准确性提高了多达 3 倍。

对于较小的模型,问题在远未达到 30 个工具时就开始了。我们在上一篇文章中提到的一篇论文《Less is More》,证明了 Llama 3.1 8b 在给定 46 个工具时无法通过一个基准测试,但在只给 19 个工具时却能成功。问题在于 Context Confusion (上下文混淆),而并非 Context 窗口的限制。

为了解决这个问题,《Less is More》背后的团队开发了一种使用 LLM 驱动的工具推荐器来动态选择工具的方法。他们引导 LLM 去推理“它‘认为’回答用户查询需要多少个以及哪种类型的工具”。然后对这个输出进行语义搜索(又是工具 RAG),以确定最终的 Loadout。他们在伯克利函数调用排行榜上测试了这种方法,发现 Llama 3.1 8b 的性能提升了 44%。

《Less is More》的论文还指出了小 Context 的另外两个好处:降低功耗和提高速度。这在边缘设备(即在你的手机或个人电脑上,而非专用服务器上运行 LLM)上是至关重要的指标。即使他们的动态工具选择方法未能改善模型的结果,节省的能源和速度的提升也值得这样做,分别节省了 18% 和 77%。

幸运的是,大多数 Agent 的应用场景都比较小,只需要少数几个精心挑选的工具。但如果功能范围或集成数量需要扩展,请务必考虑你的 Loadout。

一个玻璃钟罩

Context Quarantine (上下文隔离)

Context Quarantine 是指将不同的 Context 隔离在各自专用的线程中,每个线程由一个或多个 LLM 单独使用。

当我们的 Context 不过长且不包含不相关内容时,我们会得到更好的结果。实现这一点的一个方法是将我们的任务分解成更小的、隔离的工作——每个工作都有自己的 Context。

这种策略有许多例子,但 Anthropic 详细介绍其多 Agent 研究系统的博文是一个通俗易懂的案例。他们写道:

搜索的本质是压缩:从浩瀚的语料库中提炼洞见。子 Agent 通过并行运行在各自的 Context 窗口中来促进压缩,它们同时探索问题的不同方面,然后为主研究 Agent 浓缩最重要的 Token。每个子 Agent 还提供了关注点分离——独特的工具、Prompt 和探索路径——这减少了路径依赖,并实现了彻底、独立的调查。

研究工作天然适合这种设计模式。当给定一个问题时,可以识别出几个子问题或探索领域,并使用多个 Agent 分别进行 Prompting。这不仅加快了信息收集和提炼的速度(如果计算资源充足),还能防止每个 Context 累积过多信息或与特定 Prompt 不相关的信息,从而提供更高质量的结果:

我们的内部评估表明,多 Agent 研究系统尤其擅长处理需要同时进行多个独立方向探索的广度优先查询。我们发现,一个以 Claude Opus 4 为主 Agent、Claude Sonnet 4 为子 Agent 的多 Agent 系统,在我们的内部研究评估中,性能比单 Agent 的 Claude Opus 4 高出 90.2%。例如,当被要求找出信息技术标准普尔 500 指数中所有公司的董事会成员时,多 Agent 系统通过将任务分解给子 Agent 找到了正确答案,而单 Agent 系统则因缓慢的顺序搜索而未能找到答案。

这种方法也有助于 Tool Loadout,因为 Agent 设计者可以创建几种具有自己专用 Loadout 和工具使用说明的 Agent 原型。

因此,对于 Agent 构建者来说,挑战在于找到那些可以拆分成独立线程的隔离任务。需要多个 Agent 共享 Context 的问题并不特别适合这种策略。

如果你的 Agent 领域适合并行处理,一定要阅读 Anthropic 的整篇文章。写得非常棒。

修枝剪

Context Pruning (上下文修剪)

Context Pruning 是指从 Context 中移除不相关或不需要的信息。

Agent 在调用工具和组合文档时会不断累积 Context。有时,我们有必要停下来评估一下已经组合的内容,并剔除其中的糟粕。你可以把这个任务交给你的主 LLM,也可以设计一个单独的、由 LLM 驱动的工具来审查和编辑 Context。或者你也可以选择一个更适合修剪任务的专用工具。

Context Pruning 有着(相对)悠久的历史,因为在 ChatGPT 出现之前,Context 长度在自然语言处理(NLP)领域是一个更棘手的瓶颈。目前的一种修剪方法,Provence,正是在这一历史基础上发展的,它是一个“用于问答的高效且稳健的 Context 修剪器”。

Provence 速度快、准确、使用简单,而且相对较小——只有 1.75 GB。你只需几行代码就可以调用它,像这样:

from transformers import AutoModel

provence = AutoModel.from_pretrained("naver/provence-reranker-debertav3-v1", trust_remote_code=True)

# 读入加州阿拉米达维基百科条目的 markdown 版本
with open('alameda_wiki.md', 'r', encoding='utf-8') as f:
    alameda_wiki = f.read()

# 根据一个问题来修剪文章
question = '我有哪些离开阿拉米达的交通方式?'
provence_output = provence.process(question, alameda_wiki)

Provence 对文章进行了编辑,削减了 95% 的内容,只给我留下了这个相关的子集。它做得非常完美。

你可以使用 Provence 或类似的功能来精简文档或整个 Context。此外,这种模式也充分说明,你应该以字典或其他形式维护一个结构化1 Context 版本,并在每次调用 LLM 之前从中组合出一个编译好的字符串。这种结构在修剪时会非常方便,可以确保主要指令和目标被保留,而文档或历史记录部分则可以被修剪或总结。

一个榨鸭机

Context Summarization (上下文总结)

Context Summarization 是指将累积的 Context 浓缩成一个简短的摘要。

Context Summarization 最初是作为处理较小 Context 窗口的工具出现的。当你的聊天会话快要超出最大 Context 长度时,系统会生成一个摘要,然后开启一个新线程。聊天机器人用户以前会在 ChatGPT 或 Claude 中手动操作,要求机器人生成一个简短的回顾,然后粘贴到新的会话中。

然而,随着 Context 窗口的增大,Agent 构建者发现,总结的好处不仅仅是保持在总 Context 限制之内。随着 Context 的增长,它会变得分散注意力,导致模型减少对其训练期间所学知识的依赖。我们称之为 Context Distraction。玩《精灵宝可梦》的 Gemini Agent 背后的团队发现,任何超过 10 万 Token 的内容都会触发这种行为:

虽然 Gemini 2.5 Pro 支持 100 万+ Token 的 Context,但如何为 Agent 有效利用它是一个新的研究前沿。在这种 Agent 设置中,我们观察到,当 Context 显著增长超过 10 万 Token 时,Agent 倾向于重复其庞大历史记录中的动作,而不是构思新的计划。这个现象,虽然只是个例,但它突显了用于检索的长 Context 和用于多步生成式推理的长 Context 之间的重要区别。

总结你的 Context 很容易,但要为任何特定的 Agent 做到完美却很难。知道应该保留哪些信息,并将其详细告知一个由 LLM 驱动的压缩步骤,这对 Agent 构建者来说至关重要。值得将这个功能作为一个独立的、由 LLM 驱动的阶段或应用来开发,这样你就可以收集评估数据,从而直接为这个任务提供信息和优化。

一个银行家用的文件箱

Context Offloading (上下文卸载)

Context Offloading 是指将信息存储在 LLM 的 Context 之外,通常通过一个工具来存储和管理数据。

这可能是我最喜欢的策略,只因为它太简单了,以至于你不敢相信它会奏效。

同样,Anthropic 对这项技术有一篇很好的文章,详细介绍了他们的“think”工具,这基本上就是一个草稿本 (scratchpad):

通过“think”工具,我们让 Claude 能够在得出最终答案的过程中增加一个额外的思考步骤——并有其自己专属的空间……这在执行长链条的工具调用或与用户进行长时间多步骤对话时特别有帮助。

我真的很欣赏 Anthropic 发表的研究和其他文章,但我不太喜欢这个工具的名字。如果这个工具叫 scratchpad (草稿本),你会立刻知道它的功能。它是一个让模型记笔记的地方,这些笔记不会干扰它的 Context,但又可以在之后参考。而“think”这个名字与“扩展思考”的概念冲突,并且不必要地将模型拟人化了……但这是题外话。

拥有一个记录笔记和进度的空间是有效的。Anthropic 展示了将“think”工具与特定领域的 Prompt (这在 Agent 中你本来就会做) 相结合,可以带来显著的收益,针对专门的 Agent,基准测试的提升高达 54%。

Anthropic 确定了三种 Context Offloading 模式有用的场景:

  1. 工具输出分析。当 Claude 需要在行动前仔细处理之前工具调用的输出,并可能需要回溯其方法时;
  2. 策略繁重的环境。当 Claude 需要遵循详细的指导方针并验证合规性时;以及
  3. 顺序决策。当每一步行动都建立在前一步的基础上,且错误代价高昂时(常见于多步骤领域)。

Context 管理通常是构建 Agent 最难的部分。正如 Karpathy 所说,对 LLM 进行编程,以“恰到好处地填充 Context 窗口”,巧妙地部署工具、信息,并定期维护 Context,这就是 Agent 设计师的工作。

上述所有策略的核心洞见在于,Context 不是免费的。Context 中的每个 Token 都会影响模型的行为,无论好坏。现代 LLM 巨大的 Context 窗口是一项强大的能力,但它不是你在信息管理上偷懒的借口。

当你构建下一个 Agent 或优化现有 Agent 时,问问自己:这个 Context 中的所有东西都物有所值吗?如果不是,你现在有六种方法来修复它。


  1. 说真的,这整个策略列表都在有力地证明你应该用编程的方式来构建你的 Contexts

评论 (0)

请登录后发表评论

暂无评论,快来发表第一条评论吧!