Whistle: распознавание речи в 16,9 МБ даже на микроконтроллере

Whistle: распознавание речи в 16,9 МБ даже на микроконтроллере

Модель на 16,9 МБ распознаёт речь точнее Whisper base на большинстве публичных тестов, декодирует впятеро быстрее и весит в 8,6 раза меньше. Называется она Whistle, сделала её команда Cactus Compute, и за этими цифрами скрывается смена списка устройств: файл помещается на умные часы, робота и микроконтроллер, где раньше распознавание речи просто не жило.

Whistle вышла в начале октября. Она работает на CPU без единой внешней зависимости и запускается где угодно: в браузере, на часах, в автомобильной системе, на RISC-V плате. А ещё она говорит на языке своего предшественника: вместе с Needle обе модели живут в одном бинарнике и превращают аудиоклип прямо в вызовы инструментов, без облака.

Что такое Whistle

Whistle: открытая модель распознавания речи (speech-to-text) от Cactus Compute, той же команды, что выпустила Needle. Поставляется одним файлом формата .cact размером 16,9 МБ, работает на CPU без зависимостей и разворачивается в том же C++ движке, что Needle, с той же квантизацией.

Модель решает три задачи, и все три выполняются на устройстве. Транскрипция: на вход идёт моно-аудио 16 кГц любой длины, до 30 секунд за один проход, дальше окнами. Таймстемпы: каждое слово получает начало, конец и вероятность, выровненные по вниманию декодера. Речевые эмбеддинги: выход энкодера, одна строка значений на каждые 80 миллисекунд, причём без декодирования транскрипта вообще.

Языков семь: английский, немецкий, французский, испанский, итальянский, нидерландский и польский. Если язык не указан, модель определит его сама и вернёт результат с отдельным языковым токеном.

Почему размер решает

Распознавание речи годами жило в облаке не из вредности. Приличная модель весит сотни мегабайт, и до недавнего времени её некуда было положить, кроме сервера. Whisper base занимает 145,3 МБ, Moonshine tiny v2 от Useful Sensors уже 41,9 МБ, но и это много для железки с бюджетом памяти в сотни килобайт. Whistle заходит в 16,9 МБ, а значит, список устройств расширяется до всего, где есть CPU: носимые гаджеты, слуховые аппараты, игрушки, промышленные датчики. Причём 145,3 МБ это только веса: openai-whisper тянет за собой Python и PyTorch, гигабайты рантайма, которых на встраиваемом железе просто нет. Whistle ставится одним файлом и одним бинарником. Подробности релиза авторы выложили в посте на сайте Cactus.

Для приватности это тоже сдвиг. В браузерном сандбоксе Cactus модель скачивается по первому нажатию кнопки и работает прямо во вкладке, аудио не покидает вашу машину. Голосовые заметки, врачебная диктовка, разговоры в машине: всё остаётся на устройстве. Облачный сценарий добавляет сети лишний круг задержки и отправляет вашу речь на чужой сервер, и для многих задач это дороже, чем несколько процентов точности.

Как устроена модель

Путь звука начинается с простого фронтенда. Аудио 16 кГц режется окнами по 25 миллисекунд с шагом 10 миллисекунд и превращается в 80 лог-мел-бинов в полосе от 250 до 3500 Гц. Тридцатисекундный клип это 3 000 кадров, а свёрточный стем на 128 каналов с ядром 9 уменьшает их число трижды, оставляя 375 кадров, по одному на каждые 80 миллисекунд. Все следующие шаги работают на этой частоте.

Энкодер собран из восьми блоков Simple Attention, тех же, что в Needle: четыре остаточные линии mHC и Monarch Hadamard MLP вместо обычного feed-forward. Monarch Hadamard MLP это структурированные матрицы вместо плотных: меньше умножений на каждом проходе, и именно поэтому модель так быстро считает на CPU. Внимание некаузальное, кадр на третьей секунде видит кадр на двенадцатой: вся запись доступна целиком, как и должно быть при транскрипции.

Декодер это восемь блоков Laddered Simple Attention шириной 512, с восемью головами запросов и двумя головами KV, 48-мерными запросами и ключами, 64-мерными значениями и трёхтаповой каузальной свёрткой на Q, K и V. На слоях 3 и 7 работают engram-поиски. Словарь состоит из 8 192 текстовых фрагментов и семи языковых токенов.

Речевая часть в архитектуре ровно одна: каждый слой декодера читает энкодер через gated cross-attention. Проекции K и V считаются один раз, когда приходит клип, это 375 кадров на восемь слоёв, и держатся весь декод. Поэтому пять лучей beam search стоят пять коротких кэшей транскрипта, а не пять повторных проходов по аудио. Декодирование устроено так: пять лучей со счётом из лог-вероятности, нормализованной по длине, keyword biasing через автомат Ахо-Корасик, который поднимает шансы заранее переданных фраз вроде имён и терминов, и потолок транскрипта в 320 токенов.

Есть и две детали в довесок. Лестница глубин: каждая урезанная версия декодера начиная с двух слоёв обучалась как самостоятельная модель, и флаг --audio-depth выбирает её в момент загрузки, при этом энкодер всегда считает все восемь блоков. И детектор тишины: перед запуском декодера движок измеряет диапазон громкости клипа и на тишине возвращает пустой транскрипт, не запуская поиск вообще.

Бенчмарки: где Whistle впереди, а где нет

Цифры в релизных постах обычно подобраны льстиво, но Cactus выложила полные таблицы, включая проигрыши. Все замеры сделаны на CPU Apple M4 Pro, на десяти секундах аудио, официальными рантаймами на дефолтах, у Whistle с пятью лучами.

Размер: 16,9 МБ против 145,3 МБ у Whisper base и 41,9 МБ у Moonshine tiny v2. Время до первого токена: 11,1 миллисекунды против 73,2 и 22,8. Скорость декодера: 1 319 токенов в секунду против 266 и 262. У Whisper время до первого токена не зависит от длины клипа, он всегда дополняет вход до 30 секунд. У Whistle оно растёт вместе с клипом: 5,9 мс на пяти секундах, 11,1 на десяти, 36,3 на тридцати. Разница заметна в интерактивных сценариях: пока облачный сервис только устанавливает соединение, Whistle уже печатает первый токен.

По точности (Word Error Rate, меньше значит лучше) Whistle впереди на LibriSpeech test-clean и test-other, на SPGISpeech, на Earnings-22 и в среднем по FLEURS. Whisper base отыгрывается на TED-LIUM, на AMI и в среднем по MLS. Авторы оговаривают нюансы: у Whisper в таблице другой поднабор AMI (AMI-IHM), а Moonshine и вовсе только английский.

Методика тоже открыта. WER считается нормализаторами Whisper, результаты Whistle посчитаны по 86 174 высказываниям. Отдельно проверено, что тестовое аудио не попадало ни в обучение, ни в валидацию: сверяли чексуммы аудио и идентификаторы спикеров по всем тестовым наборам. Для релиза модели распознавания речи это редкая аккуратность.

Голос сразу в вызовы инструментов

Дальше самое интересное для практиков. Whistle и Needle живут в одном бинарнике, 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, где рядом лежат вызовы и поля речи с префиксом audio_. Вызывающему коду не нужно видеть транскрипт вообще:

{
  "function_calls": [{"name": "set_lights", "arguments": {"room": "kitchen", "on": false}}],
  "confidence": 0.94,
  "audio_text": "turn off the kitchen lights",
  "audio_language": "en"
}

Это и есть сценарий, ради которого всё затевалось: голосовой ассистент без облака. Раньше его собирали из трёх сервисов, распознавание, языковая модель и слой вызова инструментов, каждый со своей задержкой и своим счётом. Теперь это один бинарник и два файла весов: произнесли фразу, получили JSON с функциями. Одиннадцать миллисекунд до первого токена оставляют запас на обработку ответа, а если транскрипт всё же нужен, audio_text всегда рядом.

Как попробовать

Python-путь занимает две строки:

pip install cactus-needle
import needle
print(needle.transcribe("clip.wav")["text"])

Каждый вызов возвращает текст, язык, миллисекунды до первого токена и скорость декодера после него. Флаг word_timestamps=True добавляет слова с временами и вероятностями, keywords=["Siobhan", "Krzysztof"] заранее поднимает шансы нужных фраз в поиске, language="de" отключает автоопределение языка. Объект needle.Whistle() открывает доступ к embed(audio) для речевых эмбеддингов. В CLI есть две удобные команды: needle whistle playground распознаёт речь с микрофона прямо в терминале, а needle whistle compare прогоняет один клип через Whistle, Whisper и Moonshine и печатает тайминги рядом.

Движок собран под семнадцать целей: macOS и Linux, Android, iOS, watchOS, Windows на ARM, RISC-V, MIPS, браузер и WASI-компонент. В каждой папке лежат бинарник, libneedle.a и заголовок needle.h, которые принимают любой .cact. Веса опубликованы на Hugging Face, движок лежит в репозитории Cactus-Compute/needle3 на GitHub. Сандбокс в браузере работает уже сейчас: первое нажатие скачивает те самые 16,9 МБ, а дальше весь инференс идёт на вашей машине. В сандбоксе есть и live-режим: слова появляются по мере речи, без ограничения длины.

Частые вопросы

Whistle работает без интернета?

Да. Модель целиком помещается в один файл и считает на CPU без внешних библиотек и сетевых вызовов. Веса скачиваются один раз, это те же 16,9 МБ, дальше распознавание идёт офлайн. В браузерном сандбоксе аудио вообще не покидает устройство.

Whistle поддерживает русский язык?

Пока нет. Релиз включает семь языков: английский, немецкий, французский, испанский, итальянский, нидерландский и польский. Язык определяется автоматически, если не задать его явно, а результат приходит с отдельным языковым токеном. Планов по расширению списка авторы не публиковали.

Whistle лучше Whisper?

Смотря для чего. Whistle выигрывает по размеру (в 8,6 раза меньше Whisper base), по скорости до первого токена и по точности на LibriSpeech, SPGISpeech, Earnings-22 и FLEURS. Whisper точнее на TED-LIUM, AMI и MLS, и он знает больше языков. Для устройств и голосовых интерфейсов выбор очевиден, для пакетной транскрипции не всегда.

Итог

Экономия мегабайт здесь не самоцель. 16,9 МБ меняют класс устройств, на которых распознавание речи становится обычной функцией: часы, наушники, роботы, датчики, браузер. И меняют схему сборки голосовых агентов: Whistle стыкуется с Needle, так что голос становится не отдельным сервисом, а входом в tool-calling движок. Если пропустили наш майский разбор Needle, начните с него: 26-миллионная модель, которая вызывает инструменты быстрее GPT-4. А сандбокс Whistle открывается в один клик: десяти секунд речи хватит, чтобы составить собственное мнение.

← Все записи