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

Но главный минус этих роботов — они говорят и воспринимают только заранее заданные фразы и ничего больше. Очень часто этого бывает недостаточно, поэтому мы пытаемся поскорее переключиться на человека.

Ситуацию поможет исправить искусственный интеллект. Эта сфера далеко продвинулась в последнее время и продолжает развиваться с высокой скоростью. Уже существует множество так называемых AI-компаньонов, с которыми можно общаться, как с живыми людьми, практически не замечая разницы. Такие роботы обучаются в процессе общения, понимают различные фразы и стараются отвечать по-разному даже на один и тот же вопрос.

А что если объединить такого AI-компаньона и голосового робота? На выходе можно получить голосового помощника, с которым можно вести естественный диалог, как с реальным человеком. А если обучить этого помощника всему, что он должен знать, добавить сверху реалистичный синтез речи, неотличимый от настоящего голоса, на выходе получаем аватара от компании Voximplant.

Как работает аватар

Avatar — это сервис, использующий NLP (native language processing) и искусственный интеллект для голосового или текстового общения с живым человеком. Аватара можно обучить любой информации, например, времени работы вашей кофейни и подробностям доставки, чтобы он мог отвечать на вопросы клиентов. А можно интегрировать с вашим CRM, и тогда аватар сможет помогать клиентам, например, бронировать столики в вашем заведении.

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

Создаём своего аватара

Давайте попробуем создать своего аватара, который выполняет все вышеупомянутые действия. Для этого нужно иметь учётную запись в Voximplant. Зайдите в панель управления, раздел Avatars, и нажмите Создать. Придумайте название своему аватару, выберите язык, часовой пояс и создавайте!

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

Обучаем аватара

Для этого откройте вашего аватара, перейдите в раздел Намерения и нажмите Создать.

Намерения — это то, что аватар должен извлечь из речи собеседника. Например, клиент может спросить о времени работы. Но поскольку вопрос можно задать по-разному, аватару нужно обучение.

Открываем текущее намерение, раздел Тренировочные фразы и пишем несколько примерных фраз клиента:

  • Какое у вас время работы?

  • До скольки вы работаете?

  • Когда к вам можно прийти?

Далее переходим в раздел Ответы и пишем варианты ответов на это намерение.

Как только намерение будет сохранено, вверху экрана появится жёлтая кнопка Требуется обучение.

Жмём Обучиться и ждём некоторое время. Искусственный интеллект проанализирует все возможные способы того, как клиент может задать этот вопрос, и в реальной ситуации будет знать, как можно на него ответить.

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

Далее пишем простой сценарий общения с клиентом на вкладке Сценарий диалога. Сценарий пишется на JavaScript. Нам нужно, чтобы аватар поздоровался с клиентом, искал в его речи намерение узнать время работы заведения или информацию о доставке и мог дать ответ. Я использую такой сценарий:

addState({
    name: 'start',
    onEnter:async(event)=> {
        // когда клиент подключается, здороваемся с ним
        return Response({utterance: 'Pineapple garden, how can I help you?', listen: true})
    },
    onUtterance:async(event)=>{
        // ищем в речи клиента намерения
        if (event.intent === 'openHours' || event.intent === 'delivery' || event.intent === 'reservation') {
            // возвращаем клиенту ответ на его намерение и продолжаем слушать
            return Response({utterance: event.response, listen: true});
        } else {
            // если намерение не ясно, просим перефразировать
            return Response({utterance: 'Sorry, I didn\'t catch that. I can help you with open hours, deliveries, and reservations', listen: true});
        }
    }
});

// устанавливаем состояние начала диалога
setStartState('start');

Более подробно о сценариях аватара можно узнать на сайте Voximplant.

Настало время протестировать, что у нас получилось. Нажимаем в верхнем правом углу кнопку Debug, чтобы запустить сценарий. Открывается окошко чата с аватаром:

Задаём какой-нибудь вопрос, чтобы проверить, как обрабатываются намерения. Аватар должен обнаружить намерение в любой естественной речи и дать на него ответ. Пробуем:

Получилось! Аватар обнаруживает намерения клиента и отвечает на поставленные ему вопросы. Теперь надо научить аватара не просто отвечать на вопросы клиента, но и что-то сделать, например, забронировать столик.

Учим аватара бронировать столики

Для этого понадобится обучить аватара распознавать намерение "бронирование" методом, рассказанным выше, и собрать всю информацию для бронирования: дату и количество человек.

Так как часть этой информации может быть сообщена уже на моменте намерения, информацию начинаем собирать сразу. То есть, если клиент скажет: "Могу забронировать столик на двоих", то при обнаружении этого намерения уже известно количество человек.

Создаём в сценарии объект бронирования:

let reservationForm = {
    slotTime: null,
    slotPeopleCount: null,
    uncertainUtterancesCount: 0
};

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

Когда вся информация собрана, подтверждаем у клиента, на какую дату и на сколько человек делаем бронирование. Если всё правильно, записываем объект бронирования и можем отправлять его в вашу CRM или бэкенд через API-запрос.

Я добавил в сценарий несколько точек выхода, чтобы не делать его зацикленным, например, если аватар не понял клиента три раза, или если аватар спросил, может ли помочь клиенту, а тот ответил "нет" или попрощался. Финальный сценарий диалога выглядит так:

let reservationForm = {
    slotTime: null,
    slotPeopleCount: null,
    uncertainUtterancesCountweirdUtterancesInRow: 0
};

addState({
    name: 'start',
    onEnter:async(event)=> {
        // если попадаем в это состояние впервые, то  здороваемся с клиентом. если нет, спрашиваем, чем ещё можем помочь
        if (event.visitsCounter === 1) {
            return Response({utterance: 'Pineapple garden, how can I help you?', listen: true})
        } else {
            return Response({utterance: 'Can I help you with somehting else?', listen: true})
        }
    },
    onUtterance:async(event)=>{
        // ищем в речи клиента намерения
        if (event.intent === 'openHours' || event.intent === 'delivery') {
            // отвечаем на заданный клиентом вопрос и переходим в состояние 'start'
            return Response({utterance: event.response, nextState: 'start'});
        } else if (event.intent === 'reservation') {
          	// клиент может начать сразу сообщать нужные данные
            if (event.entities.systemTime) {
                reservationForm.slotTime = event.entities.systemTime[0].value;
            }
             if (event.entities.systemNumber) {
                reservationForm.slotPeopleCount = event.entities.systemNumber[0].value;
            }
            return Response({utterance: 'Sure!', nextState: 'reservation'});
        } else if (event.intent === 'no') {
          	// если клиент скажет "нет, спасибо", то прощаемся с ним и завершаем диалог
            return Response({utterance: 'Ok! Hope I\'ve helped. See you!', nextState: 'final'});
        } else if (event.intent === 'yes') {
          	// если клиент скажет, что у него есть вопрос, спрашиваем и слушаем
            return Response({utterance: 'Sure, so what\'s your question?', listen: true});
        } else {
          	// если намерение клиента не ясно, переспрашиваем три раза, но не более
            if (event.utteranceCounter < 3) {
                return Response({utterance: 'Sorry, I didn\'t catch that. I can help you with open hours, deliveries, and reservations', listen: true});
            } else {
                return Response({utterance: 'I\'m so sorry, but I couldn\'t understand you. Bye!', nextState: 'final'});
            }
        }
    }
});

addState({
    name: 'reservation',
    onEnter:async(event)=> {
        if (reservationForm.uncertainUtterancesCount > 2 ) {
          	// если клиент не может дать ответов на вопросы или Аватар его не понимает, прекращаем задавать вопросы
            reservationForm.uncertainUtterancesCountweirdUtterancesInRow = 0;
            return Response({utterance: 'Sorry I couldn\'t understand you', nextState: 'start'});
        } else if (reservationForm.slotTime && reservationForm.slotPeopleCount) {
          	// если вся информация получена, переходим к состоянию подтверждения
            return Response({nextState: 'reservationConfirm'})
        } else if (!reservationForm.slotTime && !reservationForm.slotPeopleCount) {
          	// если чего-то не хватает, спрашиваем
            return Response({utterance: 'For how many people and which date would you like a reservation?', listen: true})
        } else if (!reservationForm.slotPeopleCount) {
            return Response({utterance: 'And for how many people do you need a table?', listen: true})
        } else {
            return Response({utterance: 'And for which date?', listen: true})
        }
    },
    onUtterance:async(event)=>{
      	// проверяем, есть ли вся требуемая информация
        if (event.entities.systemTime || event.entities.systemNumber) {
            if (event.entities.systemTime) {
                reservationForm.slotTime = event.entities.systemTime[0].value;
            }
            if (event.entities.systemNumber) {
                reservationForm.uncertainUtterancesCount = 0;
                reservationForm.slotPeopleCount = event.entities.systemNumber[0].value;
            }
            reservationForm.uncertainUtterancesCount = 0;
            return Response({nextState: 'reservation'});
        } else {
            reservationForm.uncertainUtterancesCountweirdUtterancesInRow += 1;
        }
        
        if (event.intent === 'openHours' || event.intent === 'delivery') {
          	// если во время заполнения формы обнаружены другие намерения, даём ответ и продолжаем заполнять форму
            return Response({utterance: event.response, nextState: 'reservation'});
        } else {
            // продолжаем заполнять форму
            return Response({nextState: 'reservation'});
        }
    }
});

addState({
    name: 'reservationConfirm',
    onEnter:async(event)=> {
        // приводим дату в понятную человеку
        const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
        const monthStr = months[parseInt(reservationForm.slotTime.substring(5, 7), 10) - 1];
        const day = parseInt(reservationForm.slotTime.substring(8, 10), 10);
        const hour = parseInt(reservationForm.slotTime.substring(11, 13), 10);
        const minute = reservationForm.slotTime.substring(14, 16);
        return Response({utterance: `So you want to book a table for ${reservationForm.slotPeopleCount} people at ${day} ${monthStr} ${hour}:${minute}`, listen: true});
    },
    onUtterance:async(event)=>{
        if (event.intent === 'yes') {
            return Response({utterance: 'Awesome! We will be waiting for you', nextState: 'start'});
        } else if (event.intent === 'no') {
            reservationForm.slotTime = null;
            reservationForm.slotPeopleCount = null;
            reservationForm.uncertainUtterancesCount = 0;
            return Response({utterance: 'I see, sorry.', nextState: 'start'});
        } else {
            if (event.utteranceCounter < 3) {
                return Response({utterance: 'I\'m sorry, so do you want to make a reservation?', listen: true});
            } else {
                return Response({utterance: 'Sorry, I can\'t help you. Hopefully I will be able to assist you next time. Bye', nextState: 'final'});
            }
        }
    }
});

addState({
    name: 'final',
    onEnter:async(event)=> {
        return Response({isFinal: true, needRedirectionToOperator: false, reservation:reservationForm})
    }
});

// устанавливаем состояние начала диалога
setStartState('start');

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

Подключаем телефонию и чат

Остаётся только дать аватару голос и посадить за телефон отвечать на звонки. Для этого копируем код из вкладки Интеграция нашего аватара, создаём приложение на платформе Voximplant и вставляем код в сценарий приложения.

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

Аватара также можно подключить к текстовому каналу связи, например, к окошку чата на вашем сайте, где он будет так же свободно общаться с клиентами и делать всё, что от него требуется. Вы можете попробовать пообщаться с аватаром в чате в этом демо на Node.js.

Итог

Мы сделали простейшую рабочую схему аватара, который может общаться, отвечать на вопросы и бронировать столики, интегрируясь с вашей системой через API-запросы. Но это лишь самый простой вариант его использования. Аватара можно многому научить и сделать его незаменимым помощником для вашей горячей линии или контакт-центра.

Модули синтеза и распознавания речи в Voximplant позволяют выбрать очень реалистичные голоса или интегрировать голоса со сторонних платформ. Благодаря им ваши клиенты не сразу поймут, что с ними говорит не человек. А постоянно развивающийся искусственный интеллект и NLP будут делать аватара лучше каждый день!

Регистрируйтесь на платформе и пробуйте создать своего аватара! Каждый, кто протестирует аватара и оставит о нём отзыв, получит приз от Voximplant.

Остались вопросы?

Voximplant проведёт бесплатный вебинар на тему аватаров 30 марта в 11:00 (МСК). На нём вы узнаете:

  • как Voximplant Avatar помогает создавать FAQ ботов, разгружающих контакт центры;

  • способны ли голосовые роботы совершать продажи и не раздражать клиента в процессе;

  • 5 шагов по разработке голосового бота для разработчиков с базовыми знаниями JS;

  • как создать голосового бота, который помогает разбираться со статусом доставки.

Там же вы сможете задать интересующие вас вопросы и получить ответы в реальном времени! Регистрируйтесь на вебинар по ссылке: https://clck.ru/dnoNA