Павел 2.0: консультант-рептилоид на JS, node.js с сокетами и телефонией

    Вот и отгремел наш INTERCOM’18, c преферансом и бизнес-кейсами. Как обычно, вход на коференцию был платным: желающие могли купить билеты на TimePad по полной цене, либо… получить скидку у консультанта-рептилоида прямо на сайте. В прошлом году это работало как привычный коллбэк: вы оставляете телефон в специальной форме, Павел звонит вам через минуту и задает вопросы; чем больше правильных ответов, тем выше скидка. В этот раз мы решили поменять механику, сделав ее сложнее как технически, так и в плане вопросов. Под катом – кишки Павлика 2.0, с текущей нодой и веб-сокетами, не забудьте надеть спецодежду перед вскрытием.


    Механика конкурса


    Вы заходите на сайт intercomconf.com с декстопного браузера, в правом нижнем углу «просыпается» Павлик в виде чата и предлагает сыграть в игру. Вводите номер, нажимаете «Вот мой номер» – после этого Павел поднимает сессию между вашим браузером и нашим бэкендом.



    Если всё успешно поднялось и ваш номер еще не участвовал в розыгрыше, то Павел предложит позвонить на номер 8-800. Тут уже вступает облако Voximplant и начинается викторина:


    Ответ: дедлайн/deadline. За основу взят мем This is fine.

    Да, ребусы были примерно вот такими. На каждый вопрос давалось три попытки: сначала шла «сложная» картинка, потом проще и в конце – самая простая. Первые попытки давали больше всего очков; после 5 ребусов Павел подсчитывал баллы и либо давал бесплатный билет, либо скидку 10%-30%.

    При этом наш рептилоид достаточно умён: выдавал сообщения об ошибках (если неправильно ввести номер телефона, например), определял, что номер уже участвовал в розыгрыше («Знакомый номер я вижу на экране моего несуществующего мобильного. Одна попытка в одни руки — таковы правила.») и, самое главное, соотносил браузер и облако. Как же работал этот дерзкий IVR?

    В пасти безумия рептилоида



    Ответ: колл-центр. Nuff said.

    Говоря сухо, Павел 2.0 – это IVR, выполняемый в нашем облаке. Следовательно, вся логика рептилоида должна быть прописана в JS-сценарии, верно? Да, но нет.

    Вторая версия Павла синхронизируется с браузером клиента: на сайте Павел показывает ребусы, а по телефону слышит ваши ответы, в зависимости от которых сменяются картинки и выводится результат. С первого взгляда, такое взаимодействие можно было реализовать с помощью нашего HTTP API:

    • сначала браузер запускал бы сценарий с помощью метода StartScenarios. В ответе метод отдает параметры media_session_access_url и media_session_access_secure_url в которых лежат URL’ы для HTTP и HTTPS соответственно;
    • с запущенным сценарием можно было бы общаться с помощью полученных URL’ов;
    • сценарий бы говорил браузеру, какие картинки использовать и обновлял бы сумму баллов с помощью метода httpRequestAsync.

    Но как «поймать» пользовательский браузер? Ведь в httpRequestAsync надо передавать однозначный URL. И да, картинки – их же надо где-то хранить.

    Поэтому кроме облачного JS-сценария мы использовали свой бэкенд на express.js в паре с socket.io: когда посетитель вводил номер, браузер отдавал этот номер бэкенду по http, после чего http-сессия превращалась в сессию на веб-сокетах. В итоге сценарий постоянно общался с бэкендом по http, а уже бэкенд использовал веб-сокеты, чтобы быстро прокидывать в браузер картинки и подсчитанные баллы.

    В части веб-сокетов бэкенд выглядел так:

    Но все-таки, бОльшая часть логики хранилась в сценарии. Рассмотрим рептилоида с этой стороны…

    Идем по сценарию



    Ответ: machine learning / машинное обучение. Взято из Инстаграма самого Арни.

    Из очевидного: обязательно нужно подключить модуль распознавания ASR.

    require(Modules.ASR);

    Из интересного:

    • в сценарии был объект questions со всеми ответами и именами файлов .jpg;
      при каждом запуске сценария questions перемешивались с помощью функции-хелпера shuffle:

      показать код
    • «верхнеуровневый» хендлер для входящего звонка (CallAlerting) проверяет телефон на уникальность, а также содержит хендлеры для соединения и окончания звонка. Как раз внутри onCallConnected происходит обращение к бэкенду (читай, к socketio):

      показать код
    • чуть выше видно startGame, в ней как раз вопросы перемешиваются, нарезаются и отправляются на бэкенд вместе с индексами картинок:

      показать код
    • startASR создает экземпляр ASR и указывает предпочтительный словарь распознавания. Когда игрок проговаривает ответ, функция останавливает ASR и запускает обработку услышанного – onRecognitionResult;
    • onRecognitionResult убирает лишнее из ответа:

      let rr = e[0].replace("это ", "").replace("вероятно ", "").replace("может быть ", "").replace("может это ", "");
      rr = rr.replace(/ /g, '');

      А потом начинает подсчет попыток, баллов, а также озвучивает комментарии по ходу дела:

      показать код

      Также функция инкрементирует переменные с попытками и номером вопроса, чтобы переключиться на следующий вопрос либо завершить игру;
    • итоговая функция gameFinished отдает бэкенду сумму баллов, если человек выиграл промокод – это видно в браузере и слышно по телефону, т.к. Павлик озвучивает выигрыш; после этого делается hangup.

    Общий листинг сценария приближается к 300 строкам, самый объемный кусок – это обработка результата распознавания, onRecognitionResult.

    Говорящее ископаемое



    Ответ: Firefox. У нас всё.

    Хоть Павел и динозавр, но таки идет в ногу со временем: развивается год от года и все так же любит пошутить. Надеемся, вы оценили вторую версию нашего рептилоида и «вживую», и с точки зрения реализации. Делитесь мнениями в комментах, будьте здоровы и помните – Павел любит вас!
    • +28
    • 4,1k
    • 4
    Voximplant
    117,00
    Облачная платформа голосовой и видеотелефонии
    Поделиться публикацией

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

      0
      Мне немного дико это, не разу не использовать Kamalio/Asterisk + WebRTC, а в качестве ML, Python, или хипстеры с node-й. Захватили настолько уже всё?
        +1
        Мне немного дико это, не РАЗУМННО ли не использовать Kamalio/Asterisk + WebRTC, а в качестве ML, Python, или хипстеры с node-й. Захватили настолько уже всё? (опечатался в метро с телефона пишу)
          +4
          А вы поднимите на том что вы написали что-нибудь аналогичное за 1 день? Было бы интересно посмотреть

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое