Context 管理:AI 工程里最被低估的核心能力

大多数人以为 prompt 工程就是写好一段话。但真正决定 AI 输出质量的,是你往上下文里塞了什么、没塞什么、以什么顺序塞的。Context 管理是注意力预算管理,不是 token 管理。

一个被反复验证的事实

用 AI 写代码的人都会遇到这个场景:你把整个项目丢给 AI,说”帮我改一下登录页面的 bug”。AI 迅速改完了登录页面,但顺手把旁边的支付模块也”优化”了一下。

你以为它不懂你的需求?不,它懂。但你的 context 里塞了太多跟登录页面无关的东西,它的注意力被分散了。就像你让一个人在嘈杂的工地里念一段电话号码,他能听到,但记不全。

这不是个别现象。我在多个项目里反复验证过同一个规律:context 的质量决定了 AI 输出的质量,而 context 的质量跟 token 数量几乎无关。

注意力是有预算的

很多人对 LLM 有一个根本性的误解:以为 context window 是一个”容器”,往里面装的信息越多,AI 就越”了解”你的项目。

但 context window 更像是一个注意力预算池。你往里面放的每一条信息,都在消耗这份预算。

Lost in the Middle

2023 年有一篇论文(Lost in the Middle: How Language Models Use Long Contexts)做了一个实验:把一条关键信息放在 context 的不同位置,然后让模型回答基于这条信息的问题。

结果很直观:

信息位置:开头 ████████████ 回答准确率:~95%
信息位置:中间 ░░░░░░░░░░░░ 回答准确率:~55%
信息位置:结尾 ████████████ 回答准确率:~90%

模型对 context 中间部分的信息,关注度显著低于开头和结尾。这不是 bug,是 Transformer 架构的固有特性,self-attention 机制天然会给首尾位置更高的权重。

所以当你把 200K tokens 的代码一股脑塞给 AI 时,真正被它”看到”的信息,可能只有开头和结尾的各 20%。中间那 60%,它大概是扫了一眼,就过去了。

这跟 AI Coding 有什么关系

关系很大。

你在 Cursor 或者 Claude Code 里打开一个项目,AI 能”看到”的东西包括:

  • 你当前编辑的文件
  • 你通过 @ 引入的其他文件
  • 项目结构
  • linter 错误
  • terminal 输出
  • git diff
  • system prompt

每一项都在消耗注意力预算。

一个常见的反面案例:你在改一个 React 组件的样式问题,但 context 里还残留着上一次对话讨论的 API 重构方案。AI 这时候可能会把”API 优化”的思路带到”改 CSS”的任务上,给出的方案里夹带了完全不相关的建议。

这就是注意力偏移。它不是 AI”犯傻”,是你给了它错误的信号。

Context 管理的本质:信噪比

把 context 管理理解为 token 管理,是把问题想浅了。

真正的 context 管理是在做信噪比优化。你要做的是:

  1. 提升信号:只放跟当前任务直接相关的信息
  2. 压制噪声:过滤掉跟任务无关的内容
  3. 排列顺序:把最关键的信息放在注意力最高的位置

用一个具体的例子。假设你要让 AI 帮你修复一个 bug,你有两种 context 策略:

策略 A(大而全)

整个项目的文件结构
bug 所在文件的全部代码(800 行)
相关的类型定义文件
相关的测试文件
最近的 git diff
README
package.json

策略 B(精准裁剪)

bug 相关的函数及上下文(50 行)
函数的输入输出类型定义
触发 bug 的测试用例
一行项目背景说明

策略 B 的效果几乎总是更好。因为 AI 在 50 行代码里找 bug,和在 800 行代码里找 bug,是完全不同的任务。前者它真的在读每一行,后者它大概率只扫了前 200 行和后 200 行。

需求专注度:最常见的失败模式

AI Coding 里最常见的失败,不是 AI 写不出代码,是它偏离了你的需求

偏离是怎么发生的

需求偏离通常不是一步到位的,而是一个渐变过程:

  1. 你给了一个明确的任务
  2. context 里有一些相关信息,AI 觉得”顺便一起改了会更好”
  3. AI 的修改引入了新的 context(改了文件 A,现在文件 B 也需要调整)
  4. 新的 context 又触发了新的”顺便”
  5. 你要的是改一个按钮颜色,AI 给你重构了整个组件体系

这个过程很像人类的”注意力漂移”。区别在于,人类漂移了自己能意识到,AI 漂移了它完全不知道,还觉得自己做得很好。

怎么防

几个实践中验证过的做法:

缩小 context 边界。 只给 AI 跟当前任务相关的文件和代码。不要把”可能有用”的东西也塞进去,“可能有用”和”确定有用”之间隔着巨大的信噪比差距。

显式声明约束。 在任务描述里加上明确的边界:“只修改这个函数的逻辑,不要改动其他函数。不要重构。不要优化。只修 bug。“这种看起来很”啰嗦”的约束,实际上是在帮 AI 划定注意力的边界。

分步执行。 一个大任务拆成几个小步骤,每一步只加载必要的 context。第一步做完,清掉跟第二步无关的上下文,再开始第二步。不要在一个超长对话里把所有事情都做了。

及时纠偏。 AI 开始”自由发挥”的时候,马上打断。不要指望它自己绕回来,它不会的。每发现一次偏离,就是一次重新校准 context 的机会。

Context 管理的几个工程模式

在 Agent 设计和 AI Coding 的实践中,有几个比较成熟的 context 管理模式。

1. 渐进式加载

不要一次性把所有信息塞进去,按需加载。

第一轮:任务描述 + 核心文件
第二轮:根据第一轮的分析结果,加载相关依赖
第三轮:根据前两轮的结果,加载测试和边界情况

每一轮只加载”当前缺少的信息”。这样做的好处是,AI 的注意力始终聚焦在当前步骤需要的信息上,不会被还没用到的内容分散。

2. 上下文裁剪

定期检查和清理 context,把已经完成、不再需要的上下文移除。

  • 已修复的 bug 相关的报错信息?删掉
  • 上一个任务的讨论记录?删掉
  • 仅供参考、已经用完的文档?删掉

context 不是越积越多的,应该是流动的。用完的信息就应该腾出位置,给新的信息让路。

3. 结构化注入

往 context 里放信息的时候,不是堆砌,而是有结构的组织。

## 任务
修复用户注册表单的邮箱验证 bug

## 约束
- 只修改 validateEmail 函数
- 不改动表单组件的其他逻辑
- 保持现有的错误消息格式

## 相关代码
[只包含 validateEmail 函数及其直接依赖]

## 测试用例
[只包含邮箱验证相关的测试]

结构化的 context 让 AI 能快速定位每一部分信息的角色,减少”理解成本”,把更多注意力留给任务本身。

4. 场景隔离

不同场景之间共享 context 要极其谨慎。

A 项目的技术栈偏好,不要自动带入 B 项目。昨天对话里的临时决策,不要自动出现在今天的对话里。CLI 会话中的操作,不要自动关联到 Web 界面的会话。

这一点在我之前那篇讲 Hermes 和 OpenClaw 的文章里展开聊过。context 跨场景流动看起来像是”智能”,实际上往往是”污染”。每个任务、每个项目、每个会话都应该有自己干净的 context 边界。

5. 上下文预算

给每次 AI 调用设定一个隐性的”上下文预算”。比如:

  • 简单 bug 修复:500-1000 tokens 的 context 就够了
  • 功能开发:2000-5000 tokens
  • 架构重构:5000-10000 tokens

如果你发现一个简单 bug 修复需要加载 20000 tokens 的 context,要么是你的任务拆分有问题,要么是项目结构需要优化了。

从”写好 prompt”到”管好 context”

Prompt engineering 这个词很容易让人产生一种错觉,以为 AI 工程的核心就是”写好一段话”。

写好 prompt 当然重要。但 prompt 只是 context 的一个组成部分。真正的能力在于:你知道在什么时间点,用什么结构,往 AI 的视野里放什么信息,不放什么信息。

这个能力的背后,是对注意力机制的直觉理解。你知道 AI 的注意力是有限的、是不均匀分布的、是容易被噪声带偏的。所以你做的每一个 context 相关的决策——给什么文件、不给什么文件、信息怎么排列、什么时候清理——都是在帮 AI 把有限的注意力花在刀刃上。

回到开头那个比喻。context window 不是容器,是注意力预算。你管理 context,本质上是在帮 AI 管理它的注意力。

做不好这件事的人,会在 AI 的”自由发挥”里反复踩坑。 做好这件事的人,会让 AI 的输出看起来像是它真的”懂”你的项目。

区别不在于 AI 的能力,在于你往它的视野里放了什么。