Reach

Grow

Manage

Automate

Reach

Grow

Manage

Automate

Cómo usar Flows con Google Vision API y Google Cloud Functions

Constructor de Flujos

1 min read

Cómo usar Flows con Google Vision API y Google Cloud Functions

Constructor de Flujos

1 min read

Cómo usar Flows con Google Vision API y Google Cloud Functions

Flows es un motor de automatización potente de arrastrar y soltar para crear flujos de comunicación. Inicialmente lo concebimos como una solución sin código, pero descubrimos que muchos usuarios podían lograr un comportamiento realmente poderoso escribiendo algo de código para casos de uso específicos. Estos fragmentos de código pueden estar dentro de Flow Builder, o pueden ser funciones en la nube de terceros como funciones de AWS Lambda o Google Cloud Functions.

Esta es una demostración simple usando GoogleCloud Functions y Flows para hacer reconocimiento de imagen en una imagen enviada por Telegram.

Flujos y Beyond

Como desarrollador de Flows, a menudo pienso quiénes son nuestros usuarios, por qué usan Flows y qué necesitan para lograr sus objetivos; y luego, qué características necesitamos implementar para servir mejor a esos usuarios.




Flows es un potente motor de automatización de arrastrar y soltar para crear flujos de comunicación. Inicialmente lo concebimos como una solución sin código, pero descubrimos que muchos usuarios podían obtener un comportamiento realmente poderoso escribiendo algo de código para casos de uso específicos.   Estos fragmentos de código pueden estar dentro de Flows, o pueden ser funciones en la nube de terceros como funciones de AWS Lambda o Google Cloud Functions




Un caso de uso interesante: Reconocimiento de Imágenes 

Para un ejemplo corto y divertido, te mostraré cómo implementar una aplicación que reconoce perritos calientes. Configuraremos un flujo en Flows, el cual recibirá imágenes de los usuarios y decidirá si han enviado un perrito caliente o no.




Para muchos de nuestros clientes, este tipo de reconocimiento de imágenes puede ser muy poderoso. Imagina que diriges un servicio de entrega y quieres verificar automáticamente las entregas exitosas. Similar a lo que voy a mostrar, podrías usar datos de ubicación, fotos de paquetes e incluso firmas de destinatarios para crear un flujo de verificación en Flows. 

Un plan para el éxito

Primero, configuraremos una función en la nube, que recibe una solicitud con una URL de una imagen, luego utiliza una API de reconocimiento de imágenes para procesar la imagen, y responde si hay un hotdog en la imagen o no.




Luego construiremos un flujo, que recibe un mensaje de un usuario a través de un canal de mensajería (Telegram en este caso), ejecuta la función en la nube mencionada anteriormente, y responde al usuario si hay un hotdog en una foto que él envió.

Primero, configuraremos una función en la nube, que recibe una solicitud con una URL de una imagen, luego utiliza una API de reconocimiento de imágenes para procesar la imagen, y responde si hay un hotdog en la imagen o no.




Luego construiremos un flujo, que recibe un mensaje de un usuario a través de un canal de mensajería (Telegram en este caso), ejecuta la función en la nube mencionada anteriormente, y responde al usuario si hay un hotdog en una foto que él envió.

Primero, configuraremos una función en la nube, que recibe una solicitud con una URL de una imagen, luego utiliza una API de reconocimiento de imágenes para procesar la imagen, y responde si hay un hotdog en la imagen o no.




Luego construiremos un flujo, que recibe un mensaje de un usuario a través de un canal de mensajería (Telegram en este caso), ejecuta la función en la nube mencionada anteriormente, y responde al usuario si hay un hotdog en una foto que él envió.

Configurando la Google Cloud Function

Primero, necesitaremos configurar una función en la nube. Para comenzar rápidamente, crea una función en la nube utilizando este tutorial: https://cloud.google.com/functions/docs/quickstart-console. Como 'Trigger' elige activación HTTP, entorno de ejecución: Node.js 10, y en el campo de código fuente inserta el fragmento de código. Es un código simple que verifica si la solicitud contiene código JSON y responde sí o no. 




/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
 exports.helloWorld = (req, res) => {
  let message = req.query.url ? "yes" : "no";
  res.setHeader('Content-Type', 'application/json');
  res.status(200).send(JSON.stringify({ isHotDog: message }));
 };







A continuación, necesitarás implementar esta función. Para probarlo dentro de Google Cloud Platform, sigue los pasos del tutorial. 

Para probar desde tu navegador, ve a la siguiente URL insertando la dirección específica de tu función:




https://your-function-address.cloudfunctions.net/HotDogOrNot/?url=hello debería devolver {“isHotDog”: true} y la dirección https://your-function-address.cloudfunctions.net/HotDogOrNot debería devolver {“isHotDog”: false}.




¡Buen trabajo! Has configurado una función de Google Cloud. Ahora necesitamos hacer que nuestra función en la nube sea más inteligente.

Configurando el Google Vision API

Para hacerlo más inteligente, añadamos reconocimiento de imágenes. Para este propósito, utilizaremos el Google Vision API. Para comenzar, siga los pasos 1-4 de este tutorial: https://cloud.google.com/vision/docs/quickstart-client-libraries. En el tutorial activarás el Vision API y crearás una cuenta de servicio para usarlo.




Ahora regrese a la función en la nube que creó. Active “Variables de entorno, redes, tiempos de espera y más” y en el archivo “Cuenta de servicio” elija la cuenta de servicio VisionAPI que acaba de crear. Ahora podemos acceder al Vision API dentro de nuestra función.







Ahora cambiemos el código. En la pestaña "Package.json", inserte este código. Añadirá la biblioteca de Google Vision API como una dependencia para su función.

{
  "name": "sample-http",
  "version": "0.0.1",
  "dependencies": {
  "@google-cloud/vision": "^1.11.0"
  }
 }




En la pestaña "Index.js" actualice el código existente con el siguiente fragmento de código.

/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
 exports.helloWorld = (request, response) => {
  var url = request.query.url || request.body.url;
  if (url == null || url == "" ) {
  response.status(400).json({ error: "Must include a 'url' query parameter." });
  }
  
  
  getImageLabels(url)
  .then(labels => {
  // You can use 'console.log(labels);' command to check labels you got
  // We filter all labels if they contain "hot dog" in label description
  // And have a score > 0.6, which mean that VisionAPI is at least 60% sure that there is a hotdog on a picture
  labels = labels.filter(function(label) {
  return label.description.toLowerCase().includes("hot dog") && label.score > 0.6;
  });
  
  // If labels array contains at least 1 element, then we found a hot-dog!
  if (labels.length > 0) {
  response.status(200).json({isHotDog: true, error: ""});
  } else {
  response.status(200).json({isHotDog: false, error: ""});
  }
  })
  .catch(err => {
  response.status(500).json({ error: err });
  });
 };
  
 async function getImageLabels(imageUrl) {
  // Imports the Google Cloud client library
  const vision = require('@google-cloud/vision');
  // Creates a client
  const client = new vision.ImageAnnotatorClient();
  // Performs label detection on the image file
  const [result] = await client.labelDetection(imageUrl);
  const labels = result.labelAnnotations;
  return labels
 }










¿Cuál es la diferencia en comparación con la versión anterior? Añadimos una solicitud a VisionAPI, que devuelve las ‘etiquetas’ que encontró en la imagen. Luego filtramos estas etiquetas por descripción: si contiene “hot dog” y si tiene más del 60% de confianza en esa etiqueta. Si queda al menos 1 etiqueta después de filtrar, eso significa que encontramos un hot dog en la imagen.




Para entender cómo funciona Google VisionAPI y cómo se ve la respuesta, consulte su documentación, https://cloud.google.com/vision/docs




Después de eso, despliegue la nueva versión de nuestra función. Para probarla desde su navegador, encuentre cualquier imagen de un hot dog y guarde su URL. Ahora vaya a la URL de su función (insertando la dirección correcta para su función) https://su-dirección-de-función.cloudfunctions.net/HotDogOrNot?url=url_a_la_imagen y reemplace “url_a_la_imagen” por una URL de la imagen encontrada. Si hay un hot dog en la imagen, la página devolverá {“isHotDog”: true}.




Ahora conectemos esta función a Flow Builder.

Creating a flow in Flows

Inicia sesión en el Tablero de Bird o regístrate para obtener una cuenta si no tienes una.




Si eres nuevo en Flows y no tienes ningún canal configurado, necesitarás ir a la página de configuración de Canales, y elegir configurar el canal de Telegram. Elegí Telegram para esta demostración porque es fácil y rápido de configurar.







Ahora tienes un canal que podemos usar en Flows. Ve a la página de Flows, crea un nuevo flujo personalizado y elige el desencadenante del canal “Telegram”.







Serás redirigido a la página de flujo, donde deberás elegir tu canal de Telegram como desencadenante, en nuestro caso es “Hotdog”. Por favor añade 2 pasos: “Obtener variables” y “Responder a mensaje de canal”.




Dentro del paso “Obtener variables” llamaremos a nuestra función en la nube y recuperaremos la respuesta en la variable “isHotDog” que contendrá “true” o “false” como respuesta de la función GoogleClound. En el campo URL inserta la URL de tu función https://your-function-address.cloudfunctions.net/HotDogOrNot y llena todos los demás campos como se muestra en la imagen de "Contenido del paso Obtener variables".




Y dentro del paso “Responder a mensaje de canal” responderemos al cliente con un mensaje que contiene la respuesta de sí o no. Para ello inserta en el campo "Responder con mensaje" el siguiente texto "¿Hotdog en la imagen? {{isHotDog}}".







Si tienes algún problema para construir el flujo, puedes usar el siguiente fragmento:

{
  "id": "",
  "revisionId": "",
  "trigger": "onReceivedConversationMessage",
  "options": {
  "callbacks": [],
  "targets": []
  },
  "metadata": {
  "title": "Image recognition",
  "isDraft": false,
  "triggerIntent": "onReceivedTelegramMessage"
  },
  "steps": [
  {
  "id": "19c3560f-a8d0-4787-8714-37c698108b69",
  "action": "fetchVariables",
  "options": {
  "url": "https://your-function-address.cloudfunctions.net/HotDogOrNot",
  "variableKeys": [
  "isHotDog"
  ],
  "intent": "fetchVariables",
  "label": "Is there a hotdog on the image?",
  "method": "POST",
  "body": "{\"url\":\"{{messageImage}}\"}",
  "contentType": "application/json"
  }
  },
  {
  "id": "ca9314a2-2f9d-489c-b4b1-50fc7a0b2cb6",
  "action": "sendConversationMessage",
  "options": {
  "content": {
  "text": "Hotdog on the image? {{isHotDog}}",
  "image": {
  "url": ""
  },
  "audio": {
  "url": ""
  },
  "video": {
  "url": ""
  },
  "file": {
  "url": ""
  },
  "location": {
  "latitude": "",
  "longitude": ""
  },
  "email": {
  "from": {
  "name": "",
  "address": ""
  },
  "subject": "",
  "content": {},
  "headers": null
  }
  },
  "type": "text",
  "recipients": {
  "conversationIds": [
  "{{conversationId}}"
  ]
  },
  "intent": "replyConversationMessage",
  "highThroughput": false
  }
  }
  ],
  "published": true,
  "createdAt": "2020-08-28T18:25:19.665815708Z",
  "updatedAt": "2020-08-29T01:15:43.669252097Z",
  "revisionCount": 22
 }







Para probarlo, envía una imagen a tu bot de Telegram.

¡Hasta ahora, se ve genial! Creamos un pequeño chatbot, que verifica las imágenes que envían los clientes. Para hacerlo más bonito, agreguemos algunos pasos más como se muestra a continuación: 







Si tienes algún problema para construir el flujo, puedes usar el siguiente fragmento:

{
  "id": "",
  "revisionId": "",
  "trigger": "onReceivedConversationMessage",
  "options": {
  "callbacks": [],
  "targets": []
  },
  "metadata": {
  "title": "Image recognition",
  "isDraft": false,
  "triggerIntent": "onReceivedTelegramMessage"
  },
  "steps": [
  {
  "id": "0c3e4f35-0950-44dd-8682-0a21a111de77",
  "action": "switch",
  "options": {
  "cases": [
  {
  "conditions": [
  {
  "variable": "{{messageImage}}",
  "operator": "isEmptyOrNotSet",
  "value": "",
  "options": {
  "intent": "custom"
  }
  }
  ],
  "steps": [
  {
  "id": "ffd13531-a3b9-41de-a2fa-0e515feed2fe",
  "action": "sendConversationMessage",
  "options": {
  "content": {
  "text": "Please send an image.",
  "image": {
  "url": ""
  },
  "audio": {
  "url": ""
  },
  "video": {
  "url": ""
  },
  "file": {
  "url": ""
  },
  "location": {
  "latitude": "",
  "longitude": ""
  },
  "email": {
  "from": {
  "name": "",
  "address": ""
  },
  "subject": "",
  "content": {},
  "headers": null
  }
  },
  "type": "text",
  "recipients": {
  "conversationIds": [
  "{{conversationId}}"
  ]
  },
  "intent": "replyConversationMessage",
  "label": "Ask to send an image",
  "highThroughput": false
  }
  },
  {
  "id": "3d752bc6-cf35-4971-8155-44a2bea4bb49",
  "action": "endFlow",
  "options": {
  "intent": "endFlow"
  }
  }
  ],
  "id": "aa_QVqjIn9"
  }
  ],
  "defaultCase": {
  "steps": [
  {
  "id": "8f3748cf-9059-44fb-a177-bc0dab194e7b",
  "action": "sendConversationMessage",
  "options": {
  "content": {
  "text": "Thank you for the image! We started to detect a hotdog on the image.",
  "image": {
  "url": ""
  },
  "audio": {
  "url": ""
  },
  "video": {
  "url": ""
  },
  "file": {
  "url": ""
  },
  "location": {
  "latitude": "",
  "longitude": ""
  },
  "email": {
  "from": {
  "name": "",
  "address": ""
  },
  "subject": "",
  "content": {},
  "headers": null
  }
  },
  "type": "text",
  "recipients": {
  "conversationIds": [
  "{{conversationId}}"
  ]
  },
  "intent": "replyConversationMessage",
  "label": "Send \"Thanks for the image\"",
  "highThroughput": false
  }
  },
  {
  "id": "808debc0-974d-4b3f-bd4f-ed4efb30a499",
  "action": "fetchVariables",
  "options": {
  "url": "https://your-function-address.cloudfunctions.net/HotDogOrNot",
  "variableKeys": [
  "isHotDog"
  ],
  "intent": "fetchVariables",
  "label": "Send image to VisionAPI",
  "method": "POST",
  "body": "{\"url\":\"{{messageImage}}\"}",
  "contentType": "application/json"
  }
  },
  {
  "id": "c9f771fb-06ff-4362-b783-07e4bd3ff53d",
  "action": "switch",
  "options": {
  "cases": [
  {
  "conditions": [
  {
  "variable": "{{isHotDog}}",
  "operator": "==",
  "value": "true",
  "options": {
  "intent": "custom"
  }
  }
  ],
  "steps": [
  {
  "id": "02629417-e3ac-4bfa-94a9-83047c250d54",
  "action": "sendConversationMessage",
  "options": {
  "content": {
  "text": "There is a hotdog on the image. Thank you!",
  "image": {
  "url": ""
  },
  "audio": {
  "url": ""
  },
  "video": {
  "url": ""
  },
  "file": {
  "url": ""
  },
  "location": {
  "latitude": "",
  "longitude": ""
  },
  "email": {
  "from": {
  "name": "",
  "address": ""
  },
  "subject": "",
  "content": {},
  "headers": null
  }
  },
  "type": "text",
  "recipients": {
  "conversationIds": [
  "{{conversationId}}"
  ]
  },
  "intent": "replyConversationMessage",
  "label": "Send \"we detected a hotdog!\"",
  "highThroughput": false
  }
  }
  ],
  "id": "AWzLv6jksY"
  }
  ],
  "defaultCase": {
  "steps": [
  {
  "id": "b00034ce-db49-4ddf-bf8f-2be006e3fbbd",
  "action": "sendConversationMessage",
  "options": {
  "content": {
  "text": "Sorry, we didn't detect a hotdog on the image. Please try again.",
  "image": {
  "url": ""
  },
  "audio": {
  "url": ""
  },
  "video": {
  "url": ""
  },
  "file": {
  "url": ""
  },
  "location": {
  "latitude": "",
  "longitude": ""
  },
  "email": {
  "from": {
  "name": "",
  "address": ""
  },
  "subject": "",
  "content": {},
  "headers": null
  }
  },
  "type": "text",
  "recipients": {
  "conversationIds": [
  "{{conversationId}}"
  ]
  },
  "intent": "replyConversationMessage",
  "label": "Notify that we didn't detect a hotdog",
  "highThroughput": false
  }
  }
  ],
  "id": "mwk5RoiCo"
  },
  "intent": "smsConditional"
  }
  },
  {
  "id": "8778c563-c045-4aa6-80e5-4c2a29b38b3f",
  "action": "endFlow",
  "options": {
  "intent": "endFlow"
  }
  }
  ],
  "id": "iuFXBNrWTr"
  },
  "intent": "smsConditional",
  "label": "Check if user sent an image"
  }
  }
  ],
  "published": true,
  "createdAt": "2020-08-28T18:25:19.665815708Z",
  "updatedAt": "2020-08-29T01:25:15.614170299Z",
  "revisionCount": 26
 }

Resultados




Aunque este es un ejemplo divertido, creemos que este tipo de funcionalidad puede ser muy útil para nuestros usuarios. 

Si deseas más características como esta integradas en Flows, escribe a nuestro equipo de soporte para hacérnoslo saber. 

Únete a nuestro Newsletter.

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Únete a nuestro Newsletter.

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Únete a nuestro Newsletter.

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Pinterest logo
Uber logo
Square logo
Logo de Adobe
Meta logo
PayPal logo

Company

Configuración de privacidad

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Uber logo
Square logo
Logo de Adobe
Meta logo

Company

Configuración de privacidad

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.

Uber logo
Logo de Adobe
Meta logo

Company

Configuración de privacidad

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Al enviar, aceptas que Bird pueda contactarte sobre nuestros productos y servicios.

Puedes darte de baja en cualquier momento. Consulta el Aviso de Privacidad de Bird para obtener detalles sobre el procesamiento de datos.