Как мы научили Алису реагировать на быстрые команды
Голосовые ассистенты активируются «по имени» — это всем привычно. Но как быть, если нужно несколько раз повторять команду из одного слова? Например, чтобы настроить музыку, говорить каждый раз «Алиса, громче» и «Алиса, дальше» утомляет. Кроме того, в некоторых сценариях важна скорость выполнения действия: например, когда нужно включить свет в комнате.
Для таких случаев мы научили Алису распознавать быстрые команды — то есть те, для которых её не нужно звать по имени. Достаточно просто сказать «громче», «дальше» или «включи свет». И в этой статье я расскажу, что из себя представляет новая функция, как мы её разрабатывали, с какими сложностями столкнулись. А ещё немного поговорим про распознавание и свёрточные модели.
Почему мы задумались о быстрых командах
Сейчас общение с колонкой можно разделить на достаточно длинные запросы, например, «Алиса, какая погода завтра в Москве», и короткие, которые нужны для управления экраном, проигрыванием, громкостью и умным домом, например, «Алиса, дальше» или «Алиса, громче». При этом часто эти короткие команды могут идти потоком — пока не дойдёшь до понравившегося трека или до нужной громкости.
Если смотреть на обращения к Алисе, большую долю составляют упомянутые короткие, односложные команды для базовых действий. Например, самые частые из них — это «дальше» и «стоп». Половину времени, которое произносится быстрая команда, занимает обращение к Алисе. Вывод напрашивается сам: убрав необходимость сперва обращаться к ассистенту, пользователь сможет тратить меньше времени и усилий для частых команд.
Кроме удобства и скорости, эта фича совпадает с нашим желанием двигаться в сторону более естественного общения с голосовым помощником. Согласитесь, люди крайне редко общаются между собой, постоянно называя друг друга по имени. Здесь нам хотелось добиться такого же эффекта: Алису не надо лишний раз звать, чтобы она выполнила простое действие, которое понятно по контексту.
Про разработку
Ещё в 2018 году в Станциях и Максах появились быстрые навигационные команды для управления экраном: «выше», «ниже», «дальше», «назад». Фича была необходима для нового взаимодействия с Алисой: навигацией по интерфейсу телевизора. Без этого процесс был ужасно долгим и неприятным, требуя постоянно повторять «Алиса». Отчасти текущий заход — это логическое продолжение навигационных споттеров в виде расширения их количества и новых сценариев использования.
Разработка фичи началась ещё в 2020 году, но быстро свернулась. Мы споткнулись о ложные срабатывания — ситуации, в которых ассистент ошибочно активируется на похожую фразу, например, на слово «что» вместо «стоп». Тогда этих срабатываний было очень много.
В 2022 году мы возродили разработку, и во время внутреннего тестирования поняли, что фича имеет большую ценность для пользователей: люди привыкали использовать быстрые команды, так как это здорово экономит время и энергию. К тому же голосовая модель Алисы с тех пор научилась распознавать речь втрое лучше. Многие улучшения можно было перенести на модель быстрых команд.
Сама разработка фичи велась в несколько этапов:
Начали переобучать модель на данных для тренировки голосовой модели.
Получили на выходе первую минимально работоспособную модель. Запустили её на артефактах того, что осталось от первого захода в 2020 году, пофиксили какие-то баги и отправили в альфа-релиз.
Вывели фичу в статус бета-теста. За десяток месяцев мы улучшили качество работы нейросетей, добавили ещё больше фраз и снизили затраты оперативной памяти. А ещё переделали логику работы всей системы. За два года у нас появилось много новых функций (мультирум, стереопара, тандем), которыми тоже нужно мочь управлять.
Выпуск фичи для всех пользователей.
Сейчас у нас работает две голосовых модели: основная модель Алиса и модель быстрых команд. Дальше я расскажу про то, как мы обучали вторую модель и какие подходы заложены в её работу.
Подготовка признаков
Эта часть полностью совпадает с подготовкой признаков для модели голосовой активацией на слово «Алиса», о чём мы уже писали в этой статье. Не буду останавливаться на этом этапе очень подробно — расскажу только основные моменты.
Обработка звука начинается с записи, полученной с микрофона. Она представляет собой массив отклонений микрофонной мембраны от исходного состояния в некоторые моменты времени. В нашем случае используется звук с частотой 16 кГц, то есть за одну секунду звука получаем 16 000 значений. Нейронные сети, особенно достаточно маленькие, обычно плохо работают с такими длинными неструктурированными последовательностями. Поэтому дальше такой формат звука часто приводится к спектрограмме или другим преобразованиям поверх неё, после чего получается примерно такая картинка:
Сейчас для модели быстрых команд используются фреймы с окном 25 мс и сдвигом 10 мс, а в качестве признаков используются фильтрбанки.
Свёрточные модели
Алиса слышит и понимает команды за счёт большой модели распознавания речи, которая работает на серверах Яндекса: её архитектура основана на трансформерах и она умеет предсказывать все слова языка. Однако из-за большого размера такую модель не получится поместить на устройство. Поэтому модель для быстрых команд больше похоже на основную модель голосовой активации по слову «Алиса», но с бо́льшим числом выходов для всех слов.
По своей архитектуре модели для быстрых команд являются свёрточными. Они часто применяются в работе с распознаванием звуков или изображений — особенно если речь про небольшие модели, которые встраиваются в устройство. Однако в отличие от картинок, где используются двумерные свёрточные модели для высоты и ширины, в звуке могут использоваться одномерные, потому что есть только одно измерение — время.
В случае быстрых команд вычислительная эффективность особенно важна, так как на устройстве уже есть модель «Алиса», которая использует почти все доступные ресурсы. Именно поэтому для быстрых команд нужно было сделать модель, которая помещалась бы в остаток ресурсов. Для этого мы использовали depthwise-separable свёртки. Основная их идея заключается в том, что одна большая свёртка разбивается на несколько маленьких, чтобы уменьшить потребление CPU и оперативной памяти. Если более формально, то свёртка размера T * N_in * N_out раскладывается в две последовательные свёртки:
T * N_in * 1,
1 * N_in * N_out.
T — это ядро свёртки по времени, N_in — количество входных каналов, N_out — количество выходных каналов. К этому можно относиться как к SVD разложение, но только для свёрток, а не для матрицы.
Нейронная сеть в основе модели голосовой активации учится распознавать отдельные слова, чего достаточно для бо́льшей части быстрых команд. Но как быть, если команда состоит из двух слов? Например, «включи свет».
На этом этапе в игру вступает декодер — он комбинирует «показания» двух выходов нейросети отвечающих за слова «включи» и «свет». После этого он решает, насколько вероятно, что из этого получится фраза «включи свет». Если вероятность выше, чем порог, который мы установили во время тестов, модель активируется.
Обучение и функции потерь
Обучение модели для быстрых команд не сильно отличается от обучения основной модели голосовой активации для «Алисы» или «Яндекса». Здесь используется комбинация из двух функций потерь.
Пофреймовая. Для каждого маленького кусочка звука в соответствие ставится некоторый таргет. Например, в качестве таргета может стоять 0 (это значит, что ничего не происходит) или определённый идентификатор слова. Такая функция потерь используется для стабильности процедуры обучения, а также для задания времени активации. Это не позволяет модели сильно увеличить задержку между произношением активационной фразы и активацией быстрой команды на устройстве. Дальше поверх данных таргетов мы применяем многоклассовую кросс-энтропию.
Поатерансовая. Для всей произнесённой пользователем фразы в соответствие ставятся слова из словаря модели, а вероятность, предсказанная моделью для отдельного слова, для всей фразы вычисляется как максимум среди вероятностей по всем фреймам. Дальше к этим значениям применяется бинарная кросс-энтропия.
Проще говоря, пофреймовая функция потерь — это когда находится максимальный конфиденс и таргет внутри маленького окошка, а поатерансовая — тоже самое, но на всей аудиозаписи (или атерсансе).
В случае быстрых команд произошёл переход от многоклассовой функции потерь к бинарной из-за того, что при переходе от кусочков звука к целой фразе задача классификации (то есть в один момент времени может произносится только одно слово) меняется на задачу тегирования (то есть на всей фразе могут произносится несколько слов из словаря модели).
Поатерансовая функция потерь используется, чтобы улучшить качество модели, которое может просаживаться на пофреймовой функции потерь из-за того, что может быть неточно проставлен момент времени, содержащий конец произношения слова. При этом пофреймовая функция потерь нужна для того, чтобы контролировать задержку после срабатывания.
Но несмотря на то что этот пайплайн отточен ещё на большой модели Алисы, нам пришлось столкнуться с некоторыми сложностями.
Как мы победили сложности
Ложные срабатывания. На первый взгляд, внедрить быстрые команды легко — просто увеличить количество активационных фраз. После этого Станция волшебным образом начнёт реагировать ещё на 10–30 слов, и задача решена.
Но повышение числа активационных фраз неизбежно ведёт к повышению случаев ложных срабатываний колонки. Представьте, как трек у вас каждые 15 секунд скачет по громкости и перематывается то вперёд, то назад. В отличие от предшественников быстрых команд, навигационные споттеры гораздо меньше раздражали в случае ложных срабатываний и, как следствие, требовали меньше работы.
Первый шаг по преодолению этой проблемы — натренировать модель. Про структуру сети я рассказал выше, однако есть ещё одна важная часть обучения модели — данные. Мы попросили большое количество людей наговорить нужные нам командные фразы. Также мы использовали голосовые запросы в Алису с отрезанным словом-активатором. При этом такие запросы фильтровались и выбрасывались те, где люди очень быстро говорят сам запрос — мы называем такие запросы «бесшовными». Такие запросы не получается обрезать так, чтобы не захватился кусок нужного слова или не остался кусок слова-активатора. Это нужно было для того, чтобы модель училась активироваться именно на сами быстрые команды, а не на их комбинацию с «Алисой».
Дальше было ещё несколько шагов по улучшению модели:
После раскатки модели в бета-тестирование мы дообучили её на примерах использования командных споттеров, в особенности на ложных срабатываниях.
Для наговоренных данных пробовали использовать аугментации. Например, накладывали музыку, так как большая часть использования быстрых команд («стоп», «дальше», «следующая», «громче», «тише») связаны с музыкой. Однако в отличие от прошлого пункта, добавление аугментаций не дало значимого эффекта.
Но даже с самой совершенной моделью от ложных срабатываний никуда не деться — они будут расти. Поэтому, кроме непосредственного улучшения модели, мы добавили несколько продуктовых решений.
Научили колонку понимать контекст. Например, вводим условие: если ничего не играет, то команды управления проигрыванием не работают. Кроме того, особенность работы командных споттеров позволяет им не быть активным всё время. Это позволяет сильно нивелировать неизбежный рост числа ложных срабатываний из-за большого количества новых активационных слов.
Откалибровали чувствительность модели. Чувствительность модели — это крутилка: слева стоит отзывчивость, а справа — уменьшение ложных срабатываний. После обучения модели мы тестировали текущее решение на закрытой группе, настроив баланс между ложными срабатываниями и чувствительностью командных споттеров для удобства использования данной фичи.
Дали возможность пользователям выбрать нужные быстрые команды в приложении. Если ошибочных активаций одной из них стало много, её можно отключить и пользоваться привычной активацией через слово «Алиса». Особенно это помогает в случае ненужных команд: например, если всегда держать активной команду «включи свет», то в квартире без умных лампочек на ложные активации Алиса будет отвечать, что не может найти такое устройство.
Схематически текущая схема работы командных споттеров выглядит так:
Нехватка данных. Чтобы снизить долю некорректных активаций, мы создаём большие датасеты из негативных примеров. Это наговоры фраз, похожих на быстрые команды, или аудиодорожки стороннего видео. Также на этих сетах негативных примеров подбирается порог срабатывания для моделей голосовой активации, чтобы сократить число ложных активаций.
Слово | Что вместо него может послышаться |
Что / Сто | Стоп |
Вижу / Ближе | Ниже |
Молча / Короче | Громче |
Датчики | Дальше |
Должен | Продолжи |
Проблема | Влево |
Глаза | Назад |
Пишет | Тише |
Вышла | Выше |
Успешно решив все возникшие сложности, мы получили решение, которым мы довольны. Теперь вы можете попробовать его у себя.
Как включить быстрые команды
Функция распознавания быстрых команд работает на всех умных колонках Яндекса: от Лайта до Макса. Её можно включить в приложении «Дом с Алисой» на Android и iOS. Перейдите в Настройки → Голосовой помощник → Настройка быстрых команд. Там же можно отдельно включать разные группы команд.
Вот какие быстрые команды теперь понимает Алиса.
Музыка, фильмы и голос
Воспроизведение и пауза (играй / стоп / хватит / пауза / продолжи)
Переключение треков (дальше / назад / следующий)
Регулировка громкости (тише / громче)
Навигация по ТВ
Управление интерфейсом (выше / ниже / вверх / вниз / вправо / влево / дальше / назад)
Возврат в начало (домой)
Умный дом
Управление светом (включи свет / выключи свет)
Управление телевизором (включи телевизор / выключи телевизор)
Приятный бонус
При внедрении быстрых команд у нас получилось сделать так, чтобы ответ Алисы не прерывался. Раньше было так: пользователь спрашивает у Алисы, какая сейчас погоды, а она начинает отвечать на большой громкости. Он говорит: «Алиса, громкость пять». Она ставит громкость, но при этом перестаёт рассказывать про погоду — синтез ответа прерывается. И пользователю приходится снова спрашивать про погоду.
Сейчас с быстрыми командами громкость можно поменять во время ответа Алисы и синтез её ответа не прервётся. Дело в том, что активация на слово «Алиса» в момент ответа считается перебиванием: в большинстве случаев это означает, что человек не хочет дослушивать ответ. А быстрые команды вроде «громче» или «тише» перебиваниями не считаются.