Я не художник...

Привет. В очередной раз задумался о локальном голосовом управлении устройствами умного дома, а тут как раз наткнулся на статью @CyberexTech "Моя безумная колонка" - https://habr.com/ru/companies/timeweb/articles/772080. Их там две части. Я тоже запускал на распбери готовые проекты типа voice2json, но все это оказалось не о том, речь распознавалась, но дальше никакого движения. А тут статья от Кибертеха (мне проще его так называть). Очень интересный проект показался, особенно после видео довольно быстрого распознавания vosk-ом голоса, но дочитав до конца я понял, что это опять не то, нам-то нужно чтобы включалось/крутилось всякое железо, навешанное на умный дом, типа лампочек и кондиционеров, а в статье это оказалось как-то очень усложненно и неявно. В общем решил сам попробовать что-нить запилить. А самая хохма в том, что я не программист и писать код не умею, но у нас теперь есть программист от бога, которого называют ChatGPT. Пришлось обращаться к нему.
Так, вступление закончил, теперь от чего отталкивался и к чему все это пришло. Задача состояла в том, чтобы для начала произнести две обычные фразы "Включи свет в зале" и "Открой шторы на кухне", после чего микрокомпьютер не просто распознал бы речь, а в зависимости от фразы произвел необходимое действие - включил свет в зале и открыл шторы в кухне, ну, это понятно. Одним из вариантов, кстати основным и практически единственным во всех готовых голосовых проектах, которые я пробовал, это был вариант отталкиваться от речи, чтобы комп эту фразу разбил на слова, разобрался что в этой фразе действие, что местоположение, что функционал, как-то понял как привязать все это к конкретному устройству и как-то дать команду на устройство, короче логику я не осилил, тут выходило что на комп надо ставить чуть ли не обученную нейросеть. Подумав , я решил не к фразам устройства прикручивать, а к к железу - фразы. Итак, что у нас представляет обычный умный дом? Это комп, на котором крутится софт, позволяющий по проводу/беспроводу дать команду на устройство, лампочку там, пылесос, телевизор и так далее. А на подавляющем большинстве умных домов команды взаимодействие крутится вокруг MQTT. Итак, на каждом умном доме есть куча устройств и все умения этого устройства в софтовом виде - это топики MQTT. Немного подумав, я решил убрать локацию (типа кухня, зал, прихожая) из отдельного свойства устройства и привязал ее непосредственно к идентификатору, то есть не "Свет" в "Ванной", как отдельные элементы, а использовал как общность "Свет в ванной". Если нужно будет прикрутить локацию с устройству, то ее можно будет вывести как отдельно дополнительное свойство. Это важное замечание кстати.
Дальше. В своей статье Кибертех описал очень классную штуку - словарь соответствия, типа вот этого:
command_dic = {
"SmartSwichON": ('включи розетку', 'вкл розетку', 'розетку включить', 'розетку вкл'),
"SmartSwichOFF": ('выключи розетку', 'выкл розетку', 'розетку отключи', 'розетку выкл'),
Вот сама идея такого словаря и решила проблему точного преобразования голоса в команду, но все же есть один нюанс. Кибертех пошел по пути отталкивания от команды. Я же решил во первых, словарь перевернуть и оттолкнуться от железа, а во вторых - использовать два словаря:

equipment_dic = {
"zigbee2mqtt/8acc.ЗАЛ Свет/set": ['свет в зале'],
"zigbee2mqtt/jdyЖелезка": ['лампа в кухне'],
"zigbee2mqtt/5e24.КУХНЯ Пылесос/set": ['пылесос']

action_dic = {
"включи": ['on', 'true', '1'],
"открой": ['on', 'true', '1'],
"выключи": ['off', 'false', '0'],
"закрой": ['off', 'false', '0'],
"громче": ['+1'],
"выше": ['+1'],
"следующий": ['+1'],
"тише": ['-1'],
"ниже": ['-1'],
"прежний": ['-1'],
"предыдущий": ['-1']
Результат: фраза управления не разбивается на несколько элементов, которые надо еще обработать и, что сложнее, понять что к чему относится, а собирается из них и уже собранный пакет сравнивается в результатом распознавания голоса. Что происходит в дальнейшем? Если фразы совпадают, ну например "включи" "лампа в кухне", то берутся соответствующие элементы, это топик mqtt из equipment_dic, в который загоняется 'on' в качестве нагрузки из action_dic. Могут конечно возникнуть возражения, мол фразы не везде одинаковые, но это просто обойти, достаточно расширить словари на элементы/синонимы, например сделать строки типа "'включи','запусти','вруби'": ['on', 'true', '1'],и пропустить их при сравнении через фильтры и к этому же привязать функции нечеткого сравнения, но это мелочи, расширить код.
Короче, составив примерную логику работы, подал это в виде обычного текстового запроса с кусками словарей на блюде великому программисту. Программист справился!! В результате я смог подключиться к своему умному дому, который живет на распбери и управляется Алисой, и включить/выключить две лампочки, находящихся в разных комнатах, не используя Алису, а чисто локально. Понадобилось два скрипта на питоне, один из которых был взят у Кибертеха и немножко допилен, а второй полностью написал ChatGPT. Что они делают. Первый обрабатывает речь и преобразовывает ее в текст, а также открывает сокет, в который отправляется результат распознавания, а второй - получает из сокета этот же результат, дальше, вот тут кстати я не допонял, сравнивает его со словарями, скорей всего перебором вариантов, при совпадении отправляет в соответствующий топик MQTT нагрузку, ну и после чего включается/выключается требуемое устройство.
Так как программист от бога, но неопытный, скрипты сырые и постоянно отваливаются. Но сама идея оказалась рабочей, так что теперь вся надежда на опытных программеров, которые смогут это все допилить.
Ну и как отчет что ли, резюмирую короче. Настройка микрокомпьютера вот отсюда
https://habr.com/ru/companies/timeweb/articles/772080/ - самый конец, где тестировал работу микрофона и динамиков, все что до того - для желающих
https://habr.com/ru/companies/timeweb/articles/817929/ - а вот здесь от начала и до примерно середины, дальше идет настройка синтеза речи, в что я пока не буду вникать. Но вот идея использовать нечеткое сравнение для распознавания это очень хорошая идея, я ее попробую реализовать.
Ну и сами скрипты
https://github.com/alex1iam/crazyGPT
Скрипты запускаются по очереди, сначала сервер, потом клиент. Без запущенного сервера клиент сразу упадет. Ну, он упадет и после, но сначала отработает)))

UPD: Пришля мысля, а нафига я я заморочился с двумя скриптами и сокетами? Переделал на один скрипт, в котором все крутится. И падать перестало

https://github.com/alex1iam/crazyGPT. Скрипт 1.comm_voice.py

Комментарии (4)


  1. janvarev
    20.08.2024 20:31
    +1

    Простите, но порекомендую использовать свое готовое решение, голосовой помощник Ирину.

    Уже 3 статьи на Хабре про неё писал, и все команды есть "из коробки", добавляются плагинами. Работает в куче мест. Нечеткое сравнение есть, MQTT кто-то делал, Home Assistant - 3 плагина, немного разных.


  1. alex1iam Автор
    20.08.2024 20:31

    Привет. Она может управлять устройствами при помощи голоса в отсутствии сети?


  1. Neuronix
    20.08.2024 20:31

    А чем Алиса не подходит, кроме необходимости Интернета? Так же можно настроить на определённые фразы и подружиться с HA (у меня так и сделано, необходимые устройства управляются в том числе и голосом)

    Из плюсов - отличное распознавание голоса, TTS из коробки (ну почти) и не нужно городить где то микрофоны (которые будут качеством хуже чем в Алисе) и куда то из подключать


  1. telobezumnoe
    20.08.2024 20:31

    себе реализовывал подобное с помощью таскера, правда плагин аатовойс распознавания речи использует гугловский, просто парсишь текст и if свет, освещение, подсветку, затем иф включи, вруби - то публиковать данные в нужный топик. и на каждом телефоне можно сделать свои сценарии.