Звуковое управление в 1С 8.3
В данной статье описано создание библиотеки для звукового управления (выполнение команд голосом) для платформы 1С 8.3. Задача была поставлена так, чтобы модуль функционировал непосредственно на клиенте 1С, осуществляя управление формами и взаимодействовал с интерфейсом.
Результат тестовых испытаний на примере нескольких команд:
Примененные технологии:
NAudio (open source .NET audio library)
Первая задача, которую нужно было решить - выбор API для распознавания речи.
Вторая - разработать механизм работы с записью звука.
Третья - как получить команду, которую потом можно будет превратить в функцию 1С и вызвать ее.
Четвертая - как это импортировать в 1С и обеспечить работу модуля на клиенте.
Выбор Speech Recognition API
Казалось бы, первое решение возможно самое простое, ведь у нас есть Windows Speech Recognition, да и подавляющее количество пользователей 1С работают в клиентах под ОС от компании Майкрософт. Примеров работы довольно много, причем готовых приложений под Visual.Net - бери, пользуйся. Один минус - нет поддержки русского языка.
Альтернативы? Либо взять облачное решение или воспользоваться open source готовым решением, которое можно будет установить на клиентском компьютере. Я выбрал первый вариант, хотя у него есть и минусы - да, вам нужен доступ в Интернет для его работы. Но и у второго варианты они есть - увеличивается дистрибутив, вычислительные затраты (вычисления, связанные с распознаванием речи ложатся на клиентский компьютер), при обновлении модуля распознавания необходимо будет обновлять его, тогда как в облачных решениях эволюция библиотеки происходит без вашего участия. Еще один минус облачных решений - они как правило платные. Но если мы возьмем модуль от Google, то плата скажем скорее символическая.
Конечно, при дальнейшей разработке этого модуля никто не мешает сделать выбор чем пользоваться предоставив выбор пользователю и сделав поддержку разных API: установить локально бесплатную библиотеку для работы с речью или пользоваться облачным сервисом за небольшую плату.
Решение от Google требует регистрации в их сервисе, я не буду здесь описывать этот процесс, пройдя по ссылке вы разберетесь что надо делать (вкратце - зарегистрироваться в Google, подключить Google Cloud, добавить Google Speech-To-Text API, получить ключ, прописать путь к нему в глобальных переменных системы). Да у пользователя это может вызвать легкий ступор. Но без ключа система работать не будет. Хотя это требуется сделать всего один раз.
Итак. После того как ключ установлен, мы можем работать с API.
Запись и обработка звука
Здесь мы должны сделать примерно такой же механизм, которым пользуются многие владельцы Android-смартфонов, когда они выполняют голосовой поиск Google.
Вы нажимаете кнопку (горячую клавишу), говорите. Получаете результат. Ваша речь распознается и формируется запрос в поисковую систему. В нашем случае - выполняется команда в 1С.
Сам гугловский API не работает с записью, это API для работы с уже сформированным файлом/буфером а как вы его сформируете - ваша задача.
С решения этой задачи началась разработка библиотеки классов для 1С. То есть задача номер 4 (как это импортировать в 1С) была решена в пользу технологии COM.
В качестве инструмента был выбран Visual.Net 2019. Язык программирования - С#.
Лучшим решением для обработки звука была признана библиотека NAudio - за простоту, понятность, наличие хорошо разобранных примеров.
В NAudio есть два ключевых класса, которые управляют записью. WaveFileWriter - класс, который собственно пишет звук, и WaveInEvent, класс, который определяет качество звука и работает с событиями. У него обработчик событий DataAvailable - он вызывает определенную вами функцию, если получены записанные с микрофона данные. Именно здесь придется решить важную задачу: а что собственно писать для передачи в Google?
Во-первых, мы знаем старт записи - он вызывается по нажатию кнопки, но НЕ знаем когда запись нужно остановить.
Во-вторых, следует ли писать паузы и тихую, едва разборчивую речь?
И первая и вторая проблема была решена через анализ громкости записи. Чтобы отсечь тихую речь, а также обозначить конец команды достаточно получить уровень громкости в дате, полученной по событию DataAvailable, чтобы брать из буфера, где лежит запись, только то, что нам нужно. То есть если пользователь сказал что-то, допустим “Открой оборотно-сальдовую ведомость” и замолчал, то мы отсчитаем от последнего события DataAvailable с нужным нам уровнем громкости 1 секунду и генерируем событие RecordingStopped, чтобы остановить запись.
А если пользователь говорит без остановки? Тогда введем ограничение на длину записываемой команды. Скажем, 4 секунды. И останавливаем запись по времени.
После остановки записи нам остается отправить наши данные в Google через его класс SpeechClient (метод Recognize) и ждать ответа.
Обработка полученной строки
Итак, мы получили распознанную строку, преобразованную в текст. Например “Открой оборотно-сальдовую ведомость”, или “ журнал документов реализаций покажи”. Как нам получить команду, то есть строковую команду “ОткрытьОСВ” или “ОткрытьЖурналРеализаций”? Ведь ту или иную команду можно сказать по разному, и порядок слов будет произвольный. Например “открыть журнал реализаций”, “покажи расходные накладные”, или “открой список документов продаж” должно приводить к одной и той же команде: “ОткрытьЖурналРеализаций”.
Заставить пользователя выучить список регулярных выражений? Можно, а если подойти гибче и допустить множество вариантов одного и того же действия? Можно конечно сделать поиск по ключевым словам с кучей условий. Это не очень удобное решение, особенно если учесть что количество команд может быть велико.
Здесь было принято решение воспользоваться технологиями машинного обучения, и дать возможность пользователям самими расширять варианты произношения команд.
В рамках этой статьи описать принципы работы текстового классификатора будет сложно, поэтому ограничимся очень простым объяснением. С помощью алгоритмов машинного обучения мы должны натренировать модель, которая знает наборы различных фраз и выражений, сопоставленные с определенной командой. То есть тренировочные данные будут выглядеть так, если мы говорим о команде “ЖурналРеализаций”, где слева - варианты (признаки) (X), а справа - ответы (Y).
журнал реализаций;ЖурналРеализаций
список реализаций;ЖурналРеализаций
журнал реализации;ЖурналРеализаций
журнал реализацией;ЖурналРеализаций
журнал расходных накладных;ЖурналРеализаций
журнал расходные накладные;ЖурналРеализаций
список продаж;ЖурналРеализаций
список документы продаж;ЖурналРеализаций
список документов продаж;ЖурналРеализаций
список расходных документов;ЖурналРеализаций
список расходных накладных;ЖурналРеализаций
расходные накладные;ЖурналРеализаций
А по ОСВ, скажем, так:
оборотно-сальдовая;ОборотноСальдоваяВедомость;
оборотно-сальдовую;ОборотноСальдоваяВедомость;
оборотку;ОборотноСальдоваяВедомость;
оборотка;ОборотноСальдоваяВедомость;
оборотно-сальдовая ведомость;ОборотноСальдоваяВедомость;
осв;ОборотноСальдоваяВедомость;
сальдовку;ОборотноСальдоваяВедомость;
сальдовка;ОборотноСальдоваяВедомость
бухгалтерский отчет по счетам;ОборотноСальдоваяВедомость
И т. д.
Принцип работы этой модели достаточно прост. Итак, мы получаем распознанную фразу от Google Cloud. Следующим шагом мы выбрасываем из этой фразы все ненужные нам слова, то есть те, которых нет в нашем словаре команд (список всех слов, используемых в модели). То есть из фразы “ А покажи мне, пожалуйста, ну. Ммм...эээ, ну, расходных накладных журнал, например” останется “расходных накладных журнал”. И потом уже просим нашу модель найти наиболее подходящий ответ (команду).Так как порядок слов для нас не важен, то программа выдаст нам очевидный ответ - “ЖурналРасходныхНакладных”.
Чтобы добавить свой вариант команды или новую команду, достаточно внести в файл тренировки данных нужные строки и вызвать функцию звукового модуля для перестройки модели (с запуском 1С модель перестраивается при старте).
Сначала это было протестировано в Python, в виду быстроты разработки, потом было переделано на ML.NET на С# и включено в библиотеку управления звуком. Это было сделано для того чтобы не перегружать библиотеку, написанную на C# питоном. (Я не поклонник IronPython).
Итак, после распознания речи наша звуковая библиотека готова передать в 1С и саму распознанную строку и команду (если она найдена).
Отдельно стоит упомянуть размышления о работе с периодами и отборами. Особенно с датами. Скажем, нам нужно сформировать ОСВ по определенному счету и за определенный период. Здесь простого решения не получится. Скажем можно сделать еще одну модель, которая будет распознавать регулярные выражения дат - “с ..по”. “ за текущий год, “ за год”, “ за месяц” и т.д. И уже далее осуществлять поиск периодов работая со строкой аналитически, зная какое выражение здесь указано.
Работа в 1С
После того как библиотека классов была создана в .NET и зарегистрирована в Windows, мы можем использовать ее в 1С через технологию COM на уже клиенте.
В 1С было реализовано исполнение несколько команд для демонстрации работы с формами и простыми отборами (по периоду, номер счета в ОСВ).
Для получения результата на клиенте запускается Обработчик Ожиданий, который проверяет результат выполнения команды.
Возвращаемое значение - строка текста и команда, если она распознана. Команде соответствовала функция в 1С. Например:
Сначала для теста была написана внешняя обработка и события обрабатывались по кнопке. Вот так это работало:
Но в реально работающей модели это неудобно. Не будем же мы заставлять пользователя каждый раз переключаться в окно голосового управления чтобы нажать кнопку.
Тогда было принято решение сделать глобальную команду через расширение и ее выполнение по комбинации горячей клавиши, что позволяет работать с модулем фоновом режиме. То есть для голосовой команды вы нажимаете комбинацию клавиш (например CTRL+W) и говорите что вы хотите от модуля:
Дальнейшая разработка
Планы по дальнейшей разработке следующие:
Доработка механизма регулярных выражений для работы с отборами по датам.
В расширении 1С для этого модуля создать справочник шаблонов команд, что позволит разработчику добавлять новые исполнение команд без помощи конфигуратора.
Реализация многоуровневых команд со сложным отбором (запуск отчетов с отбором по полям, создание и заполнение документов).