
「提示词工程」这个词流行了两年,近来越来越多人改说「上下文工程」。这不是换说法,是关注点真的变了。
## 为什么说法变了
提示词工程的隐含假设是:**有一个魔法咒语,写对了模型就变强。** 于是大家收集各种「你是一个资深 XX」的模板。
上下文工程的出发点是:**模型每次能看到的输入总量是有限的,你的活是把这个有限的空间分配给最该放进去的东西。**
前者是修辞问题,后者是资源调度问题。做应用做到一定规模,一定会碰到后者。
## 上下文是预算,不是仓库
一次调用能塞进去的东西包括:
- 系统提示词(角色、规则、输出格式)
- 工具定义(可用函数及其参数 schema)
- 检索回来的外部资料
- 历史对话
- 用户当前的输入
这些**共用同一个窗口上限**。塞满会截断,而截断往往发生在你最需要的位置。
更要命的是:每多一个 token,成本上升(见《大模型 API 的账怎么算》),延迟也会变长。**窗口越大不代表越该塞满——塞进去的东西如果无关,反而会干扰模型判断。**
这叫「大海捞针」问题:相关信息埋在一大堆无关内容中间,模型的注意力会被稀释,表现反而变差。
## 四条实践
**1. 把稳定的放前面,变化的放最后**
系统提示词、工具定义这些内容要固定不变,放在最前——顺带还能命中前缀缓存省钱。用户输入、检索结果这些每次都变,放最后。
**2. 工具定义要精简**
给智能体接十个工具,每个工具的详细 schema 加起来可能吃掉几千 token。如果其中七个这次根本用不上,那就是纯浪费。
按需加载工具定义,或者分层:常用工具常驻,冷门工具在需要时再注入。
**3. 历史要压缩,不是要保留**
多轮对话越往后越臃肿。定期把早期对话压缩成一段摘要:
```
[历史摘要] 用户正在配置一台新服务器的 SSH,
已完成:创建 deploy 用户、配置密钥、禁用密码登录。
当前目标:配置 fail2ban。
```
信息密度高得多,占用少得多。
**4. 检索结果要裁剪**
召回 10 条文档直接全塞进去是常见做法,但其中可能只有 2 条真正相关。先做重排(见《RAG 入门》),只取前几条;每条再截断到必要长度。
## 输出也是上下文的一部分
这一点常被忽略:**模型自己生成的东西也会占窗口。**
让模型「边想边说」地输出长篇推理,会把窗口填满,导致后面轮次可用空间骤减。
实践中可以:
- 限制单次输出长度;
- 要求结构化输出(JSON 而非散文);
- 长任务拆成多个短调用,每个调用只处理一小块。
## 一个判断标准
怎么知道上下文设计得好不好?看这个指标:
**把窗口里的每一段拿出来问一句——如果删掉它,模型这次还能完成任务吗?**
答「能」的,就该删。做几轮这样的减法,通常能砍掉一半以上的 token,效果还更好。
## 小结
从提示词工程到上下文工程,本质是从「怎么措辞」转向「怎么分配有限资源」。
具体做法其实就是四件事:稳定内容前置、工具按需加载、历史定期压缩、检索结果裁剪。都不复杂,但做与不做的差距,在长对话和复杂任务上会非常明显。
---
**延伸阅读**:本站另有《大模型 API 的账怎么算:token、上下文与缓存》和《RAG 入门:从切分到召回的一条完整链路》,可与本文对照。
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法