Главная » Хабрахабр » Раз, Два, Три! Чат-бот из Google Таблицы на примере PvP-игры для Алисы

Раз, Два, Три! Чат-бот из Google Таблицы на примере PvP-игры для Алисы

Появившись, Алиса увлекла пользователей неожиданно качественными синтезом речи и чат-ботом. Сегодня от неё ждут полезных навыков и интересных игр с бекендом, способным учитывать контекст пользователя и реализовывать широкий спектр сценариев. В этой статье рассматривается создание навыка на базе Google Таблицы, хорошо знакомого многим инструмента с большим потенциалом для небольших чат-ботов.

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

Раз! Диалог

Игра начинается с правил. Я придумал такие: каждый из двух игроков сперва размещает за тремя дверями сокровище и ловушку, а затем открывает любую из дверей соперника. Открываете сокровище — получаете монеты соперника, открываете ловушку — отдаёте монеты ему. Количество монет, от 1 до 3, определяет сам игрок. За оставшейся дверью находится ящик Пандоры, открыв который можно найти/потерять случайное количество монет. Играть можно как с Алисой, так и против других пользователей.

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

  1. восстановление контекста пользователя;
  2. интерпретация запроса в восстановленном контексте;
  3. формирование ответного сообщения;
  4. сохранение изменившегося контекста пользователя.

Восстановление и сохранение контекста пользователя

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

Этого достаточно для сохранения и последующего восстановления его контекста. В каждом запросе, согласно протоколу, Алиса передаёт идентификатор пользователя.

К объективным преимуществам этого решения относятся бесплатное использование, наглядность и простота эксплуатации. В качестве хранилища данных возьмём Google Таблицы. Встроенный редактор скриптов позволяет описывать логику игры на Apps Script (базирующемся на JavaScript), обращаясь к API таблиц, и публиковать её в виде web-приложения.

Создав таблицу с нужными заголовками, можно перейти к редактору скриптов:

Логику игры можно описать в проекте на Apps Script, организовав её в виде набора gs-файлов, и перейти к публикации:

При публикации нужно указать доступность приложения анонимным пользователям:

На выходе вы получите URL опубликованного веб-приложения. Функции doGet() и doPost() в скрипте будут обрабатывать запросы соответствующих типов, чтобы получать и сохранять контексты пользователей.

Ниже схема работы с API таблиц для оперирования данными:

//получение листа var sheet = SpreadsheetApp.openById("<id таблицы>").getSheetByName("<название вкладки>"); //получение диапазона var range = sheet.getRange(<нужные ячейки>); //извлечение данных диапазона var values = range.getValues(); //сохранение данных в диапазон range.setValues(<нужные данные>);

Интерпретация запроса в восстановленном контексте

В общем случае корректная интерпретация текстовых запросов требует использования интеллектуальных NLU-алгоритмов. И хотя такие алгоритмы доступны в несложных инструментах вроде описанного мной Aimylogic, в этом случае от обработки естественного языка я решил отказаться в пользу простоты.

Для простоты я всегда предлагаю игроку три возможных действия: отправить “Раз”, “Два” или “Три”. В предложенной игре взаимодействие игрока с Алисой ограничивается десятком возможных состояний и может быть сведено к небольшому набору намерений. На любой другой запрос Алиса просит уточнить действие.

Сценарий в этом случае сводится к следующему коду на Apps Script:

//для каждого состояния в игре
switch(user.state) break; //здесь все другие состояния default: //формируем ответ на случай непредвиденного состояния
}

Для пользователя решённое таким образом взаимодействие представляется как выбор одного из трёх вариантов, смысл которых явно определён в каждом ответе Алисы. Сами варианты представлены кнопками “Раз”, “Два”, “Три”, которые существенно ускоряют игровой процесс.

Формирование ответного сообщения

Ответ Алисы состоит из нескольких частей, каждую из которых нужно сформировать, в том числе:

  • текст для отображения на экране;
  • текст для синтеза речи;
  • набор кнопок-подсказок.

Недавно я сформулировал концепцию ЛЁГКОГО диалога, описывающую принципы проектирования разговорного интерфейса в том числе для Алисы. Формат ответа Алисы позволяет реализовать эти принципы.

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

В сценарии предложенной игры список кнопок не зависит от контекста и добавляется к каждому сообщению. Кнопки-подсказки реализуют принцип инициативы: Алиса всегда обозначает и предлагает возможные действия для продолжения диалога.

Приложение написано на Apps Script, оно интерпретирует действие пользователя в соответствии с его контекстом и формирует данные для ответного сообщения. Итак, у нас есть Google Таблица с данными пользователей, которые сохраняются и получаются через URL веб-приложения.

Осталось подключиться к Алисе…

Два! Интеграция

Яндекс.Диалоги позволяют разработчикам добавлять в Алису свои навыки. Подключение навыка сводится к трём основным вещам:

  • активация;
  • оформление;
  • веб-хук.

Активация и оформление

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

В оформление навыка входят название, описание, иконка, категория и т.п.
Стоит учесть, что в списке навыков в каталоге отображаются только иконка и активационная фраза, а поиск в каталоге осуществляется преимущественно по описанию.

Получение веб-хука

Веб-хук — это адрес, по которому Алиса будет отправлять сообщения к вашему навыку и ждать JSON-ответ в описанном формате.

Веб-приложение, созданное на Apps Script, по умолчанию возвращает ответ в виде html-странички, но с помощью ContentService его можно заставить возвращать и JSON:

return ContentService.createTextOutput(JSON.stringify(<JSON ответа>)) .setMimeType(ContentService.MimeType.JSON);

Однако Google при использовании ContentService перенаправляет запрос пользователя на временный URL, к чему Яндекс.Диалоги не готовы. Поэтому адрес веб-приложения в качестве веб-хука не подходит.

В Zenbot для предложенной игры можно написать короткий скрипт, обращающийся к гугловому веб-приложению и возвращающий ответ вместе с кнопками. Существуют бесплатные сервисы, которые предлагают подходящий для Алисы веб-хук, например Zenbot. Кстати, таким образом игру можно интегрировать не только с Алисой, но и с другими каналами.

Ниже пример скрипта, который обеспечивает работу игры “Раз, Два, Три!” в Telegram-боте @RazDvaTriBot:

<context> <input pattern="$Text"> <var name="Utterance" value="$Text" scope="input"/> <get url="https://script.google.com/macros/s/<id веб-приложения>/exec" var="Result"> <param name="userId" value="$req_telegram_chat"/> <param name="utterance" value="$Utterance"/> <param name="channel" value="telegram"/> </get> <var name="Answer" value='javascript: $Result.text'/> <output value="$Answer"/> <sample> <item value="Раз"/> <item value="Два"/> <item value="Три"/> </sample> </input> </context>

Для большей гибкости в обработке запросов можно написать свой сервер, используя для этого, например, Google App Engine. Этим инструментом тоже можно пользоваться бесплатно.

После создания проекта в Google App Engine интерфейс Cloud Shell позволяет на одной веб-странице писать код сервера и деплоить его на нужный URL вида https://<id проекта>.appspot.com, который и будет адресом веб-хука.

Работа сервера состоит из следующих этапов:

  1. получение данных запроса из Алисы;
  2. взаимодействие с веб-приложением игры;
  3. отправка ответа в формате Алисы.

Получение/отправка данных Алисы

От Алисы важно получить идентификаторы сессии, пользователя, сообщения, а также текст запроса. Ниже пример на PHP:

$data = json_decode(file_get_contents("php://input")); $session_id = $data->session->session_id; $user_id = $data->session->user_id; $utterance = $data->request->original_utterance; $messageId = $data->session->message_id;

В качестве ответа в игру возвращаются кнопки-подсказки и тексты для отображения и проговаривания:

$button1 = array('title' => '1️⃣ Раз', 'hide' => true); $button2 = array('title' => '2️⃣ Два', 'hide' => true); $button3 = array('title' => '3️⃣ Три', 'hide' => true); $yaButtons = array($button1, $button2, $button3); $yaResponse = array('text' => $text, 'tts' => $tts, 'buttons' => $yaButtons, 'end_session' => false); $yaSession = array('session_id' => $session_id, 'message_id' => $messageId + 1, 'user_id' => $user_id); $yaResult = array('response' => $yaResponse, 'session' => $yaSession, 'version' => '1.0'); echo json_encode($yaResult);

Три! Синхронизация

Отправка/получение данных от веб-приложения занимает время, а Алисе не терпится дать ответ пользователю, поэтому в дело вмешиваются вопросы синхронизации.

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

Если сервер не успевает выдать ответ за это время, пользователь видит грустное сообщение в духе “Извините, <имя диалога> не отвечает”. Таймаут синхронного протокола Алисы — 1,5 секунды на ответ. Никаких подсказок, что делать дальше, система не предлагает.

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

После исполнения логики скрипт готов выдать пользователю ответ сразу, до окончания записи результатов. Зачитать данные таблицы достаточно один раз.

На получение ответа следует отвести ограниченное время — например, 1100 мс:

$request_params = array( 'userId' => $user_id, 'utterance' => $utterance, 'channel' => 'alice' ); $get_params = http_build_query($request_params); $ctx = stream_context_create(array('http'=> array( 'timeout' => 1.1 ) )); $answer = file_get_contents('https://script.google.com/macros/s/<id веб-приложения>/exec?'. $get_params, false, $ctx);

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

if($answer === FALSE) { $text = ' Помедленнее, я не успеваю.'; $tts = 'Помедленнее, я не успеваю.'; } else { $answer = json_decode($answer); $text = $answer->text; $tts = $answer->tts; //сохранение в таблице $data2store = $answer->data; $postdata = json_encode(array( 'data' => $data2store )); $opts = array('http' => array( 'method' => 'POST', 'header' => 'Content-Type: application/json', 'content' => $postdata, 'timeout' => 0.1 ) ); $context = stream_context_create($opts); file_get_contents("https://script.google.com/macros/s/<id веб-приложения>/exec", false, $context); }


В многопользовательской игре для Алисы должны быть решены задачи синхронизации как между серверами игры и Яндекса, так и между игроками. Если игрок хочет играть против другого пользователя, игра сама подбирает соперника — из тех, кто хотел играть в последнее время. Пользователи должны подтвердить готовность играть друг с другом, чтобы игра началась.

Поэтому в скрипте игры предусмотрена проверка готовности соперника и отведённой под раунд игры минуты. На текущий момент навык не может инициировать отправку сообщения пользователю Алисы. Если минута игры заканчивается, игра завершается. Если соперник задерживает игру, пользователю предлагается подождать его: “Подождём соперника ещё чуть-чуть?” Соглашаясь подождать, пользователь запускает очередную проверку.

Заключение

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

Предложенная игра доступна в магазине навыков Яндекс.Диалогов под названием “Раз, Два, Три! Надеюсь, данная статья поможет энтузиастам и разработчикам быстрее создавать полезные навыки для Алисы или других каналов. Многопользовательская игра”.

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


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

2019 — год, когда Intel остановился

Заглядывать в будущее – рискованный талант, но сегодня на рынке микропроцессоров сложилась ситуация, которая, пожалуй, разворачивается впервые с 1978 года. Корпорация Intel, правившая балом производства полупроводниковых технологий, первый раз за 40 лет теряет хватку, уступая звание лидера небезызвестной компании TSMC, ...

[Из песочницы] Краткое введение в Клеточную биологию

В свободное время балуюсь биоинформатикой, классическими ML задачами, и спортивной биомеханикой. Последние пару лет я занимаюсь исследованиями в области биологии растительной клетки, в частности, я занимаюсь вопросом сигналинга и регуляции клеточных процессов. Это и натолкнуло меня на мысль написать цикл ...