Clover-35B-A3B拆解:块扩散95%置信解锁,Agent中位1.52秒快一倍的账怎么算
一、发布与定位:扩散模型第一次以 Agent 为主场
10 月 28 日,落地深圳的扩散智能(DiffuSpace)发布并开源了 Clover-35B-A3B-Preview,权重与模型卡同步挂上 Hugging Face。官方给它的定位不是又一个聊天模型,而是面向 Agent 场景的产业级扩散语言模型,写代码、生成网页、调用工具、连续执行任务都在首批演示里。
先看硬规格:MoE 架构,总参数 350 亿,每个 token 只激活约 30 亿参数(型号里的 A3B 就是这个意思),支持思考模式,上下文给到明确的 128K。这个体量放在 2026 年底不算大,真正让它出圈的是解码方式——它不是自回归那样一个字一个字往外蹦,而是用块扩散把 32 个位置编成一组并行解锁。
官方自报的纸面成绩先摆在这里,后面再逐项讨论可信度:
| 评测 | 考察内容 | Clover 成绩 |
|---|---|---|
| τ³ Overall | 工具使用 | 65.3 |
| BFCL-v4 | 函数调用 | 67.9 |
| SWE-bench Verified | 真实仓库改 bug | 73.6 |
| Terminal-Bench 2.1 | 终端任务 | 51.7 |
做这件事的团队背景值得一提。扩散智能由香港大学孔令鹏教授和两位博士生龚珊三、叶佳成创立,2026 年 5 月才落地深圳。这条技术路线他们走得很早:2022 年的 DiffuSeq 研究怎么用扩散做序列到序列文本生成,2025 年 4 月推出 70 亿参数的 Dream 7B,官方称其在 Hugging Face 累计下载超过 250 万次。
资本节奏和模型发布咬得很紧。10 月初团队宣布连续完成两轮融资,合计近 5 亿人民币,经纬创投、顺为资本、君联资本联合领投,中科创星、华为哈勃、地平线跟投。哈勃和地平线同时出现,指向很明确:端侧。AI PC、智能汽车、机器人这些算力有限又要求响应快的场景,正好是并行生成能打的地方。
二、自回归的成本结构:为什么"快"在 Agent 场景是硬指标
今天你在用的几乎所有大模型都是自回归的:给它前半句,它猜下一个 token;把猜出来的接上去,再猜下一个。你盯着屏幕看它一个字一个字冒出来,就是这个过程的直接可视化。这不是实现偷懒,而是架构决定——每一步的条件概率都依赖前面已经定稿的全部内容。
问题在于成本结构。每产出一个 token,都要把模型从头到尾跑一遍前向,几十亿参数从显存里完整读一次。KV cache 能省掉历史 token 的注意力重算,但参数读取本身一次都省不掉。写一篇一千 token 的回答,就是一千次完整前向,跟回答第几个字没关系,第一个字和第一千个字的边际成本完全一样。
打个不严谨的比方:你写一篇作文,每写一个字就要把整本字典从头翻一遍。字越多翻得越多,而且每次翻字典的开销是恒定的。这就是为什么长输出的延迟是按 token 数线性涨的——架构里没有"批量定稿"这个概念。
普通聊天里这种浪费还能忍,Agent 场景会把它放大到无法接受。一次真实任务动辄几十轮:思考一段、拼一个工具调用、等返回、再思考、再调用。每一轮都要生成几十到几百个 token 的思考内容和结构化参数,用户感知到的不是"每秒多少 token",而是"这一步怎么还没动"。
算一笔粗账:一个 10 轮工具调用的任务,每轮生成 200 token,就是 2000 次串行前向。如果单次前向 15 毫秒,光生成就要 30 秒,网络和执行还没算。所以 Agent 产品卷到最后,卷的就是单步延迟——谁能把每轮的生成时间砍一半,谁的 Agent 就"跟手"。这正是 Clover 切入的位置。
把这笔账落到硬件上更直观。Clover 每个 token 激活约 30 亿参数,按 FP8 精度算是大约 3GB 的权重读取;一块 HBM 带宽 3TB/s 的卡,理论下限就是约 1 毫秒一次前向。自回归生成 1000 个 token,光权重读取就是 1 秒起步,注意力和采样还没算。这个下限对任何优化都免疫——除非一次前向能定稿不止一个 token,而这正是块扩散动的那一刀。
三、扩散模型怎么写字:先打码,再一点点擦干净
扩散这个词你在 AI 生图里早就见过:从一团噪点开始,一步步去噪,画面慢慢变清晰。它的本质是逆向工程——先把完整的东西弄糊弄乱,再让模型学着从乱还原出序。搬到文本上,玩法对应起来:先把要写的一段文字全部盖住,每个位置都是 MASK,然后让模型猜被盖住的是什么,猜一轮擦掉一部分遮盖,再猜一轮,直到整段清晰。
这个范式里藏着并行生成的全部来源。因为开局整段都是空的,模型可以同时对所有位置给出猜测,它不需要"先有第一个字才能猜第二个字"。一次前向,几十个位置同时拿到候选——这和自回归"一次前向只出一个 token"是根本性的差别,不是优化幅度的差别。
但直接把整篇文章交给扩散一起猜,效果并不行。要同时决定的位置越多,位置之间越容易前后打架:第三段的一个词可能推翻第一段的措辞,而语言的意思又严重依赖顺序铺垫。无条件放开全局并行,换来的是连贯性崩塌。所以工程上必须回答一个问题:并行的粒度切多大,才能既吃到速度又不丢一致性。
Clover 给出的折中叫块扩散。把序列切成一块一块,每块 32 个位置。块和块之间老老实实按顺序来——前一块彻底解完才轮到下一块;但块内部,32 个位置一起猜、互相参照。像一条流水线:工位之间串行,每个工位内部 32 个工人同时干活。这个粒度的选择本身就是这篇模型卡里最有工程味道的决定。
四、95% 置信解锁:一次签字,没有撤回键
块内 32 个位置一起猜,但模型对每个格子的把握并不一样。紧邻标点和格式化结构的位置往往十拿九稳,处在语义转折点的位置则纯属瞎蒙。Clover 的规则非常干脆:每一轮去噪,只把置信度超过 95% 的格子写死定稿,其余的继续保持遮盖,留给下一轮。像考试先把会做的题做掉,不会的空着回头再补,而且及格线就划在 95%。
明眼人会立刻问:万一某一轮 32 个格子里没有一个过 95% 呢?它有兜底规则——挑出置信度最高的那一个位置先定上,保证整块一定能往前走,不会死锁。这条兜底保证了推进性,代价是偶尔要在信心不足时强行落子,这个代价后面还会回来谈。
等一块 32 个位置全部定稿,这一块就固定下来,成为下一块解码的前提条件,然后流水线向前滚动。从"一个字一个字"变成"一块一块",中间隔的就是这一步。官方演示里那个 1 秒思考加 4 到 5 秒生成可交互太阳系模拟器的手感,根源就在这里:跑一遍模型的成本几乎没变,但一遍能定下来的 token 从一个变成了一块里的一部分。
这里必须点破一个容易被宣传盖住的性质:块扩散的每次接受都是永久提交,没有撤回键。对比一下大家更熟的投机解码——草稿模型先猜一串,目标模型事后验证,猜错了把草稿扔掉重来,错误不会留在输出里。块扩散不一样,某一块里混进一个错 token,它就成了后续所有块的已知前提,后面全部内容都要围着这个错误继续写下去。
所以那个 0.95 不是拍脑袋调的魔法数字,它是在"每轮多定几个字"和"别把错的字定死"之间,刻意往保守方向站的一步。门槛调低,速度更快但错误锁定率上升;调高,质量更稳但并行度浪费。95% 是这个权衡在 Agent 场景下的当前答案——Agent 的工具调用格式错一个字符就是整步报废,宁慢勿错。
块大小为什么是 32,也值得停下来看一眼。块切得太小,比如 4 或 8,就退化回接近自回归,并行收益被摊薄到没有意义;块切得太大,比如 256,块内联合一致的难度指数上升,一个块里前后打架的概率跟着涨,错误锁定的代价被放大。32 是从结果反推出来的工程甜点:大到足够摊薄前向成本,小到块内一致性还能被置信门槛兜住。这个数字今后大概率会跟着硬件和任务分布继续调,但"块粒度是核心旋钮"这个判断不会变。
五、GDN 与 128K:长上下文怎么记住又不拖慢
Agent 还有一个结构性麻烦:上下文越跑越长。系统提示、历史对话、每一步工具返回的结果全部堆在那里,传统做法是把它们统统塞回注意力里重算,序列越长越慢,这是自回归时代就存在的老问题,块扩散并不自动免疫。
Clover 的做法换了思路:把已经生成的历史压缩成一份持续更新的状态单元,而不是把每句话原样留在注意力窗口里。相当于做笔记——你不会背下老师讲过的每句话,而是记成几行要点,用的时候翻一眼。历史信息的"读出"被做成一个独立的信息单元,和当前正在解码的块一起参与计算,前文占多少权重、当前占多少权重,交给模型自己学。
这一整套改动是围绕块扩散把门控 Delta 网络(GDN)重构出来的,128K 上下文是写进规格的明确指标。翻译成人话就是四个字:记得住,又不拖慢。对需要连续几十轮工具调用的 Agent 来说,长上下文不衰减和单步够快是同一张门票的两面——只解决一半,另一半会在第 30 轮的时候找你收账。
补一句背景:门控 Delta 网络属于线性注意力一族,核心思想是用一个持续更新的状态代替全量 KV 缓存,每来一个 token 就对状态做一次带门控的增量改写,而不是把所有历史重新注意一遍。它和块扩散是天然搭档——块内 32 个位置需要双向互相可见,适合局部全注意力;块外的漫长历史只需要一份压缩读出,适合线性状态。两种机制各管一段,谁都不硬扛自己不擅长的部分。
六、Agent 稳定性才是真正的门槛
说句实话,单段文字生成快一点慢一点,用户体验差别没那么大。Agent 不一样,它是连续动作:调用工具、读返回、判断对不对、调整、再调用,任何一步出错,后面全部跟着歪。扩散语言模型过去在 Agent 场景里恰恰口碑不稳,常见的翻车方式有三种——工具调用的格式写错了接口直接不认,同一个步骤反复尝试出不来,拿到返回结果不知道下一步该怎么改。
Clover 这次演示的重点就压在连续操作上。官方演示里它通过 WebMCP 连续处理六项任务:开票、课程报名、金额汇总、活动状态查询、客户信息查询、发票信息查询,一项接一项跑完,中间根据页面返回调整下一步动作。在购物演示里,它按要求找到指定款式、黑色、L 码的 T 恤,加购物车,填访客信息,走完测试结账流程。这些都不是单步生成,是长链路的状态跟踪。
媒体实测组数据也来自发布当天:让它把一堆简历信息整理成 LaTeX 排版代码,十来秒交活;从零生成一个个人 Agent 的网页界面,十几秒成型。真正值得看的对照组是网页 Agent 评测 WindTunnel:49 个任务、每个任务跑 3 次,Clover 中位执行时间 1.52 秒,Jev 加 Mercury 2.5 的组合是 3.21 秒,用时少了超过一半;尝试成功率 98.6% 对 95.9%,还略高。官方演示里同表的 Gemini 3.6 Flash 被甩开数倍。
| 方案 | WindTunnel 中位耗时 | 尝试成功率 |
|---|---|---|
| Clover-35B-A3B-Preview | 1.52 秒 | 98.6% |
| Jev + Mercury 2.5 | 3.21 秒 | 95.9% |
再把第四节那个风险接回来:块定稿不可改,意味着 Agent 场景里一个格式错误不是"这一步重来"的问题,而是后续步骤全部基于一个坏前提继续推理。Clover 能把成功率稳在 98% 以上,靠的是置信门槛加格式约束训练把错误拦在定稿之前,而不是定稿之后的事后修补——这是它和早期扩散模型玩具演示的本质区别。
还有一个容易被忽略的互相成全:工具调用恰好是结构化程度最高的文本。JSON 的括号、引号、冒号这些骨架 token,正是置信度最高、每一轮最先被定稿的部分;参数值这些语义 token 置信度低,被留到后面几轮。于是解码顺序天然变成先搭骨架、再填血肉,格式的硬约束在生成早期就被钉死。自回归从左到右写到哪算哪,块扩散则是一轮先把整块的语法骨架锁了——对 Agent 来说,这个顺序差异就是成功率差异。
七、三个冷静事实,先别急着喊颠覆

第一,目前所有数字全是官方自报。发布当天,知乎、Reddit、Hacker News 上都还没有像样的第三方复现,模型和报道同一天上线,社区想验证也得先把 35B 权重跑起来。SWE-bench Verified 73.6 这个分数如果坐实,已经不是玩具扩散模型的水平,但"如果坐实"四个字现在还不能省。
第二,模型卡自己承认了一个短板,原文写着"我们观察到非常长的生成有时会变得重复",为此内置了重复控制和渐进收尾的控制项。这句话翻译过来是:长文本翻来覆去说同一件事的问题,还没有被架构本身解决,只是被工程手段压住了。对动不动连续跑几十轮的 Agent 来说,这不是小细节,是一个明确的待观察项。
第三,它不是从零训练出来的新物种。Clover 从 Qwen3.6-35B-A3B 的权重出发改造,好处是省掉天价预训练成本、直接继承成熟模型的语言能力,代价是能力上限相当程度上仍受底座约束。"扩散"带来的增量主要落在两处:并行生成换来的速度,和块内互相参照换来的灵活性。官方口径里每个 Agent 任务成本低至 0.0010 美元,同样属于自报数据,先记账再核账。
那么第三方复现该盯什么?τ³ 和 BFCL-v4 都是公开评测,谁都能跑;WindTunnel 的 49 个网页任务和 1.52 秒的中位耗时,需要同硬件、同网络条件才有可比性;最值得等的是长任务压测——连续五十轮以上的工具调用里,模型卡自承认的那个超长生成重复问题会不会复发。这三张答卷交出来之前,73.6 的 SWE-bench 成绩先按方向参考,不按定案引用。
八、78 行 Python 亲手复现:快一倍到底从哪来
机制讲到这层,不如亲手跑一遍。下面这段程序只用 Python 标准库,把三种解码路径放在同一个合成任务上对比:自回归逐字生成、投机解码草稿加验证、块扩散按置信度解锁。目标序列模拟一段工具调用流水,置信度按 token 的结构化程度给初值,每轮去噪后剩余位置的置信度随已确定上下文小幅上调——这和真实模型里"邻居定稿后条件分布变尖锐"是同向的。
直接保存运行即可,输出一张对照表:三种方案各用多少次完整前向、块扩散每次前向平均定稿多少 token、相对自回归的加速比,以及置信门槛之下被强行锁定的错误数。数字是仿真出来的,但它们背后的不等式——一次前向的成本不变、一次能定稿的 token 变多——就是 1.52 秒对 3.21 秒的全部来源。
# Block-diffusion vs autoregressive decoding cost simulator (stdlib only).
import random
VOCAB = ["tool_call", "{", "}", "\"", "name", ":", "args", "city", "query",
",", "result", "status", "ok", "step", "id", "=", ";", "return",
"retry", "json", "value", "none", "true", "false"]
EASY = {"{": 0.99, "}": 0.99, "\"": 0.985, ":": 0.975, ",": 0.965,
";": 0.98, "=": 0.97} # structural tokens are nearly free
COMMON = {"tool_call", "args", "result", "status", "ok", "json", "return"}
def make_target(n, seed=42):
rng = random.Random(seed)
return [rng.choice(VOCAB) for _ in range(n)]
def base_confidence(token, rng):
if token in EASY:
return min(0.999, EASY[token] + rng.random() * 0.005)
if token in COMMON:
return 0.86 + rng.random() * 0.10 # some cross the bar early
return 0.55 + rng.random() * 0.25 # rare identifiers stay hard
def ar_passes(target):
return len(target) # one full forward per token
def speculative_passes(target, draft=5, accept_p=0.72, seed=7):
rng = random.Random(seed)
pos, passes = 0, 0
while pos < len(target):
passes += 1 # draft pass
accepted = 0
for _ in range(min(draft, len(target) - pos)):
if rng.random() < accept_p:
accepted += 1
else:
break # wrong draft is discarded, no lock-in
passes += 1 # verification pass
pos += accepted + 1 # verifier bonus token
return passes
def block_diffusion(target, block=32, tau=0.95, seed=42, lift=0.09):
rng = random.Random(seed)
passes = locked_errors = 0
for start in range(0, len(target), block):
chunk = target[start:start + block]
conf = {i: base_confidence(tok, rng) for i, tok in enumerate(chunk)}
masked = set(conf)
while masked:
passes += 1 # one forward per denoise round
ready = [i for i in masked if conf[i] >= tau]
if not ready: # fallback: commit the single best
i = max(masked, key=lambda j: conf[j])
ready = [i]
if rng.random() < 0.18: # forced pick may lock an error in
locked_errors += 1
for i in ready:
masked.discard(i)
for j in masked: # committed neighbours sharpen the rest
conf[j] = min(0.999, conf[j] + lift)
return passes, locked_errors
def main():
head = ("tokens", "AR", "spec", "blkDiff", "tok/blkPass", "speedup", "lockedErr")
print(("{:>6} | {:>6} | {:>6} | {:>7} | {:>11} | {:>7} | {:>9}").format(*head))
for n in (128, 256, 512, 1024):
target = make_target(n)
ar = ar_passes(target)
spec = speculative_passes(target)
bd, wrong = block_diffusion(target)
print(("{:>6} | {:>6} | {:>6} | {:>7} | {:>11.2f} | {:>6.1f}x | {:>9}")
.format(n, ar, spec, bd, n / bd, ar / bd, wrong))
t = make_target(512)
ar, bd = ar_passes(t), block_diffusion(t)[0]
assert bd < ar, "block diffusion must use fewer forward passes"
assert 1.5 < ar / bd < 12, "speedup should land in a plausible range"
print("sanity checks passed: fewer passes, plausible speedup, errors visible")
if __name__ == "__main__":
main()
跑完会看到两个值得盯着看的数字。一是 speedup 列稳定在数倍区间,这就是"块内并行"的直接兑现;二是 lockedErr 列不为零——它把第四节说的"没有撤回键"变成了账本上一行看得见的成本。投机解码那一列则告诉你另一个方向:草稿可以扔,所以它没有锁定错误列,但草稿加验证的两段式前向让它的加速天花板明显低于块扩散。三条路线不是谁消灭谁,而是各自把成本付在不同的地方。
九、成本账与选型:一条新车道,适合一种车
把账算到钱上。官方口径每个 Agent 任务成本低至 0.0010 美元,配合 1.52 秒的中位耗时,指向的是同一笔账:Agent 产品的成本大头从来不是模型单价,而是"步数乘以每步延迟再乘以重试率"。块扩散同时压前两项,置信门槛压第三项,三个乘数一起动,总账才会出现数量级变化的可能——注意是可能,第三方复现出来之前都按自报处理。
端侧是这条路线最自然的去处。华为哈勃和地平线同时出现在股东名单里不是巧合:AI PC、智能车、机器人这些场景的共同点,是算力有限、电池有限、用户对响应延迟却最敏感。自回归在端侧的痛点是每 token 都要把模型读一遍,块扩散把同样一次读取摊到多个定稿 token 上,等于在功耗不变的前提下换吞吐。团队与 Acrab 的端侧适配合作、多模态版本的规划,都是在给这条车道铺路。
但选型上没有免费的午餐。开放式创作、极长自由生成、对单步质量要求苛刻到不能容忍任何锁定错误的场景,自回归仍是更稳的答案——逐字串行的"慢"在这些场景里买的是可控性。而工具调用、结构化输出、固定格式生成、端侧延迟敏感任务,输出空间本来就受格式强约束,恰好是置信门槛最容易发挥的地方,块扩散的账最划算。判断你的场景属于哪边,比追新模型重要。
接下来一个月,三件事值得盯着。一看第三方复现:35B 权重已经在 Hugging Face 上,社区能不能在自己的硬件上复现出 1.52 秒和 98.6%;二看端侧落地:与 Acrab 的合作和多模态版本能不能把并行生成的功耗优势变成真实产品;三看长任务:五十轮以上的连续 Agent 任务里重复率是否可控。三个信号里有两个兑现,这条车道就算真正通车了。
所以这不是"扩散干掉了自回归"的故事。它更像在同一条路上多修了一条车道,而这条车道特别适合一种车:一个人干活、没人陪跑、上下文还特别长的任务。Agent 恰好就是这种车。这条路最终是工程捷径还是下一代模型的雏形,要等社区把权重跑起来、把长任务压测做完才有答案。现在能确定的是:那个"AI 只能一个字一个字往外蹦"的时代,在技术上已经被绕过去了。
更多推荐
所有评论(0)