Часть 1
Часть 2
Часть 3
В четвертой части, как и было обещано, рассмотрим ограничения и недостатки Asterisk как голосовой платформы и особенности его взаимодействия с VoiceNavigator.
Голосовая платформа – это программно-аппаратный комплекс с функциями синтеза и распознавания речи, позволяющий создавать решения, направленные на оптимизацию работы контакт-центра, усовершенствование работы с клиентами и построение систем голосового самообслуживания.
Asterisk голосовой платформой в чистом виде не является, т.к. работа с серверами синтеза и распознавания не является его основной задачей и реализуется посредством UniMRCP. Поэтому часть недостатков и ограничений связана именно с реализацией работы в UniMRCP.
Среди больших и известных голосовых платформ, использующихся в колл-центрах для построения СГС, стоит отметить Avaya Voice Portal, Genesys Voice Platform, Siemens OpenScape CCVP, Cisco Unified CCX, Voxeo, Voxpilot.
Информации в Рунете очень не много, как и специалистов по данным продуктам с соответствующим уровнем компетенции. Используются в больших колл-центрах, стоимость соответствующая, и доступна она только для больших компаний.
Если будет интерес к какой-то из платформ, готов написать о них отдельно.
Два основных недостатка, существующие в Asterisk+UniMRCP — это отсутствие поддержки VoiceXML и неработающий barge-in для синтеза речи.
Отсутствие поддержки VoiceXML
Стандартом индустрии для создания голосовых приложений является использование языка VoiceXML, поддержка которого в UniMRCP и Asterisk отсутствует.
VoiceXML (Voice Extensible Markup Language) – язык, разработанный для создания сценариев звуковых диалогов, который может синтезировать речь, переводить голос в цифровую форму, распознавать DTMF, SGRS-грамматики.
Язык VXML во многом напоминает HTML. VoiceXML страница может содержать текст, который должен
быть озвучен синтезированным голосом, заранее записанные звуковые файлы, а также формы,
позволяющие воспринимать и распознавать речевую информацию. В зависимости от произнесенной
пользователем команды или ввода DTMF, может происходить переход на другие VoiceXML-страницы.
VXML — это то, что используется во всех голосовых платформах и значительно облегчает создание приложений.
Вот пример приложения, которое просит назвать число от нуля до десяти и повторяет названное число. Попробуйте сделать аналогичное в Asterisk и сравнить)
<?xml version="1.0" encoding="UTF-8"?> <vxml version="2.0" xmlns="http://www.w3.org/2001/vxml" xml:lang="ru-RU"> <form id="digits"> <property name="bargein" value="false"/> <field name="digitfield"> <prompt bargein="false">Пожалуйста, назовите число от нуля до десяти.</prompt> <noinput>Вы не назвали никакого числа. Пожалуйста, назовите число от нуля до десяти.</noinput> <nomatch>Извините, не удалось распознать сказанное число, повторите, пожалуйста.</nomatch> <grammar type="application/srgs+xml" version="1.0" mode="voice" root="boolean" xml:lang="ru-RU"> <rule id="boolean" scope="public"> <one-of> <item>ноль</item> <item>один</item> <item>два</item> <item>три</item> <item>четыре</item> <item>пять</item> <item>шесть</item> <item>семь</item> <item>восемь</item> <item>девять</item> <item>десять</item> <item><ruleref special="GARBAGE"/></item> </one-of> </rule> </grammar> <filled> <prompt>Вы назвали число <value expr="digitfield"/>.</prompt> <goto next="#digits"/> </filled> </field> </form> </vxml>
Для Asterisk есть проект VXI* от i6net. Это VoiceXML Browser — интерпретатор VoiceXML для Астериска на базе OpenVXI.
Мои попытки заставить его работать успехом не увенчались. Для распознавания используется UniMRCP, для синтеза какой-то собственный HTTP-TTS коннектор, который разрабатывается под каждый конкретный движок.
К тому же продукт платный.
Если у кого-то есть опыт работы с VXI* или OpenVXI, буду очень рад вашим комментариям.
Отсутствие barge-in для синтеза
В предыдуших статьях я рассказывал про barge-in и параметр f функции MRCPRecog. В качестве этого параметра можно передать звуковой файл, который будет проигрываться как приветствие. Если при этом также установлен параметр b=1, то озвучивание файла прервется при начале речи и запустится сессия распознавания.
Поддержка barge-in обязательная фича, необходимая при построении голосовых приложений. Например, в случае длинного сообщения или когда абонент звонит не первый раз и знает сообщения системы, не нужно заставлять его прослушивать сообщение до конца. Да и вообще, любим мы перебивать других, тем более робота))
Функция MRCPSynth не поддерживает barge-in. Т.е. динамически созданное сообщение, например, ответ системы на предыдущий выбор абонента, прервать нельзя.
Синтез можно прервать DTMF-ом, но в данном случае это не решение.
Как мне видится, при выбранной в UniMRCP реализации, когда синтез и распознавание запускаются разными сессиями, наличие barge-in для синтеза до конца не решит проблему. Даже, если прервать синтез голосом на последующий запуск сессии распознавания, которая идет после синтеза, понадобится время. И в это время не попадут первые доли секунды сказанной абонентом фразы, что может ухудшить качество распознавания. В VoiceXML такой проблемы нет, там barge-in работает и для предзаписанных фраз и для синтеза. Сессия распознавания запускается одновременно с сессией синтеза, точнее даже раньше нее, и голосовая платформа уже готова получать и передавать MRCP-cерверу голосовые данные (см. пример выше).
В приведенном ранее приложении, достаточно поменять bargein=«false» на bargein=«true», чтобы синтезированную речь можно было прерывать.
Способ немного обойти этот недостаток и обмануть barge-in
Основной способ обойти данный недостаток — минимизировать количество синтеза и там где используются статические фразы, стараться применять предзаписанные файлы, особенно в конце фразы.
Т.к. люди часто начинают говорить, не дослушав фразу до конца, то фразу необходимо строить так, чтобы последняя часть была предзаписана и ее можно было прервать. Даже если это будет одно слово.
Например, если мы уточняем сказанную человеком фразу (значение в кавычках — распознанная на предыдущем этапе фраза).
— Вы сказали «отдел продаж»? (синтез)
— Это правильно? (записанная фраза)
— Вы выбрали «операции со счетом» (синтез).
— Подтверждаете?(записанная фраза)
Пример приложения, сообщающего о стоимости проезда и пункта А в пункт Б.
;Используем предзаписанный файл. Спрашиваем: Произнесите город отправления. exten => app,n(level1),MRCPRecog(${GRAMMARS_PATH}/towns.xml,ct=0.1&b=1&f=${SND_PATH}/level1) exten => app,n,SET(RECOG_HYP_NUM=0) exten => app,n,SET(RECOG_UTR0=ошибка) exten => app,n,AGI(${AGI_PATH}/NLSML.agi,${QUOTE(${RECOG_RESULT})}) ;Если город не распознан, идем в приоритет error_start, иначе идем в check_start exten => app,n,GotoIf($["${RECOG_UTR0}" = "ошибка"]?error_start:check_start) ;Запускаем AGI-скрипт, где проверяем город, что-то считаем и т.д exten => app,n(check_start),AGI(${AGI_PATH}/check_start.agi) ;В первой части фразы используется синтез с результатом распознавания exten => app,n,MRCPSynth(<?xml version=\"1.0\"?><speak version=\" 1.0\" xml:lang=\"ru-ru\" xmlns=\"http://www.w3.org/2001/10/synthesis\"><voice name=\"Мария8000\"><p>Вы выбрали ${Start_Town}.</p></voice></speak>) ;Во второй части - предзаписанный файл: Назовите пункт назначения exten => app,n(level2),MRCPRecog(${GRAMMARS_PATH}/towns.xml,ct=0.1&b=1&f=${SND_PATH}/level2) exten => app,n,SET(RECOG_HYP_NUM=0) exten => app,n,SET(RECOG_UTR0=ошибка) exten => app,n,AGI(${AGI_PATH}/NLSML.agi,${QUOTE(${RECOG_RESULT})}) ;Если город не распознан, идем в приоритет error_finish, иначе идем в check_finish exten => app,n,GotoIf($["${RECOG_UTR0}" = "ошибка"]?error_start:check_finish) ;Запускаем AGI-скрипт, где проверяем город, считаем стоимость проезда exten => app,n(check_finish),AGI(${AGI_PATH}/check_finish.agi) ;Сообщаем результаты расчетов exten => app,n,MRCPSynth(<?xml version=\"1.0\"?><speak version=\" 1.0\" xml:lang=\"ru-ru\" xmlns=\"http://www.w3.org/2001/10/synthesis\"><voice name=\"Мария8000\"><p>Стоимость проезда из города ${Start_Town} в город ${Finish_Town} составляет ${Price}.</p></voice></speak>)
Ограничение длины переменной в 256 символов
В Asterisk имеется ограничение на длину переменной — 256 символов. Если переменная больше указанного размера, то лишняя часть просто отбрасывается.
Пока я столкнулся с этим ограничением в двух случаях.
1) Необходимо передать на синтез VoiceNavigator строку более 256 символов.
В голосовых меню все фразы должны быть короткими и емкими, но иногда приходится, например, озвучивать справочную информацию, которая может превышать данное ограничение. В этом случае приходится разбивать текст на части не более 256 символов и озвучивать частями.
Наверное, можно найти и перекомпилировать Asterisk с большим значением этого параметра.
Я пока смог найти в исходниках только как изменить размер для переменных, передаваемых в call-файлах, но не во всем Астериске. Если есть умельцы, опять же, буду рад услышать ваш опыт.
2) Необходимо обрабатывать N-Best более 2-х.
N-Best — это количество возвращаемых результатов распознавания. По умолчанию N-Best=1. Можно увеличить его и тогда VocieNavigator будет возвращать несколько результатов распознавания с наибольшими Confidence Level (достоверностью распознавания).
Например, можно брать два наиболее достоверных результата распознавания и если разница в Confidence Level между ними очень низкая, то просить абонента уточнить что именно он сказал:
— Простите, вы сказали коммерческий отдел или отдел исследования космоса?
Если N-Best>2 и MRCP-сервер возвращает более двух ответов, то NLSML-ответ получается больше 256 символов, конец его обрезается, в итоге парсер не может разобрать NLSML, т.к. он становится не валидным.
Этот кейс встречается совсем редко, обычно N-Best=2 достаточно, но помнить об этой проблеме стоит.
Не работает распознавание DTMF
На сегодня VoiceNavigator не умеет понимать DTMF-сигналы от UniMRCP и, соответственно, работать с DTMF-грамматиками. Разработчики обещают решить проблему в ближайшее время.
DTMF распознается непосредственно самим Астериском (это его стандартная возможность), но при этом невозможно предложить пользователю сказать фразу ИЛИ ввести добавочный номер, т.е. распознавать в одной ветке меню и DTMF и голос сейчас нельзя.
Это является серьезным ограничением и должно быть учтено при построении голосового меню.
В связке VoiceNavigator с другими платформами данная проблема отсутствует.
Вот основные проблемы и ограничения, с которыми приходилось сталкиваться при работе в связке Asterisk+UniMRCP+VoiceNavigator.
Готов ответить на ваши вопросы.
PS: У ЦРТ есть тестовый VoiceNavigator, который смотрит в интернет. Если описанные в статьях технологии заинтересовали, пишите в личку, дам контакты и инструкции, куда и что написать, чтобы вам открыли доступ для тестирования.