Acciones en Google: escribir una aplicación simple para el Asistente de Google en Dialogflow y Cloud Functions para Firebase

A fines del mes pasado, el Asistente de Google se lanzó oficialmente en ruso, por lo que es hora de descubrir cómo hacer sus propias aplicaciones ( acciones ) para el Asistente en la pila de tecnología estándar de Google. En este artículo, consideraremos crear una acción en Actions on Google , analizar el proceso de extracción de entidades e intenciones de frases en Dialogflow , aprender a escribir controladores para la información extraída y trabajar con una red en Cloud Functions para Firebase .


Fig. 1. Arquitectura de la aplicación para el Asistente.

El desarrollo del Asistente ha comenzado a desarrollarse relativamente recientemente, por lo que la red tiene pocos materiales y la cantidad de herramientas y tecnologías utilizadas aumenta significativamente el umbral de entrada. Este artículo, aunque no resuelve, pero al menos contribuye a la solución de estos problemas. Comencemos con la arquitectura de la aplicación para el Asistente (Fig. 1), implementada en la pila de tecnología estándar de Google:

  • Actions on Google es una plataforma para crear aplicaciones para Google Assistant.
  • Dialogflow : motor NLU (comprensión del lenguaje natural), responsable del procesamiento de lenguajes naturales y diálogos de diseño.
  • Funciones en la nube para Firebase (por conveniencia, utilizaremos la abreviatura Funciones de Firebase): funciones en la nube para procesar la lógica compleja de la interacción del usuario y para trabajar con servicios de terceros. Firebase Functions y Dialogflow interactúan a través de webhook, por lo que técnicamente se puede utilizar cualquier otra solución de servidor. Sin embargo, Firebase Functions es una buena alternativa y, a veces, un reemplazo para su propio backend. Le permite crear y ejecutar servicios en la infraestructura de Google, sin preocuparse por la asignación, el escalado o la administración de servidores. Por un lado, esto le permite concentrarse en el componente del producto del desarrollo y la funcionalidad del servicio, sin perder tiempo en tareas de infraestructura y administración. Pero, por otro lado, por regla general, la delegación implica un debilitamiento del control sobre la situación.

El artículo se centra en el aspecto técnico del desarrollo; no se analizará el costo de usar los servicios enumerados.


Fig. 2. Interacción de los componentes del Asistente de Google (Basado en material: Google Home y Google Assistant Workshop ).

Dentro de la pila descrita, la lógica de acción se ve así (Fig. 2):

  • El usuario accede a la aplicación Asistente de Google e inicia una conversación con una acción específica.
  • El Asistente de Google a través de Acciones en Google representa cada frase de usuario en un formato de texto en Dialogflow, además de proporcionar información sobre el propio usuario (previa solicitud y con el consentimiento del usuario) y la conversación actual .
  • Dialogflow procesa la frase recibida, extrae de ella la información necesaria y, sobre la base de ML, toma decisiones sobre qué respuesta se generará.
  • En algunos casos, Dialogflow puede delegar la formación de una respuesta al servidor en las funciones de Firebase, que, a su vez, pueden usar servicios de terceros para obtener la información necesaria para la respuesta.
  • Después de que se forma la respuesta, Dialogflow lo devuelve a Actions on Google, desde donde ingresa a la aplicación Google Assistant.

Idea


Nuestra acción determinará por frase qué tipo de gifs quiere ver el usuario, y luego los buscará a través de la API GIPHY y los devolverá al usuario en forma de tarjetas. Al implementar la acción, analizaremos la solución de las siguientes tareas:

  1. Configure y vincule Acciones en Google, Dialogflow y Firebase Functions.
  2. Extraer palabras clave de frases de usuario (Dialogflow).
  3. Diálogo de secuencias de comandos (Dialogflow).
  4. Trabajar con contexto de diálogo (Dialogflow).
  5. Crear y conectar un webhook para generar una respuesta a una frase de usuario (Dialogflow, Firebase Function).
  6. Muestra el carrusel de tarjetas en la interfaz (Funciones Firebase).
  7. Descarga de información de un servicio de terceros (Funciones de Firebase).

Configuración inicial



Fig. 3. Crear un agente de Dialogflow.

En primer lugar, necesitamos una cuenta de Google. Comencemos creando un proyecto en Dialogflow, para esto, en la consola, haga clic en el botón Crear agente y complete los campos obligatorios (Fig. 3):

  • El idioma predeterminado es "ruso - ru".
  • Zona horaria: "(GMT + 3: 00) Europa / Moscú".
  • Google Cloud Project: se creará automáticamente un nuevo GCP para su agente de Dialogflow, o puede elegir uno de los proyectos de GCP existentes, si los hay.

Luego haga clic en el botón Crear en la esquina superior derecha y espere a que la consola configure un nuevo proyecto.


Fig. 4. Intenciones estándar.

De manera predeterminada, al crear un agente de Dialogflow, se crean dos intentos (Fig. 4):

  • "Intención de bienvenida predeterminada": es responsable de saludar al usuario;
  • “Intento de reserva predeterminado”: ​​procesa frases desconocidas que Dialogflow no puede atribuir a ningún otro intento.

La creación de cuadros de diálogo en Dialogflow ya se ha descrito en detalle en los artículos aquí , aquí y aquí , por lo que no me centraré en su principio de funcionamiento.


Fig. 5. Respuestas para "Intención de bienvenida predeterminada".

Agregaremos algunas respuestas de bienvenida a la "Intención de bienvenida predeterminada" que ayudará al usuario a comprender para qué sirve la acción y qué funciones puede realizar. En la sección "Respuestas", seleccione la pestaña "Asistente de Google" y en "Buques de sugerencias" escribiremos ejemplos de frases para decirle al usuario cómo comunicarse con la acción (Fig. 5).

La acción se puede depurar en el Asistente de Google tanto en el teléfono como en el emulador oficial. Para abrir el emulador, debe ir a la sección "Integraciones", en la tarjeta "Asistente de Google", hacer clic en el botón "Configuración de integración" y hacer clic en "Administrar aplicación de asistente". Tanto en el teléfono como en el emulador, la acción se puede activar con la frase de código "Ok Google, quiero hablar con mi aplicación de prueba".

Escenario base: búsqueda de GIF


Cree una nueva intención de búsqueda, que extraerá palabras clave de la frase del usuario y las enviará a través del servidor webhook a las funciones de Firebase. El servidor, a su vez, utilizando la API GIPHY encontrará los gifs correspondientes y devolverá el resultado al usuario en forma de tarjetas.


Fig. 6. Agregar frases de entrenamiento.

Para comenzar, agregaremos frases típicas para el entrenamiento en la sección de Frases de entrenamiento (Fig. 6):

  • "Quiero ver bailar jirafas".
  • "Encuentra el animashki".
  • "Mostrar los sellos".
  • Muéstrame los gifs.
  • "Búscame elefantes animados".
  • "Mostrar gifs de panda".
  • "Gifs con rayas de mapaches".
  • "Tienes sellos".
  • "Encuentra las caídas divertidas".


Fig. 7. Extracción de parámetros del texto.

Para las frases agregadas, tenga en cuenta el parámetro de búsqueda, que Dialogflow debe seleccionar del texto. En este caso, el tipo de parámetro más apropiado es @sys.any , ya que casi cualquier construcción de lenguaje puede usarse como parámetro de consulta de búsqueda. Llamamos a esta query parámetros y la marcamos como sea necesario (Fig. 7).


Fig. 8. La lista de preguntas principales.

En la subsección "Avisos", escribiremos preguntas aclaratorias que Dialogflow le preguntará si no puede extraer palabras clave de la frase (Fig. 8).

A continuación, vaya a la sección "Cumplimiento" en la parte inferior de la página (no debe confundirse con la sección del mismo nombre en el menú de la izquierda). haga clic en el botón "Habilitar Fullfilment" y luego habilite la configuración "Habilitar llamada de webhook para este intento". Esto permitirá que Dialogflow delegue la formación de una respuesta de Firebase Functions cuando llegue a la intención.

Ahora vaya a la pestaña "Cumplimiento" en el menú de la izquierda y active el "Editor en línea", donde escribiremos la lógica para el "Intento de búsqueda" recién creado. Para buscar GIF por palabras clave, utilizaremos la solicitud https://api.giphy.com/v1/gifs/search , que devuelve una lista de objetos encontrados en formato JSON de acuerdo con la especificación . La respuesta recibida de GIPHY se mostrará en forma de carrusel de navegación , un carrusel de tarjetas con imágenes que, al hacer clic, abre una página web. En nuestro caso, cuando hace clic en la tarjeta, el usuario irá a la página de servicio GIPHY con esta animación y una lista de otras similares.

El código que implementa la funcionalidad descrita anteriormente se presenta a continuación.

 'use strict'; const GIPHY_API_KEY = 'API_KEY'; const SEARCH_RESULTS = [ '-,    .', ',   .', ',   !' ]; // Import the Dialogflow module from the Actions on Google client library. const { dialogflow, BrowseCarouselItem, BrowseCarousel, Suggestions, Image } = require('actions-on-google'); // Import the firebase-functions package for deployment. const functions = require('firebase-functions'); // Import the request-promise package for network requests. const request = require('request-promise'); // Instantiate the Dialogflow client. const app = dialogflow({ debug: true }); function getCarouselItems(data) { var carouselItems = []; data.slice(0, 10).forEach(function (gif) { carouselItems.push(new BrowseCarouselItem({ title: gif.title || gif.id, url: gif.url, image: new Image({ url: gif.images.downsized_medium.url, alt: gif.title || gif.id }), })); }); return carouselItems; } function search(conv, query) { // Send the GET request to GIPHY API. return request({ method: 'GET', uri: 'https://api.giphy.com/v1/gifs/search', qs: { 'api_key': GIPHY_API_KEY, 'q': query, 'limit': 10, 'offset': 0, 'lang': 'ru' }, json: true, resolveWithFullResponse: true, }).then(function (responce) { // Handle the API call success. console.log(responce.statusCode + ': ' + responce.statusMessage); console.log(JSON.stringify(responce.body)); // Obtain carousel items from the API call response. var carouselItems = getCarouselItems(responce.body.data); // Validate items count. if (carouselItems.length <= 10 && carouselItems.length >= 2) { conv.data.query = query; conv.data.searchCount = conv.data.searchCount || 0; conv.ask(SEARCH_RESULTS[conv.data.searchCount % SEARCH_RESULTS.length]); conv.data.searchCount++; conv.ask(new BrowseCarousel({ items: carouselItems })); } else { // Show alternative response. conv.ask('      ,   - ?)'); } }).catch(function (error) { // Handle the API call failure. console.log(error); conv.ask(',     .'); }); } // Handle the Dialogflow intent named 'Search Intent'. // The intent collects a parameter named 'query'. app.intent('Search Intent', (conv, { query }) => { return search(conv, query); }); // Set the DialogflowApp object to handle the HTTPS POST request. exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app); 

Dependencias
 { "name": "dialogflowFirebaseFulfillment", "description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase", "version": "0.0.1", "private": true, "license": "Apache Version 2.0", "author": "Google Inc.", "engines": { "node": "~6.0" }, "scripts": { "start": "firebase serve --only functions:dialogflowFirebaseFulfillment", "deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment" }, "dependencies": { "actions-on-google": "2.0.0-alpha.4", "firebase-admin": "^4.2.1", "firebase-functions": "^0.5.7", "dialogflow": "^0.1.0", "dialogflow-fulfillment": "0.3.0-beta.3", "request": "^2.81.0", "request-promise": "^4.2.1" } } 

Dado que el usuario puede acceder a la misma intención varias veces, se recomienda devolverle varias respuestas. Para hacer esto, utilizamos el objeto Conversation.data JSON, que conserva su valor tanto al acceder a la intención nuevamente como al referirse a otros scripts de conversación.


Fig. 9. Inicialización de la conversación (a la izquierda), refinamiento de los parámetros de búsqueda y posterior visualización de resultados (en el centro), visualización de resultados de búsqueda para una nueva consulta (a la derecha)

Nota: para trabajar con la API de servicios de terceros a través de las funciones de Firebase, debe habilitar la facturación; de lo contrario, al intentar trabajar con la red, se producirá un error:
"Cuenta de facturación no configurada. La red externa no es accesible y las cuotas están severamente limitadas. Configure la cuenta de facturación para eliminar estas restricciones ".
Para hacer esto, haga clic en "Cuenta paga" en el menú de la izquierda y seleccione Flame ($ 25 por mes) o Blaze (pagar según lo use) entre los planes tarifarios propuestos. Elegí la última opción, porque como parte del desarrollo de una aplicación de prueba, me pareció más rentable.

Escenario avanzado: paginación


En la mayoría de los casos, para una consulta de búsqueda, GIPHY encontrará significativamente más de diez GIF, por lo que será correcto permitir que el usuario vea el resultado completo de la búsqueda, es decir, Añadir paginación.

En la consola de Dialogflow, desplace el cursor sobre la celda Intento de búsqueda. Aparecerán varios botones a la derecha, haga clic en "Agregar intención de seguimiento". Esto nos permitirá crear una rama de conversación siguiendo el intento de búsqueda. Entre los elementos de la lista desplegable, seleccionamos "más", un elemento estándar para iniciar la visualización de información adicional.


Fig. 10. El contexto de la intención es "Intento de búsqueda - más".

Vayamos a la intención recién creada y realicemos cambios en la sección "Contexto". Dado que el usuario puede solicitar mostrar más GIF varias veces seguidas, esta intención debería poder llamarse de forma recursiva. Para esto, en el contexto de salida, es necesario registrar la misma línea que se indica en la entrada (Fig. 10). En la sección "Fullfilment", también debe habilitar la configuración "Habilitar llamada de webhook para este intento".

Ahora volvamos al "Relleno" desde el menú lateral, donde inicializamos el controlador para "Intento de búsqueda - más". También agregamos el parámetro de offset a la función de search , que se utilizará para la paginación en la API GIPHY.

 const SEARCH_RESULTS_MORE = [ '   !', ',    .', ',   .  ,    .' ]; function search(conv, query, offset) { // Send the GET request to GIPHY API. return request({ method: 'GET', uri: 'https://api.giphy.com/v1/gifs/search', qs: { 'api_key': GIPHY_API_KEY, 'q': query, 'limit': 10, 'offset': offset, 'lang': 'ru' }, json: true, resolveWithFullResponse: true, }).then(function (responce) { // Handle the API call success. console.log(responce.statusCode + ': ' + responce.statusMessage); console.log(JSON.stringify(responce.body)); // Obtain carousel items from the API call response. var carouselItems = getCarouselItems(responce.body.data); // Validate items count. if (carouselItems.length <= 10 && carouselItems.length >= 2) { conv.data.query = query; conv.data.offset = responce.body.pagination.count + responce.body.pagination.offset; conv.data.paginationCount = conv.data.paginationCount || 0; conv.data.searchCount = conv.data.searchCount || 0; // Show successful response. if (offset == 0) { conv.ask(SEARCH_RESULTS[conv.data.searchCount % SEARCH_RESULTS.length]); conv.data.searchCount++; } else { conv.ask(SEARCH_RESULTS_MORE[conv.data.paginationCount % SEARCH_RESULTS_MORE.length]); conv.data.paginationCount++; } conv.ask(new BrowseCarousel({ items: carouselItems })); conv.ask(new Suggestions('')); } else { // Show alternative response. conv.ask('      ,   - ?)'); } }).catch(function (error) { // Handle the API call failure. console.log(error); conv.ask(',     .'); }); } // Handle the Dialogflow intent named 'Search Intent - more'. app.intent('Search Intent - more', (conv) => { // Load more gifs from the privious search query return search(conv, conv.data.query, conv.data.offset); }); 


Fig. 11. Paginación al buscar gifs.

Resultado


El video de la acción se presenta a continuación.



Código de proyecto y volcado de asistente disponible en Github .

Instrucciones para instalar el proyecto e importar el volcado
  1. Vaya a la consola de Dialogflow y cree un nuevo agente o seleccione uno existente.
  2. Haga clic en el icono de configuración, vaya a la sección "Exportar e importar" y haga clic en el botón "Restaurar desde ZIP". Seleccione el archivo ZIP del directorio raíz del repositorio.
  3. Seleccione "Cumplimiento" en el menú de navegación izquierdo.
  4. Active la configuración "Editor en línea".
  5. Copie el contenido de los archivos del directorio de functions a las pestañas apropiadas en el "Cumplimiento".
  6. Ingrese su clave de acceso API GIPHY en la pestaña index.js .
  7. Ve a la consola de Firebase y cambia tu plan a Flame o Blaze. El trabajo con servicios de terceros a través de la red no está disponible con un plan tarifario gratuito.

Source: https://habr.com/ru/post/es419261/


All Articles