砍掉一半专家,一个 354GB 的 MoE 被塞进了单张 32GB 卡
DASLab 昨天在 Hugging Face 上放了个叫 Qwen3.8-Flash-Next-GSQ-RCO-Coder-GGUF 的模型卡。名字很长,但它干的事值得专门拎出来看:把一个 176.9B 参数的 MoE——就是 Qwen3.8-Flash-Next——从 354GB 的 BF16 压到 58.4GB,其中必须常驻内存的只有 29.6GB。也就是说,这个参数规模的原生模型,现在能塞进一张 32GB 的加速卡里跑。
我一开始也被这个数字震了一下,但方法比结果更值得聊。这不是我们熟悉的纯量化,而是先做了另一件事:把模型的专家直接砍了一半。Flash-Next 每层有 512 个专家、一共 48 层,每个 token 只激活其中 10 个。绝大多数参数都躺在专家里,而每个 token 只用上一小撮,那么"把整组专家删掉"就成了比"把每个权重压得更低"更狠的一手。删掉一半专家,再把剩下的权重压到 3.5 bpw,两个动作叠加,就出现了那个 1.89 bits per parameter 的说法。
这里有个容易误导的地方,模型卡自己也专门解释了:没有任何单个权重是存在 1.89 位的,那是把删掉的专家摊回原始参数数上算出来的"等效"rate。真实留下的权重还是 3.5 bpw,减少里的另一大半来自砍掉的专家数。
真正有意思的其实是砍哪些专家的选择逻辑。专家会特化,一个专家重不重要不是它自己的属性,而是相对某一批输入来定义的——所以砍谁,完全取决于你喂给它的校准数据。DASLab 用的是 RCO,在一个 Riemannian 流形上做约束优化,最小化剪枝前后模型的 KL 散度,而不是按某个启发式重要度分数去排专家。这里面还有个很实际的约束来自 GGUF 这个格式本身:它整套模型只能存一个统一的专家数量,所以每层必须保留同样多的专家。RCO 干脆把"每层一个预算"直接当成约束来解,各层约束互不干扰,但目标函数又是全局的、没法分解,所以梯度仍然反映全模型状态,只是收预算时分到每层去做。
效果上,这套"定向压缩"的取舍很诚实。LiveCodeBench v6 保留了 98.7%,SWE-bench Verified 保留了 91.3%——那个多步的 agentic 轨迹在长流程里逐轮累积误差,所以比单题代码生成更能暴露容量损失。模型卡说得也很直白:删掉一半专家必然损伤能力,这个发布的贡献不在于消除损伤,而在于把损伤导引到代码、agentic 工具调用、视觉和空间推理之外的地方,保留下来的专家正好支撑这些域。所以它是个"Coder"定向版,不是通用版——你要拿来干通用的事,应该去下那个没剪枝的 GSQ-RCO 版本。
视觉能力的保留是这条链路里最有说服力的一个细节。他们先只用代码和 agentic 数据做了一版搜索,结果视觉通路的专家被整个删掉,图像能力大幅退化——这不是方法的失败,而是校准数据里根本没有视觉,搜索自然判断这些专家对目标没贡献。他们把视觉加进校准集之后,模型就保住了这能力,还放了一张"鹈鹕骑自行车"的 SVG 当非正式质检:这需要物体知识、空间构图和正确的 SVG 语法同时成立。
落地层面,两个 shard 都得下,llama.cpp 直接 hf download <this-repo> --local-dir . 再 llama-cli 就能跑,注意那个命令样例里 n-gram 那部分可以存在磁盘上、不用进内存。很多用户还反馈说用 Strata 这个第三方引擎,8GB 显存的单张 NVIDIA 卡就能跑,带一键安装和 localhost 上的 OpenAI 兼容端点。协议是 apache-2.0(继承基础模型),这个 repo 上个月下载量 261,136。
我对这套路最欣赏的地方,是它把"压缩的方向性"摆到了台面上。量化保住了一切、只是降精度;剪枝则是直接把参数抹掉,文件大小和常驻内存一起变小。把两者结合、再把损失定向到不重要的域,这才是 1.89 bpw 这种数字能成立的前提。当然这也意味着它天生有上限:SWE 掉了 9 个点不是 bug,是定价。所以别拿它当通用模型用,它是一把专为代码场景磨的刀。校准数据里没覆盖的域到底崩成什么样,模型卡也明说了,这种实验性发布的反馈是开放的——真要评价它,你得自己跑一遍那 91.3% 之外的东西看看。