Jean's Blog

一个专注软件测试开发技术的个人博客

0%

上下文工程

Context(上下文)是什么?

核心定义:上下文指的是大语言模型在处理你的当前请求时,所能“看到”和“考虑”的所有文本信息。

你可以把它类比为人类的短期记忆工作记忆

  • 当你和一个人对话时,你会记住刚才聊了什么,对方说了什么,这样才能做出连贯的回应。
  • 对大模型来说,上下文就是这个“刚才聊过”的全部内容

如下图形象的展示

image-20251029141401415

上下文的组成部分

一个典型的上下文通常包括:

  • 系统提示:在对话开始前,开发者或用户给模型的“人设”或“指令”。例如:“你是一个乐于助人的、专业的AI助手。”
  • 对话历史:你和模型之间已经进行的所有多轮问答。
  • 当前查询:你刚刚提出的新问题。
  • 外部知识/文档:你主动提供给模型的额外信息,比如一篇论文、一份数据表等。

上下文的内容常有:

  • 用户问题
  • 背景信息
  • 相关资料
  • 可用工具列表
  • 工具执行结果
  • 历史对话
  • ……

关键点:模型只理解上下文内的信息。如果信息不在上下文中,就如同没有发生过一样,模型无法基于它进行推理。

运行时上下文(Runtime context)

  • 定义:运行时上下文指的是本地上下文,即你的代码运行所需的数据和依赖关系。它包含了代码在执行过程中所依赖的各种资源,例如变量、函数、库等。
  • 作用:它为代码的运行提供了必要的环境和条件,确保代码能够正常执行。

LLM上下文(LLM context)

  • 定义:LLM上下文是指传递给LLM(大型语言模型)提示(prompt)的数据。它包含了用于引导LLM生成响应的输入信息。
  • 示例:在与LLM交互时,你可能会提供一段文本作为提示,让LLM根据这段文本生成相关的回答或内容,这段文本就是LLM上下文的一部分。

运行时上下文与LLM上下文的关系

  • 区别:运行时上下文主要关注代码运行的本地环境和依赖,而LLM上下文关注的是传递给LLM的输入数据以及与LLM交互过程中相关的数据。
  • 联系:运行时上下文可以被用来优化LLM上下文。例如,你可以利用运行时上下文中存储的用户元数据(如用户偏好设置等)来获取用户的相关信息,然后将这些信息作为输入数据传递给LLM,从而优化LLM生成的响应,使其更符合用户的期望和需求。

上下文窗口(Context Window)

核心定义:上下文窗口是指大模型一次性能处理和接受的最大文本量(模型的输入中最多能包含的Token数量)。这个容量通常以令牌为单位来衡量。

  • 令牌:是模型处理文本的基本单位。在英文中,一个令牌可能是一个单词或一个词根(例如,“unbelievably” 可能被拆成 “un”, “believe”, “ably” 三个令牌)。在中文中,通常是一个汉字或一个词。
  • 单位:常见的上下文窗口大小表示为 4K、8K、32K、128K、200K 甚至更高。例如,一个32K的窗口意味着模型可以一次性处理大约32,000个令牌的文本。

上下文窗口是指可以传递给LLM的最大令牌(token)数量。令牌是文本数据在处理过程中被分割成的最小单位,例如单词、短语或字符等。

限制:由于LLM的处理能力和资源有限,因此对输入数据的长度有一个上限,这个上限就是上下文窗口的大小。

为什么上下文窗口很重要?

  1. 决定对话深度:窗口越大,模型能记住的对话轮次就越多,可以进行更长的、连贯的对话。
  2. 限制处理能力:如果你提供的文档(比如一本电子书)超过了上下文窗口,模型将无法完整阅读它。
  3. 技术成本:处理更长的上下文需要更多的计算资源和内存,技术上更具挑战性,成本也更高。

举个例子
假设一个模型的上下文窗口是4K令牌(约3000个汉字)。

  • 如果你的对话历史加上当前问题已经达到了3800字,你还能再提供一篇2000字的文章让它总结吗?
  • 不能。因为总文本量会超过4K的限制,系统会报错或者自动截断前面的部分对话,导致模型“忘记”了开头的内容。

重要区分

  • 上下文窗口:是模型的短期记忆容量,关乎一次交互中能处理多少信息。
  • 训练数据:是模型在训练时“学习”到的长期知识,是固定的,模型无法实时更新它。

上下文工程(Context Engineering)

已经对上下文的概念有一个详细的了解,那么关键的部分上下文工程是我们在使用大模型及构建智能体中的核心了。

超越提示词:深入理解 AI 应用成功的关键—上下文工程

核心观点: 大多数 AI 智能体的失败,其根源不在于模型本身的能力不足,而在于“上下文工程”(Context Engineering)的缺失。

上下文工程”这个概念近期在 AI 大模型领域迅速升温,它究竟是新瓶装旧酒,还是真正揭示了构建强大AI应用的核心秘诀?它与我们熟知的提示工程(Prompt Engineering)和检索增强生成(RAG)有何不同?

image-20251029145451783

什么是上下文工程?

上下文的真正含义

上下文不是简单的历史聊天记录。它是提供给大语言模型(LLM)用于完成下一步任务的全部信息集合。我们可以将其分为三类:

image-20251029145748257

  • 指导性上下文 (Guiding Context): 告诉模型“做什么”和“怎么做”。这部分是提示工程的核心优化对象。
    • 系统提示词 (System Prompt): 定义模型的角色和行为准则。
    • 任务描述 (Task Description): 明确当前需要完成的任务。
    • 少量样本示例 (Few-shot Examples): 提供范例,指导模型输出风格。
    • 输出格式定义 (Output Schema): 规定模型必须遵循的输出格式,如JSON。
  • 信息性上下文 (Informational Context): 告诉模型“需要知道什么”。这部分为模型提供解决问题所需的事实和知识。
    • RAG: 从外部知识库(比如:文档、数据库)中检索相关信息。
    • 记忆 (Memory): 包括当前对话的短期记忆和跨对话的长期记忆(比如:用户偏好)。
    • 状态/草稿纸 (State / Scratchpad): 记录模型在任务过程中的中间思考和计划。
  • 行动性上下文 (Actionable Context): 告诉模型“能做什么”和“做了之后的结果”。这部分赋予模型与外部世界交互的能力。
    • 工具定义 (Tool Definition): 描述模型可以使用的工具(API、函数等)。
    • 工具调用记录 (Tool Traces): 记录模型调用了哪些工具以及返回了什么结果。

上下文工程的定义

上下文工程是一门系统性学科,专注于设计、构建并维护一个动态系统。该系统能在 AI 智能体执行任务的每一步,为其智能地组装出最优的上下文组合,从而确保任务能够被可靠、高效地完成。

一个绝佳的类比是,如果 LLM 是计算机的 CPU,那么上下文窗口(Context Window)就是内存(RAM)上下文工程就是这个系统中的“内存管理器”。它的任务不是简单地把信息塞满内存,而是通过精密的调度,决定在每个时刻加载什么、丢弃什么,以保证 CPU 高效运转,最终产出正确结果。

image-20251029150146285

与提示工程、RAG 的区别

image-20251029150244909

  • 提示词工程 (Prompt Engineering): 是上下文工程的子集,专注于优化“指导性上下文”,即如何下达清晰的指令。
  • RAG (Retrieval-Augmented Generation): 是实现上下文工程的关键技术手段之一,主要负责动态填充“信息性上下文”。

因此,上下文工程是一个更宏大、更系统的概念,它统筹管理所有类型的上下文,目标是构建一个最高效的信息供给系统。

为什么我们需要上下文工程?

当 AI 系统的表现不佳时,我们往往会怪罪于模型本身。但大多数情况下,问题出在上下文的供给上。

示例1:缺失上下文的代价

假设 AI 智能体收到邮件:“Hi, 明天有空聚一下吗?”

  • 上下文贫乏的 AI: “感谢您的消息。我明天有空。请问您希望约在什么时间?” (无效回复,未推进任务)
  • 上下文丰富的 AI: 在回复前,它的上下文工程系统会自动组装信息:
    • 信息性上下文: 检索日历发现明天已满;识别发件人 Jim 是重要伙伴;分析历史邮件确定应使用非正式语气。
    • 行动性上下文: 知道自己有 send_calendar_invite 这个工具。
    • 最终回复: “Hi Jim! 我明天日程完全满了。周四上午有空,你看方便吗?我发了一个暂定邀请,如果时间合适请确认。” (高效、智能)

这里的“魔力”并非来自更聪明的模型,而是来自一个能够为任务动态组装恰当上下文的系统。

示例2:上下文退化的挑战

既然上下文如此重要,是不是把它全部塞给模型就行了?答案是否定的。对于长期、复杂的任务(比如:编程),简单的信息累加会导致“上下文退化”:

  • 第一、性能下降: 无关紧要的旧信息会干扰当前任务,造成“上下文干扰”。
  • 第二、成本与延迟激增: 上下文越长,API 调用成本越高,响应越慢。
  • 第三、最终崩溃: 当信息量超过模型的上下文窗口上限时,系统将直接报错或因信息截断而出错。

结论: 上下文是一种需要被主动管理的、有限的资源。简单的缺失或无脑的堆砌都无法构建出强大的 AI 智能体应用。因此,我们需要一套系统性的方法论——上下文工程

如何实践上下文工程?

上下文工程的实践核心在于对上下文进行智能的写入(Write)、选取(Select)、压缩(Compress)和隔离(Isolate)

image-20251029150810491

  1. 写入 (Write): 将有价值的信息持久化,超越单次对话的限制。

    • 会话内写入: 将中间思考和计划写入“草稿纸”,供当前任务使用。
    • 持久化写入: 将用户偏好、关键事实等存入外部记忆系统(比如:向量数据库),实现跨会话的“学习”和“成长”。
  2. 选取 (Select): 在每次调用 LLM 前,从所有可用信息中,动态拉取与当前子任务最相关的信息。

    • 确定性选取: 根据预设规则加载固定上下文(比如:启动时加载项目配置文件)。
    • 检索式选取: 通过相似度搜索从知识库、记忆中拉取最相关的信息(RAG 的核心)。
  3. 压缩 (Compress): 在信息进入上下文窗口前,对其进行“降噪”,用更少的 Token 承载最核心的信号。

    • 自动总结: 当上下文过长时,自动总结历史对话,只保留关键部分。
    • 专用压缩模型: 使用一个专门微调过的“压缩 LLM ”来对上下文进行提炼。
    • 修剪策略: 例如,直接截断最早的历史记录。
  4. 隔离 (Isolate): 在系统架构层面设置信息边界,防止信息污染和干扰。

    • 多智能体架构: 这是最经典的隔离策略。让多个“专家”子智能体并行处理各自领域的信息,然后只将最关键的结论“压缩”并上报给主智能体。这极大地减轻了主智能体的认知负担,提高了信息密度,避免了长上下文带来的各种问题。

      image-20251029150936083

    • 工具调用: 将复杂的计算或操作隔离在沙盒环境中执行,只将最终结果返回到上下文中。

上下文工程标志着 AI 智能体应用开发的范式转变。我们的重心正从“寻找那句完美的提示词”,转向“如何设计一个能够为模型在每一步都动态组装出完美上下文的、健壮可靠的系统”。

理解并熟练运用写入、选取、压缩、隔离这四大实践,将是区分一个“有趣的演示”和一个“可靠的、可规模化的应用”的关键。归根结底,所有努力都指向同一个目标:在模型做出决策前,为它准备好一份恰到好处的上下文。这,就是上下文工程的禅意所在。

上下文的两个关键维度

可变性(Mutability)

  • 静态上下文(Static context)定义:静态上下文是不可变的数据,在执行过程中不会改变。
    • 示例:用户元数据(如用户的基本信息)、数据库连接、工具等。
    • 特点:这些数据在应用启动时被加载,并在整个运行过程中保持不变。
  • 动态上下文(Dynamic context)定义:动态上下文是可变的数据,随着应用的运行而变化。
    • 示例:对话历史(如用户与AI的交互记录)、中间结果(如计算过程中的临时数据)、工具调用的观察结果等。
    • 特点:这些数据会根据应用的运行状态和用户的交互动态更新,反映了应用的实时状态。

生命周期(Lifetime)

  • 运行时上下文(Runtime context)定义:运行时上下文是指在单次运行或调用中有效的作用域数据。
    • 特点:这些数据仅在当前运行实例中存在,当运行结束时,数据也会随之消失。
  • 跨对话上下文(Cross-conversation context)定义:跨对话上下文是指在多次对话或会话中持续存在的数据。
    • 特点:这些数据可以跨越多个运行实例,保留用户的历史信息和偏好设置等,为用户提供更加连贯和个性化的体验。