Главная » Хабрахабр » Раз, Два, Три! Чат-бот из 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 Интересное!

Google оштрафован на рекордные $5 млрд за нарушение антимонопольного законодательства в Европе

Это самый большой штраф в истории компании. Еврокомиссия закончила многолетнее расследование против Google и потребовала рекордный штраф в 5 миллиардов долларов (4,3 млрд евро). Товары из каталога Google Shop, согласно обвинению, намеренно ставились выше, чем остальные. Прошлый рекордный штраф, кстати, ...

«Яндекс» начал работу над созданием собственной системы «умный дом»

Сегодня стало известно о том, что компания «Яндекс» осенью может представить собственную систему «умный дом». Во всяком случае, она зарегистрировала в странах Евразийского экономического союза устройство «Яндекс.Модуль», о чем сообщает «Коммерсант». Этот девайс был создан американской компанией NotAnotherOne, у истоков ...