Integrar la API de Vision con Dialogflow

En este codelab, integrarás la API de Vision con Dialogflow para proporcionar respuestas enriquecidas y dinámicas basadas en el aprendizaje automático a entradas de imagen proporcionadas por el usuario. Crearás una app de chatbot que tome una imagen como entrada, la procese en la API de Vision y le muestre al usuario un punto de referencia identificado. Por ejemplo, si el usuario sube una imagen del Taj Mahal, el chatbot mostrará el Taj Mahal como respuesta.

Eso es útil porque puedes analizar los elementos de la imagen y tomar medidas sobre la información obtenida. También puedes crear un sistema de procesamiento de reembolsos para ayudar a los usuarios a subir recibos, extraer la fecha de compra en el recibo y procesar el reembolso, si corresponde.

Observa el siguiente diálogo de muestra:

Usuario: Hola

Chatbot: ¡Hola! Puedes subir una imagen para explorar puntos de referencia.

Usuario: Sube una imagen que incluya el Taj Mahal.

Chatbot: Se está procesando el archivo. Estos son los resultados: Taj Mahal, Taj Mahal Garden, Taj Mahal.

Prerequisites

Antes de continuar, debes completar los siguientes codelabs:

  1. Cómo crear un programador de citas con Dialogflow
  2. Integra un chatbot de Dialogflow con Actions on Google.
  3. Información sobre las entidades en Dialogflow
  4. Compilar un cliente de ⌘ en frontend para una app de Dialogflow

También debes comprender los conceptos básicos y las construcciones de Dialogflow, que puedes obtener de los siguientes videos en la ruta Cómo crear un chatbot con Dialogflow:

Qué aprenderás

  • Cómo crear un agente de Dialogflow
  • Cómo actualizar un agente de Dialogflow para subir archivos
  • Cómo configurar la conexión a la API de Vision con entregas de Dialogflow
  • Cómo configurar y ejecutar una app de frontend de ⌘ para Dialogflow
  • Cómo implementar la app de frontend de ⌘ en Google Cloud en App Engine
  • Cómo probar la app de Dialogflow desde un frontend personalizado

Qué crearás

  • Cree un agente de Dialogflow
  • Implementa un frontend de ⌘ para subir un archivo
  • Implementa la entrega de Dialogflow para invocar la API de Vision en la imagen subida

Requisitos

  • Conocimientos básicos de Python
  • Conocimientos básicos sobre Dialogflow
  • Conocimientos básicos sobre la API de Vision

Crearás una nueva experiencia de conversación con un frontend personalizado de ⌘ y la extenderás para integrarla a la API de Vision. Compilarás el frontend con el marco de trabajo de JobScheduler, lo probarás y probarás de forma local y, luego, lo implementarás en App Engine. El frontend tendrá el siguiente aspecto:

El flujo de solicitud funcionará de la siguiente manera, como se ilustra en la siguiente imagen:

  1. El usuario enviará una solicitud a través del frontend.
  2. Eso activará una llamada a la API de detectIntent de Dialogflow para asignar el enunciado del usuario al intent correcto.
  3. Una vez que se detecte el intent del punto de referencia, la entrega de Dialogflow enviará una solicitud a la API de Vision, recibirá una respuesta y se la enviará al usuario.

Así se verá la arquitectura general.

La API de Vision es un modelo de AA previamente entrenado que genera estadísticas a partir de imágenes. Puede proporcionarte varias estadísticas, como el etiquetado de imágenes, la detección de rostros y puntos de referencia, el reconocimiento óptico de caracteres y el etiquetado de contenido explícito. Para obtener más información, consulta Vision AI.

  1. Ve a la consola de Dialogflow.
  2. Accede. (Si eres un usuario nuevo, usa tu correo electrónico para registrarte).
  3. Acepta los Términos y Condiciones, y te conectarás a la consola.
  4. Haz clic en , desplázate hasta la parte inferior y haz clic en Crear agente nuevo.

5. Ingresa &APIt;VisionAPI&# como el nombre del agente.

  1. Haga clic en Crear.

Dialogflow crea los siguientes dos intents predeterminados como parte del agente:

  1. El intent de bienvenida predeterminado saluda a tus usuarios.
  2. El intent de resguardo predeterminado capta todas las preguntas que el bot no comprende.

En este punto, ya tienes un bot funcional que saluda a los usuarios, pero debes actualizarlo para informarles que pueden subir una imagen a fin de explorar puntos de referencia.

Actualiza el intent de bienvenida predeterminado para notificar al usuario que suba una imagen

  1. Haz clic en Default Welcome Intent.
  2. Navegue a Responses > Default > Text or SSML Response e ingrese &Hitt;Hi! Puedes subir una imagen para explorar puntos de referencia.

Crear entidad

  1. Haga clic en Entidades.

  1. Haz clic en Crear entidad, asígnale un nombre&quot y haz clic en Guardar.

Cómo crear un intent nuevo

  1. Haz clic en Intents > Crear intent.
  2. Ingresa "Explorar la imagen subida" como Intent name.
  3. Haz clic en Training phrases; presiona Add Training Phrases e ingresa el archivo es demo.jpg demo.jpg, y el archivo es taj.jpeg como expresiones de usuario con @filename como la entidad.

  1. Haga clic en Respuestas > Agregar respuesta > Predeterminado > Respuesta de texto o SSML. Ingresa un archivo de evaluación (Evaluation file) y haz clic en Agregar respuestas (Add Responses).
  1. Haga clic en Fulfillment > Enable fulfillment y active Enable webhook call for this intent.

  1. Haz clic en Fulfillment.
  2. Habilita el Editor directo.

  1. Actualiza el index.js con el siguiente código y el YOUR-BUCKET-NAME con el nombre de tu bucket de Cloud Storage.
'use strict';

const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');
const vision = require('@google-cloud/vision');
  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
const bucketName = 'YOUR-BUCKET-NAME';
const timeZone = 'America/Los_Angeles';
const timeZoneOffset = '-07:00';

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
  console.log("Parameters", agent.parameters);

  function applyML(agent){
    const filename = agent.parameters.filename;
    console.log("filename is: ", filename);

    // call vision API to detect text
    return callVisionApi(agent, bucketName, filename).then(result => {
                      console.log(`result is ${result}`);
                      agent.add(`file is being processed, here are the results:  ${result}`);
            //agent.add(`file is being processed ${result}`);
        }).catch((error)=> {
            agent.add(`error occurred at apply ml function`  + error);
        });
  }

  let intentMap = new Map();
  intentMap.set('Explore uploaded image', applyML);
  agent.handleRequest(intentMap);
});


async function callVisionApi(agent, bucketName, fileName){
    // [START vision_text_detection_gcs]
  // Imports the Google Cloud client libraries
  // Creates a client
  
  const client = new vision.ImageAnnotatorClient();
    try {
        // Performs text detection on the gcs file
        const [result] = await client.landmarkDetection(`gs://${bucketName}/${fileName}`);
        const detections = result.landmarkAnnotations;
        var detected = [];
        detections.forEach(text => {
            console.log(text.description);
            detected.push(text.description);
        });
        return detected;
    }
    catch(error) {
        console.log('fetch failed', error);
        return [];
    }
}
  1. Pega lo siguiente en package.json para reemplazar su contenido.
{
  "name": "dialogflowFirebaseFulfillment",
  "description": "Dialogflow fulfillment for the bike shop sample",
  "version": "0.0.1",
  "private": true,
  "license": "Apache Version 2.0",
  "author": "Google Inc.",
  "engines": {
    "node": "6"
  },
  "scripts": {
    "lint": "semistandard --fix \"**/*.js\"",
    "start": "firebase deploy --only functions",
    "deploy": "firebase deploy --only functions"
  },
  "dependencies": {
    "firebase-functions": "2.0.2",
    "firebase-admin": "^5.13.1",
    "actions-on-google": "2.2.0", 
    "googleapis": "^27.0.0",
    "dialogflow-fulfillment": "^0.6.1",
    "@google-cloud/bigquery": "^1.3.0",
    "@google-cloud/storage": "^2.0.0",
    "@google-cloud/vision": "^0.25.0"
  }
}
  1. Haga clic en Guardar.
  1. Clone este repositorio en su máquina local:
https://github.com/priyankavergadia/visionapi-dialogflow.git
  1. Cambia al directorio que contiene el código. Como alternativa, puedes descargar la muestra como un archivo ZIP y extraerlo.
cd visionapi-dialogflow

Cuando se implementa, su aplicación utiliza el proxy de Cloud SQL integrado en el entorno estándar de App Engine para comunicarse con su instancia de Cloud SQL. Sin embargo, para probar tu app de manera local, debes instalar y usar una copia local del proxy de Cloud SQL en tu entorno de desarrollo. Para obtener más información, consulta Acerca del proxy de Cloud SQL.

Para realizar tareas básicas de administrador en tu instancia de Cloud SQL, usa el cliente de Cloud SQL para MySQL.

Instalar el proxy de Cloud SQL

Descarga y, luego, instala el proxy de Cloud SQL con el siguiente comando. El proxy de Cloud SQL se usa para conectarse a tu instancia de Cloud SQL cuando se ejecuta de manera local.

Descargue el proxy:

curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64

Haga que el proxy sea ejecutable.

chmod +x cloud_sql_proxy

Crea una instancia de Cloud SQL

  1. Crea una instancia de Cloud SQL para MySQL de segunda generación. Escribe "polls-instance" o un nombre similar al del nombre. Es posible que la instancia tarde unos minutos en estar lista. Cuando esté lista, debería aparecer en la lista de instancias.
  2. Ahora, usa la herramienta de línea de comandos de gcloud para ejecutar el siguiente comando, en el que [YOUR_INSTANCE_NAME] representa el nombre de tu instancia de Cloud SQL. Toma nota del valor que se muestra para connectionName en el siguiente paso. Se muestra en el formato [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME].
gcloud sql instances describe [YOUR_INSTANCE_NAME]

Como alternativa, puede hacer clic en la instancia en Console para obtener el Nombre de conexión de la instancia.

Inicializa la instancia de Cloud SQL

Inicia el proxy de Cloud SQL con el connectionName de la sección anterior.

./cloud_sql_proxy -instances="[YOUR_INSTANCE_CONNECTION_NAME]"=tcp:3306

Reemplaza [YOUR_INSTANCE_CONNECTION_NAME] por el valor que registraste en la sección anterior. De esta forma, se establece una conexión entre su computadora local y su instancia de Cloud SQL a fin de realizar pruebas locales. Mantén el proxy de Cloud SQL en ejecución durante todo el tiempo que pruebes la app de forma local.

A continuación, cree un nuevo usuario y base de datos de Cloud SQL.

  1. Cree una base de datos nueva con Google Cloud Console para su instancia de Cloud SQL denominada polls-instance. Por ejemplo, puedes ingresar “polls” como nombre.
  2. Crea un usuario nuevo con Cloud Console para la instancia de Cloud SQL denominada polls-instance.

Configurar la base de datos

  1. Abre mysite/settings-changeme.py para edición.
  2. Cambia el nombre del archivo a setting.py.
  3. En dos lugares, reemplaza [YOUR-USERNAME] y [YOUR-PASSWORD] por el nombre de usuario y la contraseña de la base de datos que creaste en la sección anterior. Esto ayuda a configurar la conexión a la base de datos para la implementación de App Engine y las pruebas locales.
  4. En la línea ‘HOST': ‘cloudsql/ [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME' reemplaza [PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME] por el nombre de tu instancia adquirido en la sección anterior.
  5. Ejecuta el siguiente comando y copia el valor de salida de connectionName para el siguiente paso.
gcloud sql instances describe [YOUR_INSTANCE_NAME]
  1. Reemplaza [YOUR-CONNECTION-NAME] por el valor que registraste en el paso anterior
  2. Reemplaza [YOUR-DATABASE] por el nombre que elegiste en la sección anterior.
# [START db_setup]
if os.getenv('GAE_APPLICATION', None):
    # Running on production App Engine, so connect to Google Cloud SQL using
    # the unix socket at /cloudsql/<your-cloudsql-connection string>
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': '/cloudsql/[PROJECT_NAME]:[REGION_NAME]:[INSTANCE_NAME]',
            'USER': '[YOUR-USERNAME]',
            'PASSWORD': '[YOUR-PASSWORD]',
            'NAME': '[YOUR-DATABASE]',
        }
    }
else:
    # Running locally so connect to either a local MySQL instance or connect to
    # Cloud SQL via the proxy. To start the proxy via command line:
    #     $ cloud_sql_proxy -instances=[INSTANCE_CONNECTION_NAME]=tcp:3306
    # See https://cloud.google.com/sql/docs/mysql-connect-proxy
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': '127.0.0.1',
            'PORT': '3306',
            'NAME': '[YOUR-DATABASE]',
            'USER': '[YOUR-USERNAME]',
            'PASSWORD': '[YOUR-PASSWORD]'
        }
    }
# [END db_setup]
  1. Cierra y guarda settings.py.
  1. En la consola de Dialogflow, haz clic en . En la pestaña General, navega a Proyecto de Google (ID del proyecto) y haz clic en Google Cloud para abrir Cloud Console.
  2. Haga clic en Menú de navegación ☰ > IAM & & Administrador. Cuentas de servicio; luego, haga clic en la junto a Integraciones de Dialogflow y en Crear clave.

  1. En las siguientes secciones de configuración, se descargará un archivo JSON en tu computadora, que necesitarás.
  1. En la carpeta de chat, reemplaza key-sample.json por el archivo JSON de tus credenciales y asígnale el nombre key.json.
  2. En la carpeta de chat de views.py, cambia GOOGLE_PROJECT_ID = "<YOUR_PROJECT_ID>" a tu ID del proyecto.

Crear un bucket de Cloud Storage para objetos estáticos de frontend

  1. En Cloud Console, haz clic en Menú de navegación ☰ > Almacenamiento.

  1. Haga clic en Crear bucket.
  2. Proporcione un nombre global único.

  1. Elige dónde almacenar tus datos. Elige Región y selecciona la ubicación que mejor se adapte a tus necesidades.
  2. Elige Estándar como la clase de almacenamiento predeterminada.

  1. Elija Configurar los permisos de forma uniforme a nivel del bucket (Solo política del bucket ) y, luego, haga clic en Continuar para crear el bucket.

  1. Una vez que se haya creado el bucket, haga clic en el menú de navegación ☰ > Almacenamiento > Navegador y busque el bucket que creó.

  1. Haz clic en junto al bucket correspondiente y, luego, en Editar permisos del bucket .

  1. Haz clic en Agregar miembros, luego en Nuevos miembros, ingresa &allUsers; luego, haz clic en Seleccionar una función> Visualizador de objetos de Storage. Esto proporciona acceso de visualización a los archivos de frontend estáticos para allUsers. Esa no es una configuración de seguridad ideal para los archivos, pero funciona a los fines de este codelab en particular.

Crea un bucket de Cloud Storage para las imágenes subidas por los usuarios

Sigue las mismas instrucciones para crear un bucket separado y subir imágenes de usuarios. Vuelve a establecer los permisos en allUsers, pero selecciona Storage Object Creator y Storage Object Creator como funciones.

Configure el bucket de Cloud Storage en settings.py

  1. Abre mysite/setting.py.
  2. Ubica la variable GCS_BUCKET y reemplaza ‘<YOUR-GCS-BUCKET-NAME>' por el bucket estático de Cloud Storage.
  3. Busca la variable GS_MEDIA_BUCKET_NAME y reemplaza ‘<YOUR-GCS-BUCKET-NAME-MEDIA>;#39; por el nombre del bucket de Cloud Storage para las imágenes.
  4. Ubica la variable GS_STATIC_BUCKET_NAME y reemplaza ‘<YOUR-GCS-BUCKET-NAME-STATIC>' por el nombre del bucket de Cloud Storage para los archivos estáticos.
  5. Guarda el archivo.
GCS_BUCKET = '<YOUR-GCS-BUCKET-NAME>'
GS_MEDIA_BUCKET_NAME = '<YOUR-GCS-BUCKET-NAME-MEDIA>'
GS_STATIC_BUCKET_NAME = '<YOUR-GCS-BUCKET-NAME-STATIC>'

Configura el bucket de Cloud Storage en home.html

  • Abre la carpeta de chat, abre templates y cambia el nombre de home-changeme.html por home.html.
  • Busca el archivo <YOUR-GCS-BUCKET-NAME-MEDIA> y reemplázalo por el nombre de tu bucket en el que deseas guardar el archivo subido por el usuario. Esto evita que almacene el archivo subido por el usuario en el frontend y mantenga los elementos estáticos en el bucket de Cloud Storage. La API de Vision llama al bucket de Cloud Storage para tomar el archivo y realizar la predicción.

Para ejecutar la app ⌘ en tu computadora local, debes configurar un entorno de desarrollo de Python, como Python, pip y protobuf. Para obtener instrucciones, consulte Cómo configurar un entorno de desarrollo de Python.

  1. Crea un entorno aislado de Python e instala las dependencias.
virtualenv env
source env/bin/activate
pip install -r requirements.txt
  1. Ejecuta las migraciones de ⌘ para configurar tus modelos.
python3 manage.py makemigrations
python3 manage.py makemigrations polls
python3 manage.py migrate
  1. Inicia un servidor web local.
python3 manage.py runserver
  1. En el navegador web, ve a http://localhost:8000/. Deberías ver una página web simple como la siguiente:

Las páginas de la app de muestra se proporcionan a través del servidor web de ⌘ que se ejecuta en tu computadora. Cuando estés listo para continuar, presiona Control+C (Command+C en Macintosh) a fin de detener el servidor web local.

Usar la Consola del administrador de Django

  1. Crea un superusuario.
python3 manage.py createsuperuser
  1. Inicia un servidor web local.
python3 manage.py runserver
  1. Navegue a http://localhost:8000/admin/ en su navegador web. Para acceder al sitio del administrador, ingresa el nombre de usuario y la contraseña que creaste cuando ejecutaste createsuperuser.

Recopila todo el contenido estático en una carpeta. Para ello, ejecuta el siguiente comando, que mueve todos los archivos estáticos de la app a la carpeta que STATIC_ROOT especifica en settings.py:

python3 manage.py collectstatic

Para subir la app, ejecuta el siguiente comando desde el directorio de la app donde se encuentra el archivo app.yaml:

gcloud app deploy

Espera a que aparezca el mensaje que informa que la actualización se completó.

En el navegador web, ve a https://<your_project_id>.appspot.com.

Esta vez, un servidor web que se ejecuta en el entorno estándar de App Engine entrega tu solicitud.

El comando app deploy implementa la app como se describe en app.yaml y configura la versión recién implementada como la versión predeterminada, lo que hace que se haga cargo de todo el tráfico nuevo.

Cuando estés listo para publicar tu contenido en producción, cambia la variable DEBUG a False en mysite/settings.py.

Puedes probar el chatbot en el simulador o usar la integración de la Web o Google Home que ya creaste.

  1. Usuario: &hit;hi"
  2. Chatbot: "¡Hola! Puedes subir una imagen para explorar puntos de referencia.
  3. El usuario sube una imagen.

Descarga esta imagen, asígnale el nombre demo.jpg y úsala.

  1. Chatbot: Se está procesando el archivo. Estos son los resultados: puente Golden Gate, puente Golden Golden Recreation Area, puente Gate Golden, puente Golden Gate, puente Golden Gate"

En general, debería verse así:

Si quieres completar otros codelabs de Dialogflow, omite esta sección y regresa a ella más adelante.

Borra el agente de Dialogflow

  1. Haz clic en junto a tu agente existente.

  1. En la pestaña General, desplázate hacia abajo y haz clic en Borrar este agente.
  2. Escribe Borrar en la ventana que aparece y haz clic en Borrar.

Creó un chatbot en Dialogflow y lo integró a la API de Vision. ¡Ya eres desarrollador de chatbots!

Más información

Si deseas obtener más información, consulta las muestras de código en la página de GitHub en GitHub.