Cactus Compute 发布 16.9 MB 语音识别模型 Whistle
Whistle: Speech to Text in 16.9 MB
Cactus Compute 发布语音识别模型 Whistle,单个文件 16.9 MB,在 CPU 上无依赖运行,支持英语、德语、法语、西班牙语、意大利语、荷兰语和波兰语七种语言,首 token 延迟 11 ms。
模型研究
一个开放语音识别模型,与 Needle 运行在同一个 CPU 引擎上。它可转写七种语言,11 毫秒内产出首个 token,并与 Needle 一同加载,因此一个二进制文件就能把一段音频直接变成工具调用。
JM
Jakub Mroz
HN
Henry Ndubuaku
|2026年10月2日|6 分钟阅读
今天我们发布 Whistle,一个面向手机、可穿戴设备、机器人、智能家居、汽车和微控制器的语音识别模型。它是一个 16.9 MB 的文件,在 CPU 上运行且无依赖,并加载进与 Needle 相同的 C++ 引擎,来自同一个容器和同一种量化。
Whistle 沙盒
说话,Whistle 会在你的设备上转写
16.9 MB · 在此标签页中运行
按下麦克风并说点什么。
Whistle 做三件事,全部在设备上完成:
- 转写。 16 kHz 单声道音频,单次最多 30 秒,支持英语、德语、法语、西班牙语、意大利语、荷兰语和波兰语。除非你指定语言,否则会自动检测。
- 词级时间戳。 每个词及其起始、结束和概率,由解码器的注意力对齐得出。
- 语音嵌入。 编码器输出,每 80 毫秒一帧一行,无需解码转写文本。
--audio-depth 选择解码器层数;编码器始终运行全部八层。前端。 16 kHz 单声道音频以 25 毫秒窗口和 10 毫秒步长分帧为 80 个对数梅尔频带,带限于 250-3500 Hz,并按通道归一化。三十秒即 3,000 帧。一个 128 通道、卷积核为 9 的卷积主干将该数量三次减半,留下 375 帧,每 80 毫秒一帧。此后的每个阶段都以该速率运行,embed 每帧返回一行。
编码器。 八个 Simple Attention 块:四条 mHC 残差通道,以及一个替代前馈网络的 Monarch Hadamard MLP,与 Needle 使用的块相同。注意力不是因果的。3 秒处的帧会关注 12 秒处的帧。
解码器。 八个 Laddered Simple Attention 块,宽度 512,8 个查询头对 2 个 KV 头,48 维查询和键,64 维值,对 Q、K 和 V 施加 3 抽头因果卷积,并在第 3 层和第 7 层对 18,432 个槽位进行 engram 查找。这就是 Needle 的块列表,只是层数不同。
语音特定的部分只是每层增加了一个模块。每个解码器层通过一个门控交叉注意力读取编码器,x ← x + σ(g) · softmax(q̂ K̂ᵀ/√d) V,门控按层学习,K 和 V 取自音频片段。这些投影在音频片段到达时运行一次,375 帧跨 8 层,然后在整个解码过程中保持不变。因此五个束只花费五个简短的转写缓存,而不是对音频的五次遍历。
解码。 五个束按长度归一化的对数概率评分。关键词偏置在你传入的短语上运行 Aho-Corasick 自动机,与束并行,并随着自动机推进提升它们的对数概率。转写文本上限为 320 个 token。词表为 8,192 个文本片段加上七个语言 token,每种语言一个,因此检测到的语言会作为 token 输出,而不是带外返回。
阶梯在解码器上。从 2 层起的每个深度都作为独立模型训练,--audio-depth 在加载时选择其中一个。编码器从不切片:所有八个块在每个深度都运行。
静音。引擎在解码器启动前测量片段的响度范围。低于阈值时,它返回空转录和空语言,并且从不进入束搜索。
WhistleWhisper baseMoonshine tiny v2
Whistle 在 LibriSpeech test-clean 和 test-other、SPGISpeech、Earnings-22 以及 FLEURS 平均值上领先。Whisper base 在 TED-LIUM、AMI 和 MLS 平均值上领先,大小为 145.3 MB 对 16.9。
大小
兆字节,越小越好
Whistle16.9 MB
Whisper base145.3 MB
Moonshine tiny v241.9 MB
首个 token 时间
毫秒,越小越好
Whistle11.1 ms
Whisper base73.2 ms
Moonshine tiny v222.8 ms
解码
每秒 token 数,越大越好
Whistle1,319/s
Whisper base266/s
Moonshine tiny v2262/s
每个模型都在其官方运行时上以默认设置运行:Whistle 的 C++ 引擎使用 5 个束,openai-whisper,以及 moonshine-voice 对整个音频进行非流式处理。首个 token 时间是从音频输入到首个 token。解码是 token 数除以其后的挂钟时间,因此编码器不会被重复计算。Whisper 将每个输入填充到 30 秒,因此其首个 token 时间在片段长度上保持不变。Whistle 的则随片段变化:5 秒时 5.9 ms,10 秒时 11.1 ms,30 秒时 36.3 ms。
词错误率使用 Whisper 归一化器评分。Whistle 的数值是在 86,174 条话语上测量的。Whisper 和 Moonshine 的数值是其作者发布的,来自多语言检查点而非仅英语检查点。Whistle 的训练或验证数据中没有出现测试音频,通过比较每个报告的测试集的音频校验和和说话人 ID 验证。
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 对象,包含 calls 和 speech 字段,speech 字段以 audio_ 为前缀。调用方不处理任何转录。
{"function_calls":[{"name":"set_lights","arguments":{"room":"kitchen","on":false}}],
"confidence":0.94,
"audio_text":"turn off the kitchen lights",
"audio_language":"en"}pip install cactus-needleimport needle
print(needle.transcribe("clip.wav")["text"])
# turn off the kitchen lights16 kHz WAV 或原始样本除基础安装外不需要任何东西。其他采样率和麦克风捕获需要 [mic] 额外项,它添加了 soxr 和 sounddevice。
每次调用返回文本、语言、到首个 token 的毫秒数以及其后解码器的每秒 token 数。word_timestamps=True 添加每个词及其时间和概率。keywords=["Siobhan", "Krzysztof"] 在搜索过程中提高这些短语的对数概率。language="de" 强制指定语言而不是检测它。needle.Whistle() 是作为对象的同一模型,用于 embed(audio) 或持有一个调优的 .cact。
needle whistle playground 在终端中从麦克风转录,needle whistle compare 将同一片段通过 Whistle、Whisper 和 Moonshine 并排运行,并显示它们的计时。
该引擎为十七个目标平台提供预构建版本,涵盖 macOS 和 Linux,到 Android、iOS、watchOS、Windows on ARM、RISC-V、MIPS、浏览器以及一个 WASI 组件。每个文件夹都包含一个 needle 二进制文件、libneedle.a 和 needle.h,并可加载你交给它的任何 .cact。
needle download macos-arm64
needle download whistle
./macos-arm64/needle --model whistle.cact --audio clip.wav --audio-word-timestampsneedle_load、needle_transcribe 和 needle_embed 就是整个语音 C API。该引擎不读取任何环境变量。每个行为要么是编译时的默认值,要么是显式标志。
权重位于 Hugging Face,引擎及其平台文件夹位于 Cactus-Compute/needle3,源代码位于 GitHub。
来源:Hacker News · cactuscompute.com