上下文工程导论:从提示词到系统设计
第 1 章 上下文工程导论:从提示词到系统设计
当 LLM 应用的复杂度从"单轮问答"演进到"自主多智能体协作","上下文"这一概念的内涵发生了根本变化——它从一段静态的输入文本,演化为一个动态、多源、有状态的信息流。管理这一信息流的难度,已经远远超出了传统提示词工程的范畴。理解这一演化的内在逻辑,是建立系统化上下文工程思维的起点。
1.1 LLM 应用范式演化与上下文瓶颈的形成
LLM 应用在过去三年经历了五次显著的范式跃迁,每一次跃迁都重新定义了"上下文"的边界与工程挑战。
第一阶段:单轮提示(2022 年至 2023 年上半年)
ChatGPT 的爆发让"提示词工程"成为显学。此时的应用范式极其简单:用户输入一段文本,模型输出回复。上下文就是用户输入本身,外加一段静态的系统提示。工程师的全部工作集中在文本本身的措辞优化——调整角色设定、加入 few-shot 示例、改进思维链引导。
这一阶段的工程假设是"模型每次推理相互独立"。历史信息可以被丢弃,状态可以被忽略。整个系统的瓶颈在于"如何让单次推理更准确",而非"如何管理跨次推理的信息"。
第二阶段:多轮对话与初步的会话状态(2023 年)
GPT-4、Claude 2 等模型上线后,长达数十轮的对话成为可能。新的工程问题迅速浮现:会话历史如何累积?早期轮次的内容如何在不超出窗口的前提下保留?历史中的错误如何不污染后续推理?
这一阶段出现了第一批上下文管理工具:滑动窗口(只保留最近 N 轮)、周期性摘要(每 K 轮压缩一次)、关键信息抽取(用模型提取实体与事实)。这些工具标志着"上下文"从文本问题转变为数据管理问题。但此时的工具仍然是"补丁式"的,缺乏系统性的设计原则。
第三阶段:检索增强生成与外部知识接入(2023 年至 2024 年)
企业级应用落地后,模型参数化的静态知识已无法满足业务需求。RAG 架构成为标准方案:检索器从向量数据库或搜索引擎拉取相关文档,组装进模型的输入。
此时上下文的构成显著复杂化:系统提示 + 用户当前输入 + 会话历史 + 检索片段 + few-shot 示例 + 工具定义。每一个组件都有独立的优化目标——检索要精准、排序要合理、压缩要不失真、组装要符合注意力偏好。提示词工程对此束手无策,需要的是一套端到端的上下文组装流水线。
第四阶段:智能体与持续运行的状态(2024 年至今)
AutoGPT、Devin、各类 Coding Agent、Research Agent 的涌现把上下文问题推到了临界点。一个智能体可能连续运行数百步,每一步都涉及调用工具、接收返回、执行推理、生成下一步规划。上下文不再是简单的"历史累积",而是整个执行轨迹的结构化快照。
此时上下文的典型构成包括:
- 系统提示与角色定义
- 工具 schema 与可用工具列表
- 长期记忆(跨会话的事实与偏好)
- 工作记忆(当前任务相关的中间结论)
- 执行历史(过去的动作与观察)
- 当前观察(最新的工具返回)
- 下一步规划与候选动作
这个"上下文"已经等同于"系统状态"。它需要被精心地增、删、改、压缩、结构化——而不是简单追加。提示词工程的边界被远远超越。
第五阶段:多智能体协作(2025 年及展望)
多个智能体协同完成复杂任务时,上下文问题进一步复杂化。每个智能体都有自己的私有上下文(私有记忆、专属工具),同时又需要与其它智能体共享部分信息(任务进度、中间产物、协调信号)。多智能体系统的本质是分布式状态机,"上下文"则是每个智能体在每一时刻能看到的局部视图。
这一阶段,上下文工程不仅是单机问题,更是分布式系统问题——涉及一致性、最终一致性、消息传递、冲突解决等经典分布式概念。
```mermaid flowchart TD A[单轮提示 2022] --> B[多轮对话 2023] B --> C[RAG检索增强 2023-2024] C --> D[单智能体 2024] D --> E[多智能体协作 2025+]
A --> F[静态Prompt优化 / 文本层] B --> G[会话历史管理 / 上下文工程1] C --> H[检索与重排序 / 上下文工程2] D --> I[状态机与压缩 / 上下文工程3] E --> J[分布式状态管理 / 上下文工程4] ```
从五次范式跃迁可以看出清晰的趋势:上下文从"用户文本"演化为"系统状态",从静态演化为动态,从单一来源演化为多源融合。相应地,管理上下文的难度从"写好一句话"升级为"维护一个分布式系统的局部视图"。这就是"上下文工程"作为独立学科出现的根本原因。
1.2 提示词工程、上下文工程与智能体工程的边界
在工程实践中,"提示词工程"(Prompt Engineering)、"上下文工程"(Context Engineering)、"智能体工程"(Agent Engineering)三个术语经常被混用。它们实际上指代了三个不同层级的工作,建立清晰的边界是构建系统化思维的前提。
提示词工程:文本层的微观优化
提示词工程的核心对象是单次推理的输入文本。它的优化目标是:在给定的上下文窗口预算内,调整文本的措辞、结构、示例、角色设定,使模型的输出尽可能符合预期。
典型的提示词工程技巧包括:角色扮演("你是一位资深律师")、思维链引导("让我们一步步思考")、few-shot 示例组织、自一致性提示、ReAct 框架的文本模板。这些技巧的本质是"在不改变输入信息的前提下,让模型更准确地理解任务"。
提示词工程的隐含假设是:输入文本是一个相对静态、可控的产物。在单轮对话场景下,这个假设成立。但在多轮对话、RAG、Agent 场景下,输入文本由系统动态组装,提示词工程师无法控制其中的检索片段、工具历史、压缩摘要等内容。
上下文工程:组装层的系统设计
上下文工程的核心对象是单次推理输入文本的组装过程。它的优化目标是:决定哪些信息进入上下文窗口、以何种结构呈现、占用多少 token、如何排序、如何压缩。
上下文工程关注的是一组相互耦合的工程问题:在有限的 token 预算下应该包含哪些信息?当信息超出预算时按什么策略压缩?检索出的多条片段如何排序以最大化注意力效率?工具调用历史以何种粒度保留?不同类型的上下文(指令、记忆、检索、历史)如何分层?
可以用一个类比来描述:提示词工程是"写好一句话的措辞",上下文工程是"设计一栋建筑的房间布局"。前者关心"既有的内容如何表述",后者关心"内容如何被组织与取舍"。
智能体工程:编排层的架构规划
智能体工程的核心对象是整个感知-规划-行动循环。它的优化目标是:让智能体在环境中高效地完成目标。
智能体工程关注的是更高层的问题:智能体如何拆解复杂任务?应该调用哪些工具、何时调用、以何种顺序?如何从工具返回中提取有用信息?如何处理工具失败、超时、异常?如何在多步推理中避免循环、保持目标?如何让多个智能体协同?
智能体工程的边界在于:它假设"上下文组装"已经被处理好。智能体工程师通常不关心一段摘要应该怎么写、一个检索片段应该怎么排序——这些是上下文工程师的工作。但智能体工程师需要知道:上下文窗口的限制、能容纳的工具数量、压缩策略的触发条件。
三层关系的同心圆模型
可以用同心圆来描述三者的关系:
- 内层:提示词工程——文本层的微观优化
- 中层:上下文工程——组装层的系统设计
- 外层:智能体工程——编排层的架构规划
每一层都是上一层的必要不充分条件:没有好的提示词,上下文工程再精妙也可能浪费 token;没有好的上下文组装,智能体工程再聪明也无法让模型看到关键信息;但即便前两层都做对了,智能体层的规划与编排仍然决定任务能否完成。
实践中的两类典型误区
第一类误区是把"提示词工程"等同于"上下文工程"。很多团队花费数周时间打磨 system prompt 的措辞,但忽略了对检索质量的优化、对历史压缩策略的设计、对工具调用结果的过滤。这种"提示词崇拜"在单轮场景下有效,但在 Agent 场景下会让整个系统的脆弱性暴露无遗。当生产环境出现故障时,团队往往归因于"模型不够聪明",但真正的根因往往是"模型没有看到关键信息"。
第二类误区是把"上下文工程"简化为"压缩"。压缩只是上下文工程的四大支柱之一,而不是全部。一个完整的上下文工程体系还应该包括:长上下文建模(让模型能处理更大窗口)、检索系统(按需调入外部知识)、状态管理(维护多步执行的系统状态)、可观测性(追踪上下文在生产中的实际表现)。
1.3 典型失败模式:上下文爆炸、信息丢失、指令漂移
生产环境的故障统计表明,超过七成的 LLM 应用故障都可以归因于上下文管理不当。这其中有三个最高频的失败模式:上下文爆炸、信息丢失、指令漂移。下面分别剖析它们的成因、表现与缓解策略。
失败模式一:上下文爆炸(Context Explosion)
症状:随着对话或任务推进,模型响应延迟线性增长,单次调用成本指数级上升,最终超出上下文窗口限制,任务被迫中断。
典型场景:一个研究类 Agent 在网上搜索资料,每一步都会拉取若干网页,每个网页平均 5,000 token。运行 20 步后,累积的网页内容已经达到 50 万 token——这已经远超任何主流模型的窗口容量。即使是 GPT-4 的 128K 上下文窗口也无法容纳。
更隐蔽的爆炸来自工具定义。当 Agent 接入了 50 个工具(每个工具 200 token 的 schema),光是工具列表就占用 10,000 token。每一步推理都需要处理这些 schema,造成显著的延迟与成本。
根因分析:上下文爆炸的本质是"信息无差别累积"。系统没有区分"当前必需"与"未来可能需要"的信息,所有内容都被无脑地追加到上下文末尾。Transformer 的自注意力机制对所有 token 的处理是 O(n²) 的复杂度——token 数量翻倍,推理成本与延迟增加四倍。生产环境中常见的现象是:前 10 轮响应延迟稳定在 2 秒,第 15 轮突然飙升到 15 秒,第 20 轮超过 30 秒甚至超时。
缓解策略需要从四个层面同时入手: 1. 分层压缩:定期(每 10 步)对执行历史进行摘要,保留关键事实与决策依据,丢弃执行细节。摘要本身也可以递归压缩。 2. 工具结果截断:对工具返回的结果(如网页内容、数据库查询结果)做长度限制,仅保留与当前任务最相关的部分。可以用 LLM 做相关性过滤,也可以用启发式规则(如保留首尾段落)。 3. 工具动态加载:不一次性加载所有工具 schema,而是根据当前任务阶段动态注入最相关的 3-5 个工具。这需要工具检索器(tool retriever)的支持。 4. 注意力预算分配:通过结构化的 XML 标签或 Markdown 标题,让关键信息(系统指令、当前任务)出现在模型注意力最集中的位置——序列开头或结尾,避免落入中段的"注意力低谷"。
失败模式二:信息丢失(Information Loss)
症状:模型在后续轮次"忘记"了用户在早期轮次提供的关键信息(如账号、订单号、特殊偏好),导致回答错误或需要用户重复提供。
典型场景:客服机器人的典型故障链。用户第一轮提供了订单号 "ORD-20240115-A009",并描述了问题。系统在第 10 轮对话时,对前 9 轮做了摘要以控制上下文长度,摘要中将订单号改写为"用户的订单"。当第 11 轮用户询问"该订单的发货状态"时,模型无法定位到具体订单,只能给出"请提供订单号"的通用答复——这既暴露了系统的健忘,又严重破坏了用户体验。
根因分析:信息丢失的根本原因是压缩策略的无损性不足。当前的摘要方法(无论是抽取式还是抽象式)都会不可避免地丢失低频但高价值的信息——尤其是命名实体、数字、专有名词、专有约束。这些信息在原始上下文中只占少量 token,但在压缩后可能被改写、合并甚至丢弃。
第二个根因是"位置偏见"。Transformer 的注意力对序列开头与结尾的信息记忆最强,对中段信息最弱。如果关键信息(如系统指令、关键约束、用户核心需求)恰好落在中段,它被模型"看见"的概率显著降低。在 128K 上下文中,位置 5% 和 95% 处的"大海捞针"测试准确率通常在 95% 以上,但位置 50% 处的准确率可能跌至 60-70%。
缓解策略需要从四个层面同时入手: 1. 关键信息外置:将高价值低频信息(如实体、数字、约束)从对话历史中提取出来,放入结构化的"记忆槽"(memory slot),独立于对话摘要保留。记忆槽可以用 KV 存储或关系数据库实现。 2. 实体优先保留:设计专门的实体识别与保留机制,确保命名实体、数字、专有名词在压缩过程中不被改写。可以使用占位符机制——压缩时用 `<ENTITY_1>` 替换具体实体,在生成时再回填。 3. 锚定重注入:定期(每 5 轮)将系统指令与核心约束重新注入到上下文开头,强化模型的注意力。这是一种"显式的注意力锚定"。 4. 结构化记忆:用 KV 存储或向量数据库实现可寻址的记忆(addressable memory),模型在需要时可以按需检索,而非依赖线性扫描整个历史。这是 RAG 架构在长对话场景下的延伸。
失败模式三:指令漂移(Instruction Drift)
症状:模型在对话初期严格遵循系统提示中的格式要求、行为约束、角色设定,但随着对话推进,逐渐偏离这些约束——回答变长、格式变化、角色弱化、出现禁忌行为。
典型场景:代码助手。系统提示明确要求"所有函数必须包含类型注解与文档字符串"。对话初期,模型输出完全符合规范。运行 30 轮后,用户在某段代码中故意省略了类型注解(出于简洁考虑),模型随后在新的代码生成中也省略了类型注解,甚至忽略了系统提示中"必须"的措辞。再运行 10 轮,模型开始出现与系统提示矛盾的输出风格。
根因分析:指令漂移的根因是"注意力稀释"与"上下文学习偏差"的叠加。
注意力稀释:系统指令通常出现在上下文的开头,Transformer 对开头内容的注意力权重随距离衰减。随着对话轮次增加,系统指令的"有效注意力"持续下降。经验数据显示,系统指令在对话前 5 轮的遵循率通常在 95% 以上,到第 30 轮可能跌至 70%,到第 100 轮可能跌至 50%。
上下文学习偏差:模型在长对话中会从上下文中"学习"到新的模式——即使这些模式与初始指令冲突。当用户多次省略类型注解后,模型会将"无类型注解"作为新的隐式偏好,开始覆盖系统指令。"上下文学习"(in-context learning)这把双刃剑在这里体现得淋漓尽致。
缓解策略需要从四个层面同时入手: 1. 指令周期性重注入:每 5-10 轮将系统指令的核心约束重新写入当前消息的开头。这是一种"显式的指令强化"。 2. 结构性锚点:使用 XML 标签(如 `<system_policy>`、`<instruction>`)或 Markdown 标题包裹系统指令,使其在视觉与语义上区别于对话内容。结构化标记可以显著提升模型对系统指令的遵循率。 3. 负向示例强化:在系统指令中加入"反例"——展示不应该出现的输出模式,让模型明确边界。例如:"不要输出不带类型注解的函数,例如 `def add(a, b): return a+b` 是错误示例"。 4. 输出校验:在模型输出后增加一道后处理校验,检查是否符合格式与约束。不符合则要求重生成或自动修正。这是一种"输出侧的防御"。
三个失败模式的关联性
这三个失败模式并非孤立存在,它们经常共同出现并形成"上下文管理失败循环":
- 上下文爆炸导致上下文窗口被填满,触发摘要机制 → 引发信息丢失。
- 信息丢失导致模型对早期约束的记忆模糊 → 触发指令漂移。
- 指令漂移导致模型输出偏离预期,可能需要更长的"修复指令"来纠正 → 加剧上下文爆炸。
这个失败循环是大多数 LLM 应用在生产环境中性能衰退的根本原因。打破循环需要系统性的上下文工程设计——这正是本书后续章节的核心议题。
1.4 上下文工程的四大支柱
上下文工程作为一个独立的工程学科,其核心知识体系可以归纳为四大支柱:长上下文建模、压缩与摘要、检索增强记忆、状态管理。这四者并非互斥的选项,而是协同的层次。
支柱一:长上下文建模(Long Context)
这是最基础的支柱——模型到底能"看见"多少信息?上下文窗口的长度从 GPT-3.5 的 4K 扩展到 Claude 2 的 100K,再到 Gemini 1.5 的 1M,每一次扩展都打开了新的应用空间。
但长上下文不只是"窗口大"。真正的问题在于:当窗口扩展到 100K、1M 时,模型对窗口内不同位置信息的注意力质量是否一致?答案并不乐观。研究表明,即使在最先进的长上下文模型中,"大海捞针"测试在某些位置仍然表现不佳,尤其是序列中段。这种"U 型注意力曲线"是当前长上下文模型的结构性挑战。
长上下文建模的工程挑战覆盖了模型架构的多个层面:
- 位置编码的扩展(RoPE 的 NTK-aware 插值、ALiBi 的线性偏置、YaRN 的频率缩放)
- 注意力机制的稀疏化(Sliding Window Attention、Global Attention、Longformer 的混合模式)
- KV Cache 的高效管理(PagedAttention 的内存分页、KV Cache 的量化与压缩)
- 推理成本的优化(Flash Attention 的 IO 感知、Continuous Batching 的吞吐优化)
本书第 4 章将系统讨论长上下文模型的架构演进,第 5 章深入剖析位置编码与注意力机制的工程实现,第 6 章专门讨论 KV Cache 优化与推理加速。
支柱二:压缩、摘要与蒸馏(Compression)
当上下文无法完全装入窗口时,压缩成为必需。压缩的目标是:在显著减少 token 数量的同时,尽可能保留原始信息的关键语义。
压缩的技术路径包括多个层次:
- **抽取式摘要**:从原文中挑选关键句子或段落,拼接成压缩版本。优点是无损、忠实于原文;缺点是压缩率有限,通常只能达到 30-50% 的压缩率。
- **抽象式摘要**:用模型生成新的、更短的表达。优点是压缩率高、可达到 80-90%;缺点是可能引入幻觉、改写关键实体、丢失关键事实。
- **结构化压缩**:将非结构化文本转换为结构化字段(如 JSON、表单),保留关键属性,丢弃冗余描述。压缩率介于抽取与抽象之间,通常达到 60-80%,但更适合后续程序化处理。
- **递归摘要**:分层递归压缩——先用摘要模型压缩每一段,再压缩所有摘要,再压缩……理论上可以达到任意压缩率,但信息损失也最大。适用于多轮 Agent