到了2026年,我们已经拥有100万token的上下文窗口。Gemini、GPT-5和Claude(配合扩展思考)都支持这种规模。演示中,模型可以一次读完整本书。那个梦想似乎终于成真了:只要把所有内容都塞进上下文,让模型自己处理即可。
但现实一如既往,要复杂得多。100万token只是技术容量,并不保证实际性能。现实场景中的模型通常在5K–50K token的上下文范围内表现最佳。达到100K以上后,细微的质量问题便会出现;达到500K以上后,模型会反复漏掉重要信息;到了1M,模型就会不堪重负。
这种现象称为“上下文退化”,它确实存在,已有充分研究记录,也能在评估中观察到。这意味着你不能只是把所有内容一股脑塞进上下文,就认为万事大吉。你需要上下文工程:有意识地决定该纳入什么、该总结什么、该动态检索什么,以及如何组织最终形成的上下文。
本文将介绍面向严肃生产系统的有效上下文工程模式与实践方法。
什么是上下文退化
“上下文退化”是一种经验现象:即使上下文仍在技术上限之内,LLM的性能也会随着上下文增长而下降。
具体的失效模式包括:
中间信息遗失(Liu et al., 2023)。模型会更多关注上下文开头和结尾的内容,对中间信息的利用则不那么可靠。同一个事实放在100K token上下文中的50K位置,比放在1K或99K位置时更容易被遗漏。
近因偏差。 模型会过度重视较新的内容。在对话历史中,较早的上下文实际上会逐渐变得不可见。
容易受干扰项影响。 即使任务根本不需要某些内容,把这些无关内容放进上下文也会降低性能。模型必须进行筛选,而筛选过程中难免会受到干扰。
推理质量下降。 随着上下文增长,多步推理会变得不那么可靠。模型需要追踪的内容更多,追踪质量也会随之下降。
成本与延迟。 这与质量无关:大上下文按token计费,成本高;对许多模型而言,延迟会随token数量线性增加,因此速度也更慢。
这些并非理论上的担忧。生产实践反复表明,直接使用未经筛选的大上下文,其效果始终不如经过精心整理的上下文。
核心原则:少即是多
核心认识是:上下文是一种宝贵且会随使用量增加而退化的资源,应当有策略地使用。
经过精心筛选的30K token上下文,通常胜过把所有内容全部塞入的300K token上下文。无论质量、成本还是延迟,较小的上下文通常都更有优势。
这会改变工程工作的重点。问题不再是“想办法往上下文里放入更多内容”,而是“确定哪些内容确实需要放入上下文,并以恰当方式放进去”。
上下文预算
把上下文看作一项需要分配的预算。
下面是一个客户支持智能体的典型分配:
上下文总预算:30K token
- 系统提示词:1500 token(5%)
- 工具描述:1000 token(3%)
- 用户资料/上下文:500 token(2%)
- 对话历史摘要:1000 token(3%)
- 近期完整对话轮次:4000 token(13%)
- 检索到的相关知识:12000 token(40%)
- 用户当前消息:500 token(2%)
- 输出token预算(回复):10K token(33%)
每个组成部分都在争夺空间。随着上下文增长,你必须作出取舍。
关键纪律是明确规定各部分的分配,不让任何一部分无限增长。
模式1:分层对话记忆
在多轮对话中,完整历史会无限增长。大多数生产系统都会采用分层记忆:
第1层:完整保留近期轮次。 原样保留最近5–10轮交流。
第2层:总结较早轮次。 将对话中更早的内容压缩成简短摘要。
第3层:提取事实。 从对话中提取关键信息,例如用户姓名、偏好和已作出的决定,并存为结构化事实。
实现方式如下:
每一轮执行:
1. 获取对话历史。
2. 原样保留最近10轮。
3. 将第11–30轮总结为200字(“此前,用户讨论了X,我们一致决定Y”)。
4. 将第31轮及更早内容缩减为提取出的事实(“用户偏好Python。用户使用企业版套餐。”)。
5. 无论对话多长,记忆总量都维持在约2K token。
这是所有长时间对话的基础模式。缺少这套机制,对话质量就会随着长度增加而下降。
需要注意的是,摘要必须保留智能体后续会用到的信息。如果用户在第5轮提到账户号码,而智能体没有将其纳入长期记忆,那么到第50轮时,这个账户号码就会丢失。
执行总结时,应明确说明需要保留哪些内容:
总结截至目前的对话。保留:
- 关于用户的所有事实(姓名、角色、偏好、账户信息)。
- 已作出的所有决定。
- 所有尚未履行的承诺或待跟进事项。
- 当前对话目标。
舍弃:
- 寒暄。
- 重复信息。
- 已经解决的问题所涉及的详细推理过程。
模式2:即时检索
不要预先加载上下文,而要在内容变得相关时再检索。
一种反模式是把用户的所有文档都塞进上下文,“以防模型需要”。大多数查询只需要其中很小一部分,这样做既浪费上下文,也会损害性能。
更好的方式是根据当前查询检索文档。不同查询获得不同文档,每次调用的上下文总量保持较小,相关性则保持较高。
这其实就是严谨地运用RAG。关键在于,不要因为“放得下”就忍不住把所有内容都放进去。长上下文模型出现后,即使经验丰富的团队也很容易受到这种诱惑。
模式3:压缩表示
对于确实需要长期保留在上下文中的信息,应使用压缩表示。
原文(冗长):
这名用户从事软件工程已有8年,最初在一家名为Acme Corp的小型初创公司负责后端系统。3年后,这名用户跳槽到规模更大的Beta Inc,从事前端工作,目前在Gamma LLC负责机器学习系统。
压缩后:
用户:软件工程师,8年经验,目前在Gamma LLC从事机器学习。此前:Acme后端(3年),Beta前端。
压缩版本用更少的token保留了相关事实。对于大多数用途,模型使用两个版本的效果相当。
这种方法可以用于:
- 用户资料。
- 文档摘要。
- 过往对话上下文。
- 知识库条目(不需要完整内容时)。
代价是压缩会丢失细节。需要保留细节时使用全文,不需要时再使用压缩版本。
模式4:分层检索
面对非常庞大的知识库,应采用分层检索。
第1步: 根据查询检索大类或文档摘要。
第2步: 在最相关的类别中检索具体文本块。
第3步: 最终只把第2步选出的文本块放入上下文。
这样可以避免“我有10K份文档,那就把它们全嵌入上下文”的做法。通过逐层收窄范围,上下文可以保持精简。
还有一种变体:在文本块进入主要调用之前,先让一个小型LLM调用筛选出最相关的内容。这样会增加少量成本,却能显著减少上下文膨胀。
模式5:反思上下文
对于执行长期任务的智能体,应定期检查当前上下文中有什么,以及真正应该保留什么。
智能体每执行10个步骤,就会:
1. 检查当前上下文。
2. 找出与正在进行的工作相关的内容。
3. 总结或删除已经不再需要的内容。
4. 记录还有哪些额外上下文可能有帮助。
5. 用整理后的版本替换旧上下文。
这相当于对上下文执行“垃圾回收”。如果没有这一步,智能体会不断积累陈旧信息,挤占新信息和相关信息的空间。
实现这一模式需要自定义编排,因为大多数框架都不能原生处理。具体做法是在不同步骤之间加入“记忆整合”阶段,用来调整上下文内容。
模式6:动态上下文窗口
智能体执行过程中的不同环节,所需的最佳上下文大小可能不同。
- 决策步骤: 使用较小的上下文,聚焦当前需要作出的决定。
- 综合步骤: 使用较大的上下文,纳入多个信息来源。
- 生成步骤: 使用中等大小的上下文,并提供风格与格式参考。
一种可行模式是,让智能体工作流中的每个步骤使用不同的上下文结构,由编排层决定哪些内容进入哪个步骤。
这要求把智能体的工作拆分成明确步骤,而不是放进一个大循环。此处的框架选择很重要:LangGraph可以自然地处理这种模式,直接调用API则需要手动实现。
模式7:根据位置安排内容
既然模型会更多关注上下文的开头和结尾,就应把重要内容放在这些位置。
效果较差: 把关键指令埋在很长的系统提示词中间。
效果更好: 把关键指令放在最开头,并在接近末尾处再次强调。
在包含多份检索文档的RAG场景中,可以把最相关的文档放在开头,把相关性第二高的文档放在末尾,相关性较低的文档则放在中间。
这是一种战术性优化,但对输出的影响可以实际测量。
模式8:有选择地总结
总结方式并非全都一样。应根据下游任务的需要来设计摘要。
较差: 使用通用摘要,导致用户偏好被丢弃。
更好: 在摘要中明确保留与下游任务相关的用户偏好。
总结这份文档,重点关注:
- 已作出的技术决策。
- 提到的利益相关方。
- 尚未解决的问题或风险。
舍弃:
- 团队已经了解的一般背景。
- 重复的观点。
这段总结提示词是专门针对下游用途设计的。
模式9:结构化上下文
纯文本只是一种选择。结构化上下文(JSON、XML或特定标记)可以用更紧凑的形式承载信息。
冗长的叙述:
客户名叫John Smith,自2023年3月起成为客户。目前使用Pro套餐,按月付费,每月29美元。他启用了3项集成:Slack、Notion和Linear。过去30天的使用量为中等,共调用API 1,250次。
结构化表示:
{
"customer": {
"name": "John Smith",
"since": "2023-03",
"plan": "Pro",
"billing": "monthly $29",
"integrations": ["Slack", "Notion", "Linear"],
"usage_30d": {"api_calls": 1250, "tier": "moderate"}
}
}
结构化版本更短,而且通常更便于模型使用。模型可以迅速定位具体事实。
但要注意,并非所有模型都同样擅长处理结构化输入。应针对你的用例测试两种格式。
模式10:按优先级分层上下文
按照优先级划分上下文:高优先级内容始终纳入,中优先级内容在相关时纳入,低优先级内容按需检索。
始终纳入:
- 系统提示词(身份、行为)。
- 当前用户上下文(必要事实)。
- 近期对话。
相关时纳入:
- 与查询匹配的检索文档。
- 最近步骤产生的工具输出。
按需获取:
- 智能体通过工具调用请求的特定数据。
- 超出近期窗口的历史上下文。
“按需获取”模式对系统扩展至关重要:智能体只在需要时检索所需内容,而不是预先加载一切。
模式11:淘汰策略
上下文接近上限时,应该淘汰什么?
- 基于时间顺序: 最旧的内容最先淘汰。
- 基于相关性: 与当前任务最不相关的内容最先淘汰。
- 基于重要性: 标记为低重要性的内容最先淘汰。
一种实用做法是为上下文项标记优先级。需要淘汰时,按照优先级顺序删除。
context_items = [
{"content": "...", "priority": "critical"}, # 永不淘汰
{"content": "...", "priority": "high"}, # 最后淘汰
{"content": "...", "priority": "medium"}, # 必要时淘汰
{"content": "...", "priority": "low"}, # 最先淘汰
]
def evict_to_fit(items, budget):
items_by_priority = sorted(items, key=lambda x: priority_value(x.priority))
while total_tokens(items) > budget:
items.remove(items_by_priority.pop(0)) # 删除优先级最低的项
return items
模式12:缓存重复使用的上下文
许多调用会重复使用相同的上下文,例如相同的系统提示词、工具描述和用户资料。
目前大多数供应商都支持提示词缓存:
- Anthropic:在消息中显式添加
cache_control标记。 - OpenAI:自动缓存前缀匹配的请求。
- Google:通过API显式创建缓存内容。
重复使用相同前缀时,缓存版本速度更快、价格更低,通常可便宜90%。
如果智能体会在一个会话中执行大量调用,应确保静态部分(系统提示词、工具、用户上下文)可以缓存。把动态内容(当前步骤、近期结果)放在可缓存前缀之后。
这是投资回报率最高的优化之一。假设会话中的50次调用都使用同一个10K token静态前缀:第一次按全价计费,之后每次都便宜90%,节省的成本相当可观。
模式13:上下文感知提示词
提示词可以引导模型更好地使用上下文:
请参考下方文档回答用户的问题。务必引用具体文档,并摘录相关段落。
如果在所提供的文档中找不到答案,请明确说明。不要编造信息。
如果多份文档中的信息都与问题有关,请综合这些信息,并指出其中不一致之处。
这种提示方式可以减少基于上下文回答任务中的幻觉,并提高引用质量。
何时应该使用更长的上下文
尽管存在上下文退化,但对于某些任务而言,更长的上下文确实更好:
单文档分析。 如果任务是“分析这份合同”,把整份合同放进上下文通常比分块检索更好。
比较多个项目。 并排比较10份合同时,把10份合同全部放进上下文会更有帮助。
在上下文中编辑代码。 要修改一个5K行代码文件中的函数,把整个文件放进上下文比只使用检索出的片段更容易。
总结完整对话。 要总结一段长对话,在一定范围内,使用完整上下文的效果更好。
一般规律是:如果任务本质上需要理解不同内容之间的关系,更长的上下文会有帮助;如果只需一小部分内容就能完成任务,则较小的上下文更好。
一个实用的经验法则是:50K token以内的上下文通常没有问题;50K–200K token仍可使用,但质量会有所下降;200K token以上的上下文往往不如更短的上下文。务必通过实际测试验证。
评估纪律
如何知道上下文工程是否有效?答案是评估。
具体可以开展以下评估:
召回测试。 在长上下文的不同位置埋入关键事实,测试模型能否使用这些事实,并衡量召回率随位置的变化。
干扰项测试。 对比同一查询在包含和不包含无关上下文时的表现,衡量性能下降幅度。
长上下文与RAG对比。 分别使用完整上下文和检索出的文本块回答相同查询,并比较质量。
token效率。 衡量每花一美元获得的质量。上下文越长,成本越高;质量是否也相应提升?
这些评估能够揭示你的上下文选择是否真的带来帮助。缺少评估,一切都只是猜测。
完整示例:研究助理
来看一个现实案例:为小型团队构建AI研究助理。
任务: 回答有关200份文档构成的语料库的问题,其中包括论文、内部文档和会议记录。
简单粗暴的做法: 把所有文档嵌入上下文,共300K token。质量尚可,但成本高、延迟大。
经过工程优化的做法:
上下文预算:25K token
- 系统提示词:1500 token(已缓存)
- 工具描述(search、fetch_doc等):800 token(已缓存)
- 对话记忆:1500 token(最近10轮)
- 针对当前查询检索的文本块:18000 token(通过RAG取得最相关的12个文本块)
- 用户当前问题:200 token
- 输出预算:约3000 token
智能体根据问题动态检索文本块。对话记忆保留近期上下文,静态元素则进行缓存。
结果:
- 延迟:2–3秒,而使用300K上下文时为10–15秒。
- 成本:约€0.01/次查询,而原来约为€0.10。
- 质量:根据评估集测得的结果,质量有所提升,因为模型能够恰当地关注相关内容。
这就是严谨的上下文工程:它不是一次性决定,而是需要持续调优。
常见错误
以下是几种常见模式:
错误1:“上下文越多越好。” 一遇到质量问题,就试图用更长的上下文来解决。实际情况往往恰恰相反。
错误2:没有上下文预算。 各组成部分无限增长。用户资料部分膨胀到5K token,检索文本块部分膨胀到50K token,毫无约束。
错误3:忽略位置。 把关键指令埋在中间,指望模型自己找到。模型有时能找到,但往往找不到。
错误4:用冗长叙述表达事实。 明明结构化数据就足够,却使用长句,浪费token。
错误5:不总结对话。 对话不断增长,直至超出限制,随后要么质量逐渐下降,要么直接失败。
错误6:不使用缓存。 每次调用都为重复的静态前缀支付全价,白白错失轻松节省成本的机会。
错误7:不评估上下文选择。 想当然地认为“更好的上下文工程”正在奏效,实际却未必如此。
错误8:使用通用摘要。 总结时不考虑下游任务需要什么,导致重要信息丢失。
要点总结
长上下文窗口确实已经存在,但这不代表可以忽视上下文工程。远未达到技术上限时,质量就会开始下降,成本与延迟也同样不可忽视。
上下文工程需要遵循以下实践:
- 把上下文视为一项预算。
- 对记忆进行分层:近期内容原样保留,较早内容进行总结,最早内容提取为事实。
- 即时检索,而不是预先加载。
- 在不丢失信息的前提下进行压缩。
- 把关键内容放在模型注意力较高的位置。
- 按优先级对上下文进行分层。
- 缓存静态前缀。
- 持续评估。
与简单粗暴地“把一切都扔进上下文”相比,这些模式能让系统效果更好、速度更快、成本更低。
对于成熟的生产系统,上下文工程是杠杆效应最高的领域之一。底层技术并不复杂;能否严谨地运用这些技术,才是“演示可用”与“生产可靠”之间的分水岭。
持续投入这些模式,并建立严格的工程纪律。最终得到的AI系统,才能在面对更多数据、更长对话和更高复杂度时平稳扩展。



