上下文工程
提示工程关乎你选择的词语。上下文工程关乎你交给模型的工作空间——里面有什么、顺序如何、以及你刻意省略了什么。
这个区别很重要,因为上下文窗口不是一张便笺纸。它是一种有限、昂贵、关乎注意力的资源。你如何填充它,会改变模型聚焦于什么、它让你付出多少成本,以及随着会话增长它是否还保持有用。
- 分清上下文工程和提示工程——并理解这个领域为何发生了转变
- 把上下文窗口当作注意力预算,而非储物箱
- 在上下文腐烂和“迷失在中间”毁掉一场长会话之前发现它们
- 把指令放在注意力真正落脚的地方——顶部、末尾,绝不埋在中间
- 运用三大主力战术:压缩、记笔记和即时检索
上下文预算
每个模型都有一个最大上下文大小——一个以 token 衡量的硬性上限。把它想象成一笔预算。你把它花在:
- 你的系统提示和常驻指令
- 检索到的文档、代码库片段、工具定义
- 对话历史
- 模型的输出(在多轮会话中,它同样要占用窗口)
当你用完时,总得有所取舍。要么旧内容被丢弃,要么会话撞上一堵墙。
大多数入门指南把上下文窗口当作“越多越好”。上下文工程把它当作一种需要谨慎分配的资源:把它花在模型这一轮真正需要的东西上,而不是花在一切可能相关的东西上。Anthropic 把整个学科框定为对“尽可能小的一组高信号 token”的求索——你添加的每一个 token 都在争夺有限的注意力预算,这是 transformer 把每个 token 与其他每个 token 相关联这一机制的直接后果。
上下文腐烂与“迷失在中间”
在长上下文 LLM 中有一个有据可查的现象:模型对靠近上下文开头和结尾的内容投入不成比例的注意力,而对埋在中间的内容回忆能力会退化。研究这一效应的学者称之为“迷失在中间”。
实际后果是:如果你往一个 10 万 token 的上下文里塞满文档,并把最关键的指令埋在第 60,000 个位置,模型可能实际上会忽略它——不是因为它读不到那么远,而是因为注意力并非在整个窗口上均匀分布。
“上下文腐烂”是更宽泛的模式:随着会话增长,回应的质量往往会漂移。早期指令被稀释。反复来回挤占了原始任务。模型开始含糊其辞、自我重复,或丢失了你真正所要求之事的线索。
这些不是你靠更好的提示就能彻底修复的 bug。它们是注意力在大规模下运作方式的结构性特性。工程上的应对之道是让上下文保持更小、更锐利,而不是把它填满然后寄希望于运气。
顺序很重要
你把内容放在哪里和你包含什么同样重要。公认的良好实践:
| 位置 | 该放什么 |
|---|---|
| 最顶部(系统提示) | 稳定、持久的指令。人设、规则、格式要求。 |
| 系统提示之后 | 当前任务,用直白的话说清楚。 |
| 紧挨着最后一次用户发言之前 | 针对这个确切请求的、最关键、最具体的上下文。 |
| 中间 | 支撑文档、检索到的片段——按相关性排序,而非按时间顺序。 |
| 对话历史 | 只保留维持连贯性所必需的内容。要积极裁剪。 |
总的规则是:越靠近当前这一轮,得到的注意力越多。只存在于长历史中段的关键指令是有风险的。
指令的“恰当海拔”
一个系统提示可能以两种相反的方式失败。太低,你就会硬编码出脆弱的、若此即彼的逻辑,一旦现实有所不同就崩溃。太高,你写出的就是含糊的指引,它假定了模型并不具备的上下文。Anthropic 把目标称为**“恰当海拔”**——那个恰到好处的区间,它“足够具体以有效引导行为,又足够灵活以提供强有力的启发式”。瞄准那里:具体的规则和示例,而不是一棵决策树,也不是一种氛围。
检索优于塞满
诱惑在于把一切都放进去:所有文档、整个代码库、整段对话。要抵制它。
更好的做法是选择性检索:识别模型为这个具体请求真正需要什么,并只注入那些内容。一段检索得当的、来自正确文档的 2,000-token 片段,胜过一份 40,000-token 的倾倒,因为后者的答案藏在中间某处。
这正是检索增强生成(RAG)存在的原因——不仅是为了克服上下文限制,更是通过保持上下文经过策划来提升质量。其智能体版本是即时检索:智能体不预先加载每一份文档,而是持有轻量级标识符(文件路径、ID、查询),只在需要的那一刻才把实际内容拉进上下文。
对于交互式会话,同样的逻辑也适用:不要积累一切,而要定期压缩或清空历史,以移除对当前任务不再相关的内容。Claude Code 的 /compact 和 /clear 命令是上下文工程工具,而不只是会话管理。在 API 上,同样的模式由记忆与上下文编辑自动完成——旧的工具结果从窗口中被裁剪掉,而重要的内容被写入一个持久的记忆存储。
三大主力战术
对于长周期工作,三种技术承担了大部分重活。它们可以叠加使用——大多数真实的智能体三者都用。
- 当一场会话接近窗口上限时,将其总结并用提炼后的版本重新初始化。保留承重的细节——架构决策、未解决的 bug、关键实现选择——并丢弃逐步流水账。这就是 Claude Code 中 /compact 所做的事。
- 让智能体把持久的事实写入一个外部记忆(一个文件、一个草稿本、一个 CLAUDE.md),稍后再读回来。这以极小的窗口内开销提供了持久记忆——这些笔记在需要之前都存在于预算之外。
- 不要预先塞满每一份文档。持有轻量级引用,并在运行时只为需要它的那一步加载实际内容。一次 2,000-token 的精准拉取胜过一份 40,000-token 的倾倒。
成本视角
你发送的 token 就是你付费的 token——既在金钱上,也在延迟上。用松散相关的材料塞满上下文会让两者都膨胀。上下文工程和成本效率是同一个问题。
更具体地说:
- 你从模板复制粘贴来的臃肿系统提示,会在每一次调用上被付费。
- 你因为“也许有用”而一路携带的旧对话历史,会在每一次调用上被付费。
- 你“以防万一”而注入的文档,会在每一次调用上被付费。
裁掉不需要存在的东西,既对质量更好,运行起来也更便宜。
给 Claude 用户的实用战术
在 Claude.ai 中:
- 为不同的任务使用不同的对话。别让一个下午的离题闲扯污染一个专注项目的上下文。
- 在问一个依赖于长线程的复杂问题之前,先把它总结一下。一份明确的摘要往往比原始历史更有用。
- 把你想要的具体东西放在长消息的末尾,而不是埋在中间。
在 Claude Code 中:
- 让你的
CLAUDE.md文件保持精简。其中的每一行都会被注入到每一次会话中。参见 CLAUDE.md 和上下文管理。 - 当切换到一个确实不同的任务时使用
/clear。当你想继续但会话正在变大时使用/compact。 - 当当前这一步并不需要完整文件时,用路径引用文件,而不是粘贴它们的内容。
在 API 层面:
- 设计系统提示,使其只包含每个请求都真正需要的内容。把任务专属的指令移到用户发言中。
- 对于文档密集的用例,检索并注入相关片段,而不是上传整个语料库。
- 把提示组织成稳定、可复用的前缀放在最前面——这也能启用提示缓存,它是上下文工程的天然伴侣。
当你想把一份长文档交给 Claude 时,位置规则每次都胜过单纯的体量:
指令在先,末尾重述
任务:找出本合同中每一处对我方责任设限的条款,并连同其条款编号逐字引用每一条。 [... 在此粘贴完整的 40 页合同 ...] 任务提醒:列出上面每一条责任限制条款,逐字精确引用,并附条款编号。如果一条都没有,请明确说明。
同一条指令既坐落在顶部又坐落在底部——这两个位置正是注意力所偏爱的——因此即便经过一段很长的中间,它也能存活下来。
心态的转变
提示工程问的是:“我该说什么?” 上下文工程问的是:“模型该看到什么、以什么顺序、以及我该刻意把什么挡在外面?”
第二个问题更难,但它才是真正在大规模下决定质量的那个问题。
Check yourself
0/3- 上下文窗口是注意力预算,不是存储——只把它花在高信号 token 上。
- 位置胜过体量:关键指令放在顶部和紧挨最后一轮之前,绝不埋在中间。
- 压缩、记笔记和即时检索是让长程智能体保持连贯的三大战术。
- 策划上下文与削减成本是同一根杠杆——更少的 token、更好的答案、更低的账单。