返回博客列表

Clover-35B-A3B 发布:扩散语言模型是什么、快在哪、又卡在哪

2026-10-29T18:10:00+08:00
扩散语言模型CloverDiffuSpaceMoEdLLM

Clover-35B-A3B 发布:扩散语言模型是什么、快在哪、又卡在哪

一个 35B 的模型,把「并行填空」这条路推到了能看的位置——但也只是能看的位置。

结论先放这:10 月 28 日,从港大 Dream 团队出来的扩散智能(DiffuSpace)开源了第一个模型 Clover-35B-A3B-Preview。350 亿总参数、30 亿激活、128K 上下文,SWE-bench Verified 73.6,单张 GB300 上 batch=1 跑到 680 tokens/s。它是第一个在通用 Agent 榜单上不只「勉强追平」、而是咬住甚至略压同尺寸自回归模型(Qwen3.6-35B-A3B)的扩散语言模型。

这件事的意义不在「又一个开源模型」,而在于它回答了一个悬了两年的问题:扩散语言模型能不能在大参数下同时守住速度和质量。Dream 7B 时代答案是「小模型可以」,现在 Clover 给的答案是「35B 也可以」。

但 Preview 就是 Preview。它有一套真实的、结构性的限制,官方自己也承认一部分。这篇文章把三件事讲清楚:扩散模型到底是什么、Clover 靠什么拿到这个速度、以及在什么场景下你该用它、什么场景下千万别用。

本文提纲

  1. 先看三个数字
  2. 扩散模型到底是什么:从去噪到填空
  3. Clover 改了什么:双向 GDN、32 个 token 的块、块内专家复用
  4. 快在哪:把「每 token 一次前向」变成「每块几次前向」
  5. 卡在哪:六个必须知道的限制
  6. 使用场景:什么时候该用,什么时候别用
  7. 怎么跑起来:最小可运行代码
  8. 该怀疑的地方
  9. 参考文档与链接

先看三个数字

第一个数字是 35B-A3B。总参数 350 亿,每 token 只激活约 30 亿。结构上从 Qwen3.6-35B-A3B 初始化,保留了 40 层、256 个路由专家、top-8 路由、每层 1 个共享专家的混合专家骨干。BF16 权重约 69GB,这是你部署前必须算的账。

第二个数字是 73.6。SWE-bench Verified。同一份评测里 Terminal-Bench 2.1 是 51.7、τ³ Overall 是 65.3,官方称这六项 Agent 评测它全部是所列模型中的最高分,对照对象包括同为扩散路线的 LLaDA2.2 flash、Mercury 2.5,以及同尺寸的 Qwen3.6-35B-A3B 和 Qwen3.5-35B-A3B。通用能力上 GPQA Diamond 83.8、ZebraLogic 95.8、AA-LCR 72.0、MMLU-Pro 84.8。

第三个数字是 680。单张 GB300、BF16、batch=1、内部 Agent 场景数据,整体生成速度 680 tokens/s;换到 H200 跑 Agent 任务是 515 tokens/s,官方给的对照是加装 DFlash2 加速的同规模 Qwen 方案 365 tokens/s。CSDN 转述官方口径时说的是「最高可达同尺寸自回归模型的 5–10 倍」。

三个数字放在一起,才是这次发布真正值得看的地方:它不是靠缩参数换速度,参数比上一代大了 5 倍,速度没掉,分数还上去了。这在扩散路线上是第一次。

扩散模型到底是什么:从去噪到填空

先说图像。扩散模型在图像上已经赢了一轮:训练时给图片逐步加噪,模型学「怎么把噪声去掉」;生成时从一张纯噪声出发,迭代几十步,噪声一点点被抹掉,图像一点点浮现。核心特征是整张图同时被优化,不是从左上角一个像素一个像素画。

文本不一样。词是离散的,没有「加一点噪声」这种连续操作。所以在语言模型上,扩散被改造成了另一个东西:掩码扩散(masked diffusion)。

做法是:把答案整段写成一句话,随机把其中一部分词替换成 [MASK],训练模型把空填回去。生成时反过来——先摆出一整排 [MASK],然后每一步让模型给所有空位打分,挑最有把握的几个填上,再重来,直到填满。

如果你写过完形填空,这就是那个感觉。**自回归是接龙,扩散是擦改。**接龙只能往后写,写错了顶多划掉重写;擦改可以先看全局,把最有把握的地方定下来,再回头啃硬骨头。

但这个「擦改」有个致命问题:如果每次都要对整段序列重新跑一遍前向,长输出的成本会爆炸。全序列扩散(比如 LLaDA 那条线)在长文本上就被这个卡住了——步数固定,序列越长,每步越贵。

块扩散(Block Diffusion)是折中方案,也是 Clover 和 Mercury 共同的选择:把序列切成 32 个 token 一块,块内并行去噪,块与块之间保持从左到右的因果顺序。已完成的块提交进前缀,成为下一块的历史。这样既保住了「块内一次前向解决多个位置」的并行红利,又保住了前缀缓存这条工程命脉。

flowchart LR
    P["Prompt tokens"] --> G["GDN recurrent memory"]
    G --> B["Current block: 32 masked slots"]
    B --> Q{"Any slot above 0.95?"}
    Q -->|"Yes"| F["Fill all confident slots in parallel"]
    Q -->|"No"| O["Fill the single top slot"]
    F --> C{"Block complete?"}
    O --> C
    C -->|"Not yet"| B
    C -->|"Yes"| K["Commit block into prefix"]
    K --> N["Next block of 32"]
    N --> B
    G -.-> B
    classDef p fill:#FF6B6B,stroke:#764ba2,color:#fff
    classDef g fill:#4ECDC4,stroke:#764ba2,color:#1a1a1a
    classDef b fill:#45B7D1,stroke:#764ba2,color:#fff
    classDef q fill:#FFEAA7,stroke:#764ba2,color:#1a1a1a
    classDef f fill:#96CEB4,stroke:#764ba2,color:#1a1a1a
    classDef o fill:#DDA0DD,stroke:#764ba2,color:#1a1a1a
    classDef k fill:#98D8C8,stroke:#764ba2,color:#1a1a1a
    class P p
    class G g
    class B b
    class Q q
    class F,O f
    class C q
    class K,N k

三条路线的差别,一张表说清:

自回归(Qwen、GPT) 全序列掩码扩散(LLaDA 线) 块扩散(Clover、Mercury)
生成顺序 严格左到右 全序列同时迭代 块内并行,块间左到右
一次前向产出 1 个 token 0 个(只降低不确定性) 0 到几十个 token
串行步数 等于输出长度 固定 T 步 块数 × 每块步数
能看到多少上下文 只有左边 全局 块内全局,块外只有前缀
工程成熟度 极高 低 中,调度要重写
前缀缓存 天然支持 难 支持,粒度是块

注意第三行和第四行是矛盾的:全序列扩散能看全局,但没法复用缓存;块扩散能复用缓存,但「全局」只剩 32 个 token 的窗口。这个取舍后面会反复出现,它是理解 Clover 所有优缺点的钥匙。

Clover 改了什么:双向 GDN、32 个 token 的块、块内专家复用

块扩散落到工程上有两个硬骨头,Clover 的处理方式比论文摘要更有信息量。

第一块硬骨头:块内要双向,但基座是因果的。

32 个位置要互相看见,就得双向注意力;可 Qwen3.6 的骨干是 GDN(Gated DeltaNet)加全注意力的混合结构,天生因果。硬改会把预训练学到的东西全废掉。

官方的做法是「重新设计双向 GDN」,拆成三件事:

  • **历史走递归,块内走注意力。**已生成的上下文用 GDN 的递归状态压缩(大小恒定,不随长度涨),当前块内的 token 用双向 softmax 注意力互相看。两种计算方式各干各擅长的事。
  • **把历史记忆的读出当成一个独立信息单元。**这一步是关键:不是简单地「先看历史再看块内」,而是让历史状态的读出与块内 token 放进同一次 softmax 里一起竞争。模型自己学「这一刻该依赖历史,还是该看块内」。
  • **加一个零初始化的右侧卷积分支。**左侧沿用预训练的因果卷积行为,右侧用零初始化新分支,从「因果」这个起点往外长,减少对预训练权重的破坏。另外还有可学习的块大小校准,补偿块内 token 变多时对历史权重的天然稀释。

这套设计的意图很清楚:别让块扩散变成「把窗口开大一点的 AR」,而是让历史压缩和块内交互各归其位。

第二块硬骨头:MoE 在块扩散里反而更划算。

这一条官方写在模型卡里,不太起眼但很值钱。参数 moe_block_coreset_enabled 默认开启,moe_block_coreset_top_p=0.9:去噪时,模型把块内每个 token 的 top-8 候选专家的路由分加起来,按总分排序,保留刚好覆盖 90% 路由质量的那批专家,整块共用。

为什么要这么做?因为 batch=1 时 MoE 的瓶颈是权重读取:每个 token 激活不同的专家,权重读取就变得碎片化,显存带宽全浪费在搬运上。而块内 32 个位置如果共用一批专家,权重读一遍能服务 32 个位置,读取就连续了。

**所以「扩散 + MoE」不是两个热点拼装,是互补的。**MoE 稀疏化本来是为了省算力,在自回归 batch=1 下却容易变成省不了带宽;块扩散的并行性刚好把这块补上。这是我觉得这次发布里最有工程含量的一点。

顺带一个容易被忽略的细节:那个 0.9 是「聚合路由质量的 90%」,不是「90% 的专家」,也不是采样用的 top_p。调低会选更少的专家,质量和速度要重新权衡。

快在哪:把「每 token 一次前向」变成「每块几次前向」

680 tokens/s 听起来像是黑科技,拆开看其实是一笔很朴素的带宽账。

自回归每输出一个 token,都要把参与计算的权重完整读一遍。batch=1 时,你花在算上的时间远少于花在搬权重上的时间——GPU 的算力单元大部分在等数据。这就是所谓「decode 阶段是内存带宽受限」。

块扩散改的是这个乘法关系:一次前向不再产出一个 token,而是同时处理块里的 32 个位置。同样读一遍权重,产出的 token 数变成 1 到几十个。680 tokens/s 换算过来是每个 token 平均 1.47 毫秒,对比同尺寸自回归模型在同等条件下常见的几十到一百多 tokens/s,差距就是这个「一次前向摊薄到多个 token」的倍数。

两个效应叠加:块内并行把权重的复用次数拉高,MoE 的 3B 激活又把单次前向要读的权重压到较小规模。加在一起才有这个数量级。

但这个红利有非常明确的前提:batch=1。

一旦并发上来,自回归靠 continuous batching 就能把「读一遍权重服务一个请求」变成「读一遍权重服务几十个请求」,权重读取的浪费被摊平了,扩散的这块优势就被吃掉大半。这也是为什么官方所有速度数字都标着 batch size = 1。

更要命的是服务端的调度语义。自回归的调度单位是 token,请求可以在任意 token 边界插队、抢占、拼批;块扩散的最小提交单位是块,一个块没解码完不能交出去,抢占和拼批的粒度全变了。SGLang 那条路要重写的正是这块。所以「扩散模型吞吐更高」这句话目前没有证据,能说的只有「单请求延迟更低」——这在 Agent 场景里恰好是最值钱的那一项,但别把它推广到 API 服务。

还有一个对比要公平:Clover 和 Qwen3.6-35B-A3B 是同一套 GDN 骨干,所以 prefill 阶段没有差异,128K 长 prompt 的处理成本两者一样(GDN 的线性递归本来就让 prefill 比全注意力便宜)。**Clover 的所有加速都发生在 decode。**这也解释了为什么它在长输出、多轮工具调用的 Agent 循环里收益最大,在「读一篇长文回答一个问题」这种 prefill 占主导的任务上收益最小。

端侧是另一条线。官方在只有 16GB 显存的 RTX 5070 Ti 上做了 INT4 量化部署,MATH-500 上跑到 101.8 tokens/s,对照的同规模 MiniCPM、Qwen 测试结果是 48.5 tokens/s。GDN 的递归状态大小恒定,128K 上下文不会把 KV cache 撑爆,这是能把 35B 塞进 16GB 卡的结构前提——换成全注意力模型,光缓存就放不下。

卡在哪:六个必须知道的限制

一、「全局生成」的实现窗口只有 32 个 token。

这是最该说清楚的一条。宣传里的「全局规划、全局一致」,落到块扩散上,指的是块内那 32 个位置可以互相参照。块一提交就冻住,进了前缀,后面所有块只能看不能改。

也就是说,模型能「全局思考」的范围是 32 个 token。超出这个窗口的依赖,仍然是从左到右硬着头皮往下走。官方 Demo 里那个「同一份合同五个关联判断一起生成」的例子之所以成立,是因为五个判断被塞进了同一个块窗口——这是设计出来的场景,不是免费得到的能力。真要跨几千 token 做全局一致,块扩散和自回归的差距没有宣传的那么大。

二、长生成会重复,官方自己承认了。

模型卡里写得很直白:观察到很长生成时有时会变得重复,所以内置了一堆压制参数——presence_penalty=0.9、repetition_penalty=1.05、dllm_length_penalty=10.0(从 8192 个 token 开始逐渐加大结束倾向)、dllm_think_end_bias=10.0(从 4096 个 token 开始逐渐催促关闭思考)。

这些偏置默认全开,而且是「软控制」。含义有两层:一是长序列上的采样稳定性还没解决,得靠外部偏置硬压;二是硬压有代价——think_end_bias 从 4096 token 就开始催模型结束思考,意味着需要长时间思考的任务会被提前截断。你如果做的是「让模型想久一点」的活,这几个默认值会跟你打架。

**三、速度只在低并发成立。**上一节说过了,所有数字都是 batch=1。生产环境要的是吞吐,这块没有公开证据,调度层也还不成熟。

四、生态还停在「能跑起来」阶段。

GitHub 仓库 10 月 27 日建,两天 99 stars、4 forks、5 个 open issue——而 5 个 issue 的内容分别是「INT4 推理」「怎么用 llama.cpp 运行」「VLLM 或 SGLang 官方镜像」和两条「火钳留名」。这就是当前社区状态的真实截面:大家在问怎么跑,还没到讨论怎么调优。

另外官方自己提示,Hugging Face 的 PyTorch 实现和 SGLang 的 kernel 有数值差异,同样的解码设置可能生成不同文本,正式服务建议用官方 SGLang 实现。这类「两套实现不等价」的情况,在多后端项目早期很常见,但意味着你复现别人的结果前得先确认用的是哪条路径。

五、能力上限是借来的。

Clover 从 Qwen3.6-35B-A3B 初始化,Apache-2.0,文本模型。它没有重新预训练一个基座,而是在别人训好的骨干上做结构改造加后训练。

这不是贬低——用成熟基座做范式验证是正确且高效的路径,Dream 7B 也是这么起来的。但要清楚两点:它的知识边界和 tokenizer 特性继承自 Qwen;「超过 Qwen3.6-35B-A3B」这个结论,是在自家 harness、自家 thinking 预算下得出的,换一套脚手架未必复现。

六、评测口径全部自报。

六项 Agent 最高分、680 tokens/s、515 对 365,都是官方博客给的。第三方证据目前只有一条:CSDN 文章提到有开发者在 WindTunnel 平台上做了 49 项任务测试,Clover 中位执行时间 1.52 秒,对照的 Jev + Mercury 2.5 组合是 3.21 秒。这是单一开发者的单点评测,能作为方向性参考,不能当成独立复现。

使用场景:什么时候该用,什么时候别用

基于上面的分析,我的判断是这样:

场景 适配度 为什么
Agent 内循环(工具调用、代码修复、多步页面操作) 高 每步延迟会沿任务链路累乘;680 tok/s 直接换成「同样的时间多探索几条路径」;SWE-bench 73.6 是硬证据
单卡/端侧本地部署 高 16GB INT4 能跑,101.8 tok/s,GDN 状态恒定不爆显存
结构化批量判断(合同条款、告警研判、多问题联合裁决) 高 块内并行天然适合「几个相关判断一起出」,官方已在做专门的决策模型,一次可联合处理最多 8 个关联问题
长上下文检索问答(128K) 中 能装下,但与同基座自回归模型相比 prefill 没有优势,收益主要在输出侧
高并发 API 服务 低 吞吐无证据,调度层语义要重写,continuous batching 不可直接套用
超长文本生成(超过 8K 输出) 低 官方承认重复倾向,靠偏置压制会牺牲质量
需要严格可回溯推理链的任务 低 块一提交不可回退,超出 32 token 窗口的规划能力与自回归无异

再补两条使用上的实用建议。

如果你想评估它,别只看榜单,先在你的真实链路上量端到端时间。Agent 任务里模型生成只占一部分,工具调用、网络往返、页面渲染都在吃时间;官方那个路径规划 Demo 里,Clover 28 步 169.9 秒完成任务,对照的 Qwen3.6 Flash 用满 30 步 578.3 秒还没做对——3.4 倍差距里既有生成速度,也有「步数更少」的因素。这种复合收益才是它真正的卖点,但也是最少被单独测量的部分。

如果你要上线,先把重复和早停这两个偏置调明白。默认值是为通用对话调的,做长报告、做深度代码重构时,dllm_length_penalty 和 dllm_think_end_bias 很可能需要放松,放松之后重复会不会回来,得你自己测。

怎么跑起来:最小可运行代码

官方给的最小路径是 Transformers + 一块能放下 69GB BF16 权重的卡。默认块大小 32、阈值 0.95:

pip install "transformers==5.19.0" accelerate safetensors
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "Diffuspace/Clover-35B-A3B-Preview"
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    trust_remote_code=True,
    dtype=torch.bfloat16,
    device_map="cuda:0",
).eval()

messages = [{"role": "user", "content": "用三句话解释块扩散和自回归的区别"}]
prompt = tokenizer.apply_chat_template(
    messages, tokenize=False, add_generation_prompt=True, enable_thinking=True
)
inputs = tokenizer(prompt, add_special_tokens=False, return_tensors="pt").to("cuda:0")

output = model.generate(
    **inputs,
    max_new_tokens=24576,
    block_size=32,      # 块大小
    threshold=0.95,     # 置信度阈值,高于它就并行填
    do_sample=False,
)
completion = output[0, inputs["input_ids"].shape[1]:]
print(tokenizer.decode(completion, skip_special_tokens=True))

几个容易踩的点:

  • max_new_tokens 要留出解析最后一个整块的余量,超 128K(131072)的请求会被直接拒绝,包括这个余量。
  • 生产服务用官方 SGLang 实现,别用 HF 的 PyTorch 路径对性能下结论,两者数值和速度都不一样。
  • block_size 调大能提升并行度,但块内要填的位置变多、平均去噪步数上升,不是越大越快;官方默认 32 是有理由的。
  • 端侧 INT4 的推理路径目前只有官方博客的数字,仓库里还在被追问(见 open issue「INT4 推理」),自己动手前先确认权重和 kernel 是否齐备。

该怀疑的地方

写到这里该把怀疑摊开说了。

**第一,「5–10 倍」是个模糊口径。**官方博客正文里给的是 680(GB300,内部 Agent 数据)、515 对 365(H200,Agent 任务)。「5–10 倍」出现在媒体转述里。同一个模型在不同任务上对着不同加速方案,倍数能从 1.4 倍到 10 倍横跨,引用时最好带上前提,不然就成了营销数字。

**第二,73.6 的 SWE-bench 需要看脚手架。**官方同时在开发自己的 Agent 运行框架(harness)和编程客户端,说明这个分数很可能是在自家脚手架下调出来的。SWE-bench 这类端到端 Agent 评测,脚手架的影响不比模型小——换个 harness,分数浮动几点很正常。等第三方在自己的框架下复现了再当定论。

**第三,也是这条线上最硬的一个问号:分数里有多少是扩散解码的功劳,多少是后训练的功劳?**模型从 Qwen3.6-35B-A3B 初始化,之后做了结构改造加后训练。社区里已经有人在问:Agent 能力的提升究竟来自块扩散这套解码方式本身,还是来自额外的后训练数据与配方?官方没有拆开说明。这个不拆开,「扩散范式更适合 Agent」就还只是一个观察,不是因果。要做消融的话,得拿同样后训练预算的纯自回归版本作对照,这个实验目前没人做。

**第四,第三方速度数据两处出处对不上。**一个 49 项任务、中位执行 1.52 秒的数字在流传:CSDN 的报道归为「开发者在 WindTunnel 平台上的测评」,对照 Jev + Mercury 2.5 是 3.21 秒;AICoder 的报道则把它归为 WebMCP 的 49 项任务评测。任务数和中位数一致,归属不同。这类不一致在二手转述里很常见,但它提醒你:这个数字目前只有转述,没有可点开的方法说明,能作为方向性参考,不能当成独立复现。

**第五,社区热度还没起来。**两天 99 stars,5 个 issue 全是「怎么跑」。这既可能是好机会(早期介入、问题少、能直接和团队对话),也可能是信号(还没多少人真正验证过)。Dream 系列积累的 270 万次 Hugging Face 下载是上一代的光环,不能自动继承到 35B 的新模型上。

**第六,也是最重要的一条:这是一条新范式的第一次规模化尝试,不是成熟技术。**它证明的是「扩散语言模型在 35B 不塌」,不是「扩散语言模型可以替代自回归」。真正的分水岭在于:当有人把 continuous batching、投机解码、prefix caching 这套自回归的工程体系在块扩散上重建一遍之后,吞吐还能不能打。这件事还没人做完。

对开发者的实际含义:如果你在做 Agent 产品、做端侧、做延迟敏感的单请求链路,Clover 现在就可以拿来试,它能给你一个别家给不了的延迟数字。如果你在选线上的模型底座,先别动,等一个独立的吞吐评测和一个稳定的非 Preview 版本。

扩散这条路值得下注——2026 年前 9 个月这个方向的论文数量已经是 2025 年全年的 2.5 倍,Google、蚂蚁、Inception 都在场,DiffuSpace 刚拿了两轮共数亿元人民币融资,是这条赛道目前最大的一笔。但「值得下注」和「现在就换」是两件事。

参考文档与链接

你会在什么场景里为「低延迟」多付这份复杂度?是 Agent 循环里的等待,还是端侧那几十毫秒?评论区聊聊你的实测数字——尤其是那些和官方数字对不上的。觉得有用点个赞,让更多在纠结要不要换底座的人看到。


作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/ 关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top

本文首发于 AI人工智能时代,转载请注明出处。

分享给朋友