Создание чат-бота Pokémon Messenger с помощью BootBot менее чем за 15 минут

Поймай их всех, тренер.

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

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

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

Несколько недель назад я создал и открыл исходный код фреймворка под названием BootBot, который помогает мне быстрее создавать ботов, абстрагируясь от сложности работы с API-интерфейсом Facebook Graph, настройкой Webhook и обработкой контекста. По сути, это многоразовый набор методов, охватывающий все распространенные случаи практически всех взаимодействий с моим ботом.

Затем я создал BootBot CLI, чтобы помочь в процессе создания нового бота и настройки локальной среды разработки.

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

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

Что мы строим?

Это простая, но увлекательная игра «угадай покемона». Бот выдаст вам одного случайного покемона из первых 151, и вам нужно будет угадать (или попытаться запомнить), что это за номер покедекса этого покемона.

Наш бот, вероятно, не получит награды Game Of The Year, но мы сможем создать его всего за несколько минут, используя менее 50 строк кода. И, что более важно, мы рассмотрим, как использовать BootBot для:

  • Общайтесь с нашими пользователями: задавайте вопросы и анализируйте их ответы.
  • Настройте «приветственное» сообщение, когда пользователь впервые взаимодействует с ботом.
  • Добавьте «меню помощи» на случай, если пользователь заблудился.
  • Добавьте постоянное меню с ключевыми параметрами, которые будут доступны в любое время.

Если вы хотите увидеть нашего бота PokéNum (да, не лучшее имя…) в действии, посмотрите это короткое видео:

Если вы просто хотите взглянуть на код, вот он: https://github.com/Charca/pokenum

И если вы хотите узнать, как создать его с нуля, просто продолжайте читать!

Шаг 1. Настройте свою страницу и приложение на Facebook.

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

Если вы впервые создаете чат-бота для обмена сообщениями, не волнуйтесь, это займет всего несколько минут.

  1. Создайте страницу в Facebook:
    перейдите на https://www.facebook.com/pages/create и выберите подходящую категорию для своего бота (если она не связана с реальным продуктом. , вы можете выбрать Бренд или Продукт ›Страница приложения), дать ему классное имя (наше называется PokéNum) и следовать остальным инструкциям.
  2. Создайте приложение Facebook:
    Пользователи будут общаться с вашим ботом через вашу страницу Facebook, но сам бот является приложением Facebook (которое связано с вашей страницей). Поначалу это может сбивать с толку, но помните, что ваша страница и ваше приложение - это две разные вещи.
    Чтобы создать приложение, перейдите на https://developers.facebook.com/apps и нажмите кнопку + Кнопка Добавить новое приложение. Нажмите ссылку базовая настройка в появившемся модальном окне и заполните форму, указав имя вашего приложения (вы можете использовать то же имя, что и ваша страница), контактный адрес электронной почты и Приложения для Категория "Страницы".

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

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

Для другого нам нужно «активировать» платформу обмена сообщениями для нашего приложения. Для этого нажмите ссылку + Добавить продукт на боковой панели панели инструментов, выберите Messenger из списка вариантов и нажмите Начать. На следующем экране вы увидите раздел «Создание токена» с раскрывающимся списком Выберите страницу. Выберите страницу, которую вы создали ранее, и вы должны получить токен доступа к странице в поле справа. Скопируйте и сохраните этот токен.

На данный момент мы закончили с приборной панелью, но не закрывайте ее! Он нам снова понадобится через несколько минут ...

Шаг 2. Создайте своего бота с помощью BootBot CLI.

Хорошо, у вас есть идентификатор приложения в Facebook и ваш токен доступа к странице. Это единственные две части информации, которые вам понадобятся для создания бота.

Как я упоминал ранее, мы собираемся использовать BootBot JavaScript Framework для написания нашего бота и BootBot CLI для создания нашего проекта. Это сэкономит нам много времени, копируя файлы и настраивая нашу локальную среду.

Для начала запустите Терминал и запустите:

npm install bootbot-cli -g

Это установит команду bootbot глобально, после чего вы сможете запустить команду bootbot new с именем вашего проекта (в данном случае pokenum):

bootbot new pokenum

Вам будет предложено ввести идентификатор приложения и токен доступа к странице, просто вставьте их…

Вот и все! У вас есть свежий бот, готовый приступить к взлому!

Но как мне его запустить, спросите вы? Рад, что ты спросил. Просто cd в новую папку (pokenum), установите зависимости npm и запустите bootbot start:

cd pokenum
npm install
bootbot start

Команда start выполняет две функции: во-первых, она запускает вашего бота локально, а затем запускает экземпляр localtunnel, который открывает доступ к вашему боту в Интернет, поэтому вы можно протестировать без развертывания на реальном сервере!

Это также даст вам две оставшиеся части головоломки: URL-адрес веб-перехватчика и токен подтверждения. Используйте их для настройки веб-перехватчика на панели управления Facebook и не забудьте установить все флажки в поле подписки (как показано здесь). Наконец, подпишитесь на свою страницу в Facebook, выбрав свою страницу из раскрывающегося списка и нажав кнопку Подписаться (например, это).

Так и должно быть! Теперь посетите свою страницу в Facebook, отправьте сообщение своему боту, и вы увидите, что он отвечает эхом.

Большой. Мы закончили настройку, теперь самое интересное ...

Шаг 3. Добавьте свою игровую логику

Давайте посмотрим на содержимое нашего файла index.js, созданного BootBot CLI:

'use strict';
const BootBot = require('bootbot');
const config = require('config');

const bot = new BootBot({
  accessToken: config.get('access_token'),
  verifyToken: config.get('verify_token'),
  appSecret: config.get('app_secret')
});

/**
 * Demo handler to echo back whatever the user says.
 * Feel free to delete this handler and start hacking!
 */
bot.on('message', (payload, chat) => {
  const text = payload.message.text;
  chat.say(`Echo: ${text}`);
});

bot.start(config.get('bot_port'));

Вверху есть некоторая конфигурация, затем есть обработчик событий (часть bot.on (‘message’)) и, наконец, вызов запуска бот-сервера. Довольно просто.

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

А) Добавьте приветственное сообщение

Когда пользователи впервые взаимодействуют с нашим ботом, у нас есть возможность показать им кнопку «Приступить к работе» и выполнить некоторые действия, когда они нажимают (или нажимают) на нее. Мы должны использовать это действие, чтобы приветствовать пользователя сообщением, объяснять ему, что может делать чат-бот, и рассказывать, как на самом деле начать работу. Посмотрим, как это сделать с помощью BootBot…

bot.setGetStartedButton((payload, chat) => {
  const welcome1 = `Hey there, trainer! How well you think you ...`;
  const welcome2 = `Type START or PLAY to join the challenge!`;
  const options = { typing: true };
  chat.say(welcome1, options)
    .then(() => chat.say(welcome2, options));
});

Мы используем метод setGetStartedButton нашего экземпляра бота, чтобы установить обратный вызов, когда пользователь нажимает кнопку Начать. Этот обратный вызов просто отправляет два последовательных сообщения с использованием метода say экземпляра chat (если вы не понимаете, в чем разница между bot и чат, прочтите этот раздел документации BootBot).

Здесь следует отметить две вещи. Во-первых, мы объединяем последовательные сообщения в цепочку с помощью метода .then (), возвращаемого нашим вызовом say (). Это необходимо для того, чтобы мы отправляли сообщения в правильном порядке. Помните, что эти вызовы являются асинхронными, поэтому вам нужно «подождать» отправки одного сообщения перед отправкой следующего. Конечно, вы можете сделать что-то вроде:

chat.say(welcome1, options);
chat.say(welcome2, options);

Но в этом случае ничто не гарантирует порядок сообщений.

Все методы BootBot’s Send API возвращают обещания JavaScript, которые вы можете использовать для цепочки сообщений и других интересных вещей.

Во-вторых, мы можем передать объект options для отправки «индикатора набора текста» перед отправкой сообщения. Это очень полезно, особенно когда мы хотим отправлять последовательные сообщения. Отправляя индикатор набора текста всего на несколько миллисекунд, мы избегаем бомбардировки пользователя кучей текста, и это делает разговор более естественным.

Все методы API отправки могут получать объект options с атрибутом typing. Если вы установите для параметра typing значение true, он будет рассчитывать продолжительность индикатора набора текста на основе длины сообщения. Но вы также можете установить его на произвольное количество миллисекунд, если хотите (ограничение составляет 20000).

Вот как это работает под капотом: он начинается с отправки сигнала typing_on. Затем он ожидает указанного или автоматически рассчитанного количества миллисекунд и отправляет сигнал typing_off. После этого он отправляет фактическое сообщение. Лучшая часть? Вам не нужно ни о чем беспокоиться, потому что параметр ввод сделает все за вас!

Б) Добавьте «Меню справки»

Ваш бот всегда должен пытаться помочь вашим пользователям, когда они застревают. Рекомендуется отвечать на просьбу пользователя о помощи (обычно используя слово помощь) с инструкциями по использованию бота. Вот как это сделать:

const helpMenu = (payload, chat) => {
  const message = `Just type START or PLAY to get started!`;
  const options = { typing: true };
  chat.say(message, options);
};
bot.hear(['help', 'help me'], helpMenu);

Мы создаем функцию helpMenu, которая отправляет пользователю сообщение с инструкциями о том, как играть в нашу игру. Затем мы используем метод услышать, чтобы отслеживать, когда пользователь вводит help или help me, и мы отвечаем, используя эту функцию. Довольно просто, да?

В) Запрограммируйте нашу игровую логику

Как и в нашем меню справки, мы хотим отслеживать, когда пользователь говорит старт, играть или давай сыграем и запускает игру:

const newGameMenu = (payload, chat) => {
  const message = `Let's see how much you know about Pokémon...`;
  const options = { typing: true };
  chat.say(message, options)
    .then(() => chat.conversation(askPokemon));
};
bot.hear([`start`, `play`, /let(')?s play/i], newGameMenu);

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

Единственное отличие от нашего предыдущего меню состоит в том, что после отправки сообщения мы начинаем новый разговор с пользователем, вызывая метод chat.conversation () с функцией askPokemon ( которые мы еще не создали). Беседы - отличный способ отправлять сообщения пользователю (например, задавать вопросы) и анализировать их ответы в контексте текущего разговора.

Например, если вы создаете бота для заказа пиццы, вы, вероятно, зададите такие вопросы, как:

  • «Какого размера вы хотите пиццу?»
  • «Какие начинки вы хотите?»
  • «Куда мне отправить ваш заказ?»

И пользователь отвечал такими ответами:

  • Большой
  • Пепперони
  • 1234 Main St, Пауни, Индиана

Но эти ответы имеют смысл только в контексте разговора, который мы ведем, и вопроса, который мы задали, поэтому мы должны анализировать их как таковые. API-интерфейс BootBot Conversation предоставляет простую, но мощную платформу для обработки этих сценариев. Давайте посмотрим, как мы реализовали нашу игру PokéNum в виде разговора.

(Это функция askPokemon, которую мы передали в предыдущем фрагменте):

const pokemon = require('./pokemon');
const askPokemon = (convo) => {
  const pokemonID = Math.floor(Math.random() * (151) + 1);
  convo.set('currentPokemon', pokemonID);
  const question = () => (
    convo.sendGenericTemplate([{
      title: pokemon[pokemonID - 1],
      subtitle: `What's this Pokémon's number?`,
      image_url: `./images/pokemon/messenger_cards/${pokemonID}.jpg`
    }])
  );
  const answer = (payload, convo) => {
    if (!payload.message) { convo.end(); }
    const options = { typing: true };
    const score = convo.get('score') || 0;
    const currentPokemon = convo.get('currentPokemon').toString();
    if (payload.message.text === currentPokemon) {
      convo.set('score', score + 1);
      convo.say('Correct! Try another one:', options)
        .then(() => askPokemon(convo));
    } else {
      convo.say(`Nope! That Pokémon is #${pokemonID}`, options)
        .then(() => convo.say(`Your score was: ${score}.`))
        .then(() => convo.end());
    }
  };
  convo.ask(question, answer);
};

Здесь много всего происходит, поэтому давайте разберемся:

В первой строке вы увидите, что мы импортировали файл pokemon. Это просто массив с именами всех покемонов (всего 721 из них, хотя нас интересуют только первые 151), которые вы можете проверить здесь.

Затем мы объявляем нашу функцию askPokemon, которая получает экземпляр convo, который мы будем использовать, чтобы задавать вопросы пользователю.

Наша функция генерирует случайный pokemonID ​​ от 1 до 151 и сохраняет его в контексте convo с помощью метода convo.set (). Затем мы объявляем две части нашего чата: вопрос, который мы задаем пользователю, и функцию ответа, которую мы выполняем, когда пользователь отвечает на наш вопрос.

Функция question просто использует метод sendGenericTemplate для отправки изображения текущего покемона, его имени и фактического вопроса («Что такое номер этого покемона?»). Мы могли бы сделать это, отправив текстовое сообщение с помощью метода say, но так выглядит лучше :)

Функция answer сравнивает ответ пользователя (хранящийся в payload.message.text) с числом, которое мы сохранили ранее в атрибуте контекста currentPokemon. . Если они совпадают, мы увеличиваем счет (также атрибут контекста) на единицу и запрашиваем еще одного покемона, снова вызывая функцию askPokemon. Если они не совпадают, игра окончена: мы печатаем счет и вызываем метод convo.end (), чтобы завершить игру.

Наконец, мы вызываем convo.ask (), передавая наши функции вопроса и ответа

И БУМ! Наш бот PokéNum готов к работе. Перейдите на свою страницу в Facebook и отправьте сообщение, чтобы попробовать.

Г) Добавить постоянное меню

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

bot.setPersistentMenu([
  { type: 'postback', title: 'New Game', payload: 'MENU_NEW_GAME' },
  { type: 'postback', title: 'Help', payload: 'MENU_HELP' }
]);
bot.on('postback:MENU_NEW_GAME', newGameMenu);
bot.on('postback:MENU_HELP', helpMenu);

Мы используем метод setPersistentMenu, чтобы добавить две кнопки: Новая игра и Справка. Затем мы настраиваем прослушиватели для двух кнопок для вызова созданных нами ранее функций меню: newGameMenu и helpMenu.

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

Ознакомьтесь с полным исходным кодом нашего бота PokéNum на GitHub:



Заключение

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

Я думаю, что BootBot и BootBot CLI - отличные примеры инструментов, которые могут помочь разработчикам выпускать отличные продукты, тратя меньше времени на размышления о настройке и стандартном коде и больше времени на улучшение взаимодействия с пользователем.

Обязательно проверьте репозиторий BootBot на GitHub. Мы высоко ценим все отзывы и предложения.

Если у вас есть какие-либо вопросы или вы просто хотите поздороваться, напишите мне в Twitter: http://twitter.com/charca

Удачи и удачного программирования!