跳至主要内容
长上下文的瓶颈不在注意力

长上下文的瓶颈不在注意力

看到”下一代模型支持百万上下文”这类消息时,我的第一反应不是兴奋,是去找那篇论文。原因很实际:窗口大小是最好写的参数,也是最容易被夸的。

这次的消息里其实混着三样东西,可信度差得很远。分开看之后,能学的东西比标题少,但比标题结实。

三个名字,三件不同的事

流传最广的是三个词:V4、Sealion-lite、DualPath。

V4 是产品名,到目前为止没有官方发布,所有关于它的参数都是推测。Sealion-lite 是社交媒体上出现的内部代号,据说对应一个早期预览版,百万上下文和原生多模态这些说法都挂在这个名字下面。DualPath 不一样,它有一篇署名论文,作者来自高校和这家公司的研究团队,描述的是推理系统怎么组织数据流。

一个是商品,一个是传闻,一个是方法。混在一起读,就会把方法当成承诺。

我读这类消息的习惯是先分层:哪些是可验证的机制,哪些是转发出来的数字。前者现在就能学,后者只能等发布。这次可验证的部分,只有一场关于推理系统的工程优化,和模型能力关系不大。

顺带说一句我对”情报汇总”这种体裁的警惕。它的结构决定了它必须显得信息量大:参数、代号、发布时间、跑分,一样不少。但这些东西的保质期最短,产品一发布就全部作废。真正留下来的,往往是那段最不吸引人的架构说明。我写这类东西时尽量把比重调过来,哪怕读起来没那么”有料”。

内部代号这类信息我给的权重也低。它们通常来自几个地方:招聘页面的措辞、API 报错里漏出的模型名、某个测试账号的列表。这些渠道能证明”有个东西存在”,不能证明它长什么样。代号尤其如此——同一个代号在不同人嘴里可能指两次不同的实验。所以我只把它当线索,不当依据。

DualPath 解决的是 I/O

先说背景。现在的大模型推理普遍用预填充和解码分离的架构:预填充阶段处理输入,算力吃满;解码阶段一个一个吐 token,吃的是显存带宽。两类任务对硬件的要求不同,所以放在不同的节点上跑。

这个设计在短文本下很顺。上下文一长,问题就来了。百万 token 对应的 KV-Cache 体积巨大,预填充节点要从存储里把它读进来,存储网卡瞬间打满;与此同时,旁边那些解码节点的存储网卡基本闲着。

这种错配本身就是分离架构的代价。把两类任务分开,是为了让各自的硬件跑在舒服的区间;代价是资源利用率变成了波动的,一会儿这边闲、一会儿那边忙。短请求的时代这个问题不明显,因为单次数据量小,闲一下也就过去了。长上下文把这个波动放大成了瓶颈。

打个不太严谨的比方:所有运货的卡车都被规定只能走一条车道,另一条车道空着但不许走。短途的时候看不出来,长途一起堵。DualPath 相当于开了潮汐车道,让闲置的那条也参与运输。

DualPath 的做法是打破”谁计算谁加载”这个惯例:让闲置的解码节点去存储里读一部分 KV-Cache,读完不做计算,直接通过高带宽的计算网络用 RDMA 写进预填充节点的显存。RDMA 的好处是绕过 CPU,延迟低、吞吐高。

本质上,它把整个集群里闲置的存储带宽聚合起来用了。不改模型结构,不改注意力算法,只是让数据走了一条更顺的路。

它没有让模型变聪明,只是让数据更快地到达显存。

这件事我之所以在意,是因为它和我自己踩过的坑对得上。本地跑长文档的时候,第一个卡住的是显存,第二个卡住的就是加载。首字延迟里相当一部分不是算出来的,是搬出来的。人等的其实是一个更大的内存带宽,而不是在等一次更聪明的推理。

对 agent 类负载,这件事的价值更高。agent 每一轮都要重新读一遍历史,KV-Cache 的复用率比单轮长文档高得多,搬运成本在总成本里的占比也就更大。这也是为什么这类优化会在 agent 火起来之后被重新提起——它不是新问题,是被放大了的老问题。

我关心这件事还有一个原因:它意味着长上下文的价格还有下降空间,而且空间在系统层,不在模型层。模型换代的收益是台阶式的,一次跳一截;系统优化的收益是持续的,一点一点挤。过去两年 API 价格掉得那么快,相当一部分不是模型变小了,是这类工程被人做出来了。所以我看到一篇讲调度和带宽的论文,比看到一份跑分表更有耐心。

代价也要说清楚:这套方案依赖 RDMA 网络和节点之间的紧密协同,对集群拓扑有要求,小规模部署根本用不上。换句话说,它解决的是”有几千张卡”的人的问题,不是我的问题。我读它,是为了理解方向,不是为了照搬。

这也解释了为什么这类工作很少出现在产品发布会上。它没有演示效果,一张吞吐曲线说服不了人,但它是把”支持百万上下文”从参数表变成可用功能的那一层。我对这类工作的兴趣,大概和大多数人相反:宣传里最响的部分我跳过,藏在附录里的调度策略我会读两遍。

标称窗口和有效窗口

百万上下文是个好数字,但它至少藏着三个不同的问题。

第一是检索准确率随位置的变化。长上下文模型普遍在中段表现最差,开头和结尾好一些。所以”支持 1M”和”在 1M 下还能找到第 50 万 token 处的一个细节”是两件事。

第二是评测的构造方式。这类测试里,针放在哪里、干扰文本和针有多像、问题怎么问,都会显著改变结果。一个漂亮的召回率,可能只说明测试出得温和。

第三是成本曲线。长上下文的定价通常是分档的,超过某个长度单价会抬升,因为它确实更贵。所以”能用”和”用得起”之间还有一段距离。我自己做产品的时候,宁可把长文档切片做检索,也不愿意把整个文档塞进去——不是为了省钱,是为了可调试。检索错了,我能看到召回了哪几段;上下文塞满了,模型答错了,我连它看了哪儿都不知道。

想验证一个模型的长上下文值不值得用,我会做一件很土的事:拿自己的一批文档,把同一个问题的答案分别放在开头、中间、结尾,各问一遍,再混进几段内容相近的干扰段落。这个测试不需要工具,二十分钟能跑完,但它能暴露出宣传数字看不到的东西。我跑过的模型里,中段明显变差是常态,差别只在幅度。有些模型会说”文档里没有提到”,有些会自信地编一段——后者更麻烦,因为我得逐条核对。

我不否认大窗口有用。它的价值在跨文档、跨章节的推理,在那些”必须先看完整体才能判断”的任务上,而这类任务用检索拼不出来。但它改变的是”能放多少”,不是”能理解多少”。把这两件事混起来,是这类消息里最常见的误读。

我试过两种做法。一次是把整个项目的源码树塞进去,让它找一处定义在哪儿;结果不算差,但贵,而且它偶尔会把两个同名文件搞混。另一次是用检索先定位,把三个候选片段给它;它更快,也更准,出错时我还能顺着召回结果查。两次对比下来,我的结论是:窗口是兜底能力,不是默认用法。能定位到片段的时候,定位更便宜也更可控;实在定位不了,再考虑把整个东西递过去。

这个结论在大窗口变便宜之后可能被推翻。如果长上下文的单价降到接近现在短上下文的水平,我大概会懒得做检索。这不是原则问题,是成本问题。

对”原生多模态”的说法我也保持同样的态度。一个权重里同时处理文本和图像,听起来很干净,实际效果取决于训练配比和对齐方式。没有评测细节,这句话基本没有信息量。我更关心的是它输出图像时的一致性——同一段描述两次调用会不会给出差别很大的东西,这比”支持多模态”这个标签更能说明工程成熟度。

至于那份关于”条件记忆”的传闻——静态知识用哈希查表、动态推理占大头、查表复杂度接近常数——我暂时当故事看。它听起来像是把 KV-Cache 卸载和检索增强混在一起讲。这类机制如果真的存在,最有价值的信息是它怎么处理”查找失败”,以及失败时会不会静默降级;而泄露出来的内容里没有这一层。

我现在怎么读这类消息

来源只留三样:论文或技术报告、官方仓库的 release、以及能复现的第三方评测。社交平台上的”内部消息”我一律当噪音,哪怕它给出的数字看起来很具体。数字越具体,越容易让人忘记它没有出处。

日期这件事我吃过亏。曾经按一篇写得很确定的文章排过计划,后来发现那个日期是聚合站点的占位符。这类错误不致命,但它会让人在错误的时间点做错误的准备。

权重下载是另一回事,风险更实在。没有官方渠道的一律不下。即使文件格式是常见的那种,模型仓库里也可能带自定义加载代码,加载时就执行。为了试一个不知道真假的版本,把自己的机器交出去,不划算。

发布时间我不太在意,但我会看一种信号:论文先出、代码后出、产品最后出。这个顺序说明东西是长出来的,不是拼出来的。反过来,先有铺天盖地的演示,几周后才有一份语焉不详的技术说明,这种情况我会把预期调低。这次属于前者,所以即使参数全是传闻,我也愿意花时间读那段架构说明。

这篇没有结论,因为产品还没发布。我唯一比较确定的是:让长上下文变便宜的是系统工程,不是参数量。这个判断如果错了,我大概会在看到第一份独立评测时改。现在还没有。

在那之前,我对所有”百万”开头的参数都保持一个默认折扣,打折力度取决于它有没有给出测试方法。

关于本文

由 Lu's Blog 撰写,采用 CC BY-NC 4.0 许可协议。

#开源模型 #推理架构 #长上下文

评论