Сегодня мы будем делать навык (приложение) для Алисы — своеобразную записную книжку (или стикер на холодильник): если во фразе пользователя (он же на профессиональном сленге юзер) есть слово "Запомни" — вся фраза сохраняется, и при следующем запуске навыка — будет любезно зачитана пользователю. Код приложения мы пишем на Node.js, для выполнения кода будем использовать Yandex Cloud Functions, а хранить данные — в Firebase Cloud Firestore. В результате у нас должен получиться точно такой же навык как "Запомни и Забудь", опубликованный в каталоге навыков Алисы.

Навык Запомни и Забудь


Код навыка выложен на GitHub. Он испещрён комментариями, словно египетские пирамиды иероглифами, и является неотъемлемой частью данной статьи.

Проект на GitHub

Итак, клонируем этот код в выбранный каталог, переходим в каталог проекта, и устанавливаем необходимые зависимости:

git clone https://github.com/stmike/alice-tutorial-remember.git
cd alice-tutorial-remember
npm install


О том как загрузить (deploy) код в Yandex Cloud Functions, подробно описано в предыдущей моей статье: "Алиса в стране Битрикс", и здесь всё это повторяться не будет. Это же касается и создания и публикации навыков Алисы в консоли для разработчиков Яндекс.Диалогов: кто не знает и этого — отсылаю к статье: "Алиса приобретает навык".

Сегодня же у нас следующая повестка дня:

  1. Создание проекта в Firebase.
  2. Использование сервисного аккаунта Firebase для интеграции с навыком.
  3. Активация базы данных Cloud Firestore.
  4. Конфигурация навыка.
  5. Рассуждения об интентах, и контексте.
  6. Планы будущих статей.
  7. Донаты (лучший раздел).


1. Создание проекта в Firebase


a) Переходим в консоль Firebase и нажимаем плитку Add project:

Консоль Firebase

b) Присваиваем проекту любое разумное имя:

Название проекта

c) Отключаем для проекта Google Analytics (здесь он нам не поможет):

Отключение Google Analytics

d) Ждём несколько секунд… готово:

Firebase проект создан

2. Использование сервисного аккаунта


Сервисный аккаунт позволяет связать Firebase-проект с другим веб-сервисом (в нашем случае это будет Yandex Cloud Functions) с помощью Firebase Admin SDK. Эта информация для общего понимания того что мы делаем.

a) Сейчас в левом меню нажимаем значок шестерни, и выбираем Project settings:

Настройки проекта

b) Затем в верхнем меню выбираем пункт Service accounts:

Сервисные аккаунты

c) Здесь нам нужно скопировать и сохранить значение свойства databaseURL для последующей вставки в код (впрочем, это можно будет сделать в любой момент позже). Теперь нажимаем кнопку Generate new private key:

Создание приватного ключа

d) В результате всплывёт модальное окно с предупреждением хранить этот файл в надёжном месте и нигде не публиковать (поэтому в моём проекте на GitHab вы его не найдёте), нажимаем кнопку Generate key, и на ваш компьютер загрузится json-файл с длинным названием.

Скачивание ключа сервисного аккаунта

e) Давайте сразу его переименуем (это не обязательно, но лучше сделать, чтобы в проекте не менять на него ссылку) в serviceAccountKey.json. С Firebase почти всё, осталось только активировать базу данный Cloud Firestore.

3. Активация базы данных


a) В левом меню выбираем пункт Database и нажимаем кнопку Create database:

Создание базы данных

b) На следующем шаге конфигурируем правила безопасности. Оставляем Start in production mode, и жмём кнопку Next:

Правила безопасности

c) И наконец, выбираем регион физического расположения базы данных. Здесь небольшой ахтунг: однажды выбрав — это изменить будет невозможно! Поэтому, сразу выбираем eur3 (europe-west) — чем ближе база данных к потребителям, тем лучше. В конце нажимаем кнопку Done:

Регион базы данных

4. Конфигурация навыка


a) В файле index.js поменять на актуальный (как это описано выше) URL базы данных:

URL адрес базы данных

b) В каталог secret загрузить актуальный файл ключа serviceAccountKey.js (полученный и переименованный как описано выше):

Загрузка файла-ключа

c) В файле src/settings.js поменять название навыка и опционально — значения других полей:

Настройки навыка

d) Из каталога images загрузить три изображения (конечно, для уникальности лучше сделать свои картинки, но с сохранением названий, чтобы не менять свойства в коде; формат JPEG или PNG, размер рекомендую 512x230 px) в консоль для разработчиков Яндекс.Диалоги, как показано на двух последующих скриншотах:

Картинки в каталоге проекта

Картинки в консоли разработчика

e) В файл src/images.js вставить идентификаторы изображений, полученные после их загрузки в консоль:

Идентификаторы изображений

Это всё! Осталось создать zip-архив проекта (все файлы и каталоги проекта в него включать не надо, а только корневой файл index.js и каталоги с файлами src, secret, node_modules), как изображено на скриншоте:

zip-архив проекта

Теперь публикуем наш код в Яндекс.Облаке, как это подробно описано в статье "Алиса в стране Битрикс".

5. Интенты и контекст


a) Если открыть файл src/nlu.js (кстати, NLU — аббревиатура от Natural Language Understanding) мы увидим определения констант CONTEXT, INTENT и функции getIntent:

NLU

b) Функция getIntent в качестве параметров принимает фразу юзера и контекст диалога. Если с фразой юзера всё понятно, то вот пара слов о контексте. Контекст — это о чём мы говорим. Если навык только-что сообщил справку о том как этим навыком пользоваться, контекст будет help (название мы придумываем сами), и в этом случае если юзер скажет "Повтори" — навык будет знать что именно повторять (т.е. в данном случае справку, а не что-то другое). Поэтому каждый раз обновлённый контекст мы сохраняем в базе данных. Далее функция с учётом фразы и контекста определяет намерения пользователя — т.н. интент, методом поиска ключевых слов, соответствующих тому или иному намерению. Для этого в данном навыке используется функция includes из библиотеки Lodash. Вот фрагмент кода из функции getIntent, определяющий намерение юзера выйти из навыка (закрыть навык):

Интенты

с) В файле index.js мы вызываем функцию getIntent и реагируем, в зависимости от того, какой интент (намерение юзера) функция нам вернула:

Вызов функции

Это была лишь зацепка для ума — самостоятельно сделайте навык, отследите все взаимосвязи в коде — тогда всё поймёте!

6. Планы будущих статей


Моей целью в этом году было написать небольшую серию статей, позволяющую научить создавать навыки Алисы на Node.js. И я считаю что эта задача выполнена, поскольку в трёх статьях (включая эту) были рассмотрены все основные вопросы: получение данных от сторонних сервисов — "Алиса приобретает навык"; отправка данных сторонним сервисам — "Алиса в стране Битрикс, и наконец, в этой статье — сохранение состояний приложения, интенты пользователей, и контекст беседы.

Но, естественно, рассказать по-прежнему всё ещё есть о чём. Итак, вот примерный план тем статей на 2020 год (не окончательный и не в хронологическом порядке):

a) Создание простого квиза (викторины) с использованием Firebase Functions и Cloud Firestore.

b) Связка аккаунтов: например начав квиз на смартфоне, пользователь должен иметь возможность продолжить его на Яндекс.Станции с того же самого места, где остановился на смартфоне.

c) Если в Яндекс.Облаке будет сделана внутренняя интеграция баз данных с Cloud Functions, а также для навыков Алисы будет предложен льготный или бесплатный тарифный план на использование баз данных — тогда будет статья и об этом. Кстати, на эту тему я открыл в Яндекс.Облаке специальный топик — приглашаю проголосовать "ЗА" — сначала кликните на скриншот внизу, а затем на кнопку «Голосовать» (я уже проголосовал, поэтому на скриншоте другая надпись):

Голосование

d) Сейчас в закрытом тестировании находится сервис приёма платежей через Алису Яндекс.Оплата. Если этот сервис будет жить, и станет публичным — будет статья и о нём.

Ну и конечно, жизнь внесёт свои коррективы, и добавит новые темы. В общем, кому интересно — подписывайтесь, чтобы не пропустить.

7. Донаты


Донаты

Комментарии (2)


  1. nckma
    25.12.2019 13:10

    Что будет если по телевизору покажут клип с песней Ротару?:

    Легче мне не станет и тебе не станет
    Но не в этом суть
    Навсегда запомни этот белый танец
    А хочешь — забудь
    Просто я всегда тебя ждала
    Одного тебя всегда ждала
    А сейчас я пришла, я пришла…


    1. mzaharov Автор
      25.12.2019 13:18

      А потестируйте сами… Я не знаю. :-)