Архитектура приложения секретаря
Приложение секретаря организовано в виде композиции docker-контейнеров, которые устанавливаются на отдельном хосте с помощью автоматизированного bash-скрипта (рисунок 1).
Рисунок 1
Состав docker-контейнеров:
- clerk — HTTP-сервер, написанный на языке программирования Go. Принимает запросы на распознавание и отдаёт результаты в виде JSON, записывает статистику и историю вызовов в БД;
- pcm-manager — HTTP-сервер, написанный на языке программирования Go. Отвечает за передачу аудио для распознавания и сохраняет аудиофайлы на диск;
- asr-server — HTTP-сервер, написанный на языке программирования Python. Отвечает за рекомпиляцию ASR-моделей и управляет перезапуском Vosk-server;
- vosk-server — websocket-сервер, написанный на языке программирования Python. Отвечает за распознавание аудио;
- mongo — база данных MongoDB, используется для хранения информации по статистике звонков и истории вызовов;
- keycloak — сервис авторизации keycloak, используется для управления учетными записями;
- keycloak-db — база данных Postgres, используется для хранения данных сервиса keycloak;
- nginx — прокси-сервер для web-интерфейса;
- webbackend — бэкенд-сервер для web-интерфейса.
Описание работы сервиса
Пользователь снимает трубку и набирает номер, на котором работает IVR-скрипт автосекретаря. После синтезированного приветствия, в котором пользователя просят произнести имя и фамилию, аудиопоток с его микрофона отправляется на специальный порт MSR, который детектирует тишину и нарезает по ней блок данных (chank). Каждый блок отправляется отдельным HTTP POST-запросом в сторону ecss-clerk (через restfs) с заголовком "Content-type: Transfer-Encoding". Идентификатором такого запроса является путь HTTP-запроса вида "/speech-recognition/domain/eltex/2021-01-25_18-30-18-866402_asr_5501-4893.wav". По имени этого wav-файла (которые по своей сути являются чистыми pcm) ecss-clerk идентифицирует блок. Каждый блок отправляется на распознавание, по результату которого происходит поиск номера абонента по адресной книге. Если найти его не удалось, то clerk просит следующий блок и так до тех пор, пока не получится найти номер или не сработает таймаут в ivr-скрипте.
В случае успеха, json-файл отправляется на MSR через сервис restfs, далее MSR пересылает его на ядро. Промежуточные ответы также доходят до ядра и имеют HTTP-код 206. Они не содержат в прилагаемом в теле json поля с номером, но имеют поле с распознанной строкой. Также промежуточный ответ может содержать поле с текстом для уточнения, если по полученной речи нашлось несколько совпадений в телефонной книге. Имея эту строку по таймауту IVR может синтезировать ответ для пользователя, уведомив его о том, что найти распознанную строку не удалось или произнести уточняющую фразу. Если до таймаута ecss-clerk не пришлёт ответ ядру, то синтезированное уведомление не будет содержать распознанной строки.
Синтез речи происходит через сервис restfs, который в свою очередь проксирует запрос на настроенный tts-сервер (на данный момент это только yandex-tts).
После получения PCM ecss-clerk выполняет следующие действия:
Отправляет pcm на распознавание: clerk (http) → pcm-manager (ws) → vosk-server;
- По результату распознавания пытается найти номер (номера) в телефонной книге;
- Посылает ответ.
Ответ, как уже сказано выше, имеет формат json.
Пример:
{ "done": true, "negative_url": "negative/2021-01-25_18-30-18-866402_asr_5501-4893", "number": "4815", "positive_url": "positive/2021-01-25_18-30-18-866402_asr_5501-4893", "recognized": "антон черненко" }
Поле done информирует о том, что распознавание закончено и номер был найден;
negative_url и positive_url — обратные вызовы, которые отправляет IVR-скрипт (через блок RPC) после получения json. Помечают запрос на clerk как успешный или не успешный;
recognized — ответ от asr-server;
answer — текст с уточнением, который используется для синтеза речи;
number — найденный номер телефона.
Пример промежуточного ответа (что-то было распознано):
{ "done": false, "negative_url": "negative/2021-01-25_18-30-18-866402_asr_5501-4893", "recognized": "василий", "answer": "уточните фамилию иванов или петров" }
Сервис синтеза речи
Начиная с версии 2.3.0 появилась возможность использовать отдельный сервис для синтеза речи, организованный в виде отдельного docker-контейнера, который устанавливается на отдельный хост с помощью автоматизированного bash-скрипта (рисунок 2).
Рисунок 2
Запросы на синтез речи приходят с программного компонента программного комплекса ECSS-10, в ответ tts-server отправляет данные в виде pcm-файлов.