6个有效的上下文工程技术
你的RAG系统返回完美的块。你的提示精美地制作。但LLM仍然产生幻觉。
你询问最新的退款政策。系统将2018年到2026年的50页文档倒入上下文。
LLM看到矛盾的政策,感到困惑,并编造答案。
你添加了更多文档。响应变得更糟。这不是提示问题,这是上下文问题。
转变: 提示工程告诉模型如何说话。上下文工程控制它在说话时看到什么。
2026年的性能提升来自动态上下文选择、压缩和内存管理。不是来自巧妙的提示措辞。
这里有6种上下文高效技术,可以将生产系统与演示区分开来。
什么是上下文工程?
上下文工程是在运行时决定AI模型看到什么信息、何时看到它以及如何结构化的做法。
- 提示工程专注于你如何问。
- 上下文工程专注于你提供什么。
在真实系统中,大型语言模型失败不是因为它们不理解指令。它们失败是因为它们被显示太多不相关的信息、冲突的数据或缺少关键事实。
上下文工程通过将上下文视为动态管道而不是静态提示来解决这个问题。
它包括:
- 选择正确的文档而不是倾倒所有内容
- 将长源压缩为特定于任务的摘要
- 在检索之前重新制定模糊的用户查询
- 跨会话注入内存和用户状态
- 使用实时工具和数据将答案落地
- 结构化所有输入,以便模型知道什么最重要
简而言之: 上下文工程是你在生产中控制模型注意力的方式。
当上下文被正确工程化时,即使较小的模型也能很好地工作。 当它做得不好时,即使最好的模型也会产生幻觉。
1、选择性检索:停止倾倒所有内容
幼稚的方法: 检索50个文档,将它们全部倾倒到上下文中,希望模型找到它需要的东西。
问题: 大型上下文窗口仍然有不均匀的注意力。模型关注早期和后期标记。中间被遗忘。这被称为"迷失在中间"效应。
更好的方法: 评分、重新排序和修剪。只让相关、非冗余的部分进入上下文窗口。
有效的三个步骤:
- 首先, 相关性重新排序。初始搜索基于向量相似性或关键词匹配返回前50个结果。但相似性并不总是意味着相关性。交叉编码器模型通过实际读取查询和每个文档来重新排序这些结果。这较慢但更准确。重新排序后只保留前5个。
- 其次, 冗余移除。你的文档可能在多个地方解释相同的概念。营销材料、技术规格和FAQ可能都提到相同的功能。使用嵌入对类似块进行聚类。如果两个块的余弦相似性高于0.9,它们基本上是重复的。删除一个。模型不需要看到相同的事实10次。
- 第三, 任务感知过滤器。利用元数据对你有利。每个文档都应该有标签:文档类型、最后更新日期、产品版本、地区、部门。当查询进来时,根据重要内容进行过滤。如果有人询问欧盟法规,不要向他们显示美国合规文档。
真实示例: 查询是"总结欧盟客户最新的退款政策变更。"
- 之前: 你的向量搜索返回50个关于退款的块。一些来自2018年,当时你有不同的政策。一些来自美国文档。一些来自从未打算让客户看到的内部备忘录。LLM看到关于14天与30天窗口、不同排除项、冲突程序的矛盾信息。它试图综合所有内容并产生一个实际上不存在的政策的幻觉。
- 之后: 过滤
region='EU'和updated_at >= 2025-01-01。这立即删除了40个块。使用在问答对上训练的交叉编码器重新排序剩余的10个块。保留前5个。检查近似重复(余弦相似性>0.9)。最终结果:3个来自当前欧盟政策的高度相关、非冗余块。
LLM现在看到: 明确的政策声明、具体的时间线、例外列表。所有都是当前的、相关的、一致的。没有幻觉。没有困惑。
结果: 更短的提示、更清晰的答案、没有矛盾。实验表明,当你删除嘈杂上下文时,准确性提高15-30%,令牌节省20-40%。但真正的胜利是信心。当你确切知道模型看到了什么上下文时,你可以调试失败。当你倾倒50个块时,你只是在希望。
实现提示: 从简单开始。为所有文档添加last_updated时间戳。首先按日期过滤。这单独消除了大多数噪音。然后添加重新排序。然后添加去重。在测量改进的同时构建复杂性。
2、上下文压缩:让每个令牌都重要
长的原始文档超过实际上下文限制并稀释注意力。案例研究表明,在保持或提高准确性的同时,令牌减少50-75%。
见解: 将长源文档压缩为密集的、特定于任务的摘要,然后将其放入上下文中。不是通用摘要。特定于任务的摘要。
三种压缩策略:
- 带有约束的LLM摘要.: 不要只是说"总结这个文档。"要说"只总结这个文档,保持2025年1月之后提到的价格变化事实。"约束是关键。它告诉LLM保留什么和删除什么。每个检索到的文档都有自己的基于查询的约束。结果:5-10个要点而不是3000个令牌。
- 句子级评分: 对每个句子与查询的相关性进行评分。使用较小的模型(如BERT变体)计算相关性分数。按分数对句子进行排序。只保留前20%。这称为上下文保留压缩。快速、有效,自动保留最相关的信息。
- 分层摘要: 这对于非常长的文档有效。将文档分块到各个部分。独立总结每个部分。然后将摘要总结到元摘要中。你得到一个3级层次结构:完整文档 → 部分摘要 → 最终摘要。使用适合你的上下文预算的级别。
真实示例: 查询是"比较我们API文档中计划A与计划B的速率限制。"
你的API文档是30页。它涵盖身份验证、速率限制、错误代码、webhook、分页、SDK和更新日志。只有2页提到速率限制。
管道: 检索3个相关部分(总共30页)。每个部分是10页。运行带有指令的LLM摘要器:"仅提取计划A和计划B的速率限制和配额。包括具体数字。忽略身份验证、示例和其他功能。"
第一部分摘要(是10页,现在是100个令牌):"计划A:1000请求/小时,10000/天。计划B:5000请求/小时,50000/天。两个计划:20%的突发允许1分钟。"
第二部分摘要: "速率限制错误返回HTTP 429。Retry-After标头指示等待时间。速率限制在UTC午夜重置。"
第三部分摘要: "企业计划提供自定义速率限制。联系销售。"
将这3个摘要(总共500个令牌)加上查询输入到最终生成。模型确切地看到它需要的东西。不需要在身份验证流程或SDK示例中挣扎。
结果: 模型获得专注的信息,而不是希望它正确阅读30页并提取相关部分。
权衡: 摘要增加延迟。你为每个文档进行额外的LLM调用。对于3个文档,那是3个额外的调用。但你在最终生成调用中节省令牌,这通常是昂贵的一个。测量你的具体情况。通常,权衡有利于压缩超过2000个令牌的文档。
3、分层布局:结构信号重要性
不要将所有内容混合到一面文本墙中。LLM对上下文的早期与后期部分有不同的关注。结构化区域帮助它们推断什么是指令与数据与示例。
想想你如何阅读研究论文。 你知道摘要是摘要。介绍提供上下文。方法部分有技术细节。讨论解释结果。这种结构帮助你高效地提取信息。
LLM从相同结构中受益。在上下文内设计具有清晰部分的固定结构。
这是一个经过验证的布局:
[系统规则]
你是一个精确的金融研究助手。
仅从提供的上下文回答。
如果信息缺失,说"我没有那个信息。"
永远不要对数值数据做假设。
[任务]
目标:使用下面的上下文回答用户问题。
输出格式:以直接答案开始,然后提供支持细节。
[用户资料 / 内存]
- 风险承受能力:低
- 投资期限:5-10年
- 地区:印度
- 之前的会话:询问HDFC Bank 3次,对银行业务表现出兴趣
- 偏好:保守投资、股息股票
[检索到的上下文]
文档1:HDFC Bank 2024年第四季度收益报告
- 收入:₹45,000亿卢比(同比增长15%)
- 净利润:₹12,000亿卢比(同比增长18%)
- NPA比率:1.2%(从1.5%改善)
文档2:2024年第四季度竞争对手分析
- ICICI Bank收入增长:同比增长12%
- SBI利润增长:同比增长10%
- HDFC Bank在数字银行采用方面领先
[工具输出]
- live_price("HDFCBANK"):₹1,842.50(2分钟前更新)
- news_summary("HDFCBANK"):"宣布FY2024每股₹19的股息。除息日期2025年3月15日。"
- sector_analysis("Banking"):"由于积极收益,银行业务本月上涨8%"
[问题]
用户:HDFC Bank有什么最新消息?
注意这个结构的作用:
系统规则首先出现。 模型在任何其他东西之前看到这些。它们设定边界。
任务澄清接下来出现。 模型知道它的目标。
用户资料提供个性化上下文。 模型知道这个用户更喜欢保守投资并且之前询问过HDFC。这影响它如何构建答案。
检索到的上下文被清楚地标记为源材料。 模型知道这是它应该参考的权威信息。
工具输出被标记为实时数据。 模型知道这些是当前的和权威的。不是推测。
问题最后出现。 模型在看到需要回答的内容之前拥有所有上下文。
这向模型澄清了什么是什么。 减少冲突的指令。让你独立地交换部分而不会破坏所有内容。对于不同代理需要不同上下文布局的多代理系统至关重要。
为什么这胜过非结构化上下文:
自己测试一下。给LLM一个5000令牌的块,其中混合了指令、数据、示例和问题。然后在结构化部分中给它相同的信息。测量准确性。在大多数领域中,结构化获胜10-20%。
原因: 注意力模式。LLM学习到开始和结束的文本更重要。通过将关键指令放在开始并将问题放在结束,你与模型的偏见合作,而不是反对它们。
4、动态查询重新制定:修复模糊问题
用户问题很模糊。缺少关键字、实体、时间范围。不要使用原始问题进行检索。让LLM先重写或扩展它。
研究表明,在检索之前生成优化的搜索查询时,会有显著提升。
这是反直觉的。感觉添加一个额外步骤应该会让事情变糟。但是模糊查询返回模糊结果。精确查询返回精确结果。
有效的三种模式:
- 代理优先的澄清: 不要猜测用户的意思,询问。代理响应"为了帮助你比较性能,我需要知道:哪个时期?我应该包括哪些竞争对手?哪些指标对你最重要(收入、利润、市场份额)?"用户提供具体信息。现在检索是精确的。
这只适用于具有多回合功能的代理。不要将其用于单次问答系统。但对于代理,它很强大。如果这意味着得到更好的答案,用户不介意回答2-3个澄清问题。
- HyDE(假设文档嵌入): 这很聪明。用户问"我们的产品有哪些最新改进?"与其搜索这个问题,不如让LLM生成一个假答案:"我们最新的产品改进包括重新设计的仪表板、快40%的加载时间、新的协作功能和增强的移动应用程序。"嵌入这个假答案。使用该嵌入进行搜索。
为什么这有效?因为假答案使用与你的实际文档相同的语言。你的文档不说"最新的改进有哪些?"它们说"我们重新设计了仪表板"和"加载时间快40%。"假答案的嵌入比问题更好地匹配真实文档的嵌入。
- 多查询扩展: 生成3-5个改写的查询。"最新的产品改进"变成:"最近的产品更新"、"本季度发布的新功能"、"产品增强更新日志"、"版本2.0中的新内容"。为每个查询进行检索。合并并去重结果。这涵盖语义变体和表达相同信息的不同方式。
真实示例: 用户问"上季度我们的表现与竞争对手相比如何?"
这个问题很模糊。哪些竞争对手?哪一年的上季度?什么指标的表现?收入?利润?市场份额?用户增长?
动态步骤: LLM重写为"从内部财务报告中比较公司X与竞争对手A、B和C的2024年第四季度(2024年10月-12月)收入增长和利润率。"注意具体性。确切的时间段。确切的竞争对手。确切的指标。具体的来源。
检索使用这个更丰富的查询加上内存中的已知竞争对手名称(分层布局的用户资料部分注意到该用户之前询问过竞争对手A和B)。
结果: 上下文与用户的意思一致,而不仅仅与他们输入的内容一致。LLM获得精确数据而不是模糊相关的内容。
实现模式:
用户查询
↓
LLM重写器:"将其扩展为精确的搜索查询。
添加时间范围、实体名称和具体指标。"
↓
重写的查询
↓
检索
重写器应该可以访问:当前日期、用户资料、会话中的先前查询。这让它推断"上季度"意味着具体日期和"竞争对手"意味着该用户关心的特定公司。
5、内存与状态:保留关系,而不仅仅是事实
这是初学者困惑的地方。检索回答问题。内存保留关系。
检索: 现在搜索所有文档的相关块。每个查询都被视为独立的。如果你今天询问HDFC Bank,明天再次询问,检索两次都从头开始搜索。
内存: 记住该用户询问了HDFC Bank三次,更喜欢保守股票,生活在印度,并且有5-10年的投资期限。这个上下文在会话之间持久存在。
给代理持久内存而不是依赖巨大的历史字符串。存储并重新注入摘要、偏好和跨轮次的关键事实。
三种类型的内存:
- 情景内存: 过去对话的摘要。"上次会议我们讨论了为法律文档构建RAG系统。用户担心处理100多页的合同。我们探索了分块策略并决定使用512个令牌块和50个令牌重叠的语义分块。"
这不是完整的对话。它是摘要。你不存储10,000个令牌的对话历史。你存储了重要内容的200个令牌摘要。
- 语义内存: 过去交互的向量数据库。"用户3周前询问了关于HDFC的类似问题。该查询是关于季度收益。当前查询是关于股息公告。两者都与HDFC财务表现相关。重用来自先前查询的公司基本面上下文。"
这让你发现模式。如果用户询问HDFC收益,然后HDFC竞争对手,然后HDFC风险因素,你可以预测他们正在对HDFC进行深入研究。主动显示相关信息。
- 偏好内存: 很少改变的稳定事实。"用户是初级投资者"、"更喜欢TypeScript而不是JavaScript"、"风险承受能力:低"、"在医疗保健领域工作"、"位于孟买时区。"
这些事实通知每次交互。初级投资者获得更简单的解释。低风险用户获得与高风险用户不同的推荐。
为什么这胜过填充聊天历史:
想象一个50回合的对话。那很容易是20,000个令牌的历史。你无法将其放入上下文。即使你能,也不应该。大多数与当前问题无关。
相反:将50个回合压缩为5个情景摘要(1000个令牌),提取10个稳定偏好(200个令牌),检索与当前问题相关的3个最相关的过去情景(600个令牌)。总计:1800个令牌而不是20,000。而且它更加专注。
你压缩并仅选择当前回合的相关部分。避免达到上下文限制。保持注意力清晰。代理在不使用更大模型的情况下变得个性化。
实现模式:
- 每次回合后: LLM调用以总结。"总结这个对话回合。用户问了什么?我提供了什么?用户表达什么偏好或需求?"将此摘要与嵌入一起存储在你的向量数据库中。
- 每次回合前: 使用当前查询通过过去情景摘要的向量搜索。检索前3个相关情景。从单独的表加载稳定偏好(这些不需要向量搜索,它们总是被包括)。将所有这些插入到分层布局的[用户资料 / 内存]部分。
与编码助手的真实示例:
用户正在构建React仪表板。在10个会话中,他们询问了关于状态管理、API集成、组件组合和测试的问题。
存储在内存中:
- 技术栈:React、TypeScript、Redux、Jest* 编码风格:更喜欢函数组件、使用hooks、喜欢描述性变量名
- 项目上下文:构建医疗保健数据可视化仪表板
- 过去的问题:Redux异步操作有问题,通过使用Redux Toolkit解决
- 常见模式:使用自定义hooks进行API调用、组件更喜欢Material-UI
当用户询问新问题时: "我应该如何处理仪表板中的实时更新?"
在检索之前,代理看到内存: 构建React/TypeScript仪表板,使用Redux,更喜欢hooks模式,正在处理需要更新的医疗保健数据。
代理现在可以提供上下文答案: "鉴于你的Redux设置和对hooks的偏好,我建议使用Redux Toolkit的RTK Query和websocket订阅。这适合你的现有模式。这里是如何..."
将其与没有内存的代理进行比较,后者会问: "你在使用什么框架?你的状态管理是什么?什么类型的数据?"用户已经回答了这些问题10次。内存防止了那种沮丧。
结果: 上下文保持专注。代理保持一致。用户感到被理解。
6、工具感知上下文:将答案基于现实
使用模型上下文协议(MCP)等协议和函数调用,以便模型以一致的格式看到来自工具/API/数据库的实时、基于数据。
不要依赖静态文本知识。
- 这是上下文工程,因为你正在改变运行时信息进入上下文的方式。
- 作为结构化上下文注入的工具输出大大减少幻觉并保持答案当前。
纯LLM知识的根本问题: 它是静态的。在具有截止日期的数据上训练。不知道今天的股票价格、当前天气、最近的新闻或你的内部数据库状态。
工具通过提供运行时数据来解决这个问题。但集成不良的工具会产生新问题。
三种模式:
MCP风格工具注册表。 代理没有硬编码的工具集成。它在运行时发现可用的工具。
代理问: "哪些工具可以解决这个问题?" MCP服务器响应工具描述、输入模式和功能**。模型决定根据任务调用什么。**
这意味着你可以添加新工具而无需重新部署代理。
新工具? 将它添加到MCP服务器。代理自动发现它。这是生产系统扩展到数十或数百个工具的方式。
结构化工具结果。不要从工具返回原始字符串。返回具有清晰键的JSON:price、date、source、confidence。将它们作为分层布局中的单独部分插入,标记为权威事实。
示例: 工具返回{"price": 1842.50, "currency": "INR", "timestamp": "2025-02-19T14:30:00Z", "source": "NSE", "change": "+2.3%"}。模型看到结构化数据。它知道1842.50是价格,而不仅仅是出现在文本中的数字。
受保护的回答。对可靠性至关重要。指示: "仅从[工具输出]和[检索到的上下文]回答。如果信息缺失,说'我在当前数据源中没有该信息。'永远不要编造数字或事实。"
这防止模型在工具返回不完整数据时产生幻觉。如果价格工具失败,模型会这样说。它不会猜测。
与金融助手的真实示例:
查询:"HDFCBANK的最新股价和今天的新闻是什么?"
流程:
代理通过MCP发现可用工具:get_live_price、get_news、get_historical_data、get_competitors、get_analyst_ratings。
代理基于查询决定调用get_live_price和get_news。
调用两者,获得结构化响应:
{
"get_live_price": {
"symbol": "HDFCBANK",
"price": 1842.50,
"currency": "INR",
"timestamp": "2025-02-19T14:30:00Z",
"change": "+2.3%",
"volume": 12500000
},
"get_news": {
"articles": [
{
"headline": "HDFC Bank宣布₹19股息",
"summary": "董事会批准FY2024每股₹19的股息",
"date": "2025-02-19",
"source": "经济时报"
}
]
}
}
这些被插入到分层布局的[工具输出]部分加上最后的用户问题。模型生成答案:"HDFC Bank目前交易价格为₹1,842.50,今天上涨2.3%。银行宣布FY2024每股₹19的股息。"
注意: 模型引用了工具输出的具体数字。没有产生幻觉。没有将股息金额与股价混淆。
关键见解: 提示措辞简单。力量来自工程化正确的运行时上下文。模型成功是因为它看到了结构化的、权威的数据,而不是因为你写了一个完美的提示。
实现提示: 从3-5个关键工具开始。让它们可靠地工作。然后扩展。不要试图在第1天集成50个工具。每个工具都需要错误处理、重试逻辑、超时管理和结果验证。首先为几个工具构建该基础设施。
7、决策框架
- 当你拥有大型文档集合(1000+文档)、检索返回太多结果(20+块)、你正在达到上下文限制(接近32K令牌)或你需要减少成本(令牌不是免费的)时使用选择性检索。 当文档很长(每个超过5000个令牌)、查询需要埋藏在文本中的特定信息或你为每个令牌付费并想要优化*时使用压缩。如果你的文档已经很短(1000个令牌以下),不要压缩。压缩开销不值得。
- 当构建多代理系统(每个代理需要不同的上下文结构)、管理多个上下文源(文档、工具、内存都存在)或调试(结构化部分让你隔离哪个部分失败)时使用分层布局。单一回合问答具有一个源?布局可能过度。
- 当用户询问模糊问题(在消费者产品中常见)、领域使用技术术语但用户不使用(医疗、法律、金融领域)或你需要桥接查询-文档词汇差距(用户说"退款"但文档说"退货商品授权")时使用查询重新制定。
- 当构建对话代理(聊天产品、编码助手)、用户跨会话返回(具有登录用户的B2B产品)、你需要个性化(推荐、偏好很重要)或上下文历史将超过限制(超过20回合的对话)时使用内存。 当答案需要实时数据(股票价格、天气、可用性)、你正在构建代理而不是聊天机器人(代理采取行动,聊天机器人只是说话)、准确性取决于当前信息(没有产生幻觉的数字)或你想要减少幻觉(工具提供基本事实)时使用工具感知上下文。
关于成本的说明: 每种技术都有成本。重新排序需要计算。压缩需要LLM调用。内存需要存储。工具需要API调用。测量改进是否证明成本合理。有时一个准确性略低的简单管道比一个成本高10倍的复杂管道更好。
8、结束语
- 提示工程: "你是一个有用的助手。简明扼要。一步步思考。"
- 上下文工程: "模型实际上需要什么信息?我如何让它到达那里?我如何构建它以便模型关注?"
第一个是你编写一次并重用的静态文本。第二个是适应每个查询的动态管道。
在2026年,生产系统在上下文工程上获胜。提示只是最后一公里。它们很重要,但它们不是杠杆所在。
如果你的RAG准确性停留在60%,你的上下文就是问题。如果你的代理产生数字幻觉,你的上下文就是问题。如果你的成本正在爆炸,你的上下文就是问题。如果用户抱怨不相关的答案,你的上下文就是问题。
如果幻觉的修复是"更好的提示",你正在调试错误的层。
修复上下文管道,模型将完成其余工作。
原文链接: Context Engineering: The 6 Techniques That Actually Matter in 2026
汇智网翻译整理,转载请标明出处