Token导航 LogoToken导航

AI 资讯 · 科技行者

AI智能体长期运行变慢 推理引擎难跟上上下文膨胀

更新 2026-11-06科技行者正文 5817字阅读约 19分钟

你有没有想过,一个能帮你写代码、查资料、跑测试的AI智能体,为什么用着用着就变慢了?

答案藏在一个很少被普通用户注意到的地方:对话记录。一个长期运行的AI智能体,比如帮你修Bug的编程助手,会不断积累历史,每次工具调用、每次推理、每次用户追问,都变成新的文字塞进上下文。几十轮下来,这段历史可能长达十几万个token。而这些历史,模型并不会主动遗忘,它得全部记住,因为任何一句话都可能在后面被重新用到。

问题是,记住不是免费的。

这篇来自哈尔滨工业大学团队的论文,讲的就是这个麻烦事:当AI智能体的记忆越来越长,运行它的推理引擎该怎么扛住这个压力。

**历史太长,会撑爆什么**

先说清楚,AI智能体为什么会越聊越卡。

模型在生成每一个新词时,都要回头看一遍它之前说过的所有话,这个"回头看"的机制叫注意力。

KV缓存*:模型在处理每个历史词时,会算出一组叫Key和Value的数字,存起来以便后面复用,这样就不用每次都重新计算全部历史,这组存储就叫KV缓存。

历史越长,KV缓存占的显存越大,算注意力要扫的范围也越大。这就是论文开头提的两个瓶颈:显存装不下,算得还慢。

学术界早就意识到这个问题,想出了四类"偷懒"办法。第一类叫动态稀疏注意力,意思是每次回答问题时,只挑历史里看起来相关的一小部分去计算,其余的先放着不管,但完整历史还留在显存里,万一后面用得上还能翻出来。第二类叫KV淘汰,直接把不重要的历史记录从显存里删掉,腾出空间,但代价是删掉的东西真的找不回来了。第三类叫KV压缩,把每段历史的信息压缩成更小的表示,占地方更少但还保留着。第四类叫KV量化,降低数字的精度,比如从32位浮点数变成4位,用更粗糙的方式省空间。

这四类方法各有各的脾气。动态稀疏的方法需要保留完整历史外加一份摘要索引,KV淘汰的方法需要持续更新一份"谁重要谁不重要"的评分,KV压缩需要额外的重建逻辑,KV量化需要存一份量化参数。它们对"历史应该长什么样"这件事,看法完全不一样。

这就带来一个很现实的工程问题:市面上的推理引擎,通常是按照某一类方法的思路搭的骨架。

论文举了几个例子。一个叫SPIN的系统,把整个流程设计成"建索引、挪到CPU、挑选、取回来、算注意力"这五步走的固定流水线。另一个叫Vortex的系统,围绕"分页"这个概念来设计所有接口,所有操作都基于页面展开。还有一个叫Tangram的系统,专门针对"不同注意力头保留不同数量历史"这种特殊情况做了优化。

这些设计各自解决了自己瞄准的问题,但换一个方法来跑,往往水土不服。论文里提到,Quest这个方法是靠查询动态选页面,而H2O这个方法不仅要动态选,还得一直维护一份持续累加的注意力分数表,外加真的把数据从显存里物理删除。如果推理引擎只为"选页面"这个动作设计了接口,那H2O那种需要持续记分、还要真删除数据的逻辑,根本没地方安放。

这就像你租了一套按单身公寓标准装修的房子,厨房很小,只够放一个电磁炉。后来你想开个小饭馆,得支起炒锅、放调料架、装抽油烟机,结果发现根本没地方塞这些设备。不是你的厨具不好,是房子从一开始就没按"可能需要大改造"的预期来设计。等你真要扩建,要么砸墙重装,要么干脆放弃,换一套毛坯房从头来。

论文的核心问题就在这里浮出水面:推理引擎的"边界"应该划在哪里?哪些东西该由系统统一管理,哪些东西该放手让每个稀疏方法自己做主?

**把边界划在"生命周期"上**

研究团队给出的答案,是SparseEngine这套系统。

它的思路和前面那些引擎不太一样。前面提到的系统,是先定好一套工作流程,比如"索引、选择、注意力计算"这样固定的三步,再要求所有方法套进这个流程里。SparseEngine反过来,它抓住的是一个所有Transformer模型都逃不开的固定顺序,模型每一层的执行步骤,归一化、算Q/K/V、算注意力、算前馈网络,这个顺序是写死在模型结构里的,不会因为换了稀疏方法就变。

SparseEngine在这个固定顺序的每一个关键节点上,都开了一个"口子",叫作生命周期钩子。

生命周期钩子*:在模型执行到某个特定节点时(比如一层算完了、一个解码步骤结束了),允许外部代码插入进来执行自定义逻辑的接口。

打个比方,这就像一条流水线上有好几个固定工位,但每个工位旁边都预留了一个插座。你可以在"注意力计算前"这个工位插上一个"挑选重要历史"的设备,也可以在"这一步结束"的工位插上一个"清理不要的数据"的设备。流水线本身的顺序没变,但每个工位能接的外部设备,完全由你自己决定接什么。如果不留这些插座,你想加设备就得把流水线拆了重装,这正是前面提到的其他引擎遇到的困境。

有了这些钩子,每个稀疏方法就可以拥有自己专属的缓存管理器。

这个管理器管什么?管这个方法自己的数据该怎么存、怎么更新、怎么释放。SnapKV这种方法在钩子里做的事情,是看一眼最后几个词对历史的注意力分布,挑出重要的部分,物理删除不重要的。H2O在每一步解码时,都要把累积分数更新一遍,再决定删谁。OmniKV这种方法更特别,它在某些层里先判断哪些历史重要,然后把这个判断结果传给后面的层直接复用,不用每层都重新算一遍。

这些完全不同的操作逻辑,都被封装在各自的缓存管理器里,互不干扰。而连接这些管理器和实际注意力计算的,是一个叫AttentionView的中间层。

AttentionView*:一种视图机制,负责把每个方法自己管理的缓存数据,转换成注意力计算模块能够直接读取的统一格式。

换句话说,无论你的历史是用稀疏选择的方式存,还是物理删除后存的,还是压缩过的,或者量化过的,到了真正算注意力这一步,都会被整理成同一种格式交出去。这就好比不同国家的货币在跨境支付时,背后系统逻辑各不相同,但最终清算时都会换算成同一种结算货币。

这套设计听起来挺朴素,但论文里给出的成果证明它确实管用。SparseEngine最终支持了15种不同的稀疏方法,横跨四大类别,还覆盖了14种不同的模型架构,包括分组查询注意力、多头潜在注意力、混合线性注意力等多种技术路线。

**聊天记录也能"续命":Chain Cache**

光是能装下各种方法还不够。论文里提了一个更现实的场景:多轮对话的智能体,每一轮之间是怎么衔接的?

正常情况下,如果你和AI对话了好几轮,系统通常会用一种叫前缀缓存的机制,把之前算过的部分直接复用,不用每次都从头算一遍。

前缀缓存*:当新的请求和之前处理过的请求共享相同的开头部分时,直接复用之前算好的结果,只计算新增的那部分内容。

这个机制对那种"完整保留历史"的稀疏方法,比如Quest、OmniKV,是天然兼容的,因为它们的历史本来就没被删,前缀自然还在。

但对H2O、SnapKV这种会真的删除数据的方法,麻烦就来了。你上一轮对话结束后,系统已经把不重要的历史物理删掉了,这时候再来一轮新对话,想复用之前的缓存,却发现缓存里的东西和"完整历史"对不上号了。常规的前缀缓存机制是按照"逐字匹配"的逻辑设计的,它假设历史是完整连续的,一旦中间被挖了个洞,匹配逻辑就失灵了。

研究团队为此设计了Chain Cache。

Chain Cache*:一种跨请求的缓存复用机制,即便某个方法已经物理删除了部分历史的KV数据,系统依然记住"逻辑上"这段历史曾经存在过的位置信息,新一轮对话到来时,可以直接从保留下来的那部分历史继续,不用重新计算整个对话。

这里的关键在于区分"逻辑前缀"和"物理存储"这两件事。逻辑前缀是指这段对话在文字层面上确实发生过,不管底层数据删没删,这个事实不变。物理存储则是实际占用显存的那部分数据。Chain Cache保留着逻辑前缀的匹配信息,哪怕物理上已经被删掉大半,只要新一轮对话还是接着这个逻辑前缀往下讲,系统就能认出来,然后只计算那些新增的、没算过的部分。

论文里举的例子很形象:"The cat sat on the mat. It was warm."这句话,SnapKV可能已经把"sat on"和"the mat"这几个词的KV数据物理删掉了,但当下一轮对话接上"Then it slept."时,系统依然认得出这整段是同一个逻辑序列的延续,只需要给新来的"Then it slept."算KV,不用把前面的句子全部推倒重算。

这就好比你在笔记本上记了一整篇会议纪要,后来发现中间几段废话没用,划掉了。但笔记本封面上的标题和页码没变,下次开会继续记,你翻到正确的那一页接着写就行,不用从头重新抄一遍整本笔记。如果没有这种"认得逻辑位置"的能力,每次开会都得把划掉的部分也重新补全抄一遍,才能保证页码对得上,那才叫浪费时间。

Chain Cache对那些依赖持续状态的方法尤其重要,比如H2O需要一直累积的注意力分数,SnapKV在不同层删除的词可能都不一样。没有这个机制,每次新对话都得从零开始重建这些状态,等于前面的优化全部作废。

**该删哪段历史,让应用自己说了算:可控前缀裁剪**

智能体的对话历史里,其实不是每一段都同等重要。

用户的提问很重要,模型自己的推理过程很重要,但工具调用返回的结果呢?比如一次搜索返回的网页全文,一次代码执行返回的报错日志,这些内容在刚出现的时候可能很关键,但一旦AI已经把里面的有效信息提炼总结出来,这段原始的长文本往往就没什么用了,留着纯粹占地方。

论文提出了一种叫可控前缀缓存裁剪的机制,让应用方可以指定"历史里的哪一段区间"可以被精简,以及精简到什么程度。

可控前缀缓存裁剪*:应用方指定一段历史区间和一个保留比例,系统用某种打分策略从这段区间里挑出最重要的部分保留,删掉其余的,同时保证这段历史在"逻辑前缀匹配"上依然完整可用。

这里用到的打分工具之一叫KVzip,它能评估一段历史里哪些词对后续生成真正有用。

论文做了一个很实际的实验,在SWE-bench Lite这个真实的代码修复任务集上,用一个叫mini-SWE-agent的编程智能体跑测试。如果粗暴地对所有工具调用结果统一裁剪,只保留20%的内容,任务完成率是会下降的。但如果换一种策略,延迟四轮再裁剪,也就是新的工具结果来了之后,只裁剪往前数第五轮的旧结果,留着最近四轮完整不动,结果完成率不但没降,反而达到了25.0%,比不做任何裁剪的原始版本23.7%还要高。

这个发现挺值得琢磨的。它说明智能体在处理任务时,确实存在"最近的证据比老证据更有价值"这种规律,老的工具调用结果往往已经完成了它的使命,继续占着显存没有意义。这就像你在整理手机相册,如果你规定"所有照片一律只留20%",可能一不小心把昨天拍的重要截图也删了。但如果你改成"超过一周没翻看的旧截图可以清理,最近几天的先留着",效果反而更好,因为这更贴近人实际使用相册的习惯。如果不做这种"延迟"的区分,一刀切的裁剪策略很容易把正在被频繁引用的信息也误删,反而损害任务表现。

**数字说话:到底快了多少**

说了这么多设计思路,终归要看实际效果。

论文在两块不同的模型上做了测试:一个是Qwen3-30B-A3B,参数规模30B但激活参数只有3B的混合专家模型;另一个是GLM-4.7-Flash,采用了多头潜在注意力架构的模型。测试场景是12.8万token的超长上下文输入。

在解码吞吐量这个指标上,也就是模型每秒能生成多少个词,SparseEngine配合SnapKV这种物理删除历史的方法,在两个模型上都达到了普通vLLM将近10倍的吞吐量。这背后的逻辑其实很直接,物理删除之后显存腾出来了,同样的硬件能同时服务更多并发请求,整体产出自然上去了。

配合Quest和OmniKV这类"只挑选、不删除"的动态稀疏方法,在相同并发数下,吞吐量也能达到普通vLLM的1.5到2.6倍。这部分的提升来源不一样,是因为每次只计算历史中的一小部分,省下来的是算力而不是显存。

论文还专门做了一个公平性检验,挑出那些和竞品系统设计思路高度吻合的方法做对比。比如Quest这个方法正好契合Vortex和HiSparse的设计初衷,SnapKV正好契合Tangram的设计初衷。结果显示,在相同的并发数下,SparseEngine跑Quest的吞吐量是Vortex的1.24倍、HiSparse的1.55倍;跑SnapKV则是Tangram的1.55倍。

这个结果有点意思。它说明SparseEngine虽然支持的方法种类更广,但广度并没有牺牲深度,就算拿到对方最擅长的那块地盘上单挑,SparseEngine依然不落下风。

质量方面,论文在LongBench这两个长文本理解基准上,对比了SparseEngine实现的各个方法和原始论文实现的差距。横跨20项整体分数对比,平均差异只有0.17个百分点,方差也很小。这个数字说明SparseEngine在追求速度的同时,确实做到了没有明显牺牲原始方法该有的效果,这也印证了前面提到的架构设计思路,给每个方法自由发挥的空间,不代表要阉割它的能力。

端到端的智能体任务测试也给出了类似的信号。在把GLM-4.7-Flash上跑的SWE-bench Lite对话轨迹完整重放的实验里,H2O方法达到了2.02倍的端到端加速。在另一个专门用来测系统效率的Gasai智能体轨迹上,SnapKV配合Chain Cache达到了2.24倍的加速。

Q&A

Q1:SparseEngine是什么?

A:SparseEngine是哈尔滨工业大学团队提出的一套稀疏优先推理引擎,专门为长上下文AI智能体设计,通过生命周期钩子让不同的KV缓存稀疏方法各自管理自己的数据表示和计算逻辑,同时共享调度、批处理、前缀缓存等基础设施,支持15种不同的稀疏方法。

Q2:Chain Cache解决了什么问题?

A:Chain Cache解决的是物理删除历史数据的稀疏方法(比如H2O、SnapKV)在多轮对话中无法复用前缀缓存的问题。它让系统记住被删除数据对应的逻辑位置,新一轮对话到来时可以直接从保留的历史继续,只计算新增部分,不用从头重算整个对话。

Q3:使用SparseEngine会不会降低AI回答的质量?

A:论文测试显示影响很小。在LongBench长文本基准上,SparseEngine实现的各个稀疏方法和原始论文实现相比,20项整体分数的平均差异只有0.17个百分点,证明加速没有明显牺牲原有方法的任务表现。

文章标签智能体

资讯来源:由AI资讯编辑整理自互联网公开内容,版权归原作者所有,未经许可,不得转载。