Extra-Chapter/Extra02-上下文工程补充知识.md
为什么上下文工程最近又再次火热起来?源自 Chroma 创始人兼 CEOJeff 在 Len Space 播客的对话, Chroma 向量数据库领域的开源霸主。连大名鼎鼎的 Voyager 论文里用的都是它。 CEOJeff 对话的标题就是关于“RAG is dead”的观念,在视频中很明显的说明了原本的RAG的局限性和现在context engnieer的重要性,
本章我们先全面讲解一下“上下文工程”的(context engnieer)概念, 并在文章最后谈一下对 Rag is dead 的看法
我们可以打一个比方,Agent就像一种新型操作系统。LLM如同CPU,其上下文窗口如同RAM,作为模型的工作内存。就像RAM一样,LLM上下文窗口的容量有限,无法处理各种来源的上下文。而上下文工程就像操作系统管理CPU的RAM一样,去管理LLM的上下文窗口,决定在何时去填充什么内容。Karpathy总结得很好: "上下文工程是...在上下文窗口中为下一步填充恰到好处信息的精妙艺术和科学。"
Context就是模型“看到”的一切,模型其实并不是只根据我们输入的prompt回复问题,还有其余的信息配合生成回复。上下文工程作为适用于几种不同上下文类型的总括:
为了清晰地区分这四个概念,我们设定一个统一的实际场景,然后看每个方法如何解决这个问题。
<strong>场景:一个旅游APP的智能助手</strong>
<strong>用户需求:</strong> “帮我规划一个为期三天的北京家庭旅行。我们是两个大人和一个5岁的孩子,喜欢历史文化,也想要一些轻松有趣的活动。我们的总预算是8000元。”
这是最基础、最直接的方法。它的核心是<strong>如何向语言模型(LLM)提一个好问题</strong>,以期它仅凭其内部的通用知识库就能给出最好的答案。
<strong>核心思想:</strong> 优化输入给模型的指令(Prompt),让它输出更符合期望的结果。
<strong>工作方式:</strong>
<strong>例子:</strong>
你是一位专业的旅行规划师。请为北京一个为期三天的家庭旅行设计一份详细行程。
# 家庭成员
- 2个成年人
- 1个5岁的儿童
# 兴趣偏好
- 历史文化(故宫、长城等)
- 轻松有趣的儿童活动
# 预算
- 总预算不超过8000元人民币,请给出大致的费用估算。
# 输出要求
- 每日行程安排(上午、下午、晚上)
- 交通建议
- 餐饮推荐(包含适合儿童的餐厅)
- 预算明细
<strong>局限性:</strong>
为了解决提示词工程“知识陈旧”的问题,RAG 引入了<strong>外部知识库</strong>。
<strong>核心思想:</strong> 在生成答案前,先从一个特定的、可信的数据库中检索相关信息,然后将这些信息和用户问题一起提供给模型。
<strong>工作方式:</strong>
<strong>例子:</strong> 系统在内部知识库中找到了三段文字:A) 故宫官网的开放时间和票价;B) 一篇关于“带娃逛天坛”的博客;C) 一份“北京家庭友好型酒店”列表。 然后,它向 LLM 发出指令:“根据以下信息:[A、B、C段文字内容],为用户规划一个北京三日亲子游,预算8000元。”
<strong>局限性:</strong>
Agent 让 AI 从一个“问答机器人”进化成一个<strong>能思考、能使用工具的“行动者”</strong>。
<strong>核心思想:</strong> 赋予模型一个“思考-行动”循环(Reasoning-Action Loop),让它能自主规划步骤、使用外部工具(如API)来完成复杂任务。
<strong>工作方式:</strong>
search_flight_api(from="上海", to="北京", date="...")。search_hotel_api(city="北京", price_max=800, family_friendly=true)。<strong>例子:</strong> 这个助手会像一个真正的人类助理一样工作:
ticket_api 查询,儿童免票。我已将此信息加入行程。”<strong>局限性:</strong>
上下文工程是<strong>一个更宏观、更严谨的学科</strong>,它着眼于<strong>如何为模型(无论是简单的 RAG 还是复杂的 Agent)构建最优的“上下文窗口”</strong>。它是对上述所有方法的优化和升华。
<strong>核心思想:</strong> 精心设计和编排进入模型上下文的所有信息(指令、检索到的数据、历史对话、工具输出等),以实现最高效、最可靠的输出。它是一门关于“喂什么”和“怎么喂”的科学。
<strong>工作方式:</strong> 它不是一个独立的系统类型,而是优化 RAG 和 Agent 的方法论。回到旅行规划的例子:
weather_api 查询北京未来几天的天气。events_api 查询是否有特殊的儿童展览或活动。[JSON object],为用户生成最终行程。”<strong>例子:</strong> 上下文工程的产出不是直接给用户的行程,而是给模型看的、最优化的“作战地图”。因为经过了上下文工程的优化,Agent 的工作变得极其简单和高效,它不需要再自己费力地一步步试错,而是基于一份完美的简报直接进行最终的规划生成。
| 概念 | 核心思想 | 工作方式 | 局限性 |
|---|---|---|---|
| <strong>提示词工程</strong> | 问对问题 | 精心设计一个完美的 Prompt | 知识过时,无法与外部世界交互 |
| <strong>RAG</strong> | 给予参考资料 | 提问前先从知识库检索相关信息 | 被动响应,无法执行任务,依赖知识库 |
| <strong>Agent</strong> | 赋予行动能力 | 通过“思考-行动”循环来使用工具、完成任务 | 复杂,不稳定,成本高 |
| <strong>上下文工程</strong> | 打造完美输入 | 系统性地收集、筛选、压缩、格式化所有信息,为模型提供最优上下文 | 是一个方法论/学科,而非具体系统,实现复杂 |
简单来说,它们是能力的递进:
随着LLM在推理和工具调用方面变得越来越好,大家对Agent的兴趣大幅增长。Agent将LLM调用和工具调用交织在一起,通常用于长时间运行的任务。Agent使用工具反馈来决定下一步操作。
然而,长时间运行的任务和积累的工具调用反馈意味着Agent通常使用大量token。这可能导致许多问题:可能超出上下文窗口大小、增加成本/延迟或降低Agent性能。
随着上下文窗口越来越长,我们原本以为“把所有对话历史和资料都丢进模型”就能解决记忆问题。但实验表明,现实远比想象复杂。随着上下文长度增长,模型越来越难保持信息的准确性与一致性,表现就像“<strong>记忆腐烂</strong>”。
这些现象在 Chroma 的研究中被称为Context Rot——即模型在长语境下的性能“腐蚀”。这正是Context Engineer这一角色诞生的根本原因:需要有人去对抗和修复这种“语境腐烂”,通过裁剪、压缩、重组和检索增强,让模型在有限的注意力资源中保持可靠表现。
上下文挑战主要存在四个方面,分别描述为:
上下文毒化(Context Poisoning)指的是幻觉(hallucination,即模型生成的错误或虚构信息)或其它错误进入上下文窗口,并被反复引用,从而嵌入错误信息,导致代理(agent)性能脱轨。这种情况会“毒化”关键部分,如目标或摘要,使得模型固执于不可能或无关的目标,导致重复的、无意义的的行为。
上下文干扰(Context Distraction)发生在上下文增长过长(例如超过10万token)时,导致模型过度依赖历史细节,而忽略其预训练知识或生成新颖解决方案的能力。这会引发重复动作而非创造性问题解决,且性能在上下文窗口满载前就已下降。
模型在面对数十万 tokens 的输入时,并不能像硬盘一样均匀记住所有信息。实验发现,精简版输入(仅几百 tokens)反而比完整输入(十几万 tokens)表现更好。研究结果显示,模型在精简版上的表现显著优于完整版。这说明当输入过长、噪音过多时,即使是最先进的模型,也很难抓住关键信息。
上下文混淆(Context Confusion)是指无关或多余的信息(如冗余工具定义)被纳入上下文,迫使模型考虑它,从而产生次优响应。即使额外内容无害,也会稀释焦点并降低质量。 真实对话和资料中,往往存在语义相似却不相关的“噪音”。短上下文里模型能区分,但长上下文时更容易被误导。这要求有人来做上下文的筛选与去噪,让模型聚焦真正相关的信息。在长上下文里,模型不光要找到相关信息,还要能分辨“哪个才是正确的 needle,哪个只是干扰项”。
上下文冲突(Context Clash)是混淆的更严重形式,指上下文中的信息相互冲突(如新工具或事实与现有内容矛盾),从而破坏推理,通常因为模型锁定在早期假设中。这比单纯无关更具破坏性:“This is a more problematic version of Context Confusion: the bad context here isn’t irrelevant, it directly conflicts with other information in the prompt.” 在多步交互中,早期的错误会传播,模型依赖于有缺陷的前提。
缺乏“计算机式”可靠性 我们希望LLM获得一致质量的输出 即使是最简单的复制任务,模型在长输入下也会出错。它不是逐字逐位的符号处理器,而是概率驱动的语言生成器。因此不能期望它像数据库或计算机一样精确地处理长上下文,而必须借助结构化设计来弥补。
因此,有效的上下文窗口管理和语境工程是必不可少的。
上一节提到上下文面临如此多的挑战,那么如何克服它们呢?这就要依靠上下文工程。其中,上下文工程的策略主要分为四种:写入(存储)、选择、压缩和隔离。
<strong>写入上下文</strong>意味着将其保存在上下文窗口之外以帮助Agent执行任务。 主要分为两种:
当信息量越来越大时,如何选择比如何存储更重要。选择上下文就是在每次调用模型时,从所有可用的信息源里,挑出真正相关的部分放入窗口。
具体可供选择的上下文有:
<strong>临时笔记板(Scratchpad)</strong>:即上文提到的临时笔记板,作为模型的"工作记忆"空间,用于记录推理过程、中间结果和思考步骤。在多步骤任务中,模型可以将当前的推理状态、已完成的子任务、待处理的问题等信息写入临时笔记板,便于后续步骤参考和调整策略。
<strong>记忆(Memory)</strong>:包括短期记忆和长期记忆两个层面。短期记忆保存当前会话中的历史对话和上下文信息,确保对话连贯性;长期记忆则存储用户偏好、历史交互模式、个性化设置等跨会话的持久化信息,帮助模型提供更加个性化和一致的服务体验。
<strong>工具(Tools)</strong>:在 Agent 系统里,工具本身就是一种上下文。当模型调用 API、插件或外部函数时,它必须理解工具的描述(包括功能说明、参数要求、返回格式等),并在合适的场景下选择正确的工具。工具调用后的反馈结果也会作为新的上下文输入,指导模型下一步的决策。工具的可用性、执行状态、调用历史都是重要的上下文信息。
<strong>知识(Knowledge)</strong>:主要指 RAG(检索增强生成)中的外部知识库。包括结构化数据(如数据库表格)、非结构化文档(如技术文档、产品手册)、向量数据库中的语义检索结果等。这些外部知识弥补了模型训练数据的时效性限制和知识覆盖面不足的问题,通过动态检索相关信息来增强模型的回答准确性和专业性。
压缩上下文涉及仅保留执行任务所需的token,通过减少冗余信息来优化上下文窗口的使用效率。
<strong>对话摘要:</strong> 在长时间的多轮交互中,完整保留所有历史对话会快速消耗上下文窗口。通过对话摘要技术,可以将早期的对话轮次压缩成简洁的摘要形式,保留关键信息(如用户偏好、重要决策、待解决问题等),同时丢弃冗余的寒暄和重复内容。这样既能维持对话的连贯性,又能为新的交互留出足够空间。
<strong>工具摘要:</strong> 工具调用往往会返回大量的原始数据(如完整的API响应、数据库查询结果等)。通过工具摘要,可以提取和保留最相关的结果字段,过滤掉元数据、调试信息等非必要内容。例如,天气API可能返回详细的气象参数,但摘要后只保留温度、天气状况等核心信息,大幅减少token消耗。
<strong>基于规则的修剪:</strong> 可以使用硬编码启发式方法来主动删除过时或低优先级的上下文。常见策略包括:
<strong>智能修剪:</strong> 更高级的方法可以基于相关性评分来动态选择保留哪些上下文片段。通过语义相似度计算或重要性打分,优先保留与当前任务最相关的信息,自动淘汰相关度低的历史内容。
隔离上下文涉及将上下文拆分以帮助Agent执行任务。
<strong>关注点分离:</strong> 将复杂的大任务拆分成多个独立的子任务,每个子任务由专门的Agent负责。这种设计遵循单一职责原则,使每个Agent专注于特定领域,提高整体系统的可维护性和可扩展性。
<strong>Agent隔离特性:</strong> 每个子Agent拥有独立的资源和配置:
<strong>Agent协作机制:</strong> 多个Agent之间通过明确的接口进行通信和数据传递,主控Agent或路由层负责任务分配和结果整合,形成协同工作流。
<strong>上下文与执行分离:</strong> 将代码执行环境与LLM的上下文窗口隔离开来,LLM不需要直接接触所有工具的原始输出数据。
<strong>处理层设计:</strong> 在工具执行和LLM之间增加处理层:
这种隔离既提高了安全性,又减少了token消耗,使LLM能够专注于高层决策而非底层细节处理。
上下文工程的四个动作——写、选、压、隔——并不是零散的技巧,而是一套系统方法。 它们分别解决了信息丢失、信息冗余、信息过载和信息冲突的问题。 当这四个策略被系统化执行,Agent 就能在复杂环境中稳定运行。
使用LangSmith和LangGraph进行上下文工程,此部分内容具体可以参考 第九章。
Jeff主要批评了传统的RAG将"检索(Retrieval)、增强(Augmented)、生成(Generation)"三个不同概念强行捆绑在一起,导致了概念上的混乱和实践上的模糊化。从上下文工程的视角重新审视RAG,可以将其拆解为更清晰的步骤:
<strong>传统RAG vs 上下文工程视角(高级RAG):</strong>
| 阶段 | 传统RAG | 上下文工程方法 |
|---|---|---|
| <strong>检索</strong> | 简单的向量相似度搜索 | 混合检索:结合向量检索、关键词匹配、重排序等多种策略 |
| <strong>过滤</strong> | 通常缺失或简陋 | 智能过滤:剔除冗余、过时或与任务无关的内容 |
| <strong>排序</strong> | 基于单一相似度分数 | 多维度排序:考虑相关性、新鲜度、可信度等因素,优先送入最关键信息 |
| <strong>评估</strong> | 缺乏系统化评估 | 构建黄金数据集,量化评估检索质量、答案准确性和上下文利用效率 |
<strong>核心改进:</strong>
这种视角将RAG从一个黑盒流程转变为可拆解、可优化的上下文工程问题,使其更具可操作性和可扩展性。
因此,上下文工程既是一门系统化的工程实践,也是一门需要权衡取舍的艺术。它要求我们在海量信息中精准地判断以下4个问题:
只有懂得这些问题,才能实现有效的上下文工程,实现艺术与工程的完美结合。
沧海九粟. 上下文工程:优化 Agent 效能的关键技术[EB/OL]. (2025-07-10)[2025-10-21]. https://www.bilibili.com/video/BV1w3GNzeEHb/?spm_id_from=333.1387.upload.video_card.click&vd_source=0f47ed6b43bae0b240e774a8fd72e3e4
Drew Breunig. How Long Contexts Fail[EB/OL]. (2025-06-22)[2025-10-21]. https://www.dbreunig.com/2025/06/22/how-contexts-fail-and-how-to-fix-them.html?ref=blog.langchain.com
Latent.Space, Jeff Huber, Swyx. RAG is Dead, Context Engineering is King[EB/OL]. (2025-08-19)[2025-10-21]. https://www.latent.space/p/chroma
万字拆解. RAG已死吗?上下文工程(context engineer)为何为王?[EB/OL]. (2025-09-03)[2025-10-21]. https://www.woshipm.com/ai/6264065.html