⚠️ Обращайте внимание на даты.
Этот блог больше не ведётся с 17 января 2023, и на тот момент с написания этой страницы (13.01.2023) прошло 4 дня.
Я уже несколько лет развлекаюсь у себя дома со всякой “умной периферией”. Из распространённых понятий это ближе всего к “умному дому”, но умным его назвать сложно. Скорее как у Вастрика, “дом-дурачок” (и через 3 года). Надо сказать, у нас системы развивались хоть и независимо, но очень похоже, так что я о своей даже не вижу резона писать. Почитайте лучше Вастрика. А я лучше расскажу о большой штуке, которой у него нет, зато есть у меня — о локальном голосовом помощнике.
Моё голосовое прошлое
Голосовой набор на мобильных телефонах
Впервые я с голосовым управлением столкнулся году, кажется, в 2008, на родительском мобильном телефоне, который теоретически поддерживал “голосовой набор”: нажимаешь специальную кнопочку, произносишь имя и где-то в 1 случае из 5 он наберёт кого надо. Во всяком случае, у меня осталось такое впечатление, это ж дело почти лет 15 назад было. При такой надёжности казалось, что применять это ещё очень и очень рано.
Позднее, через годик примерно, мне попалась на глаза Bluetooth-гарнитурка, через которую с помощью голосового управления звонить, отвечать и вешать трубку можно было одной кнопкой. Круто. Ради такого можно было и потерпеть несколько попыток распознавания. К тому же, как оказалось, английский язык распознавался гораздо лучше.
Голосовое управление ПК
Ещё несколько лет спустя я набрёл на голосовое управление в Windows. И меня заинтересовало, как можно управлять с помощью голоса интерфейсами, которые настолько жёстко приспособлены для управления клавиатурой и мышью.
Ответ нашёлся быстро — очень плохо.
Для начала, русский язык не поддерживался вообще. В смысле, при выбранном русском языке опция была попросту недоступна. Вполне возможно, что в Microsoft просто не добились хорошего результата и решили, что портить репутацию полуготовым решением не стоит. Разумный ход.
При выборе английского языка голосовое управление как минимум включалось. Но работало тоже плоховато. Есть у голосового интерфейса двухсторонняя проблема. Вот решили вы, какой элемент вам нужен. Чтобы им воспользоваться, вам нужно понять, как он в этой системе называется, чтобы на это название сослаться голосом. Но есть проблема и с обратной стороны: интерфейс может не поддерживать голосового управления вовсе и никак свои элементы не называть.
Тогда ещё не было Электрона и засилья программ, которые представляют собой браузеры для одной страницы, и достаточно много прикладного софта использовало родные элементы управления Windows. И для них хорошо работала команда “Show numbers” (покажи цифры), которая делала вот это:
Поэтому взаимодействие с компьютером часто превращалось в цикл “покажи числа”-“{число}”-“окей”. В такие моменты возвращается ощущение, что работаешь с калькулятором-переростком. Одни числа. Ыхъ.
Голосовой ввод на смартфонах
Когда произошёл следующий шаг, я даже затрудняюсь сказать. Видео из той эпохи (⚠️ 16+?) 2014 года — Google открыл собственный облачный голосовой ввод для широкой публики. И как можно увидеть на видео, он неплох. Слабые места есть, и бесят сильно, но встречаются не так уж часто.
Но вот серьёзная беда — распонавание облачное, то есть, шлёт весь текст на серверы Google и получает текст уже оттуда. Без интернета не работает, а корпорация фактически слушает всё, что вы туда произносите, какими бы километровыми соглашениями ни обещала, что не будет. В какой-то момент мы, видимо, забыли старую русскую пословицу “слово не воробей, вылетит — не поймаешь”, и придумали себе, что можно кого-то заставить какую-то информацию удалить.
💡 Кстати, если у вас есть аккаунт Google, можете провести эксперимент: зайти на Google Takeout и запросить у них архив со всеми данными на вас. Конечно, гарантий, что они пришлют вообще всё дать едва ли кто-то может, но сообщают они о многом. Вполне возможно, что там обнаружатся сказанные много лет назад команды.
Я смотрел свой архив в, кажется, 2018, и записи голоса там были. Вполне возможно, что их всё же обязали их удалить с тех пор и больше их там нет. Но, опять же, то, что их нет в архиве, не значит, что у них их нет совсем.
И шапочки из фольги далеко не убирайте, да.
Но сеансов использования полностью из голоса я тогда ещё не видел — активировать голосовой ввод всё ещё приходилось нажатием на кнопку, слова-активатора никакого не было. Или было, но не было распространено достаточно, чтобы я с ним столкнулся.
Голосовой помощник на смартфонах
Я сейчас уже не очень помню, в какой момент из множества утюгов зазвучала реклама “Окей Google”. В 2017?
Всё же случился прорыв — смартфоны научили слышать одно конкретное слово и включать голосовой ввод команд. Ассортимент команд уже позволял решать небольшие задачки, не доставая смартфона вовсе, вроде заведения таймеров/будильников и небольших информационных запросов вроде погоды.
К сожалению, он всё ещё облачный, вещает ваш голос наружу и без интернета превращается в тыкву. Или в полу-тыкву, вроде были какие-то подвижки в сторону выполнения некоторых команд оффлайн, но поскольку я такими решениями не ползьуюсь, достоверно не выяснял.
“Умные” колонки
На международном рынке умная колонка Google Home дебютировала в 2016, и русского языка тогда не поддерживала. Яндекс запустил аналогичную Яндекс.Станцию в 2018. Ситуация примерно как со смартфонами, с той лишь поправкой, что для этих устройств голосовой ввод это основное средство взаимодействия, и почти вся их функциональность доступна только через голос. И им гораздо проще постоянно заниматься анализом голосового потока, ведь вопрос о времени работы от батареи для них не стоит, они всегда у розеток.
Но “на том конце” всё то же облако, а значит и связанные с ним проблемы.
Google также выпустил AIY Voice Kit, из которого можно собрать себе некоторое подобие Google Home в картонном корпусе и на базе Raspberry Pi.
(Отступление) Voice Attack для ПК
Поигрывая в те годы (2017-2018) в Elite: Dangerous, я столкнулся с фанатским увлечением голосовыми командами для своих космических кораблей. Реализовывалось это посредством программы Voice Attack, в которую устанавливался профиль для игры, и в ответ на определённые команды программа “нажимала” на определённые горячие клавиши в нужном порядке.
Наверное самая часто используемая команда там — запросить разрешение на стыковку со станцией. Порядок клавиш можно свести к общему знаменателю — открыть левую панель, открутить на вкладку “Контакты” и ткнуть на первое же действие для первого же контакта — обычно там располагается станция, а первое действие для неё это запрос стыковки. Можно, наверное, поспорить, что такое распространённое действие заслуживает отдельной горячей клавиши. Но игра и так умудряется полностью занять несколько десятков кнопок, рычажков и выключателей на авиационных джойстиках (HOTAS), и ещё остаётся неназначенное!
Решение звучит примитивно, но на игру ложится просто великолепно. В научно-фантастических произведениях регулярно у космических кораблей демонстрируется встроенный ИИ, слушающий (хотя и не всегда выполняющий) команды пилота. А вот вдруг и решение, позволяющее почувствовать себя в шкуре такого пилота. Плюс, я упоминал, что в игре очень много элементов управления? С голосовыми командами не нужно запоминать все, достаточно помнить, что они делают.
Нашлись даже энтузиасты, которые развили эту идею дальше и даже наняли актёров, чтобы записать пакеты ответов. Сначала просто ответы, потом персонажей, сейчас уже целые экипажи. И котик. Окей, это немного театрализованные варианты с монтажом, более реалистичное впечатление можно получить из обучающего ролика.
Если что, это не реклама, мне просто понравилось это применение. Будь побольше времени на игры, я бы может даже сам попробовал.
Для чего?
С помощью голосового управления можно делать самые разные вещи, смотря чью реализацию вы используете. Распространены уже упомянутые будильники и таймеры, напоминания с пометками, поиск в интернете, звонок контакту по имени, управление умным домом или как минимум музыкальным плеером, или что-нибудь максимально простое вроде получения случайных чисел.
Разумеется, горит вопрос, зачем это вообще, если это и так можно с успехом делать на других устройствах ручками, кнопочками и тачскрином. И если вас этот вариант всем устраивает, то скорее всего вам действительно не нужно голосовое управление. И я сейчас совершенно без насмешки говорю.
Но новые возможности это даёт.
Во-первых, чтобы отдать голосовую команду, вам не нужно держать ничего в руках. Это может быть полезно, если у вас, скажем, испачканы руки, потому что вы что-то рукоделите или кашеварите. Также это полезно потому, что объект, с которым нужно взаимодействовать для решения задачи, нужно ещё найти — будь то пульт, смартфон или ещё что. А то есть у них обыкновение перемещаться и не быть на положенном месте.
Во-вторых, это чуть более простой способ подружить пожилых знакомых с минимальными удобствами техники. Не все они хорошо видят, а кто видит, не всегда хорошо воспринимает абстракции, которыми техника оперирует — все эти окна, экраны, панели, кнопки. Им бывает проще обращаться с компьютером как с эдакой простенькой личностью.
Быстрый старт
Самый простой способ попробовать эту “технологию будущего”, конечно, это купить умную колонку. Не самый дешёвый, скорее всего, но доступный и с минимум затрат времени.
Покупаете колонку, втыкаете в розетку и следуете инструкции в коробке. Скорее всего, там предложат открыть на смартфоне какое-то приложение, которое найдёт эту колонку и сообщит ей ваш аккаунт, чтобы она имела доступ к вашим данным и могла выполнять действия от вашего имени.
Такая колонка почти наверняка будет облачной, т. е. всего лишь говорилкой и микрофоном, подключенными через интернет к какой-нибудь огромной коммерческой системе. Помимо уже упомянутых проблем с обязательностью интернета и конфиденциальностью в новостях можно было увидеть ещё несколько менее очевидных курьёзов:
- Рекламщики Burger King выиграли Гран-При в Каннах за видеорекламу, в которой попросили Google Home продолжить рекламное сообщение. То есть, начинается короткое непропускаемое сообщение на, например, YouTube, а остаток рекламы запускается на умной колонке, поскольку она слушает всех.
- Alexa от Amazon в качестве челленджа посоветовала 10-летней девочке замкнуть монеткой контакты вилки питания, воткнутой в розетку не до конца. Вроде не должно быть необходимости, но на всякий случай скажу — это небезопасно, в зависимости от обстоятельств можно получить солидный удар током.
- У рынка длинные руки, поэтому Amazon отказывает в публикации навыкам для Alexa, которые даже просто подозревает, что будут применяться цифровыми пиратами, о чём неожиданно для себя узнал автор Kanzi, навыка для управления домашним медиасервером Kodi.
- Слуховой диапазон у роботов шире человеческого, и некоторые устройства оказались в состоянии слышать команды в ультразвуковом диапазоне. “Слышишь команду? Нет? И я не слышу. А она была.” Для успокоения замечу, что эксперимент проводился практически в лабораторных условиях, и умные колонки такой уязвимости не продемонстрировали.
Я и так облака не очень люблю, а истории выше отбили оставшееся желание покупать готовую умную колонку.
И где-то на этом обсуждение готовых колонок я считаю исчерпанным. Если вас я не убедил в опасности таких решений, остаток поста вряд ли будет вам интересен. Впрочем, если вам всё равно любопытно, запретить вам читать дальше я тоже не могу. 🙂
Домашние решения
Чтобы продуктивно взаимодействовать с человеком, голосовому помощнику предстоит решать целый ряд задач:
- Hotword detection, обнаружение слова-активатора — слушалка микрофона, которая, услышав некое слово (имя помощника, например), подаст сигнал остальной системе о том, что к ней обратились. Это один из немногих компонентов, который работает практически всё время. За счёт того, что он ищет одно конкретное слово, его программа может быть гораздо проще/меньше/экономичнее, чем распознавание речи в целом. А то вам же ещё за электричество платить, да и электронике лишний износ ни к чему.
- Voice activity detection, он же VAD, определение голосовой активности — что-то, что определяет, когда с помощником говорят, а когда нет. Нужно, чтобы определить границы произнесённой команды, чтобы в нужный момент остановить запись и отправить её на дальнейшую обработку.
- Speech-to-text, STT, речь-в-текст — преобразование речи в текст. Всё. Звучит просто, но это один из самых сложных, алгоритмически и вычислительно, этапов. Трудностей множество: окружающий шум (музыка тоже шум), разные языки, разные диалекты, множество слов и сложные правила произношения в естественных языках.
- Intent recognition, TTI, текст-в-команду — поиск смысла в распознанном тексте. В сущности, перевод с языка человека на язык машины.
- Intent handling, обработка команды — исполнение команды. Для голосового помощника это пограничная часть — то, что связывает чисто голосовой слой с тем, для чего он.
- Text-to-speech, текст-в-речь — голосовой помощник может только слушать, но его полезность кратно возрастает, когда он умеет ещё и разговаривать. Обработка команды может выдать ответ, который надо произнести, или снаружи может возникнуть событие, о котором нужно объявить.
- Dialog manager, менеджер диалогов — координирует взаимодействия, которые состоят из более чем одного обмена репликами. В простейшем случае взаимодействие состоит из одной команды и одного ответа. Но в таком формате нельзя задать уточняющие вопросы или провернуть любую другую многоэтапную операцию.
Кроме последних двух, компоненты перечислены более-менее в том порядке, в котором срабатывают. Но бывают исключения. Возможно, какие-то решения как-то иначе разделяют процесс на кусочки.
Вышеперечисленное устройство это грубый пересказ документации к Rhasspy, о котором я расскажу чуть позже. Сначала немного о его предшественниках, с которыми я сталкивался.
- Jasper. Он позиционировался как приватный голосовой помощник для Raspberry Pi (хвастался поддержкой Model B, ещё даже не второй или третьей) и использовал под капотом для распознавания речи Pocketsphinx или Julius. Насколько я понимаю, где-то в 2017 проект заглох. Я, к своему стыду, даже не помню, попробовал ли его, но у меня осталось смутное впечатление, что его точность распознавания очень сильно хромала.
- Mycroft. Позиционирует себя как продукт для конечного потребителя, которого приватность сильно заботит, но не слишком сильно — когда я смотрел в последний раз несколько лет назад, распознавание речи он осуществлял в облаке. Владельцы сервиса обещают, что не сохраняют ни данные, ни результаты, но обещания устраивают не всех, а совсем оффлайн он не работал. Зато у него была какая-никакая система навыков — эдаких “плагинов”, подключаемых модулей, дающих ему возможность исполнять новые команды. А также они открыли исходники (практически?) всех компонентов решения. И вроде как он развивается до сих пор, я его упомяну чуть ниже.
- Snips. К сожалению, без ссылки, т. к. их купил Sonos, и их нынешний сайт заброшен, там даже сертификат для TLS истёк. Но с работой оффлайн у него были взаимоотношения непростые. Он технически оффлайн работал, но! Добавление и удаление команд требовало перетренировки ассистента, и эту тренировку можно было провести только на веб-портале Snips. Но у него получилось две важных вещи: (1) он работал оффлайн, и показывал неплохую точность распознавания для английского языка (субъективная оценка; да, я его запускал), и (2) он ввёл в обиход протокол Hermes — простой интерфейс между компонентами голосового помощника поверх MQTT. К сожалению, после того, как их выкупил Sonos, всё заглохло и веб-консоль была вскоре отключена. У них в организации на GitHub был слоган “We make technology disappear”. Возможно, он всё ещё там. Грустно и смешно.
Rhasspy (👈 это ссылка)
Детище Майкла Хэнсена, первое голосовое решение, с которым я встретился, которое одновременно:
- Имеет полностью открытый код
- Полностью работоспособно без интернета
- Имеет очень неплохую точность распознавания (с одной неприятной оговоркой)
- Поддерживает русский язык
Убедившись, что голосовая функциональность превосходно работает даже с русским языком, я привинтил его к своему Home Assistant. Это… года полтора назад? Он работает до сих пор, приносит пользу, и у меня в заметках целый список идей, которые на нём можно реализовать.
Не голосовой ввод
Я выше упомянул неприятную оговорку. Вот она.
Хорошую точность распознавания он показывает, если тренировать его распознавать только команды. То есть, его STT (речь-в-текст) специально натренирован распознавать именно те предложения, которые ему дали для тренировки. Для него есть и “открытая языковая модель”, которая теоретически может распознавать всё, но она медленнее и гораздо чаще ошибается.
Я первое время думал, что это беда. Но на практике оказалось, что и без этого живётся неплохо. Потому что тренируется Rhasspy быстро. Секунды. На моём Intel Core i7-8559U с SSD тренировка занимает от 1 до 5 секунд. Столько времени ему требуется, чтобы обновлять свой словарный запас. И список можно обновлять автоматически — поэтому когда ему нужно знать список каких-то сущностей, и этот список иногда меняется, достаточно привязать к обновлению этого списка автоматику, которая будет сообщать новый список в Rhasspy и просить его перетренироваться.
Но из-за того, что он тренирован понимать только команды, порой он распознаёт команды даже когда ничего близкого сказано не было. Чтобы это не доставляло неудобств, стоит добавить в него немного “стоп-слов”, услышав которые, он проигнорирует сказанное. Для этого нет никакого специального поля, нужно добавить их как “команду”, которую никак не обрабатывать во всей остальной системе. Или обрабатывать как-то символически, например отзываясь “ладно”. Несколько примеров стоп-слов: “это не тебе”, “отбой”, “заткнись”. Последнее, пожалуй, грубовато — но все рычаги у вас, вы можете научить его острее реагировать на грубые ответы, например отвешивать в ответ какую-нибудь насмешливую эпиграмму.
📜 Реальная история: пришедший ко мне приятель, столкнувшись со свежезапущенным Rhasspy, его нецензурно послал. Помощник не понял, как на это реагировать, и просто промолчал. Вероятно, не распознал в сказанном никакую из команд. И я сейчас уже точно не помню, чья это идея, но за следующие 10 минут мы научили его понимать несколько вариаций таких “посылов” и отвечать с сопоставимой остротой (или тупизной, тут есть место оценочным суждениям).
Обработка команд
Поначалу я просто привязал Rhasspy прямо к Home Assistant и написал несколько “интентов” — обработчиков команд от голосового помощника. В сущности, скриптов. С разницей между интентами и скриптами в Home Assistant я на практике так и не столкнулся, есть только догадка, что у интента может быть ответ, возвращаемая строка, которую голосовому помощнику неплохо бы произнести.
Но со временем в Home Assistant стало тесно, и я перенёс обработку команд в NodeRED.
JSON’ОМЕШАЛКА!!! МЕШАЕТ JSON!!!
— Источник неизвестен, отсылка на песню “Бетономешалка” группы “Кувалда” (почитайте комментарии, кстати, там тоже весело)
Очень мощная вещь. Я за карьеру очень много разных преобразований JSON налепил. Так вот многие из них можно реализовать на NodeRED практически без программного кода. Если хочется, там есть JavaScript (а именно, Node.js), но если это слишком сложно, есть JSONata, язык не программирования, но запросов и преобразований. JSON на входе, JSON на выходе, как арифметика для чисел, но для JSON. Другие форматы тоже понимает, когда нужно и когда есть терпение их сначала понять, а потом объяснить. Я как-то через него общался с устройством на последовательном порте. Но это история для другого раза.
Скрипты Home Assistant, которыми я реагировал на команды ранее, не стояли на месте, инструментарий для их написания, выполнения и отладки здорово преобразился за 2022 год. Но NodeRED для меня всё ещё выигрывает за счёт интерфейса и разнообразия доступных действий.
В Home Assistant вы технически не заперты в умном доме и можете выполнять команды в системной оболочке (shell). Но для NodeRED уже разработан целый ворох плагинов с действиями для самых разных целей — работы с разными устройствами, протоколами, форматами, инструментами. Есть в том числе плагин, интегрирующий Home Assistant и NodeRED между собой — позволяя реагировать на происходящее в Home Assistant через NodeRED или вещая показания виртуальных устройств из NodeRED в Home Assistant. И не просто позволяя, а позволяя с лёгкостью.
Возможности
На момент написания мой голосовой помощник может:
- Управлять светом (включение, выключение, переключение, цветовая температура, яркость)
- Смеха ради я даже сделал сокращённые команды-заклинания из выдуманных слов, которые отлично распознались
- Управлять медиаплеерами (запуск, пауза, следующий/предыдущий трек)
- Есть у меня папочка, которая набита записями разных природных фоновых шумов, вроде дождя, шума травы, деревьев, птиц — и скрипт, который берёт случайный файл оттуда и запускает на медиапроигрывателе, сидящем на одном динамике с Rhasspy
- Сообщать текущую погоду с датчиков и завтрашнюю из прогноза
- Заставить телефон пожужжать через мобильное приложение Home Assistant, чтобы облегчить поиски
- Замолкать на заданное время
- Повторять, что он расслышал, и что он сказал ранее
- Смотреть в Nextcloud Deck и объявлять случайные карточки оттуда (неплохо работает для списков дел, которые надо сделать, но не срочно)
- Была даже штука, которая каждый день предлагает какое-нибудь занятие в заданное время — так я заставлял себя делать что-то полезное, пока не привык делать это самостоятельно
- С помощью эмулятора ИК-пультов отдавать ИК-команды разной бытовой технике
- Особенно приятно было сделать составную команду для вентилятора, который имел 10 скоростей, но включался всегда на третью — чтобы включить конкретную, нужно было нажать на кнопку регулировки нужное количество раз; было очень приятно перепоручить это автоматике
- Управлять примитивной системой инвентаря — отвечать, где лежит некий предмет (“где
предмет
?”), и регистрировать перемещения (“предмет
теперьгде
”) - Отвечать, когда надо полить дерево, что растёт на окне
- Причём не только когда спросят, но и когда пора
- Я собираюсь это когда-нибудь абстрагировать от полива лимона и на другие периодические домашние дела
- Сообщать о закате
и восходе(временно выключил, очень уж рано) звуками iDroid из Metal Gear Solid V: The Phantom Pain - Работать как часы с кукушкой
- Сообщать время, если спросить
- Куковать когда настаёт :00 (число часов) и :30 (один раз, но пониже); вместо звука подобных часов я взял случайную запись лесной кукушки из интернета и максимально зачистил от шумов — получился узнаваемый, но довольно мягкий звук
- Ухать совой в полночь (чтобы не куковать 12 раз, это долго)
- Сообщать, когда возникают неполадки с интернетом, а также когда соединение восстанавливается — одно время аварии прямо зачастили, а запасной канал работал плоховато, поэтому о возможности вернуться на основной хотелось узнать как можно скорее
- Отключать активацию, когда на основном медиаплеере играет фильм
- Спрашивать, не включить ли свет, когда датчик освещённости регистрирует, что стало темновато
- …но я что-то у себя в датчике освещённости испортил и это больше никогда не срабатывает, но тут не помощник виноват
Будущее
…и у меня ещё примерно такого же размера список мыслей, которые на нём можно сделать. Вот несколько примеров:
- Управление списком покупок — гораздо проще голосом сказать, когда появилась в чём-то необходимость, чем доставать смартфон, открывать там приложение, искать нужный пункт и ставить/снимать галочку
- Отсрочка любой команды — для этого, к сожалению, потребуется переработать почти все команды, что я поналепил, поскольку лепил я их скорее в режиме “хакатона”, чем как вдумчивый архитектор
- Самодокументация — дать ему возможность самому рассказать, как им пользоваться
- Управление будильником
- Или даже дальше: команда отхода ко сну, спрашивающая во сколько разбудить, и через минуту выключающая телевизор и свет
Но я постепенно начинаю приходить к мысли, что нужно объединять усилия в разработке команд для него. Договориться об общем интерфейсе, публиковать свои обработчики команд и организовать их простую установку.
Потому что один человек хоть и может многое, коллектив при участии этого же человека (не обязательно в качестве руководителя даже) может гораздо больше.
И по-моему, это отличная заключительная мысль.
📝 PS: следующий пост будет побыстрее, чем через 3 года. Но в целом я бы не рассчитывал, что здесь будут посты сколько-нибудь регулярно, потому что я начинаю осознавать, что формат блога для меня работает очень плохо, и перешёл на другое. Собственно, в следующем посте я планирую об этом и рассказать.