上下文工程:从提示工程到记忆架构的范式跃迁
1.1 从"提示"到"上下文":一个被忽视的工程问题
2024 年初,某头部电商公司的智能客服系统在季度复盘会上被定性为"重大架构事故":三个月内累计发生 17 次生产故障,平均恢复时间 4.2 小时,直接损失超过 800 万元。事后技术复盘报告的第一句话是——"我们把 LLM 当成了一个更大的搜索框,但忽略了它其实是一个状态机。"这句话揭示了过去两年 LLM 应用开发中最普遍、也最隐蔽的一类问题:当 prompt 写得足够好、单轮效果足够惊艳之后,工程师们以为剩下的只是工程化部署工作;但真正进入生产环境后,"上下文"——那个被默认塞进 LLM 输入框的字符串——才是决定系统能否稳定运行的关键变量。
1.1.1 提示工程的辉煌与隐含假设
2022 年末至 2023 年中,"提示工程"(Prompt Engineering)成为 LLM 应用开发的核心技能。一套精心设计的 system prompt 配合 few-shot 示例,可以让 GPT-3.5 完成复杂的意图识别、文本分类、风格转换等任务。在许多单轮场景下,提示工程几乎可以替代传统机器学习 pipeline:无需训练数据,无需标注,无需调参,只需要几个聪明的句子。
但提示工程的辉煌建立在两个隐含假设之上:
1. 上下文是静态的输入字符串:开发者假设每次调用 LLM 都是独立的,prompt 写好之后就不需要再变。 2. 上下文规模可控:单轮对话的 prompt 通常在 1K-4K tokens 之间,远低于任何主流模型的上下文窗口。
这两个假设在单轮问答场景下几乎总是成立。但当 LLM 应用进入对话、进入多步骤任务、进入 Agent 协作时,这两个假设同时崩塌。
1.1.2 五种典型的上下文失控症状
让我们看看在生产环境中常见的"上下文失控"症状:
- **症状 A:上下文爆炸**。某 SaaS 客服系统接入历史工单后,10 轮对话的累积上下文突破 30K tokens,每次调用的费用是单轮的 20 倍。
- **症状 B:上下文迷失**。当 system prompt、对话历史、工具返回结果同时塞入上下文窗口后,模型开始遗忘 5 轮前提到的关键订单号,幻觉率上升 3 倍。
- **症状 C:上下文污染**。一份恶意用户输入通过 prompt injection 污染了整个对话上下文,后续所有轮次都受其影响。
- **症状 D:上下文不可观测**。工程师无法回答"模型为什么这样回答",因为没有机制记录每轮上下文的具体构成。
- **症状 E:上下文失效**。当上下文窗口接近上限时,旧信息被截断,关键约束丢失,模型行为变得不可预测。
这些症状的共同根源是:缺乏对上下文的工程化管理。我们把上下文当成了"输入框里的一坨文本",但实际上它是一个随时间增长、需要主动维护、有成本有衰减有风险的状态对象。这正是"上下文工程"作为独立学科存在的理由。
1.2 三次范式跃迁与上下文的角色演化
为了理解"上下文工程"为什么在 2024 年成为独立学科,我们把 LLM 应用的演进梳理成三次范式跃迁。
1.2.1 第一阶段:单轮问答(Context = Input String)
时间:约 2020 年至 2022 年。代表场景:文本生成、翻译、摘要、分类、单轮 QA。
此时 LLM 的上下文 = 用户的输入 + 系统提示。一个典型的 prompt 长这样:
``` 你是一个翻译助手,把以下英文翻译成中文: [用户输入] ```
上下文的角色:纯输入。无状态、无演化、无管理需求。开发者只需要关心 prompt 写得好不好,不需要关心上下文本身。
1.2.2 第二阶段:对话系统(Context = Conversation History)
时间:约 2023 年至 2023 年末。代表场景:ChatGPT 类应用、客服机器人、个人助手。
此时 LLM 的上下文 = system prompt + 累积对话历史 + 当前用户输入:
``` [system prompt] User: 第一个问题 Assistant: 第一个回答 User: 第二个问题 ... User: 当前问题 ```
上下文的角色:状态。上下文从静态输入变成随时间增长的累积状态。开发者开始面临三个新问题——历史越长成本越高、超过窗口时如何截断、哪些历史对当前回答真正有用。
1.2.3 第三阶段:智能体协作(Context = Distributed State)
时间:约 2024 年至今。代表场景:AutoGPT、Agent workflows、多 Agent 协作、工具增强型 LLM。
此时 LLM 的上下文 = system prompt + 多轮对话历史 + 工具调用记录 + 工具返回结果 + 子 Agent 的中间状态 + 外部知识检索片段 + 当前任务描述:
``` [system prompt] [任务描述] [用户历史对话] [之前的工具调用: search(...), results: ...] [之前的工具调用: calculator(...), results: ...] [子 Agent 1 的中间结论: ...] [检索片段: ...] [当前指令] ```
上下文的角色:分布式状态对象。上下文不再是单一字符串,而是来自多个源头、由多个 Agent 共同读写、需要在多轮调用间保持一致性的状态。这已经超出了传统"提示工程"的能力范围。
> 范式跃迁的本质:从"写好一句话"到"管理一个状态"。这就是为什么我们需要"上下文工程"作为独立学科——它的边界、能力范围、设计哲学都必须独立定义,而非作为提示工程的延伸。
1.3 上下文工程的形式化定义
基于上述演进,我们可以给出"上下文工程"的正式定义:
> 上下文工程(Context Engineering):在 LLM 应用系统中,对所有进入模型输入窗口的信息进行生命周期管理的工程学科,包含采集、组织、压缩、检索、调度、审计等子任务,目标是让模型在任意时刻都拥有密度最高、相关性最强、风险最低、可追溯的上下文。
1.3.1 把上下文视为状态对象
传统视角下,上下文是字符串。但工程视角下,上下文是一个有结构的、可操作的状态对象。它至少包含六个属性:
| 属性 | 含义 | 典型值 | |------|------|--------| | 内容 | 上下文包含的具体信息 | 文本、消息、工具调用、检索片段 | | 结构 | 信息的组织方式 | 按时间、按角色、按重要性、按语义块 | | 大小 | 占用 token 数量 | 0 到模型上限 | | 来源 | 信息从哪里来 | 用户、工具、知识库、Agent | | 时效 | 信息的有效时间窗口 | 永久、对话级、任务级、临时 | | 风险 | 信息被滥用或污染的可能性 | 低、中、高 |
当我们把上下文视为状态对象后,"管理上下文"就有了具体含义:控制它的内容、结构、大小、来源、时效和风险。这与传统"把字符串拼起来发给模型"的思维有本质区别。
1.3.2 五大支柱
上下文工程的核心能力由五个支柱构成:
1. 长上下文管理(Long Context Management):在超出模型原生窗口时,如何分块、滑动、检索增强。 2. 压缩(Compression):在保留关键信息的前提下,减少上下文 token 数。 3. 摘要(Summarization):将长上下文转化为模型可用的浓缩信息。 4. 检索记忆(Retrieval Memory):将历史信息外置到向量数据库或知识库,按需检索。 5. 状态管理(State Management):跟踪上下文的演化历史,支持回滚、对比、审计。
这五个支柱不是独立的模块,而是协同工作的能力——它们共同决定了上下文的质量。1.4 节将逐一展开。
1.3.3 与传统特征工程的区别
熟悉传统 NLP 的读者可能会问:这和"特征工程"有什么区别?核心差异在于时机与对象:
| 维度 | 特征工程 | 上下文工程 | |------|----------|------------| | 处理对象 | 数值化特征 | 文本/结构化状态 | | 处理时机 | 训练前一次完成 | 每次推理实时进行 | | 优化目标 | 提升模型指标 | 提升单次推理质量 | | 失败模式 | 训练失败、欠拟合 | 推理时幻觉、遗忘、成本爆炸 | | 工具栈 | sklearn、Spark | 向量库、压缩器、状态机 |
特征工程是离线、静态、一次性的;上下文工程是在线、动态、每次推理都要重新组织的。这一区别决定了上下文工程必须有完全不同的工具链和设计原则。
1.4 五大支柱能力矩阵
为了帮助读者建立全景认知,我们先用一张图展示五大支柱之间的关系,以及它们与相邻学科的边界。
```mermaid graph TD A[用户输入] --> B[提示工程] A --> C[上下文工程] B --> D[LLM调用] C --> E[长上下文管理] C --> F[压缩] C --> G[摘要] C --> H[检索记忆] C --> I[状态管理] E --> D F --> D G --> D H --> D I --> D I -.协同.-> J[Agent工程] H -.依赖.-> K[RAG工程] E -.边界.-> B ```
从图中可以看出:提示工程是上下文工程的边界外延(关注单次输入),检索记忆与 RAG 工程有依赖关系,状态管理与 Agent 工程协同工作。五大支柱共同构成上下文工程的完整能力栈。接下来逐一展开。
1.4.1 长上下文管理(Long Context)
长上下文管理解决的核心问题是:当需要进入模型的信息量超过其原生上下文窗口时怎么办。
典型场景:文档问答(用户上传 100 页 PDF,要求模型基于全文回答问题)、代码库分析(要求模型理解一个 50 万行代码的项目)、长视频/音频理解(要求模型基于几小时的视频内容回答问题)。
核心挑战:模型原生窗口有限(GPT-4 是 8K/32K/128K,Claude 是 200K);即便窗口变大,"中间遗忘"(lost in the middle)现象仍然存在——研究表明,模型对位于上下文开头和结尾的信息回忆率显著高于中间;注意力机制的二次复杂度带来延迟和成本问题。
工程方案:
- **滑动窗口(Sliding Window)**:保留最近 N 轮对话
- **分块 + 检索(Chunk + Retrieval)**:将长文档分块,仅检索与当前问题相关的块
- **层次化上下文(Hierarchical Context)**:维护粗粒度摘要 + 细粒度检索
- **流式注意力优化(Streaming Attention)**:使用稀疏注意力、滑动窗口注意力降低计算量
评估指标:多文档问答准确率(Multi-Doc QA Accuracy)、关键信息位置敏感性(Position Sensitivity)、长上下文延迟(Latency at Max Tokens)。
1.4.2 压缩(Compression)
压缩的目标是:在不丢失关键信息的前提下,减少上下文的 token 数。
典型场景:对话历史压缩(将 50 轮对话压成 5 段摘要)、工具返回结果压缩(网页爬取结果 50K tokens 压成 2K tokens)、长文档压缩(保留核心段落,去除冗余)。
压缩技术分类:
- **无损压缩**:保留全部语义,仅去除冗余表达(去除多余空格、简化 JSON 格式、用缩写代替长字段名)
- **有损压缩**:保留核心语义,丢弃次要信息(如 LLM-based summarization)
- **选择性压缩**:根据当前任务,只保留相关部分(与检索结合)
核心挑战:压缩比例与信息保真度的权衡;压缩模型自身的延迟和成本;压缩后的上下文是否仍能支持准确推理。
关键公式:压缩比 $R_c = \frac{T_{in} - T_{out}}{T_{in}}$,其中 $T_{in}$ 是原始 token 数,$T_{out}$ 是压缩后 token 数。工程目标是高 $R_c$ 的同时保留高语义保真度,而非单纯追求高压缩比。
1.4.3 摘要(Summarization)
摘要是一种特殊的压缩,但它输出的不是"短版本",而是"浓缩版本"。摘要强调保留推理所需的关键事实和关系。
摘要的层次:
- **轮级摘要**:对单轮对话生成 1-2 句摘要
- **段级摘要**:对一组对话生成段落级摘要
- **全局摘要**:对整个会话生成全局摘要
- **滚动摘要**:每次新对话发生后,增量更新已有摘要
摘要策略:
- **抽取式(Extractive)**:从原文选取关键句子,保留原文措辞
- **生成式(Abstractive)**:LLM 重新组织关键信息,可能产生更精炼的表达
- **层次式(Hierarchical)**:粗粒度摘要 + 细粒度摘要并存,根据需要切换
摘要质量的评估不能只看摘要本身是否通顺,更要看基于摘要的二次推理质量。一个常见错误是只评估摘要的可读性,却忽略了下游任务的准确率,导致上线后才发现关键信息丢失。
1.4.4 检索记忆(Retrieval Memory)
检索记忆解决的是"上下文窗口装不下,但模型又需要"的问题。
核心思想:将历史信息外置到外部存储(向量数据库、知识图谱、文件系统),每次推理时按需检索相关片段。
关键技术:
- **向量检索(Vector Retrieval)**:基于语义相似度检索
- **关键词检索(BM25)**:基于词频的传统检索
- **混合检索(Hybrid Retrieval)**:向量 + 关键词,取长补短
- **重排序(Reranking)**:用 Cross-Encoder 对初排结果精排
- **元数据过滤(Metadata Filtering)**:基于时间、用户、类型等过滤
检索的工程难题:检索的精度 vs 召回率(下面用公式表达);检索的延迟(影响整体响应时间);检索片段的拼接(如何把多个片段组织成高质量上下文,而非简单拼接);索引的更新策略(什么时候把新信息加入索引)。
关键公式:检索的精确率 $P_r = \frac{|\text{Relevant} \cap \text{Retrieved}|}{|\text{Retrieved}|}$,召回率 $R_r = \frac{|\text{Relevant} \cap \text{Retrieved}|}{|\text{Relevant}|}$。F1 分数是两者的调和平均,是评估检索质量的常用指标。
1.4.5 状态管理(State Management)
状态管理是五大支柱中最抽象、也是最关键的一项。它关注的是:上下文如何在多轮、多 Agent、多工具的调用之间保持一致性、可追溯性、可回滚性。
核心要素:
- **状态对象(State Object)**:把上下文抽象成有版本号、有时间戳、有来源标签的结构化对象
- **状态演化(State Evolution)**:跟踪每次推理前后的状态变化
- **状态回滚(State Rollback)**:支持回退到任一历史状态,用于复现 bug
- **状态分支(State Branch)**:支持"如果当时那样做会怎样"的反事实分析
- **状态审计(State Audit)**:完整记录每一步的上下文构成,用于事后分析
典型实现:
- **Checkpoint 机制**:每 N 步保存状态快照
- **事件溯源(Event Sourcing)**:把每次状态变化记录为事件,可重放
- **版本化存储**:每次状态变化生成新版本,保留所有历史
状态管理是区分"玩具 LLM 应用"和"生产级 LLM 应用"的关键。任何一个严肃的 LLM 产品,都必须有状态管理能力——否则当用户反馈"模型这次回答错了"时,工程师将无法定位问题。
1.4.6 五大支柱的协同
五大支柱不是孤立工作的,它们构成一个完整的工程体系:
- 长上下文是**物理约束**(决定哪些信息可能进入模型)
- 压缩和摘要是**减负手段**(在保留关键信息的前提下降低规模)
- 检索记忆是**外部存储**(把不常用的信息外置)
- 状态管理是**治理框架**(确保上下文演化可追溯)
一个典型的协同工作流:
1. 系统接收用户请求 2. 状态管理模块查询历史会话状态 3. 检索记忆模块从外部知识库检索相关信息 4. 压缩/摘要模块对历史对话和工具结果进行压缩 5. 长上下文管理模块将所有内容组装成最终的上下文 6. LLM 基于此上下文生成响应 7. 新的对话轮次被记录,状态更新,触发必要的索引更新
任何一环缺失,整个系统都会出现对应的症状:缺少状态管理则不可观测;缺少压缩则成本爆炸;缺少检索记忆则信息覆盖不全;缺少长上下文管理则窗口溢出。
1.5 与相邻学科的边界划分
上下文工程不是孤立存在的,它与提示工程、RAG 工程、Agent 工程有交集也有差异。理解边界是做好分工的前提。
1.5.1 上下文工程 vs 提示工程
提示工程(Prompt Engineering):关注单次推理的输入字符串如何写得更好。核心产物是 prompt 模板。衡量指标是单次输出的质量。
上下文工程(Context Engineering):关注所有进入模型的动态状态如何管理。核心产物是上下文调度系统。衡量指标是整个会话生命周期内的稳定性、成本、可观测性。
关系:提示工程是上下文工程的一个子集。上下文工程包含提示工程(system prompt 也是上下文的一部分),但还包含检索、压缩、记忆等更多内容。
判断标准:
- 如果你的 LLM 应用只有单轮调用,关注提示工程
- 如果你的 LLM 应用有多轮对话或工具调用,关注上下文工程
1.5.2 上下文工程 vs RAG 工程
RAG 工程(Retrieval-Augmented Generation Engineering):关注如何从外部知识库检索信息并注入 LLM 上下文。核心产物是检索管道(retrieval pipeline)。
上下文工程(Context Engineering):包含 RAG 工程,但更广。
关系:检索记忆是上下文工程的五大支柱之一。R