Обеспечьте выполнение задач с помощью клиентской библиотеки Actions on Google Node.js (Dialogflow).

Клиентская библиотека Actions on Google Node.js — это рекомендуемый способ доступа к платформе Actions on Google и взаимодействия с ней, если вы создаете веб-перехватчик выполнения в JavaScript.

Введение

Клиентская библиотека Node.js — это библиотека выполнения действий в Google, которая предоставляет следующие функции:

  • Поддерживает все функции Actions on Google, включая текстовые и мультимедийные ответы, вход в учетную запись, хранение данных, транзакции и многое другое.
  • Предоставляет идиоматический уровень абстракции в JavaScript, который обертывает API веб-перехватчика HTTP/JSON .
  • Обрабатывает низкоуровневые детали взаимодействия между вашим выполнением и действиями на платформе Google.
  • Можно установить с помощью знакомых инструментов управления пакетами, таких как npm или yarn .
  • Позволяет легко развернуть вебхук выполнения на бессерверных вычислительных платформах, таких как Cloud Functions for Firebase или AWS Lambda . Вы также можете разместить веб-перехватчик выполнения у поставщика облачных услуг или в самостоятельно размещаемой и самоуправляемой среде.
  • Совместим с Node.js v6.0.0 и выше.

Вы можете использовать клиентскую библиотеку в сочетании с интеграцией Dialogflow для Actions on Google или с Actions SDK .

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

Посмотреть справочник API

Ссылка на API размещена на странице GitHub «Действия в клиентской библиотеке Google Node.js» .

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

yarn docs

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

Поймите, как это работает

Прежде чем использовать клиентскую библиотеку, полезно понять, как ваш веб-перехватчик выполнения использует клиентскую библиотеку для обработки запросов пользователей, которые Actions on Google отправляет вам на выполнение.

Создав вебхук выполнения в JavaScript, вы можете развернуть и разместить свой код в бессерверной вычислительной среде, такой как облачные функции Google для Firebase или AWS Lambda. Вы также можете разместить код самостоятельно без дополнительных усилий, используя веб-фреймворк Express .

В среде выполнения веб-перехватчик выполнения может вызывать функции в клиентской библиотеке для обработки пользовательских запросов и отправки ответов обратно в Actions on Google для преобразования в выходные данные пользователя.

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

Рисунок 1. Высокоуровневая архитектура клиентской библиотеки Node.js.
  1. Получение запросов пользователей . Когда пользователь делает запрос к Google Assistant, платформа Actions on Google отправляет HTTP-запрос на ваш веб-перехватчик выполнения; запрос включает в себя полезную нагрузку JSON, содержащую намерение и другие данные, такие как необработанный текст введенных пользователем данных и поверхностные возможности устройства пользователя. Дополнительные примеры содержимого полезных данных JSON см. в руководствах по формату веб-перехватчика Dialogflow и формату веб-перехватчика диалога .
  2. Обнаружение формата вызова платформы . Для поддерживаемых платформ клиентская библиотека автоматически определяет формат вызова платформы (например, если запрос поступил от веб-платформы Express или от AWS Lambda) и знает, как беспрепятственно обрабатывать связь с платформой Actions on Google. .
  3. Обработка обработчика службы: клиентская библиотека представляет API веб-перехватчика HTTP/JSON диалога для Dialogflow и Actions SDK как функцию службы. Ваш веб-перехватчик выполнения использует соответствующую службу для создания глобального экземпляра app . Экземпляр app действует как обработчик HTTP-запросов и понимает конкретный протокол службы.
  4. Обработка разговора. Клиентская библиотека представляет информацию для каждого разговора в виде объекта Conversation , прикрепленного к экземпляру app . Веб-перехватчик выполнения может использовать объект Conversation для получения сохраненных данных или информации о состоянии перекрестного диалога, отправки ответов пользователям или закрытия микрофона.
  5. Обработка промежуточного программного обеспечения. Клиентская библиотека позволяет создавать собственное промежуточное программное обеспечение служб диалогов, которое состоит из одной или нескольких определяемых вами функций, которые клиентская библиотека автоматически запускает перед вызовом обработчика намерений. Веб-перехватчик выполнения может использовать ваше промежуточное программное обеспечение для добавления свойств или вспомогательных классов к объекту Conversation .
  6. Обработка обработчиков намерений . Клиентская библиотека позволяет определять обработчики намерений, которые понимает ваш веб-перехватчик выполнения. Для Dialogflow клиентская библиотека направляет запрос к правильному обработчику намерения, сопоставляя его с точной строкой имени намерения, определенной в консоли Dialogflow . Для Actions SDK маршрутизация осуществляется на основе свойства intent , отправленного из Actions on Google.
  7. Отправка ответов пользователям: для создания ответов ваш вебхук выполнения вызывает функцию Conversation#ask() . Функцию ask() можно вызывать несколько раз для постепенного формирования ответа. Клиентская библиотека сериализует ответ в HTTP-запрос с полезными данными JSON и отправляет его в Actions on Google. Функция close() ведет себя аналогично ask() , но закрывает диалог.

Настройте локальную среду разработки

Прежде чем реализовывать веб-перехватчик выполнения, обязательно сначала установите клиентскую библиотеку.

Установите клиентскую библиотеку

Самый простой способ установить клиентскую библиотеку в локальную среду разработки — использовать менеджер пакетов, например npm или yarn .

Для установки выполните одну из этих команд из терминала:

  • Если вы используете npm : npm install actions-on-google
  • Если вы используете пряжу : yarn add actions-on-google

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

В зависимости от того, где вы планируете развернуть веб-перехватчик выполнения (облачные функции Google для Firebase, AWS Lambda или самостоятельный Express), вам может потребоваться создать определенную структуру папок проекта для сохранения файлов.

Например, если вы используете облачные функции для Firebase, вы можете настроить необходимые папки проекта, выполнив действия, описанные в разделах «Настройка Node.js и интерфейса командной строки Firebase» и «Инициализация Firebase для облачных функций ». Для облачных функций для Firebase вы обычно записываете вебхук выполнения в файле /functions/index.js .

Создайте экземпляр приложения

Actions on Google использует определенные форматы обмена сообщениями для обмена запросами и ответами с помощью вашего веб-перехватчика выполнения, в зависимости от того, создаете ли вы диалоговое действие с помощью Dialogflow или Actions SDK или создаете действие для умного дома .

Для представления этих различных протоколов запросов и ответов клиентская библиотека предоставляет три сервисные функции:

Протокол веб-перехватчика диалога используется обеими диалоговыми службами (Dialogflow и Actions SDK), но каждая служба упаковывает сообщения по-разному.

Вы используете службу для создания экземпляра app . Экземпляр app инкапсулирует глобальное состояние и логику выполнения вашего веб-перехватчика и обрабатывает связь между Actions on Google и вашим выполнением с использованием протокола, специфичного для службы.

Вы можете настроить свойства экземпляра app и вызвать его методы, чтобы управлять поведением веб-перехватчика выполнения. Вы также можете легко подключить экземпляр app к бессерверной вычислительной среде, такой как Cloud Functions для Firebase, которая принимает функции JavaScript в качестве обработчиков HTTP-запросов.

Чтобы создать экземпляр app в веб-перехватчике выполнения, выполните следующие действия:

  1. Вызовите функцию require() , чтобы импортировать модуль «actions-on-google» и загрузить нужную службу. Например, в следующем фрагменте показано, как можно загрузить службу dialogflow и некоторые элементы, используемые для построения ответов, и назначить их константе с именем dialogflow :

    // Import the service function and various response classes
    const {
      dialogflow,
      actionssdk,
      Image,
      Table,
      Carousel,
    } = require('actions-on-google');

    Здесь actions-on-google относятся к зависимости, указанной в файле package.json в папке вашего проекта (вы можете обратиться к этому примеру файла package.json ).

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

  2. Создайте экземпляр app , вызвав загруженную службу. Например:

    const app = dialogflow();

  3. Чтобы настроить экземпляр app при инициализации, вы можете предоставить объект options в качестве первого аргумента при вызове службы. (Подробнее см. в DialogflowOptions .) Например, в следующем фрагменте показано, как регистрировать необработанные полезные данные JSON из запроса или ответа пользователя, установив флаг { debug: true } :

const app = dialogflow({
  debug: true
});

Установка обработчиков событий

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

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

  • События намерения. Намерения — это уникальные идентификаторы, которые Actions on Google отправляет вам для выполнения всякий раз, когда пользователь запрашивает определенную функциональность. Если вы используете Dialogflow, это соответствует Dialogflow, сопоставляющему пользовательский запрос с намерением в вашем агенте Dialogflow.
  • События ошибок. При возникновении ошибки JavaScript или клиентской библиотеки вы можете использовать функцию catch экземпляра app для соответствующей обработки исключения ошибки. Вам следует реализовать одну функцию catch для обработки всех ошибок, которые важны для вашего выполнения.
  • Резервные события. Резервное событие происходит, когда пользователь отправляет запрос, который Actions on Google не может распознать. Вы можете использовать fallback функцию экземпляра app , чтобы зарегистрировать общий резервный обработчик, который будет запущен, если для входящего запроса выполнения не будет сопоставлен ни один обработчик намерения. Вам следует реализовать одну fallback функцию для обработки всех резервных событий. Если вы используете Dialogflow, Dialogflow может инициировать определенное резервное намерение, когда никакое другое намерение не соответствует. Вам следует создать соответствующий обработчик намерения для этого резервного намерения.

Всякий раз, когда пользователь отправляет запрос вашему действию, экземпляр app создает объект Conversation , который представляет этот сеанс разговора. Доступ к этому объекту осуществляется через имя переменной conv , передаваемое в функцию обработчика намерений в качестве первого аргумента функции. Обычно вы используете объект conv в своих обработчиках для отправки ответа пользователю.

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

  • Если вы используете Actions SDK, вы определяете параметры в пакете Action . Чтобы увидеть пример того, как можно извлечь параметры из намерений, см. пример кода Eliza .
  • Если вы используете Dialogflow, вы можете получить доступ к значениям параметров через переменную params . Чтобы увидеть примеры обработки намерений с параметрами в Dialogflow, см. Параметры и контексты доступа .

Установите обработчики для намерений

Чтобы установить обработчик намерения, вызовите функцию intent() экземпляра вашего app . Например, если вы используете Dialogflow, это функция DialogflowApp#intent() . В аргументах укажите имя намерения и укажите функцию-обработчик.

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

В следующем примере показаны обработчики намерений «приветствие» и «пока». Их анонимные функции-обработчики принимают аргумент conv и отправляют пользователю простой строковый ответ через функцию conv.ask() :

app.intent('Default Welcome Intent', (conv) => {
  conv.ask('How are you?');
});

app.intent('bye', (conv) => {
  conv.close('See you later!');
});

Обратите внимание, что функция close() аналогична функции ask() за исключением того, что она закрывает микрофон и разговор завершается.

Дополнительные сведения о том, как создавать обработчики намерений, см. в разделе Создание обработчика намерений .

Установите обработчики событий ошибок

Чтобы установить обработчики ошибок, вызовите функцию catch() экземпляра вашего app . (Например, если вы используете Dialogflow, это функция DialogflowApp#catch() .)

В следующем примере показан простой обработчик ошибок перехвата, который отправляет ошибку на вывод консоли и отправляет обратно простой строковый ответ для запроса пользователя через функцию conv.ask() :

app.catch((conv, error) => {
  console.error(error);
  conv.ask('I encountered a glitch. Can you say that again?');
});

Установите обработчики для резервных событий

Чтобы установить общий резервный обработчик, когда ни одно намерение не соответствует входящему запросу на выполнение, вызовите функцию fallback() экземпляра вашего app . (Например, если вы используете Dialogflow, это функция DialogflowApp#fallback() .)

В следующем примере показан простой резервный обработчик, который отправляет простой строковый ответ для запроса пользователя через функцию conv.ask() :

app.fallback((conv) => {
  conv.ask(`I couldn't understand. Can you say that again?`);
});

Создайте свой обработчик намерений

В этом разделе рассматриваются некоторые распространенные случаи использования при реализации обработчиков намерений с помощью клиентской библиотеки. Чтобы увидеть, как клиентская библиотека соответствует намерению, обратитесь к разделу «Обработка обработчика намерения» в разделе «Понимание того, как это работает ».

Параметры доступа и контексты

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

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

Всякий раз, когда пользователь отправляет запрос к вашему действию, экземпляр DialogflowApp создает объект parameters , который представляет значения параметров, извлеченные Dialogflow из этого запроса. Доступ к этому объекту осуществляется через имя переменной params .

В следующем фрагменте показано, как можно получить доступ к свойству name из объекта params , когда пользователь отправляет запрос:

app.intent('Default Welcome Intent', (conv, params) => {
  conv.ask(`How are you, ${params.name}?`);
});

Вот альтернативный фрагмент, который делает то же самое. Фигурные скобки ( {} ) выполняют деструктуризацию JavaScript, чтобы взять свойство name из объекта parameters и использовать его в качестве локальной переменной:

app.intent('Default Welcome Intent', (conv, {name}) => {
  conv.ask(`How are you, ${name}?`);
});

В следующем фрагменте имя параметра является full-name , но оно деструктурировано и присвоено локальной переменной с name :

app.intent('Default Welcome Intent', (conv, {'full-name': name}) => {
  conv.ask(`How are you, ${name}?`);
});

Контексты — это расширенная функция Dialogflow. Вы можете использовать контексты для управления состоянием, потоком и ветвлением разговора. Клиентская библиотека предоставляет доступ к контексту через объект DialogflowConversation#contexts . В следующем фрагменте показано, как можно программно установить контекст в веб-перехватчике выполнения и как получить объект контекста:

app.intent('intent1', (conv) => {
  const lifespan = 5;
  const contextParameters = {
    color: 'red',
  };
  conv.contexts.set('context1', lifespan, contextParameters);
  // ...
  conv.ask('...');
});

app.intent('intent2', (conv) => {
  const context1 = conv.contexts.get('context1');
  const contextParameters = context1.parameters;
  // ...
  conv.ask('...');
});

app.intent('intent3', (conv) => {
  conv.contexts.delete('context1');
  // ...
  conv.ask('...');
});

Доступ к результатам намерений помощника

Для удобства клиентская библиотека предоставляет вспомогательные классы намерений , которые обертывают распространенные типы пользовательских данных, которые часто запрашиваются действиями. К ним относятся классы, представляющие результаты различных намерений помощника Actions on Google. Вы используете вспомогательные намерения, если хотите, чтобы Google Assistant обрабатывал те части разговора, где пользователь должен внести данные для продолжения разговора.

Пример: результаты помощника по подтверждению

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

// Create Dialogflow intent with `actions_intent_CONFIRMATION` event
app.intent('get_confirmation', (conv, input, confirmation) => {
  if (confirmation) {
    conv.close(`Great! I'm glad you want to do it!`);
  } else {
    conv.close(`That's okay. Let's not do it now.`);
  }
});

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

app.intent('carousel', (conv) => {
  conv.ask('Which of these looks good?');
  conv.ask(new Carousel({
    items: {
      car: {
        title: 'Car',
        description: 'A four wheel vehicle',
        synonyms: ['automobile', 'vehicle'],
      },
      plane: {
        title: 'Plane',
        description: 'A flying machine',
        synonyms: ['aeroplane', 'jet'],
      }
    }
  }));
});

// Create Dialogflow intent with `actions_intent_OPTION` event
app.intent('get_carousel_option', (conv, input, option) => {
  if (option === 'one') {
    conv.close(`Number one is a great choice!`);
  } else {
    conv.close(`Number ${option} is a great choice!`);
  }
});

Настройка объектов ответа на диалог

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

Пример: изображение

В следующем фрагменте показано, как ваш веб-перехватчик выполнения может отправить Image в ответе, который будет автоматически прикреплен к ответу BasicCard библиотекой:

app.intent('Default Welcome Intent', (conv) => {
  conv.ask('Hi, how is it going?');
  conv.ask(`Here's a picture of a cat`);
  conv.ask(new Image({
    url: '/web/fundamentals/accessibility/semantics-builtin/imgs/160204193356-01-cat-500.jpg',
    alt: 'A cat',
  }));
});

Выполнять асинхронные вызовы функций

Клиентская библиотека Actions on Google Node.js предназначена для асинхронного программирования. Ваш обработчик намерений может возвращать обещание , которое выполняется, когда веб-перехватчик выполнения завершает генерирование ответа.

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

В этом примере мы используем поддельный API для получения данных о погоде.

/**
 * Make an external API call to get weather data.
 * @return {Promise<string>}
 */
const forecast = () => {
  // ...
};

app.intent('Default Welcome Intent', (conv) => {
  return forecast().then((weather) => {
    conv.ask('How are you?');
    conv.ask(`Today's weather is ${weather}.`);
  });
});

Следующий оптимизированный фрагмент кода имеет тот же эффект, но использует функцию async await , представленную в ECMA 2017 (Node.js версии 8). Чтобы использовать этот код с облачными функциями для Firebase, убедитесь, что вы используете правильную версию firebase-tools и имеете правильную конфигурацию.

app.intent('Default Welcome Intent', async (conv) => {
  const weather = await forecast();
  conv.ask('How are you?');
  conv.ask(`Today's weather is ${weather}.`);
});

Храните разговорные данные

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

  • DialogflowConversation#data или ActionsSdkConversation#data : сохраняет данные в формате JSON на время одного сеанса разговора между пользователем и вашим действием.
  • Conversation#user.storage : сохраняет данные в формате JSON для нескольких сеансов разговора.

В следующем фрагменте показано, как ваш веб-перехватчик выполнения может хранить данные в определенном вами произвольном свойстве ( someProperty ) и прикреплять их к объекту Conversation#user.storage . Более полный пример см. в справочной документации по классу Conversation#user.storage .

app.intent('Default Welcome Intent', (conv) => {
  conv.user.storage.someProperty = 'someValue';
  conv.ask('...');
});

Вы можете использовать объект Conversation#user для получения информации о пользователе, включая строковый идентификатор и личную информацию. Некоторые поля, такие как conv.user.name.display и conv.user.email требуют запроса conv.ask(new Permission) для NAME и conv.ask(new SignIn) для входа в Google соответственно.

const {Permission} = require('actions-on-google');
app.intent('Default Welcome Intent', (conv) => {
  if (conv.user.last.seen) {
    conv.ask('Welcome back! How are you?');
  } else {
    conv.ask('Nice to meet you! How are you doing?');
  }
});

app.intent('permission', (conv) => {
  conv.ask(new Permission({
    context: 'To greet you personally',
    permissions: 'NAME',
  }));
});

// Create Dialogflow intent with `actions_intent_PERMISSION` event
app.intent('get_permission', (conv, input, granted) => {
  if (granted) {
    conv.close(`Hi ${conv.user.name.display}!`);
  } else {
    // User did not grant permission
    conv.close(`Hello!`);
  }
});

Масштабирование с помощью промежуточного программного обеспечения

Вы можете расширить клиентскую библиотеку с помощью промежуточного программного обеспечения.

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

Службы Dialogflow и Actions SDK предоставляют функцию app.middleware() , которая позволяет добавлять свойства или вспомогательные классы к экземпляру Conversation .

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

class Helper {
  constructor(conv) {
    this.conv = conv;
  }

  func1() {
    this.conv.ask(`What's up?`);
  }
}

app.middleware((conv) => {
  conv.helper = new Helper(conv);
});

app.intent('Default Welcome Intent', (conv) => {
  conv.helper.func1();
});

Экспортируйте свое приложение

Чтобы предоставить доступ к веб-перехватчику выполнения для веб-платформы или бессерверной вычислительной платформы, необходимо экспортировать объект app как общедоступный веб-перехватчик. Клиентская библиотека сразу же поддерживает развертывание в ряде сред.

Следующие фрагменты показывают, как можно экспортировать app в разные среды выполнения:

Пример: облачные функции для Firebase

const functions = require('firebase-functions');
// ... app code here
exports.fulfillment = functions.https.onRequest(app);

Пример: встроенный редактор Dialogflow

const functions = require('firebase-functions');

// ... app code here

// Exported function name must be 'dialogflowFirebaseFulfillment'
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);

Пример: автономный сервер Express (простой)

const express = require('express');
const bodyParser = require('body-parser');  

// ... app code here

express().use(bodyParser.json(), app).listen(3000);

Пример: собственный сервер Express (несколько маршрутов).

const express = require('express');
const bodyParser = require('body-parser');

// ... app code here

const expressApp = express().use(bodyParser.json());

expressApp.post('/fulfillment', app);

expressApp.listen(3000);

Пример: шлюз API AWS Lambda.

// ... app code here

exports.fulfillment = app;