Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Голосовые и чат-роботы прочно вошли в нашу жизнь и уже никого не удивляют. Мы общаемся с ними каждый день, они записывают нас на приём к врачу, сообщают время доставки заказов, а также рекламируют всё на свете.
Но главный минус этих роботов — они говорят и воспринимают только заранее заданные фразы и ничего больше. Очень часто этого бывает недостаточно, поэтому мы пытаемся поскорее переключиться на человека.
Ситуацию поможет исправить искусственный интеллект. Эта сфера далеко продвинулась в последнее время и продолжает развиваться с высокой скоростью. Уже существует множество так называемых 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