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 lograr comportamientos realmente poderosos 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 de 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 hot dogs. Configuraremos un flujo en Flows, que recibirá imágenes de los usuarios y decidirá si enviaron un hotdog 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 perrito caliente en la imagen o no.

Luego crearemos 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, y responde al usuario si hay un perrito caliente 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 perrito caliente en la imagen o no.

Luego crearemos 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, y responde al usuario si hay un perrito caliente 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 perrito caliente en la imagen o no.

Luego crearemos 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, y responde al usuario si hay un perrito caliente 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 usando este tutorial: https://cloud.google.com/functions/docs/quickstart-console. Como 'Trigger' elige HTTP trigger, 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 }));
 };


Google Cloud Console interface with options for creating a new Cloud Function.


A continuación, necesitarás implementar esta función. Para probarla 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 la Google Vision API. Para empezar, sigue los pasos 1-4 de este tutorial: https://cloud.google.com/vision/docs/quickstart-client-libraries. En el tutorial, activará la Vision API y creará una cuenta de servicio para utilizarla.

Ahora regresa a la función en la nube que creaste. Alterna “Variables de entorno, redes, tiempos de espera y más” y en el archivo “Cuenta de servicio” elige la cuenta de servicio VisionAPI que acabas de crear. Ahora podemos acceder a la Vision API dentro de nuestra función.

Advanced options interface of a cloud service configuration.


Ahora vamos a cambiar el código. En una pestaña “Package.json”, inserta este código. Añadirá la biblioteca Google Vision API como dependencia a tu función.

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


En la pestaña "Index.js" actualiza 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
 }



Development environment displaying the code for a package.json file.


¿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 hay al menos 1 etiqueta restante después del filtrado, significa que encontramos un hotdog en la imagen.

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

Después de eso, despliega la nueva versión de nuestra función. Para probarlo desde tu navegador, busca cualquier imagen de un hotdog y guarda su URL. Ahora ve a la URL de tu función (insertando la dirección correcta para tu función) https://your-function-address.cloudfunctions.net/HotDogOrNot?url=url_to_image y reemplaza “url_to_image” con una URL de la imagen encontrada. Si hay un hotdog 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 Bird Dashboard 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.

Interface titled "Channel setup" with options to integrate communication platforms such as Telegram, Messenger, LINE, WeChat, SMS, WhatsApp, Email, and Instagram.


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".

User interface for selecting a communication channel trigger, showing options such as Telegram, Facebook Messenger, Email, Incoming Order Activity, and Shopify Order.


Serás redirigido a una página de flujo, donde deberías elegir tu canal de Telegram como desencadenante, en nuestro caso es "Hotdog". Por favor, añade 2 pasos: "Fetch variables" y "Reply to channel message".

Dentro del paso "Fetch 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 Google Cloud. En el campo URL, por favor inserta la URL de tu función https://your-function-address.cloudfunctions.net/HotDogOrNot y llena todos los demás campos como en la imagen del contenido del paso "Fetch variable step".

Y dentro del paso "Reply to channel message" responderemos al cliente con un mensaje que contenga la respuesta de sí o no. Para eso inserta en el campo "Reply with message" el siguiente texto: "¿Hotdog en la imagen? {{isHotDog}}".

User interface with a form featuring fields like URL, Method, and Headers, along with options for body content and a section for setting header type, all related to configuring a web request in a cloud function environment.


Interface showing a message type selection dropdown, and options for status reports.

Si tienes algún problema construyendo 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
 }


Flowchart illustrating an image recognition process.


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

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


A flowchart diagram illustrating an image recognition process using Telegram Bot and Vision API.


Si tienes algún problema construyendo 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

A chat interface shows a humorous exchange about detecting a hotdog in an image.A mobile chat interface shows an AI chatbot identifying a photo of a hot dog.


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. 

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

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.

Company

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.

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

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.

Company

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.

Conectémosle con un experto de Bird.
Vea el poder completo del Bird en 30 minutos.

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.

R

Reach

G

Grow

M

Manage

A

Automate

Company

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.