当前位置: 首页 > news >正文

上下文窗口不是“内存”——Context Engineering中的信息压缩与优先级淘汰策略

“把整本书塞进窗口,模型就什么都能记住”——一个代价高昂的幻觉

2026年,Gemini 2.0宣称支持2M Token上下文,Claude 4做到500K,GPT-5到了1M。看起来一个窗口能塞下一整本书、整个代码库、一整个月的聊天记录。但你试过就知道:把500页技术文档塞进去,模型到第200页时已经忘了第10页讲什么;在Cursor里打开整个项目,Agent改到第3个文件时开始“幻觉”;把过去100轮对话全部传进去,模型的回复越来越平庸。

问题不在窗口大小,在上下文管理。

Andrej Karpathy把LLM比作新型操作系统——LLM是CPU,上下文窗口是RAM。和RAM一样,上下文窗口容量有限,无法容纳所有来源的信息。但很多开发者把上下文当成了“硬盘”——能塞多少塞多少,塞不下就扩。这是一种根本性的误解。

上下文是栈内存,聊天记录是堆上的日志文件。栈上放的是当前执行帧需要的数据,堆上存的是完整历史。把全部历史搬到栈上,结果就是栈溢出——对应到LLM就是注意力稀释和上下文溢出。

即使到了2026年,上下文窗口中间位置的召回率仍然比首尾低20-40%。这是Transformer注意力机制的结构性问题,不是简单扩窗口能解决的。真正决定AI应用效果的,不是能塞多少Token,而是如何像操作系统一样管理上下文:什么该常驻、什么该检索、什么该压缩、什么该淘汰。

今天,我们从信息压缩和优先级淘汰两个维度,拆解Context Engineering的核心方法论。

一、信息压缩:让每个Token都有价值

1.1 为什么压缩不可避免?

Agent执行长任务时,每一轮“调用工具→拿到结果→再思考”都会往历史里追加大量内容:读了哪些文件、跑了哪些命令、命令吐了多长的日志……几十轮下来,历史轻松膨胀到几十万Token。

撞上窗口上限会发生三件事:Provider直接报context overflow;每轮把全部历史重发一遍,Token越多越贵;粗暴截断会把最初的任务目标也一起截掉。

多个案例研究表明,经过压缩可以在保持甚至提升准确率的同时砍掉50-75%的Token。压缩不是妥协,是必要的基础设施。

1.2 三种压缩范式

上下文压缩方法主要分为三类:

提取式压缩(Extractive Compression):从原始上下文中选择最重要的片段保留,删除冗余。2025年的研究ICML论文表明,提取式压缩是一个非常强的选择,通常能在10倍以上压缩率下保持极小的精度损失。EXIT框架(Extractive Context Compression)通过动态调整查询复杂度和检索质量,在QA任务上超越了现有压缩方法和未压缩的基线。

生成式压缩(Generative Compression):用LLM本身将长文本重写为更短的摘要。这是DeepAgents等框架采用的默认方案——当上下文压力增大时,调用LLM生成结构化摘要,替换旧消息。但生成式压缩是“查询无关的”(query-blind)和有损的,它不知道用户接下来会问什么。

选择性压缩(Selective Compression):混合策略——只压缩次要块,保留关键块的原始形式。Meta的REFRAG框架采用RL策略,以“下一段预测困惑度”为负奖励(困惑度越高说明块越重要),决定保留哪些上下文块的原始形式。这一框架在仅保留核心内容的原始Token情况下,实现了30.85倍的TTFT加速、将LLM上下文处理长度扩展16倍。

1.3 DeepAgents的分层压缩:从最便宜的开始

LangChain的Deep Agents SDK实现了一套分层压缩(Tiered Compression)策略,按上下文压力递增的顺序依次应用:

第一层:卸载大工具输出(Offloading large tool results)。当检测到工具响应超过20,000 Token时,Deep Agents将其卸载到文件系统,替换为文件路径引用和前10行预览。Agent需要时可以重新读取或搜索该内容。

第二层:卸载大工具输入(Offloading large tool inputs)。文件写入和编辑操作会在对话历史中留下包含完整文件内容的工具调用。由于这些内容已经持久化到文件系统,当会话上下文超过模型可用窗口的85%时,Deep Agents会截断旧工具调用,替换为磁盘文件指针。

第三层:摘要生成(Summarization)。当前两层卸载无法腾出足够空间时,LLM生成结构化摘要——包括会话意图、已创建的工件和后续步骤——替换完整消息历史。

这种“从最便宜的开始”的设计哲学,避免了在每一轮都触发昂贵的LLM摘要调用。

1.4 自主压缩:让Agent自己决定何时“清场”

LangChain在2026年3月更进一步:在Deep Agents SDK中为Agent暴露了一个compact_conversation工具,让模型在合适的时机自主触发上下文压缩。

什么时候是“合适的时机”?在干净的任务边界(用户示意进入新任务)、从大量上下文中提取出结果之后、在消费大量新上下文之前、在进入复杂多步流程之前、以及当新需求使先前上下文失效时。

“我们普遍看好这个想法:harness应该在可能的情况下‘让路’,并利用底层推理模型的改进。”——LangChain团队

固定阈值压缩(比如85%触发)的问题在于:有好的压缩时机和坏的压缩时机。在复杂重构过程中压缩不合适,但在开始新任务时压缩非常合适。把决策权交给Agent自己,让压缩从“被动防御”变成“主动策略”。

二、优先级淘汰:不是所有Token都生而平等

2.1 淘汰策略的演化:从“按时间”到“按价值”

当前大多数Agent框架的默认淘汰机制是近因截断(recency truncation)——当上下文超过Token预算时,丢弃最早的消息。

这种策略是“主题盲”(topic-blind)的。一个在会话早期建立的事实,仅仅因为“老”就被丢弃了——即使当前用户查询恰恰问的是这个事实。相反,冗长但无关的近期内容却被保留。需要跨多轮回忆信息的Agent——这正是记忆的典型场景——恰恰是近因截断最失效的地方

近因截断是把上下文当成“队列”——先进先出。但上下文不是队列,它是一个信息检索问题

2.2 基于新颖性的淘汰:用信息量替代Token数

一篇2026年7月的论文《Context by Distinct Information》提出了一个根本性的视角转变:上下文应该按“不同信息条目”来度量,而不是按Token

在一个典型的上下文流中,同一个名称在对话中反复出现,检索到的段落重复陈述了早期的事实,同一个工具反复输出相同的状态记录,一个代码标识符出现数百次,一个日志模板触发了数千次。标准的内存方案却仍然按Token来计量。

该论文提出的“新颖性门控缓存”(novelty-gated cache)只在传入的key是新颖时才打开缓存槽,使内存规模与不同条目的数量成比例,而非Token数量。实验表明,在字符级控制下,新颖性门控注意力达到了全注意力的性能,同时只关注了约一半的Token。

核心洞察:信息密度决定了上下文的价值,Token数量只是载体。

2.3 基于规划感知的淘汰:知道“下一步要什么”

PAACE框架(Plan-Aware Automated Context Engineering)将上下文管理建模为一个关联记忆塑造(associative memory shaping)问题。它学会根据记忆元素与即将到来的规划步骤的关联相关性(associative relevance),选择性地保留、重写、压缩或丢弃记忆元素。

这意味着:淘汰决策不是基于“这条消息有多老”,而是基于“这条消息对下一步任务有多重要”。

在RAG场景中,PACMS框架(Submodular Context Selection)将记忆条目、对话轮次和工具输出视为一个统一的候选池,在组装Prompt的时刻按相关性进行选择。它不依赖于近因截断或查询无关的压缩,而是在每一轮决策时动态选择最相关的上下文子集

2.4 上下文分层:五级缓存模型

一篇系统性的上下文管理文章提出了五级缓存模型

  • L1缓存:系统指令(~2K Tokens)——CPU寄存器级别。存放模型身份、行为规则、输出约束。生命周期最长,几乎不变。
  • L2缓存:工作记忆(~1K Tokens)——当前任务的核心上下文。
  • L3缓存:RAG检索结果——按需检索的动态知识。
  • L4缓存:对话历史摘要——压缩后的长期记忆。
  • L5缓存:完整对话日志——持久化存储,仅在需要时召回。

每一层有不同的容量、生命周期和刷新策略。设计一个生产级上下文系统,本质上就是在定义这五级缓存。

三、工程实践:从理论到代码

3.1 优先级系统:给上下文标“价”

一个成熟的上下文工程方案需要一个优先级系统(Priority System)——不是所有上下文都生而平等。

fromtypingimportDict,List,TuplefromenumimportEnumclassContextPriority(Enum):CRITICAL=0# 永不淘汰:系统指令、核心约束HIGH=1# 最后淘汰:当前任务目标、关键事实MEDIUM=2# 可压缩:历史对话、工具调用记录LOW=3# 优先淘汰:冗长输出、调试日志classPrioritizedContext:def__init__(self):self.items:List[Tuple[str,ContextPriority,str]]=[]defadd(self,content:str,priority:ContextPriority):self.items.append((content,priority,""))defevict_until(self,target_tokens:int,token_counter)->List[str]:"""按优先级从低到高淘汰,直到Token数降到目标值"""sorted_items=sorted(self.items,key=lambdax:x[1].value)kept=[]current_tokens=0forcontent,priority,_insorted_items:tokens=token_counter(content)ifcurrent_tokens+tokens<=target_tokens:kept.append(content)current_tokens+=tokenselse:# 对MEDIUM和LOW优先级的内容尝试压缩ifpriorityin[ContextPriority.MEDIUM,ContextPriority.LOW]:compressed=self._compress(content,target_tokens-current_tokens)ifcompressed:kept.append(compressed)breakreturnkeptdef_compress(self,content:str,budget:int)->str:"""使用LLM或提取式方法压缩内容到预算内"""# 实现略:可调用LLM生成摘要或使用提取式压缩pass

3.2 DeepAgents压缩中间件实战

fromdeepagents.middleware.summarizationimport(SummarizationMiddleware,SummarizationToolMiddleware,)fromlangchain.agentsimportcreate_agentfromlangchain_openaiimportChatOpenAI# 自动压缩中间件:在85%阈值时触发auto_compress=SummarizationMiddleware(model="gpt-4o",threshold=0.85,# 上下文使用率达到85%时触发压缩)# 手动压缩工具:让Agent自己决定何时压缩manual_compress=SummarizationToolMiddleware(model="gpt-4o",)agent=create_agent(model=ChatOpenAI(model="gpt-4o"),tools=[search_tool,file_tool],middleware=[auto_compress,manual_compress],)

SummarizationMiddleware自动监控Token数量,在超出阈值时将历史对话压缩为高质量摘要,保留最近消息。SummarizationToolMiddleware则暴露一个compact_conversation工具,让Agent(或人工审批流程)按需触发压缩。

3.3 双缓冲压缩:零停机上下文刷新

LangChain社区在2026年2月提出了双缓冲上下文窗口中间件(double-buffer context window middleware)——在可配置阈值(默认70%)处建立检查点,后台继续工作的同时运行摘要生成,然后在交换阈值(默认95%)处切换到预构建的后台缓冲区。

这解决了压缩期间服务中断的问题——Agent不用“停下来等摘要做完”,压缩在后台透明进行。

四、总结:上下文管理的三条铁律

铁律一:上下文不是硬盘,是缓存。不要试图把“所有东西”塞进上下文。上下文是工作内存,不是持久存储。把信息分层——哪些常驻、哪些检索、哪些压缩、哪些淘汰——是Context Engineering的第一课。

铁律二:压缩先选最便宜的。DeepAgents的三层压缩(卸载输出→卸载输入→摘要)给出了一个清晰的优先级:先做零成本的引用替换,再做低成本的截断,最后才做高成本的LLM摘要。

铁律三:淘汰看价值,不看年龄。近因截断是一个“懒惰”的默认值。对于需要跨多轮记忆的Agent,基于相关性、新颖性或规划感知的淘汰策略,远比“丢掉最早的”更有效。

上下文窗口会继续扩大——1M、2M、10M。但“Lost in the Middle”不会消失。真正决定AI应用上限的,从来不是窗口能塞多少Token,而是你能在有限的Token预算内,塞进多少有效信息

Context Engineering的本质,是在有损信道中最大化信号-令牌比

http://www.jsqmd.com/news/1297989/

相关文章:

  • Python自动化跨库查询:从NCBI蛋白名到Uniprot登录号与基因名
  • 零基础3天入门GDScript编程:游戏开发小白的第一个代码奇迹
  • 国产服务器性能实战:鲲鹏、飞腾、海光、龙芯CPU架构解析与选型指南
  • 【2027最新】基于SpringBoot+Vue的校园资料分享平台管理系统源码+MyBatis+MySQL
  • FlashKDA:月之暗面为 Kimi Delta Attention 打造的生产级高性能 CUDA 内核
  • WiX Toolset v3:企业级Windows安装包自动化构建的终极解决方案
  • 英雄联盟智能战绩查询工具:基于LCU API的数据驱动决策助手
  • 明年是否是对车模价格进行限制?
  • NumPy多级排序实战:lexsort函数原理与应用场景详解
  • C++手写shared_ptr共享智能指针|原子引用计数、强弱引用控制块、赋值重载底层深度剖析
  • Python自动化获取怀俄明大学探空数据:从网络请求到结构化处理
  • 购买前必看!这2大参数决定医疗材料拉力试验机报价高低
  • PyRadiomics安装全攻略:从环境配置到实战避坑指南
  • SQL注入第一天
  • Java多线程中sleep()与wait()的核心区别与应用场景
  • FBO焕新存储技术:如何解决UFS长期使用性能衰减问题
  • 系统化交易工具链全景:97个库与策略资源的量化交易知识图谱
  • 嵌入式步进电机控制:20秒实现按钮与遥控双模式驱动方案
  • applera1n:iOS 15-16激活锁绕过工具的完整技术指南
  • 如何用Uncle小说打造你的个人数字图书馆:全网小说下载与阅读完整指南
  • Go语言指针、方法与接口核心机制详解
  • 如何快速掌握GeoJSON.io:5个实用场景的免费在线地理数据编辑工具完整指南
  • C++游戏开发入门:从内存管理到实战框架构建
  • Barrier深度解析:构建跨平台KVM共享的技术架构与实践指南
  • DS1302实时时钟芯片驱动开发:从51到STM32的Proteus仿真全攻略
  • MaixCAM与无刷电机云台:嵌入式AI视觉跟踪系统实战
  • SpringBoot考研学习平台开发指南
  • 2026年水肥一体机生产厂家:智能、全自动、物联网水肥一体化设备专业供应商 - 优企名品
  • 非模式生物GO富集分析:基于UniProt自建注释库的完整实战指南
  • 基于Claude的深度调研工具:搜索接力机制与本地部署实践