Context Engineering:从 Prompt 到上下文的范式升级
Prompt 写再花,context 塞错了也是白搭——模型读的不是你的「文采」,而是你允许它看见的那一小片世界。
这篇文章会讲什么
如果你已经会写 System Prompt、会做 RAG、会接 Tool,但线上效果仍像「抽盲盒」,问题往往不在某一句措辞,而在整段上下文是否被正确设计:哪些信息该进窗口、以什么顺序、占多少 token、何时压缩。
本文把 Context Engineering 从口号落到表格、流程和 budget 数字上,并说明它与 Prompt Engineering、窗口管理、RAG、Agent Memory 的分工。读完你能用同一套语言跟团队对齐「我们到底在给模型看什么」。
先说结论:Context Engineering 关心的不是“喂更多”,而是“喂对、喂准、喂得起”
很多人第一次听到 Context Engineering,会把它理解成先看定义:
不就是 Prompt Engineering 的新名字吗?
这理解不算全错,但明显不够。更准确地说,Prompt 只是上下文里的一个模块;而 Context Engineering 要处理的是整条输入链路:
- 什么信息应该进来
- 什么信息不该进来
- 哪些模块优先级更高
- 哪些结果只能做“证据”,不能当“规则”
- 当预算不足时先删谁
所以它真正优化的不是「文本措辞」,而是信息装配系统。
如果把 Prompt 看成一句台词,那 Context Engineering 管的是:
这一幕到底哪些角色上场、谁先说、谁闭嘴、总时长多长。
这也是为什么 2025–2026 年它会变成高频词:模型越来越强后,很多线上问题已经不是“模型不懂中文”,而是“系统把错的东西喂进去了”。
延伸阅读
- Andrej Karpathy — 个人站点与文章 —— Karpathy 近年多次强调:应用侧真正的杠杆往往在于喂给模型的上下文,而非单句 prompt 技巧(可结合其公开演讲与 newsletter 文章一起读)。
- Lost in the Middle: How Language Models Use Long Contexts(Liu et al., 2023)—— 长上下文里信息位置对利用率的系统研究,直接支撑「不是塞满就好」。
- Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks(Lewis et al., 2020)—— RAG 经典论文:检索结果作为可替换的 context 模块。
- LLMTest_NeedleInAHaystack(Greg Kamradt)—— 「针在干草堆」压力测试的可复现实现,用于评估长上下文中的事实召回。
- MemGPT: Towards LLMs as Operating Systems(Packer et al., 2023)—— 分层记忆与上下文编排的代表性工作,和 Agent Memory 强相关。
1. 什么是 Context Engineering
先看定义:Context Engineering 是系统性地决定哪些信息进入模型上下文、以何种结构与优先级呈现的工程学科;它把「会说话」升级为「会喂料」。
2025–2026 年,产业界与开源社区的热词从「Prompt Engineering」扩散到 Context Engineering,背后原因很简单:模型能力上来了,瓶颈更多出现在信息编排——系统提示、检索块、工具输出、会话历史、用户画像是否在同一窗口内互相打架或淹没关键事实。
Andrej Karpathy 等实践者的共同观察可以概括成一句:单条 prompt 的「文笔」边际收益在下降,而「上下文设计」的边际收益在上升。这不是否定 Prompt Engineering,而是把焦点从一句话扩成整条输入管线。
| 维度 | 2023 典型关注点 | 2026 典型关注点 |
|---|---|---|
| 优化对象 | 单条指令措辞 | 多源信息的结构与优先级 |
| 失败归因 | 「模型不懂我」 | 「模型没看到该看的 / 看到了噪音」 |
| 工程化 | 文档与模板 | pipeline、监控、预算、回滚 |
2. Prompt Engineering vs Context Engineering vs Context Window Management
先看定义:三者分别回答 怎么说、塞什么、能塞多少与怎么截;前两者是「内容与表达」,第三者是不可违背的物理与产品约束。
定义对照
| 概念 | 核心问题 | 典型手段 |
|---|---|---|
| Prompt Engineering | 措辞、格式、指令怎么写模型才稳 | 角色、Few-shot、CoT、JSON 约束、否定式规则 |
| Context Engineering | 系统提示、检索、工具、历史、环境信息如何编排进同一次请求 | 模块顺序、schema、RAG 策略、tool loop、画像注入 |
| Context Window Management | Token 上限下如何截断、摘要、分级保留 | 滑动窗口、摘要压缩、优先级队列、动态 budget |
三者关系(集合与约束)
- Prompt Engineering ⊂ Context Engineering:措辞与格式是上下文的一部分(尤其是 System / Developer 层),但不是全部。
- Context Window Management 是 Context Engineering 的硬约束:再优雅的编排也不能突破窗口;管理策略决定「哪些模块先被牺牲」。
- 类比:Prompt 像台词;Context Engineering 像整场戏的剧本结构;Window Management 像演出时长——超时就得删场次。
总对比表
| 维度 | Prompt Engineering | Context Engineering | Context Window Management |
|---|---|---|---|
| 关注点 | 表达与指令设计 | 信息来源与编排 | 长度、位置、截断与压缩 |
| 输入 | 用户意图 + 写作约束 | 多源原始信号(检索、工具、DB…) | 各模块 token 计数、模型上限 |
| 输出 | 更可执行的文本指令 | 结构化、可复现的「最终 messages」 | 不超窗的可行方案 |
| 难度 | 中(强依赖经验与评测) | 高(系统 + 数据 + 产品) | 中高(算法与监控) |
| 2026 状态 | 基础能力,模板化成熟 | 主战场:与 Agent、RAG 深度绑定 | 随长上下文模型演进,但「长≠全可靠」仍是共识 |
3. Context Engineering 的核心组件
先看定义:把一次请求想成 乐高:System、User、检索、工具、历史、环境都是标准块,工程化的是拼装顺序与连接件。
组件一览
| 组件 | 典型内容 | 你在工程里常犯的错误 |
|---|---|---|
| System Prompt | 角色、合规红线、输出 schema、工具使用 policy | 写太长占满预算,或规则互相矛盾 |
| User Input | 当前用户原始问题 / 指令 | 未做意图分层,复杂任务与闲聊同一套管线 |
| Retrieved Context | RAG 片段、知识库 chunk、FAQ | 检索到即信任,不做重排与过滤 |
| Tool Results | API JSON、SQL 结果、代码执行输出 | 原样 dump,超大 JSON 撑爆窗口 |
| Conversation History | 多轮 user/assistant | 平铺全历史,早期轮次淹没当前意图 |
| Environment / State | 时区、locale、user_id、会员等级、会话级 flags | 与合规相关的状态未进 context,导致越权 |
来源、更新频率与优先级(示例基线)
下列「优先级」指默认预算紧张时先保留谁(具体业务可调整,但需显式文档化)。
| 组件 | 常见来源 | 更新频率 | 默认优先级(高→低) |
|---|---|---|---|
| System Prompt | 产品 / 合规 / Prompt 版本库 | 低频(发版) | ★★★★★ |
| User Input | 用户当前消息 | 每次请求 | ★★★★★ |
| Tool Results | 工具层执行 | 每次调用 | ★★★★☆ |
| Retrieved Context | 向量库 / 图 / 搜索引擎 | 每次检索 | ★★★☆☆ |
| Conversation History | 会话存储 | 每轮追加 | ★★★☆☆ |
| Environment / State | 网关、账户、实验系统 | 中频 | ★★★★☆(涉及权限时与 System 同级) |
不是所有上下文都该被“同等相信”
先看定义:Context Engineering 不只是「把东西塞进去」,还要定义「模型该把谁当规则、把谁当证据、把谁当噪音源」。
真实系统里,不同模块的可信级别并不一样:
| 信息源 | 默认角色 | 典型风险 | 处理原则 |
|---|---|---|---|
| System / Developer 指令 | 规则与边界 | 过长、冲突、版本漂移 | 版本化、精简、冲突测试 |
| User Input | 当前意图 | 越权、注入、误导 | 风险分类、权限绑定、必要时重写 |
| Retrieved Context | 外部证据 | 检索错、过时、断章取义 | rerank、来源标记、版本过滤 |
| Tool Results | 强事实来源 | 原始输出过大、HTML/日志注入 | 解析、裁剪、结构化再注入 |
| History | 连贯性材料 | 旧设定污染当前任务 | 摘要、过期、只保留决策事实 |
| Environment / State | 权限与运行态 | 漏注入导致模型乱猜 | 关键字段常驻或高优先级注入 |
这点在 Agent 场景尤其重要:工具返回结果不等于天然安全。例如浏览器抓下来的网页、日志系统返回的报错、工单系统里的用户留言,都可能带新的提示注入片段。如果你把这些原文不加区分地回填给模型,系统就在主动把外部噪音升级成“内部上下文”。
4. Context Budget 分配策略
先看定义:Token 是零和博弈;Budget 的目标不是用满窗口,而是在上限内最大化「可决策信号 / token」。
静态优先级(多数 B 端场景的起点)
经验法则(需用自家数据校准):
- System —— 规则与输出契约
- User Input —— 当前意图
- Tool Results —— 事实与可验证依据(已发生调用时)
- Retrieved Context —— 外部知识
- History —— 辅助连贯性,往往最先被摘要或截断
动态分配
| 场景 | 策略 |
|---|---|
| 单轮简单问答 | 压缩检索条数;历史可省略 |
| 多步 Agent | 保留最近 k 轮 + 关键 tool 摘要;中间步骤可折叠 |
| 长文档分析 | 先摘要或分块多次调用,而不是单次塞全文 |
压缩三件套
- 摘要:对历史或长工具输出做模型或规则摘要(注意摘要损失合规细节时要留原文锚点)。
- 截断:按优先级从低模块砍;同一模块内按相关性截断(配合 rerank)。
- 选择性注入:仅当意图分类器判断「需要知识库」时才挂 RAG。
示例:假设可用 1M token 上下文(模型级)
现实产品很少真把 1M 用满——成本高、延迟大、且长上下文利用并不均匀。下面是一组示意性分配(单位:千 token),用于团队对齐「量级感」:
| 模块 | 保守配比(千 tok) | 说明 |
|---|---|---|
| System + 合规 + schema | 2–8 | 再长要警惕稀释用户意图 |
| User Input + 结构化槽位 | 1–4 | 复杂表单可更大 |
| Tool Results(含中间态) | 10–200 | 大 JSON 必须管道压缩 |
| Retrieved Context | 8–120 | 由 top-k 与 chunk 尺寸决定 |
| History / 摘要 | 4–80 | 随多轮增长,优先摘要而非全量 |
| 预留缓冲 | ≥5% 总预算 | 给重试、函数调用开销、安全后缀 |
关键:1M 是「上限」不是「目标」;Latency 与费用通常先于「塞满」成为瓶颈。
更接地气的预算:32K / 128K 怎么分
大多数团队日常真正能稳定承受的,往往不是 1M,而是 32K / 128K 量级。下面这张表更适合做首版预算讨论:
| 可用窗口 | System + 规则 | User + 槽位 | 检索 / 工具 | 历史 / 摘要 | 缓冲 |
|---|---|---|---|---|---|
| 32K | 1–2K | 1K | 8–16K | 4–8K | 2K |
| 128K | 2–4K | 1–2K | 20–60K | 10–30K | 4–8K |
如果你发现 system prompt 已经 8K、历史 20K、检索还想塞 30K,那问题往往不是「窗口不够大」,而是系统边界没拆干净:有些规则该下沉到代码,有些历史该摘要,有些检索根本不该发生。
5. Context Quality > Context Quantity
先看定义:多塞一段无关文本,不仅浪费 token,还可能误导注意力——长窗口没有消灭「找不着针」问题,只是换了战场。
Needle in a Haystack
公开基准(如 Kamradt 的 needle 测试)表明:即使上下文很长,模型对中间区域的事实召回仍可能弱于两端——与 Lost in the Middle 的观察一致。因此:关键证据要靠近高注意力区域或重复结构化呈现(在合规允许前提下)。
信息密度 vs 噪音
| 现象 | 后果 | 对策 |
|---|---|---|
| 检索返回大量边缘文档 | 正确答案被淹没 | 提高阈值、metadata 过滤、rerank |
| 工具返回整页 HTML | 有效信号极低 | 解析、抽取字段、表格化 |
| 历史对话重复赘述 | 占用 budget | 滚动摘要 + 只保留决策级事实 |
检索质量 > 检索数量
线上常见误区是「top-k 加大总好一点」。更稳的路径通常是:更小的高质量候选集 + 强 rerank + 解释性过滤(例如仅某产品线的文档)。Context Engineering 在这里与 RAG 工程质量完全重叠:embedding、chunk、索引、rerank、query 改写,全是上下文质量的上游。
6. 实战:Context Engineering Pipeline
先看定义:把管线画成图,团队才能对齐「用户一句话」到「最终 messages」之间到底发生了什么。
端到端流程(示意)
flowchart LR
A[System Prompt] --> F[Context Assembly]
B[User Input] --> F
C[Retrieved Context] --> F
D[Tool Results] --> F
E[History / State] --> F
F --> G[Budget & Ordering]
G --> H[Model]
H --> I[输出质量]
示例:企业客服系统
业务约束:售后政策强合规;不同会员等级话术不同;需对接工单与物流查询。
编排要点:
- System:固定角色 + 退款规则摘要 +「不得编造工单状态」+ 输出必须含「处理单号占位说明」。
- Environment:
user_tier、locale、business_hours注入,避免模型猜。 - Retrieved Context:仅检索「当前产品类目 + 当前政策版本」下的 chunk;附
doc_id便于审计。 - Tool Results:
get_ticket、track_shipment返回 JSON;入窗前压缩为表格化短字段。 - History:保留最近 3 轮原文 + 更早的摘要;摘要由独立小模型或规则生成并版本化。
伪代码:组装器骨架
def build_messages(user_text, session, env, retriever, tools):
sys = render_system(env) # 含合规与会员规则
hist = session.recent_turns(k=3) + session.summary_blob()
docs = retriever.query(user_text, filters=env.product_line) if needs_rag(user_text) else []
docs = rerank(docs)[:6]
chunks = [
("system", sys),
("user", format_user(env, user_text)),
]
if docs:
chunks.append(("user", wrap_docs(docs))) # 结构化包裹,防串台
chunks.extend(hist)
messages = normalize_to_provider_format(chunks)
messages = budget_trim(messages, max_tokens=session.budget)
return tool_loop(messages, tools) # 内部再回填 tool results 并可能二次 trim
这条管线最常见的失败模式
先看定义:线上效果差,很多时候不是模型「能力不够」,而是装配线上某一步悄悄把信号变成了噪音。
| 失败模式 | 现象 | 常见根因 | 修法 |
|---|---|---|---|
| 规则被历史稀释 | 模型忽然不按格式输出 | System 太长、历史太多、顺序混乱 | 精简规则、提高 System 优先级、测位置敏感性 |
| 检索命中但没被用上 | 明明查到了,回答仍胡说 | chunk 太长、关键句埋中间、无 rerank | 短 chunk + rerank + 证据前置 |
| 工具输出污染上下文 | 调完工具后风格和结论开始跑偏 | 原始 HTML/日志/用户内容被直接回填 | 解析后仅保留字段级结果 |
| 会话越长越“失忆” | 前几轮约定消失 | 没有摘要机制,纯滑动窗口 | 决策级摘要 + 关键状态结构化 |
| 某些用户稳定翻车 | 同问题在不同用户表现差异大 | 环境状态、权限、语言偏好没进窗 | 将关键状态显式注入并可观测化 |
7. Context Engineering 的评估
先看定义:没有指标,就没有迭代;至少要同时看 「找不找得到」 与 「别乱来」。
| 层级 | 评什么 | 示例做法 |
|---|---|---|
| 检索 / 注入 | 相关 chunk 是否进窗 | nDCG、Recall@k;人工标注「必要证据是否出现」 |
| 端到端任务 | 业务 KPI | 一次解决率、人工转接率、合规触发率 |
| 长上下文鲁棒 | 关键事实是否可被定位 | Needle 类测试;对抗性中间位置插入 |
| 成本与延迟 | 是否 over-context | p95 token、费用、超时率 |
注意:单独测「模型写作能力」无法替代 context 评测;很多失败是证据没进窗或噪音过多,微调 prompt 也救不了。
一个很有用的工程方法是做 ablation(消融):固定模型与解码参数,只替换一个模块,例如:
- 去掉历史,看任务完成率掉多少;
- 检索从 top-8 改成 top-4,看忠实度是否反而上升;
- 工具结果从原始 JSON 改成结构化摘要,看延迟和正确率是否一起改善。
如果你没做过这种对比,就很容易把所有问题都怪到「模型不够聪明」上。
8. 与 RAG、Agent Memory 的关系
先看定义:RAG 解决「知识从哪来」,Agent Memory 解决「状态存哪」,Context Engineering 解决「此刻让模型读哪一段」——三者拼接才构成系统智能。
| 主题 | 与 Context Engineering 的关系 |
|---|---|
| RAG | 检索结果是 context 的可变模块;RAG 工程质量直接决定该模块的信噪比。参见 RAG 原论文。 |
| Agent Memory | 长期记忆在向量库 / 图 / 关系库中;只有被选中并格式化注入的那部分,才进入 context。分层架构可参考 MemGPT。 |
| Tool use | 工具输出是强事实源,通常优先级高于泛泛检索,但需要防注入与体积控制。 |
一句话总结关系:RAG / Memory 是仓库;Context Engineering 是出库单与装箱单。
常见误区
| 误区 | 为什么不对 |
|---|---|
| Context Engineering = Prompt Engineering 升级版 | 它不只改措辞,还管检索、工具、历史、状态、budget 和评估 |
| 窗口够大就不用做编排了 | 长上下文仍有 Lost in the Middle、成本、延迟和噪音问题 |
| top-k 越大越稳 | 更多候选常常意味着更多干扰,不等于更多有效证据 |
| 只要接了 RAG 就算做了 Context Engineering | RAG 只是一个模块,真正难的是和规则、工具、历史一起协同 |
核心概念速查
| 概念 | 一句话 |
|---|---|
| Context Engineering | 系统设计「哪些信息以何结构进入模型上下文」 |
| Prompt Engineering | 优化「怎么说」的指令与格式,是上下文子集上的工作 |
| Context Window Management | 在 token 上限下做截断、摘要与优先级,是硬约束 |
| Context Budget | 各模块 token 配额与动态策略,目标是信噪比而非用满窗口 |
| RAG | 用检索结果扩展模型可见知识,是上下文的一类「可插拔模块」 |
| Agent Memory | 持久化状态 + 选择性注入,服务于跨轮与跨会话任务 |