☰
Whistle 16.9MB 语音识别拆解:11 毫秒首 token 的 CPU 模型,凭什么追平 145MB 的 Whisper base
2026/10/9 7:29:32 网站建设 项目流程

10 月 2 日,Cactus Compute 放出开源语音识别模型 Whistle,单文件只有 16.9 兆。

它跑在 CPU 上,无依赖,不碰显卡,也不碰任何云端接口。

官方给的首 token 延迟是 11 毫秒,七种语言转写,词级时间戳与语音嵌入一起给。

最特别的是它和自家 Needle 模型共用同一个引擎,一个二进制同时吃语音和文本。

你给它一段「关掉厨房灯」的录音,它吐回的不只是文字,而是一段能直接执行的函数调用。

语音到工具调用中间没有文字层,这一条就是本文想算清的账。

16.9 兆到底装下了什么

Whistle 面向的不是数据中心,而是手机、手表、机器人、智能家居、车载和单片机。

官方定位很直白:一个 16.9 MB 的文件,在设备本地完成全部语音理解。

它同时承担三份工作,转写、词时间戳和语音嵌入。

转写吃 16kHz 单声道,单次最多 30 秒,七种语言自动检测。

这七种语言是英语、德语、法语、西班牙语、意大利语、荷兰语和波兰语。

语言检测在本地完成,你也可以显式点名一种语言跳过检测。

词级时间戳给每个词标出开始时间、结束时间和置信度,全部来自解码器注意力对齐。

语音嵌入直接输出编码器结果,每 80 毫秒一行,不需要先解码成文字。

音频全程不离开设备,第一下点击才下载那 16.9 兆模型。

这三份能力叠加在一个文件里,是它能塞进嵌入式设备的前提。

官方把它定位成口袋里的语音入口,而不是又一个云端转写接口。

前端:3000 帧怎么压成 375 帧

音频进来先过前端,16kHz 单声道按 25 毫秒窗口、10 毫秒步长切帧。

每帧算 80 个 log-mel 特征,频带限制在 250 到 3500 赫兹。

这个频带的裁剪本身就是一重降噪,超低音和高频噪声直接被扔掉。

每个通道独立归一化,30 秒音频总共得到 3000 帧。

接着是一个 128 通道、卷积核 9 的卷积主干,把帧数连续减半三次。

3000 帧先变 1500,再变 750,最后落在 375 帧,正好每 80 毫秒一帧。

从这里往后,每一层都按 375 帧这个节奏工作。

语音嵌入返回的就是这一层节奏下的结果,一行对应一帧。

也就是说,30 秒的音频在进入注意力之前,已经被压掉了八分之七。

卷积主干对语音这种连续信号特别合适,相邻帧高度相关,下采样损失很小。

前端这一笔先把计算量砍到八分之一,后面所有层都跟着受益。

编码器:八个非因果注意力块

编码器由八个 Simple Attention 块组成,和 Needle 用的是同一套块。

每个块包含四条 mHC 残差通道,前馈部分换成 Monarch Hadamard MLP。

mHC 是多头跨通道残差的缩写,让信息在通道间流动得更直接。

Monarch Hadamard MLP 用层级结构近似全连接,计算量远小于标准前馈。

这里的注意力不做因果掩码,任意帧都能看到整段音频的任何位置。

官方举例说,第 3 秒的帧可以 attend 到第 12 秒的帧。

对语音识别来说这是合理的,因为词义经常依赖后面的上下文。

一个词的发音要等到它后面的词出现后才能稳定解释。

后端解码时才需要因果性,那是另一套账。

编码器全部八个块在任何深度配置下都会完整运行,从不切片。

这是 Ladder 训练体系里唯一不许动的部分。

解码器:注意力账怎么省

解码端是八个 Laddered Simple Attention 块,宽度 512。

8 个查询头压缩成 2 个 KV 头,查询和键各 48 维,值 64 维。

KV 头压缩是 token 生成阶段缓存友好的关键设计。

Q、K、V 各接一个 3 抽头因果卷积,第 3 层和第 7 层挂 engram 查找。

engram 槽位一共 18432 个,这是 Needle 块清单换了个层数而已。

语音特有部分只有一处,每层一个带门的交叉注意力。

公式是 x 加上门控后的 softmax 注意力结果,门由每层自己学习。

K 和 V 直接取自音频片段,这段投影只在片段到来时计算一次。

375 帧乘 8 层,算完就一直持有到整个解码结束。

所以五个 beam 只花五份短转写缓存,而不是五遍重放音频。

这个设计把解码成本从音频长度转移到了文本长度。

音频再长,重听音频的开销也只在投影那一次。

这是它敢在 CPU 上实时转写的关键一笔省账。

解码:五束搜索与关键词偏置

解码用五个 beam,按长度归一化的对数概率打分。

长度归一化防止短句因为概率天然偏低而长期吃亏。

关键词偏置走一个 Aho-Corasick 自动机,沿着短语匹配推进。

自动机匹配到关键词时,对应 beam 的对数概率被抬升。

这样像 Siobhan 或 Krzysztof 这种罕见的专名也能被纠正出来。

转写文本封顶 320 个 token,防止失控输出。

词表有 8192 个文本片段,外加七个语言 token,每种语言一个。

检测到哪种语言,就输出对应的语言 token,而不是在带外单独返回。

如果你点名语言,默认自动检测也可以被覆盖。

静音处理也内置在引擎里,解码启动前先量响度范围。

响度低于阈值就直接返回空转写和空语言,根本不进 beam 搜索。

这一条对嵌入式常开的拾音场景很实用,省电也省时间。

静音返回空结果意味着调用方不用误解码错误,逻辑可以写得很干净。

Ladder:每层深度都是独立模型

解码器从 2 层起,每一档深度都单独训练成一个模型。

加载时用 --audio-depth 选深度,编码器永远全 8 块跑完。

官方解释,编码器从不切片,任何深度都完整过一遍。

这样同一个文件可以按设备算力裁解码器,速度与质量按需取舍。

手表用浅档,机器人用深档,我们只用一份权重。

Ladder 训练的成本是每档深度都要训一遍,但推理侧完全免费。

它把部署时的量化选择变成了加载参数,连重新导出模型都省了。

成绩单:三个模型的对比

官方用 Whisper normalizers 统一打分,Whistle 测了 86174 条话语。

Whisper base 和 Moonshine tiny v2 的数字取自作者公布的成绩。

Whistle 用的是多语 checkpoint,不是只练英文的版本。

官方还声明,所有报告测试集的音频都不在训练和验证数据里。

这个声明靠音频校验和与说话人 ID 逐条比对验证过。

避免测试集污染的声明在开源模型里很少见,值得专门点出来。

指标WhistleWhisper baseMoonshine tiny v2
模型大小16.9 MB145.3 MB41.9 MB
首 token(10 秒音频)11.1 ms73.2 ms22.8 ms
解码速度1319 tok/s266 tok/s262 tok/s
LibriSpeech test-clean胜负未公布*
LibriSpeech test-other胜负未公布*
SPGISpeech胜负未公布*
Earnings-22胜负未公布*
FLEURS 平均胜负未公布*
TED-LIUM负胜未公布*
AMI(口径不同)负胜未公布*
MLS 平均负胜未公布*

表格里带星号的地方是模型作者从未公布过对应基准。

Moonshine 只做英文,Whisper 没报 SPGISpeech、Earnings-22 和 AMI cleaned。

Whisper 的 AMI 是 AMI-IHM,和其他两个模型报的 AMI 不是同一子集。

十秒音频全部跑在 Apple M4 Pro 的 CPU 上,数字可复现。

Whistle 在八个基准里赢下五个,LibriSpeech 的 clean 和 other 都拿下了。

输掉的三个对手都大它一个量级,这个落差更说明问题。

首 token 延迟还会随音频长度变化,5 秒 5.9 毫秒,30 秒 36.3 毫秒。

Whisper 每次输入都补齐到 30 秒,所以它的首 token 延迟是平的。

Whistle 的首 token 跟着片段走,这是流式体感的关键。

解码速度上差异更悬殊,Whistle 每秒 1319 token,对手都只有二百多。

尺寸、延迟、吞吐三项全胜,这是小模型难得的完胜项。

Needle 生态:一个二进制吃语音和文本

Whistle 不是孤立模型,它被装进 Needle 的 C++ 引擎里。

needle_load 只看 .cact 文件里是什么,所以同一个二进制什么都能干。

官方给了三条命令,第一行纯转写,第二行纯工具调用。

needle --model whistle.cact --audio clip.wav needle --model needle3.cact --tools tools.json --prompt "turn off the kitchen lights" needle --model needle3.cact --model whistle.cact --tools tools.json --audio clip.wav

第三行最值得看,needle_complete 直接把音频当输入吃下去。

引擎先转写,再用转写结果对着你的工具列表作答,最后吐一个 JSON。

JSON 里带 function_calls 和语音字段,语音字段统一用 audio_ 前缀。

整条链路里调用方见不到文字转写,语音直接变成函数调用。

音频、文本、工具三种能力在一个进程里,省掉了跨服务调用的全部开销。

对智能家居和机器人这种延迟敏感场景,本地闭环意义很大。

Python 与 C 的接入方式

pip 安装 cactus-needle 之后,Python 侧一行就能转写。

import needle print(needle.transcribe("clip.wav")["text"]) # turn off the kitchen lights

16kHz 的 WAV 或裸采样什么都不用多装,基础安装就够。

其他采样率和麦克风采集需要 [mic] 附加组件,会带上 soxr 和 sounddevice。

每次调用都会返回文本、语言、首 token 毫秒数和解码速度。

word_timestamps=True 追加每个词的时间和概率。

keywords 参数可以抬升指定短语的对数概率,例如人名 Siobhan 和 Krzysztof。

language 参数直接锁定语种,跳过自动检测。

needle.Whistle() 把模型包成对象,用于 embed 或持有微调过的 .cact。

终端里还有个 playground 子命令,从麦克风实时转写。

compare 子命令把同一段音频喂给 Whistle、Whisper 和 Moonshine 做并排对比。

C 侧同样简洁,整块语音 API 只有三个函数。

needle_load、needle_transcribe、needle_embed 就是全部了。

引擎不读任何环境变量,行为要么是编译默认,要么是显式 flag。

官方说这个设计是为了让每个平台的二进制行为完全一致。

嵌入式工程最怕隐式配置,三函数加零环境变量非常难得。

十七个目标平台

引擎为 17 个目标预构建,从 macOS、Linux 一路到 ARM 上的 Windows。

Android、iOS、watchOS 都在清单里,RISC-V 和 MIPS 也在。

浏览器和 WASI 组件同样有份,网页里那个沙箱就是这么跑的。

每个目录都放一个 needle 二进制、libneedle.a 和 needle.h。

任何 .cact 文件都能被这些二进制加载,跨平台不需要重编译。

模型权重挂在 Hugging Face 的 Cactus-Compute/whistle 下。

引擎和平台目录在 Cactus-Compute/needle3,源码在 GitHub 的 cactus-compute/needle。

一个 16.9 兆的模型配上十七套预编译二进制,端侧落地的门槛被压得很低。

社区的实测反馈

Hacker News 上这条发布收获 312 分和 31 条评论,热度不低。

不少人说英语识别准得离谱,试着打断它也能理解清楚。

一位测试者表示几句带复杂时态和用词的句子都被完整转写。

西班牙语是公认短板,会写出不存在的词或者满篇错别字。

带西班牙口音的英语倒没问题,测试者特意强调了这一点。

印度口音同样被识别良好,社区里有实例佐证。

一个反复出现的限制是单次 30 秒上限,超出直接报运行时错误。

不少人问能不能上 Android,能不能加更多语言。

一条高赞评论说,这个尺寸的成绩单让人惊讶,做得漂亮。

还有人在评论区安利自家基于 Streaming Zipformer 的 10 语言 CLI。

那条安利反而印证了社区对子 20MB CPU 模型的集体兴趣。

对于量产端侧硬件的人来说,这个趋势比单个模型更重要。

评论里的短板集中在语种覆盖和长音频,架构本身几乎没有被质疑。

账本合起来怎么读

Whistle 的 16.9 兆不是靠压缩硬挤出来的,是架构设计省出来的。

非因果编码器、门控交叉注意力投影只算一次、Ladder 深度裁剪,各省一笔。

和 Needle 共用引擎又省掉一套推理栈和一份二进制体积。

它用 11 毫秒首 token 换了传统语音管线的整套部署负担。

传统方案要先转写、再调云端、再等返回,Whistle 把这条链压进一个函数。

和很多模型拆解一样,数字会随硬件与基准口径浮动。

但「语音直接进工具调用」这条路径是全新的。

它把麦克风变成了一个函数入口,这可能是端侧小模型最被低估的一步。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询