Context Engineering 上下文工程详解
Context Engineering,上下文工程,可以理解为 Prompt Engineering 的下一层:Prompt 关注“怎么把任务说清楚”,Context Engineering 关注“这次模型调用前,到底该把哪些信息放进上下文窗口”。
这也是为什么 RAG、Memory、Tools、Agent 这些东西看起来不一样,底层却经常绕回同一个问题:模型下一步要做对,眼前需要看到什么?
本文脉络:
- 一、为什么会从 Prompt Engineering 走到 Context Engineering
- 二、上下文工程到底是什么
- 三、Prompt、Context、RAG、Agent 的关系
- 四、上下文不是一段文本,而是一组分层信息
- 五、四个核心动作:写入、选择、压缩、隔离
- 六、RAG:最典型的上下文工程
- 七、Agent:动态上下文工程
- 八、上下文工程的常见失败模式
- 九、怎么评估上下文工程做得好不好
- 十、落地建议:从简单系统开始
- 十一、常见问题
一、为什么会从 Prompt Engineering 走到 Context Engineering
早期大家谈大模型应用,最常听到的是“提示词工程”。
这没错。因为模型每次生成,确实都要看输入。你把任务说得清楚一点,模型回答就更稳定一点。上一篇「提示词工程详解」里我们已经讲过:一个好 Prompt 要讲清目标、上下文、约束、输出格式和验收标准。
但真正做生产系统时,你很快会发现一个问题:
Prompt 写得再漂亮,如果该带的业务资料没带、该查的状态没查、该过滤的噪声没过滤,模型还是会答错。
比如你问一个客服 Agent:
这个用户为什么申请退款失败?
模型要答对,光靠一句“你是专业客服助手”没用。它至少需要看到:
- 当前用户是谁
- 订单状态是什么
- 支付渠道返回了什么错误
- 退款规则怎么写
- 用户历史沟通里有没有特殊承诺
- 哪些信息不能泄露
- 如果不确定,应该调用哪个工具继续查
这些信息不一定来自同一个地方。有的在用户输入里,有的在数据库,有的在知识库,有的在历史会话,有的是系统安全规则,有的是工具刚返回的结果。
于是问题从“怎么写一句好提示词”,升级成了:
怎么为每一次模型调用,动态组装一个刚刚好的上下文?
这就是 Context Engineering 要解决的问题。
二、上下文工程到底是什么
一个朴素定义:
上下文工程,是设计和构建一套机制,把正确的信息、以正确的格式、在正确的时刻,放进模型上下文窗口里。
这里有三个关键词。
正确的信息:不是越多越好,而是和当前任务有关。模型窗口再大,也不应该把一堆无关历史、重复文档、过期规则全塞进去。
正确的格式:同一份信息,用原文、摘要、表格、JSON、引用片段、工具返回结构,效果可能完全不同。
正确的时刻:不是所有信息一开始就带。Agent 执行到第二步、第三步时,真正需要的上下文可能已经变了。
所以 Context Engineering 不只是“往 Prompt 里加材料”。它更像一个信息调度系统:
| 问题 | 上下文工程要回答 |
|---|---|
| 带什么 | 当前任务需要哪些事实、规则、记忆、工具结果 |
| 不带什么 | 哪些内容过期、重复、无关、风险太高 |
| 怎么带 | 原文、摘要、结构化字段、引用片段、压缩结果 |
| 何时带 | 一开始带、按需检索、工具调用后回填、阶段性压缩 |
| 带完怎么验证 | 模型有没有用上,回答是否忠于证据 |
这也是它和传统 Prompt Engineering 的区别:Prompt Engineering 更像“写好一份任务说明”,Context Engineering 更像“搭一套任务现场的信息系统”。
三、Prompt、Context、RAG、Agent 的关系
你前面提到一个很关键的判断:RAG、AI Agent 本质上是不是在帮忙构建提示词?
答案是:它们确实都在构建模型可见的上下文,但不只是拼一段提示词。
可以用这张表理解:
| 概念 | 关注点 | 本质动作 |
|---|---|---|
| Prompt Engineering | 怎么写任务指令 | 手动组织目标、角色、约束、输出格式 |
| Context Engineering | 模型这次应该看到什么 | 动态组织指令、知识、记忆、状态、工具结果 |
| RAG | 从外部知识库取证据 | 检索、排序、截取、注入相关文档 |
| Memory | 让系统记住过去 | 保存、摘要、检索、更新历史信息 |
| Tools | 让模型接触外部世界 | 调用搜索、数据库、代码执行等工具并回填结果 |
| Agent | 多步规划与执行 | 持续更新目标、状态、观察结果和下一步上下文 |
所以更准确的说法是:
Prompt 是模型输入的一部分;Context 是模型这次能看到的完整信息环境;RAG、Memory、Tools、Agent 都是构建和更新 Context 的机制。
如果把一次模型调用想成一场会议,Prompt 是主持人说的任务说明,Context 是会议桌上所有资料:议程、背景文档、历史决议、实时数据、工具查询结果、不能违反的规则。
只会写 Prompt,就像主持人很会说话,但资料没准备好。
Context Engineering 则是在准备整张会议桌。
四、上下文不是一段文本,而是一组分层信息
很多人把上下文理解成“用户前面说过的话”。这太窄了。
在一个真实 AI 应用里,上下文通常至少有这些层:
| 层次 | 内容 | 常见来源 |
|---|---|---|
| 系统指令层 | 角色、安全边界、输出规范、工具规则 | 系统 Prompt、应用配置 |
| 用户任务层 | 当前问题、目标、输入、偏好 | 用户消息、表单、上传文件 |
| 检索知识层 | 文档片段、代码片段、引用证据 | RAG、搜索、知识库 |
| 记忆状态层 | 历史摘要、长期记忆、计划进度 | Memory、会话历史、项目状态 |
| 工具结果层 | 数据库查询、网页结果、命令输出 | Tools、MCP、函数调用 |
| 评估反馈层 | 是否答对、哪里失败、下一步修正 | Eval、人工反馈、日志 |
这里最容易出问题的是“层次混乱”。
比如把安全规则和用户输入混在一起,模型可能被用户输入覆盖;把检索证据和模型猜测混在一起,答案就容易看起来有依据,实际上在编;把工具结果原样塞回窗口,不做摘要和筛选,后面几轮上下文会越来越脏。
好的上下文工程,要让每一层信息有边界:
- 系统规则要稳定,不被用户内容轻易覆盖。
- 用户目标要清楚,不被历史信息淹没。
- 检索证据要有来源,不和模型推断混成一团。
- 工具结果要结构化,不把一堆日志直接倒进去。
- 记忆要可更新,不让旧结论长期污染新任务。
五、四个核心动作:写入、选择、压缩、隔离
LangChain 对上下文工程有一个很实用的拆法:write、select、compress、isolate。翻成工程语言,就是写入、选择、压缩、隔离。
| 动作 | 解决什么问题 | 例子 |
|---|---|---|
| 写入 | 哪些信息要保存下来 | 保存用户偏好、任务计划、工具观察结果 |
| 选择 | 当前调用该带哪些信息 | 从知识库取 Top K 文档,从记忆里取相关片段 |
| 压缩 | 信息太多时怎么变短 | 摘要长对话、提取日志关键行、合并重复证据 |
| 隔离 | 不同任务如何避免互相污染 | 子 Agent 独立上下文、工具结果单独区域、阶段性窗口 |
这四个动作听起来抽象,换到一个代码 Agent 就很好理解。
用户说:
帮我修复订单查询接口超时问题。
Agent 可能会这样做:
- 写入:记录当前目标是“修复订单查询超时”。
- 选择:读取订单查询相关文件,而不是整个仓库。
- 压缩:把长日志总结成“Redis timeout 后未降级”。
- 隔离:把测试输出、代码 diff、历史计划分开放,避免混在回答正文里。
最终模型看到的不是“整个项目 + 全部聊天记录”,而是一个经过整理的工作现场。
这就是上下文工程的价值。
六、RAG:最典型的上下文工程
RAG 是最容易理解的 Context Engineering。
用户问:
公司退款规则是什么?
模型自己并不知道你公司的最新规则。RAG 会先从知识库里检索相关文档片段,再把片段放进上下文,让模型基于证据回答。
一个 RAG 系统本质上要做这些上下文决策:
| 环节 | 上下文问题 |
|---|---|
| Query rewrite | 用户问题要不要改写成更适合检索的查询 |
| Retrieval | 该从哪些库、哪些字段里找资料 |
| Rerank | 哪些片段更相关,应该排在前面 |
| Truncation | 文档太长时截哪一段 |
| Citation | 回答时要不要带来源 |
| Faithfulness check | 答案有没有忠于证据 |
所以 RAG 不是简单的“搜几段文档塞给模型”。
低质量 RAG 经常犯三个错:
- 召回太少:关键证据没进上下文。
- 召回太多:噪声文档把模型带偏。
- 证据不清:模型分不清哪些是事实,哪些只是相似内容。
如果你读过本博客的「RAG 系统如何评估:Recall、Faithfulness、RAGAS 与 LLM-as-Judge」,会发现 RAG 评估的很多指标,本质上也在评估上下文工程:有没有找回关键证据,答案有没有忠于证据,检索内容有没有帮助模型答到点上。
七、Agent:动态上下文工程
如果说 RAG 是“一次调用前构建上下文”,Agent 就是“多步执行中持续重建上下文”。
Agent 每走一步,环境都会变:
- Planner 生成了计划。
- Executor 执行了命令。
- Tool 返回了新结果。
- 某一步失败了。
- 用户中途补充了新要求。
- Memory 找到了过去的相关经验。
这些变化都要进入下一次模型调用,但不能全量硬塞。
一次典型闭环如下:
Agent 场景里,上下文工程尤其重要,因为错误会累积。
第一步带错文件,第二步就会基于错文件分析;第二步误读工具结果,第三步就会做错决策;历史计划不压缩,后面窗口就会越来越拥挤。
这也是为什么很多 Agent 不是“模型不够聪明”,而是上下文管理很差:
- 该记的没记住。
- 不该带的一直带着。
- 工具结果没有结构化。
- 历史失败没有进入下一步判断。
- 子任务互相污染。
Agent 的核心能力之一,就是动态维护“下一步需要看到的最小充分上下文”。
八、上下文工程的常见失败模式
上下文工程做不好,模型的表现会很像“忽聪明忽糊涂”。常见失败模式有这些:
| 失败模式 | 表现 | 解决方向 |
|---|---|---|
| 上下文缺失 | 模型答得泛泛而谈,缺少业务事实 | 增加检索、工具调用、必要输入检查 |
| 上下文污染 | 模型被无关历史或错误文档带偏 | 过滤过期信息,给来源和时间戳 |
| 上下文过载 | 回答变散,重点丢失 | 压缩、分阶段、只带当前步骤相关内容 |
| 指令冲突 | 系统规则、用户要求、文档内容互相打架 | 明确信息优先级,隔离不可信输入 |
| 工具结果误读 | 明明查到了数据,结论却错 | 结构化工具输出,增加字段说明和单位 |
| 记忆陈旧 | 模型一直沿用旧偏好或旧结论 | 给记忆过期机制和更新策略 |
| 缺少评估 | 不知道上下文是否真的有效 | 建评估集,看召回、忠实度、任务成功率 |
其中最隐蔽的是上下文污染。
很多人以为“多给点资料总没坏处”。但对模型来说,资料太多且质量参差不齐时,它不一定知道哪条更可靠。旧规则、新规则、用户猜测、工具事实混在一起,模型很容易挑一个看起来顺眼的说法。
生产系统里,宁可少带一些但可信、相关、结构清楚的信息,也不要把一堆可能有用的材料全倒进去。
九、怎么评估上下文工程做得好不好
上下文工程不是靠感觉调。
至少要看四类指标:
| 指标 | 问什么 |
|---|---|
| Context Recall | 关键证据有没有进入上下文 |
| Context Precision | 带进去的信息有多少是真的相关 |
| Faithfulness | 回答是否忠于上下文证据 |
| Task Success | 用户任务最终有没有完成 |
如果是 RAG,还可以补充:
- 检索 Top K 命中率
- 引用准确率
- 无答案识别能力
- 长文档下的召回稳定性
如果是 Agent,还要看:
- 每一步是否带了正确状态
- 工具结果是否被正确解释
- 失败后是否能把失败原因带入下一轮
- 子任务之间是否互相污染
- 最终动作是否符合权限边界
一个实用做法是保留“上下文快照”。
也就是每次模型调用时,记录当时窗口里有哪些系统指令、用户输入、检索片段、工具结果和历史摘要。出错时不要只看最终回答,要回看当时模型到底看见了什么。
很多线上问题一看上下文快照就很清楚:
- 关键文档没召回。
- 召回的是旧版本。
- 工具结果单位是毫秒,模型当成秒。
- 用户要求被历史摘要覆盖。
- 系统安全规则排在太后面,被长文档冲淡。
没有上下文快照,调试 Agent 会非常痛苦。
十、落地建议:从简单系统开始
如果你要在项目里引入 Context Engineering,不建议一开始就做很复杂的 Agent 记忆系统。
可以按这个顺序来:
| 阶段 | 目标 | 做法 |
|---|---|---|
| 1. 固定模板 | 让任务说明稳定 | 把角色、目标、约束、输出格式模板化 |
| 2. 检索注入 | 让模型基于外部知识回答 | 做基础 RAG,保留引用和来源 |
| 3. 结构化工具结果 | 让工具反馈可读可靠 | 工具返回 JSON,字段含义写清楚 |
| 4. 历史摘要 | 控制长会话成本 | 定期摘要,只保留决策和未完成事项 |
| 5. 动态选择 | 按任务选择上下文 | 按意图、阶段、权限选择不同上下文 |
| 6. 评估闭环 | 知道改动是否有效 | 建样例集,记录上下文快照和失败原因 |
这里有个很实在的建议:先把上下文做可观测,再谈优化。
你至少应该能回答:
- 这次模型调用带了哪些文档?
- 这些文档为什么被选中?
- 有没有被压缩或截断?
- 工具返回了什么?
- 历史摘要从哪里来?
- 最终答案引用了哪些证据?
如果这些都看不见,上下文工程就会变成新的玄学。
十一、常见问题
| 问题 | 回答要点 |
|---|---|
| Context Engineering 是不是 Prompt Engineering 的新名字? | 不是。Prompt Engineering 更关注指令怎么写;Context Engineering 关注完整上下文系统怎么构建,包括检索、记忆、工具结果、状态和评估。 |
| RAG 属于上下文工程吗? | 属于。RAG 的核心就是把外部知识检索出来,并以合适形式注入模型上下文。 |
| AI Agent 本质上是不是一直在构建上下文? | 很大程度上是。Agent 每一步都要根据目标、计划、工具结果和历史状态重建下一步上下文。 |
| 上下文越多越好吗? | 不是。更多上下文可能带来噪声、冲突、成本和注意力稀释。关键是相关、可信、结构清楚。 |
| 长上下文模型会让上下文工程消失吗? | 不会。窗口变大只能缓解容量问题,不能自动解决信息选择、优先级、可信度、过期和隐私问题。 |
| 怎么知道上下文带对了? | 看关键证据召回、上下文相关性、答案忠实度和任务成功率。最好记录每次调用的上下文快照。 |
| 上下文工程最容易忽略什么? | 工具结果和历史记忆的质量。很多系统检索做得不错,但工具输出混乱、记忆陈旧,最后照样答错。 |
最后用一句话收束:
Prompt Engineering 让你把问题问清楚;Context Engineering 让模型在回答问题前,真的站在正确的信息现场里。
对真实 AI 应用来说,后者往往才是分水岭。