为什么你理解了概念却写不出上下文
在 AI 编码助手中,Context Engineering(上下文工程)通常被描述为“如何给模型提供最相关的信息”。但当你打开编辑器时,问题立刻变成了:该放哪些文件?应该包含多少 token 的历史?错误日志要不要一起喂?
第一个最常见卡点是:你把 Context Engineering 当成了模型微调。实际上,它和训练无关,只和当前对话或 Agent 循环中如何组织已有信息有关。这意味着你不需要 GPU,也不需要重新训练,只需要一套结构化的选择、注入和更新规则。
第二个卡点是:你试图一次性把整个代码库塞进去。很多初尝试者会拼接项目所有目录结构、README、数十个文件,结果要么超过 token 窗口,要么模型根本抓不住重点。
第一步:先搭内容注入层
有效的 Context Engineering 需要三层:采集层、筛选层、注入层。其中第一层直接决定了后续质量,但多数人更关注最后一层。
采集层的核心是“主动获取而非被动拼接”。在编码场景中,你需要明确定义什么数据是必须的:
- 当前打开的文件及其最近 20-50 行变更(而不是整个文件历史)
- 当前编译错误或 linter 警告的实时输出(如果没有则跳过)
- 最近一次 git diff 的简要描述(如果需要理解上下文变化)
- 用户最后一条自然语言指令中的关键名词和动作
一个比较具体的做法是设置文件变更监听器(如 chokidar),当文件保存时触发一次上下文快照,而不是每次键盘敲击都刷新。这样既减少 API 消耗,也不会让模型在回答中途因为上下文突变而“失忆”。

第二步:定义上下文有效期与淘汰机制
这是最容易失败的部分。很多人会设计一个完美的上下文结构,但忘记考虑“过时上下文”的清理。结果模型每次回答都引用已经被删除的函数或过时的注释。
失败场景一:你保存了一条错误消息的上下文,用户随后修改了代码并重新编译,但之前的错误上下文仍占据 token 位置,导致新模型响应误以为错误还存在。
解决方法:为每条上下文添加“有效直到”标记。例如编译错误上下文只在下一个成功编译的操作后自动移除;git diff 上下文在当前分支切换或提交后清空。你可以用简单的优先级队列来维护:高优先级(如用户当前指令)始终保留,低优先级按时间或事件过期。
另一个常见问题是上下文个数过多。即使每个都非常精准,如果一次性注入 10 条以上,模型会开始产生注意力稀释。一般建议保持主干上下文 3-5 条,其余的通过用户主动查询来加载。

第三步:最小可落地的实现路径
这里给出一个经典型的设计,不需要特殊框架,只基于 Node.js 或 Python:
- 创建一个
contextEngine.js,包含一个ContextStore类,内部用Map存储每条上下文,key 是自动生成的 ID。 - 实现三个方法:
addContext({ id, content, priority, expireOnEvent })、removeContext(id)、getActiveContexts()。 - 在你的 AI 编码助手(如 Continue、Aider、Cursor Agent)的“tool call”或“hook”中调用:当文件保存时,调用
addContext记录 diff;当编译运行结束时,检查错误并更新对应上下文。 - 在发送给模型的 prompt 组装函数中,调用
getActiveContexts(),按优先级降序拼接。
这里有一个真实的取舍:你是要“尽可能多的上下文”还是“只给模型最需要的”?前者容易把模型搞糊涂,后者需要你自己定义一套规则。以我们的实践,推荐后者,而且规则宜少不宜多,先从一个简单的“最近修改文件 + 最新错误”开始,再逐步增加。
第四步:失败时的诊断与回退
若模型回答质量下降,首先检查上下文队列是否超载或过时。建议在终端输出上下文状态日志(用简短的 JSON 行),便于复盘。还有一个检查点:观察模型是否在重复之前已经解决过的问题,这通常是上下文没有及时清除的标志。
如果频繁出现上述问题,可以回退到一个更窄的上下文策略:只包含当前文件和一条用户指令,完全放弃增量累积。虽然模型会缺少全局视野,但至少回答稳定性更高。这是一个可接受的工程权衡,尤其当你需要高可用性时。
从实践到系统提升
跑通上述最小路径后,你可能会发现还有很多优化点,例如如何跨会话保存上下文模板、如何为不同任务(重构、调试、代码审查)切换不同的上下文策略。这些已经是进阶主题,单篇文章难以穷尽。
如果你的目标是脱离“调 API”式的使用,真正掌握如何设计 Agent 级的上下文闭环,建议进入更系统的学习路径:从环境搭建开始,到微调上下文注入策略,再到多 Agent 协作下的上下文共享机制。

暂无评论,快来发表你的见解吧