Я давно хотел себе домой голосового ассистента. Самый очевидный и удобный для меня вариант — поставить дома Яндекс.Станцию с Алисой. Но я серьёзно отношусь к вопросу privacy, поэтому от такой покупки меня останавливает мысль, что компания, как минимум зарабатывающая на рекламе, получает в распоряжение устройство с микрофоном у меня дома 🌚
Кстати, один знакомый мне рассказал, что через приложение умного дома он может буквально прослушивать, что происходит в комнате, где стоит его Яндекс.Станция. То есть функционал прослушки уже есть, вопрос только в том, кто может им пользоваться..
Если что, к обработке самих запросов у меня вопросов нет — мне не нравится именно постоянное пассивное прослушивание комнаты.
Пришедшие в голову варианты
Мне очень хотелось иметь голосовой помощник, поэтому я искал альтернативы. Погуглив / пообщавшись с ChatGPT / пообщавшись в чатах Вастрик.Клуба, я пришёл к таким вариантам:
1️⃣ Самодельные голосовые ассистенты с использованием Home Assistant. Это ПО с открытым исходным кодом для настройки умных домов. На ютубе есть множество гайдов о том, как сделать свою умную колонку с упором на privacy, можно всё собрать вообще без использования облачных сервисов. По этим видосам настройка всех этих штук (для того уровня результата, что я хотел) мне показалось достаточно муторной, да и вряд ли это будет работать идеально (судя по видосам).
Надо использовать несколько моделей: для распознавания речи (speech-to-text, STT), для генерации голоса (text-to-speech, TTS) и саму LLM (большая языковая модель, которая будет генерировать текст, которым ассистент должен отвечать пользователю). В целом, это решается использованием LLM по платному API, а для STT и TTS есть небольшие модели, которые отлично работают и без видеокарт. Но синтез речи и распознавание, конечно, тут будут хуже, чем у Алисы.
Ещё проблема: для некоторых запросов к голосовому ассистенту требуется доступ в интернет. Например, у Алисы можно спросить прогноз погоды, и она отлично ответит, используя актуальные данные. А вот просто LLM-ка ничем здесь не поможет, максимум галлюцинацию выдаст. Для Home Assistant есть плагины, позволяющие подключить к LLM-ке поиск от Google, но, опять же, мне показалось очень муторным всё это настраивать, да и наверняка качество ответов было бы хуже, чем у Алисы, всё-таки правильно собрать контекст из интернета — далеко не тривиальная задача!
2️⃣ Второй подход, над которым я думал — купить Яндекс.Станцию и использовать кнопку выключения микрофона ней. Обещают (😁), что она аппаратно отключает микрофон. Вручную включать и выключать микрофон очень неудобно. Может, переложить это на самодельного ассистента из прошлого пункта? (не самого умного, но "доверенного") ? Например: я говорю "Ассистент, Алиса", он включает Яндекс.Станцию, дальше я уже общаюсь с ней, потом он её выключает сам или по команде.
Тут я нашёл два варианта: либо умные розетки, которые могут включать/выключать электричество для колонки, либо, как мне подсказали в чатах Вастрик.Клуба, устройства, которые гуглятся по слову "fingerbot" — это кубик, который умеет по сетевому запросу нажимать физические кнопки.
Можно было бы купить Яндекс.Станцию и закрепить такой "палец" на ней, а управлил бы им будет мой самодельный ассистент на страже privacy. Я долго думал над этим вариантам и в итоге забил: это всё сложно реализуется, да и как-то слишком костыльно.
Как я дошёл до решения
Небольшое лирическое отступление про то, как я дошел до решения. У меня есть пет-проект — Planty, мой самописный клон Todoist. Фронтенд там местами хромает, поэтому я так и не пересел на него полноценно. Но зато мы с женой используем его для общего списка "что надо купить в магазине" — очень удобно.
Я подумал, что было бы круто голосом добавлять продукты в этот список, чтобы не лезть лишний раз в телефон. Я снова вспомнил про свою мечту с самодельным голосовым ассистентом. Решил сделать его хотя бы в такой форме, без Алисы.
У меня уже есть устройство, где есть микрофон, динамик, Linux и немного оперативной памяти — это старый ноутбук, на котором у меня крутится медиасервер Emby. Можно на питоне написать скрипт, который будет в бесконечном цикле слушать микрофон локальной моделькой для распознавания речи, понимать команды типа "добавь продукт такой-то"
и выполнять их. Для добавления задачи в Planty я могу отправить соответствующий запрос на бэкенд.
Естественно, я отдал эту задачу ChatGPT 5. В целом, всё завелось с первого раза. Пришлось подебажить, чтобы всё заработало как надо. Для озвучки голоса он использовал pyttsx3+espeak-ng. Вроде работало, но с каким-то странным акцентом. Оказалось, что код, написанный ChatGPT, выбирал белорусский язык, потому что он циклом перебирал доступные языки и брал первый, где есть подстрока "russian"
😁
Качество синтеза речи меня всё равно не устроило: он просто разбивает слова на слоги и склеивает соответствующие аудиофайлы. Звучит не очень, в общем. Я поменял этот TTS-движок на современную опенсорс модельку от silero, т.к. я видел их прикольный телеграм-бот для генерации голосовых сообщений и кружков голосами героев из Warcraft 3. В опенсорсе доступны несколько стандартных голосов, звучит очень даже неплохо!
Для распознавания речи используется 50-мегабайтная моделька vosk-model-small-ru-0.22
, она справляется средненько, часто путает слова, самый странный пример был такой: томатная паста ≈ бумажная база. Более крутая модель требует больше памяти и не влезла в 4 Гб ОЗУ моего ноута. В целом, и с маленькой моделью норм, если привыкнуть говорить разборчиво. Спойлер: в финальном решении ниже при обращении к Алисе локальная модель вообще не используется.
Итак, я реализовал голосовые команды "ассистент купить <название_продукта>"
и "ассистент список"
. Задача с голосовым управлением таск-трекером выполнена 😎
Тут я почувствовал, что способ прикрутить Алису где-то рядом.. Осталось совсем чуть-чуть...
Приручение Алисы
API для голосового взаимодействия с Алисой не существует (кстати, у OpenAI недавно появилась в API моделька gpt-realtime
, можно будет тоже попробовать). Колонки "Яндекс.Станция" у меня нет, а если бы была, то все равно сложно придумать что-то лучше костыля с fingerbot.
Решение, которое наконец-то пришло мне в голову — по команде "ассистент алиса"
открывать с помощью библиотеки Selenium сайт https://alice.yandex.ru и нажимать на фиолетовую кнопку для активации голосового режима. Дальше можно спокойно общаться с Алисой, т.к. браузер тоже имеет доступ к микрофону.
После того как диалог с Алисой закончен, мой скрипт закрывает эту вкладку браузера. Это происходит по команде или по таймауту в 2 минуты.
Алиса, кстати, очень болтливая. Это, с одной стороны, прикольно, а с другой – ее невозможно заткнуть и приходится ждать таймаута, который ее вырубит. Перекрикивать ее не получается. Можно сделать динамический таймаут или научиться распознавать хлопки. Но в целом и так пойдёт, особенно если просить ее отвечать кратко.
Результат
В гостиной комнате лежит ноутбук, подключенный к розетке. Крышка закрыта, экран не горит (правильные настройки ОС). Подходим и говорим:
— Ассистент, Алиса
<2.5 секунды ожидания> и <звук активации Алисы>
— Какая сегодня погода?
— <ответ>
<через 120 секунд скрипт "отключает" Алису>
Питоновский скрипт, который всё это делает, запущен как systemd-сервис на ноутбуке с 4 Гб ОЗУ.
Небольшая оптимизация для скорости ответа: браузер открывается не каждый раз при запросе, а один раз в начале, дальше только переключаются вкладка между сайтом с Алисой и about:blank
(пустой страницей).
Результатом я очень доволен, всё работает как я и хотел. Красота.
Спасибо за прочтение этого поста. Он был адаптирован из серии постов в моём телеграм-канале (там много похожего контента). Там, кстати, есть кружок с демонстрацией результата.
ну вот кстати железная Алиса такого недостатка лишена - она слушается и замолкает, если попросить :)
Это не правда. «прослушивать» нельзя. Можно позвонить. В зависимости от настроек можно позвонить так чтоб Алиса сама сразу взяла трубку. Но даже в этом случае алиса голосом скажет что на колонку звонит такой-то пользователь
правильно я понял получившийся результат?
"голосовой помощник без прослушки*"
*пока вы не пользуетесь колонкой