{"id":2175,"url":"\/distributions\/2175\/click?bit=1&hash=803b6e1bcbd9dfc4ba9456fda887a878c80d24df8d3a575913b14876e18923a5","title":"TJ \u0437\u0430\u043a\u0440\u043e\u0435\u0442\u0441\u044f 10 \u0441\u0435\u043d\u0442\u044f\u0431\u0440\u044f \u2014\u00a0\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u0430\u043d\u043e\u043d\u0441 \u0441 \u0434\u0435\u0442\u0430\u043b\u044f\u043c\u0438","buttonText":"\u0427\u0438\u0442\u0430\u0442\u044c","imageUuid":"d1d355d8-93a3-5140-aeae-14b03046b760","isPaidAndBannersEnabled":false}
Разработка
Илья П.

Создаём действие для Google Ассистента. Часть 2

Продолжение перевода материала от raywenderlich.com. Первая часть доступна здесь.

Загрузка агента DialogFlow

Чтобы загрузить предварительно настроенный агент в примере проекта, нажмите на значок шестеренки > Export and Import > Restore From Zip.

Перетащите или прикрепите загруженный ранее файл RWPodcast.zip из начальных материалов для проекта. Нсли вы еще их не скачали, то можете скачать здесь. Затем введите RESTORE в соответствующее текстовое поле и нажмите Restore. После загрузки нажмите Done.

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

Заполнение

Заполнение (Fulfillment) для Google Ассистента - это код, развернутый как webhook. Каждое намерение в агенте имеет соответствующую бизнес-логику в webhook. Информация, извлеченная агентом, может генерировать динамические ответы или инициировать действия на серверной части.

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

Вы можете реализовать простой webhook в диалоге, используя встроенный редактор. Более сложные действия выигрывают от другого подхода.

Настройка среды локального развития

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

NPM обычно поставляется с Node.js. Вы можете найти инструкции по установке обоих здесь.

Установка библиотек CLI Firebase

Чтобы установить библиотеки CLI Firebase, откройте терминал и выполните команду:

npm -g install firebase-tools

Если установка не работает, возможно, вам придется изменить разрешения NPM. Подробности здесь.

Проверьте, была ли успешной установка CLI Firebase, выполнив команду:

firebase --version

После установки CLI, войдите в Firebase этой командой:

firebase login

Запустится веб-браузер для авторизации. Войдите в систему с учетной записью Google, которую вы используете для разработки. Разрешите необходимые разрешения.

После успешного входа браузер покажет такое сообщение:

Теперь вы готовы к следующим шагам!

Выбор проекта в Firebase

Сначала найдите идентификатор вашего проекта в диалоговом окне, выбрав значок шестеренки > General > Google Project Section > Project ID. Сохраните этот идентификатор проекта для следующего шага.

Затем вам нужно настроить правильный проект в Firebase CLI для развертывания локальных функций. В терминале откройте папку функций в каталоге стартового проекта. Вы можете сделать это, используя комманду cd path/to/directory заменив path тем, куда вы скачали проект.

Затем выполните следующую команду, заменив PROJECT_ID идентификатором проекта, который вы собрали на предыдущем шаге:

firebase use PROJECT_ID

Эта команда скажет CLI Firebase какой проект в данный момент используется в терминале.

Установка дополнительных библиотек NPM

Вам также понадобится библиотека NPM для парсинга RSS-канала для подкаста. Установите NPM-библиотеку rss-parser этой командой:

npm install --save rss-parser

Затем выполните команду:

npm install

Эта команда установит модули NPM.

Наконец, разверните функции в Firebase:

firebase deploy --only functions

После успешного развертывания скопируйте URL-адрес функции (Function URL):

Реализация Webhook

В Dialogflow, во вкладке Fullfilment, включите Webhook и вставьте ссылку, скопированную в предыдущем шаге. Затем нажмите Save.

Снова откройте Welcome Intent под Intents и обратите внимание, что в разделе Fulfillment включен Webhook.

Это информирует агента Dialogflow о запуске кода, найденного в функции Welcome Intent в index.js, вместо использования текстовых ответов по умолчанию, определенных в Dialogflow. Откройте index.js в любимом текстовом редакторе и найдите эту строчку:

app.intent('Welcome Intent', (conv) => { conv.ask("Hello World!"); });

Приведенный выше код использует команду conv.ask для произнесения слов Hello World! и ждёт ответа. Проверьте действие в симуляторе или на вашем устройстве. На этот раз он отвечает «Hello World!»

Теперь вы настроили локальную среду разработки. Каждый раз, когда вы вносите изменения в файл index.js, сохраняйте файл и запускайте команду firebase deploy --only functions для загрузки и применения изменений. Затем перезапустите симулятор. На устройстве самая последняя версия действия развертывается автоматически.

Создание и выполнение пользовательских намерений

Созданение намерения

В Dialogflow выберите Intents > Create Intent или нажмите знак плюса рядом с Intents. Введите имя play_the_latest_episode и добавьте обучающие фразы, показанные ниже:

Включите вызов Webhook и сохраните:

Наполнение намерения

Добавьте это намерение в файл index.js под приветственным намерением:

app.intent('play_the_latest_episode', (conv) => { //1 let parser = new Parser() //2 return parser.parseURL( 'https://www.raywenderlich.com/feed/podcast').then((feed) => { //3 let latestCast = feed.items[0]; //4 conv.close(new SimpleResponse({ speech: "Here is the latest episode", text: "Here is the latest episode" })); //5 conv.close(new MediaObject({ name: latestCast.name, url: latestCast['enclosure']['url'], description: latestCast.description, icon: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Logo', }), })); }).catch((err) => { // handle errors console.log(err) conv.close("An Error Occurred Parsing the RSS Feed, Try Again Later"); }); });

Что происходит в этом коде?

  1. Код создаёт RSS-ленту Parser и использует её для соединения к URL подкаста.
  2. Запрос оформляется в виде Обещания (Promise). Вы можете думать об этом как обратный звонок.
  3. Если Promise выполнено, последний элемент берется из ленты и присваивается к latestCast.
  4. new SimpleResponse содержит голос или текст, показанный пользователю.
  5. new MediaObject заполняется полями из latestCast, включая описание, URL-адрес изображения и ссылку на аудиофайл, полученный с помощью url: latestCast['enclosure']['url']. При использовании медиа-объекта (MediaObject) поместить простой ответ (Simple Response) прямо перед ним.

Если разговор остается открытым после отправки объекта MediaObject, следуйте Suggestion Chips. Поскольку в этом примере используется conv.close, Suggestion Chips не нужны. Вы увидите, как их создать позже.

Невыполненные обещания вызывают ответное сообщение об ошибке.

Сохраните index.js и в терминале и выполните firebase deploy --only functions для развертывания изменений.

Исправление ошибок в консоли Firebase

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

Войдите в консоль Firebase здесь и выберите проект, связанный с вашим действием. В разделе Development ▸ Functions ▸ Logs вы должны увидеть выходные данные console.log и сообщения об ошибках.

Сообщение об ошибке указывает на то, что для выполнения внешнего запроса необходимо сначала обновить план. Выберите Upgrade и выберите план Blaze. План оплаты Blaze по мере использования не взимается при тестировании.

Тестирование намерения

Теперь снова запустите тестовое действие. Когда действие приветствует вас, ответьте Latest episode. Последний эпизод подкаста должен сыграть. Обратите внимание на отображаемый медиаплеер.

Обнаружение устройств

Вы можете определить, с какого устройства инициируется действие. Замените оператор conv.ask('Hello World!') в приветственном намерении в index.js следующим текстом:

//1 if (!conv.surface.capabilities .has('actions.capability.SCREEN_OUTPUT')) { if(!conv.surface.capabilities .has('actions.capability.MEDIA_RESPONSE_AUDIO')) { conv.close("So sorry, this device does not support media playback!"); return; } //2 else { conv.ask("Greetings, Learner!"); //3 conv.ask(new Confirmation( "Would you like to play the latest episode?")); } }

Вот несколько замечаний по поводу кода выше:

  1. Если у текущего разговора нет actions.capability.SCREEN_OUTPUT и MEDIA_RESPONSE_AUDIO, то устройство не поддерживвет медиафайлы.
  2. Устройство поддерживает аудио, но у него нет экрана. Если это так, спросите пользователя, стоит ли воспроизводить последний эпизод. Это сделано для того, чтобы сделать действие более удобным на устройстве без экрана, которое опирается на голосовое управление.
  3. new Confirmation является Помощником (Helper), который просит ответа да или нет.

Намерение play_latest_episode_confirmation в Dialogflow имеет событие actions_intent_confirmation. Событие - это еще один способ вызвать намерение с помощью предопределенных значений, таких как да или нет.

Найдите play_latest_episode_confirmation в списке намерений в Dialogflow. Включите вызов Webhook для него и сохраните изменения.

Обработка события подтверждения

Поскольку вы создали подтверждение выше, вам нужно обработать ответ. Добавьте приведенный ниже код в index.js:

app.intent('play_latest_episode_confirmation', (conv, input, confirmation) => { // 1 if (confirmation) { let parser = new Parser() return parser.parseURL( 'https://www.raywenderlich.com/feed/podcast').then((feed) => { let latestCast = feed.items[0]; conv.close(new SimpleResponse({ speech: "Here is the latest episode", text: "Here is the latest episode" })); conv.close(new MediaObject({ name: latestCast.name, url: latestCast['enclosure']['url'], description: latestCast.description, icon: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Logo', }), })); }).catch((err) => { // handle errors console.log(err) conv.close("An Error Occurred Parsing the RSS Feed, Try Again Later"); }); //2 } else { conv.ask("You can say 'play latest episode' or 'play an episode about a subject' such as Kotlin or iOS."); } })

Что здесь происходит:

  1. Если параметр confirmation является true, то пользователь подтвердил, что хочет воспроизвести подкаст. Затем вы выбираете и воспроизводите эпизод так же, как вы делаете в намерении play_the_latest_episode.
  2. Если нет, то пользователь не хочет воспроизводить подкаст. Предложите пользователю вызвать другие намерения.

Сохраните index.js и в терминале выполните firebase deploy --only functions для развертывания изменений. Откройте тестовое приложение в симуляторе.

Выберите Speaker в качестве Surface и выполните разговор, чтобы воспроизвести последний эпизод. Вам также следует попробовать сказать «нет» при появлении запроса:

Использование списка опций

Вы также можете настроить список опций, чтобы дать пользователю некоторые варианты того, что он может делать. Добавьте блок else под внешним блоком if в приветственном намерении:

else { let parser = new Parser() return parser.parseURL( 'https://www.raywenderlich.com/feed/podcast').then((feed) => { let cast1 = feed.items[0]; let cast2 = feed.items[1]; let cast3 = feed.items[2]; conv.ask("Here are the three latest episodes!"); conv.ask(new List({ title: 'Latest Episodes', items: { [EPISODE_ONE]: { synonyms: ['Podcast 1'], title: cast1.title, description: cast1.description, image: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Podcast Logo', }), }, [EPISODE_TWO]: { synonyms: ['Podcast 2'], title: cast2.title, description: cast2.description, image: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Podcast Logo', }), }, [EPISODE_THREE]: { synonyms: ['Podcast 3'], title: cast3.title, description: cast3.description, image: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Podcast Logo', }), }, }, })); conv.ask(new Suggestions([ 'Latest episode', 'Episode about Kotlin', 'Episode about iOS'])); }).catch((err) => { console.log(err) conv.close("An Error Occurred Parsing the RSS Feed, Try Again Later"); }); }

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

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

В Dialogflow обязательно добавьте actions_intent_option в качестве Intent и включите веб-хук.

Добавьте следующий код для обработки намерения get_episode_option:

app.intent('get_episode_option', (conv, input, option) => { let parser = new Parser() return parser.parseURL( 'https://www.raywenderlich.com/feed/podcast').then((feed) => { let cast1 = feed.items[0]; let cast2 = feed.items[1]; let cast3 = feed.items[2]; if(option === EPISODE_THREE){ conv.ask('Here is the third episode from the list'); conv.close(new MediaObject({ name: cast3.title, url: cast3['enclosure']['url'], description: cast3.description, icon: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Logo', }), })); } else if(option === EPISODE_TWO){ conv.ask('Here is the 2nd episode from the list'); conv.close(new MediaObject({ name: cast2.title, url: cast2['enclosure']['url'], description: cast2.description, icon: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Logo', }), })); } else{ conv.close(new SimpleResponse({ speech: "Here is the first episode from the list", text: "Here is the first episode from the list" })); conv.close(new MediaObject({ name: cast1.title, url: cast1['enclosure']['url'], description: cast1.description, icon: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Logo', }), })); } }).catch((err) => { // handle errors console.log(err) conv.close("An Error Occurred Parsing the RSS Feed, Try Again Later"); }); });

В приведенном выше коде проверяется значение параметра option, чтобы можно было создать правильный MediaObject. Он передает MediaObject объекту conv в качестве ответа.

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

Когда пользователь выбирает подкаст из списка, он воспроизводится. Круто, правда?

Сущности и параметры

Обучающая фраза часто содержит полезные данные, такие как слова или фразы, которые определяют такие вещи, как количество или дата. Вы используете параметры (Parameters) для представления этой информации. Параметры в обучающих фразах представлены объектом (Entity). Они идентифицируют и извлекают полезные данные из входных данных на естественном языке в диалоге.

Объекты

Объекты извлекают такую информацию, как дата, время, цвет, порядковый номер и единица измерения. Тип объекта определяет тип извлеченных данных. Каждый параметр будет иметь соответствующий объект. Для каждого типа объекта может быть много записей объектов. Записи представляют собой набор эквивалентных слов и фраз. Примерными объектами сущностей для темы технического подкаста могут быть iOS, iPhone и iPad.

Системные объекты встроены в Dialogflow. Некоторые системные объекты включают дату, время, аэропорты, музыкальных исполнителей и цвета.

Для универсального типа сущности используйте Sys.Any, представляющий любой тип информации. Если системные элементы недостаточно конкретны, определите свои собственные объекты разработчика.

Ниже приведен пример объекта разработчика, определенного для представления темы технического подкаста.

Действия и параметры

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

Dialogflow автоматически определяет и помечает некоторые более распространенные типы системных объектов в качестве параметров.

В приведенном ниже примере Dialogflow определяет параметры времени и даты и присваивает им правильный тип.

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

В Dialogflow действие и параметры находятся ниже обучающих фраз намерения.

Есть несколько атрибутов для параметров:

  • Обязательный чекбокс для определения необходимости параметра.
  • Имя параметра идентифицирует параметр.
  • Объект или тип параметра.
  • Значение параметра относится к параметру в ответах.

Параметры могут появляться как часть текстового ответа:

Использование объекта и параметра

Пора попробовать использовать сущности и параметры, о которых вы узнали! В диалоге включите webhook для намерения play_an_episode_about. Затем добавьте обработчик намерений в index.js с помощью следующего кода:

app.intent('play_an_episode_about', (conv, {Subject}) => { let parser = new Parser() return parser.parseURL( 'https://www.raywenderlich.com/feed/podcast').then((feed) => { let latestCast = feed.items[0]; console.log('subject ' + Subject); for(let i = 0; i < feed.items.length; i++){ let entry = feed.items[i]; if(entry.title.toUpperCase().indexOf(Subject.toUpperCase()) > -1){ latestCast = entry; break; } } conv.ask(latestCast.title); conv.close(new MediaObject({ name: latestCast.name, url: latestCast['enclosure']['url'], description: latestCast.description, icon: new Image({ url: 'https://koenig-media.raywenderlich.com/uploads/2016/02/Logo.png', alt: 'RW Logo', }), })); }).catch((err) => { console.log(err) conv.close("An Error Occurred Parsing the RSS Feed, Try Again Later"); }); });

Приведенный выше код ищет в ленте самый новый эпизод. Вот как:

  • Код ищет значение параметра Subject.
  • Пользовательское высказывание предоставляет параметр.
  • Объект, определенный в Dialogflow, обеспечивает высказывание.

Первый подкаст, содержащий ключевое слово Subject, будет передан в MediaObject и воспроизведен.

Куда пойти отсюда?

Вау, это было много работы! Вы восхитителены!

В этом руководстве вы создали действие Google в консоли действий Google и использовали Dialogflow для разработки диалога для этого действия.

Вы обеспечили выполнение этого действия, реализовали локально разработанный webhook в node.js, используя обещания.

Получите окончательный проект по этой ссылке. Если вы хотите продолжать двигаться вперед, вот несколько советов:

  • Вы можете узнать больше о публикации ваших действий здесь.
  • В течение 24 часов после публикации вашего действия в разделе Analytics консоли действий будут отображаться собранные данные. Используйте раздел Analytics для проверки работоспособности и получения информации об использовании, работоспособности и обнаружении действия. Подробности здесь.
  • Узнайте больше о расширении NPM rss-parser, которое мы использовали, здесь.
  • Хотите пойти еще глубже в помощника Google? У Google есть обширное руководство по дизайну разговоров. Найдите Google Codelabs о помощнике здесь и несколько примеров от Google здесь. У Google есть полная документация.
0
Комментарии
Читать все 0 комментариев
null