Construir un Chatbot con Twilio Studio e IBM Tone Analyzer en WhatsApp

March 07, 2021
Redactado por

Twilio Studio, Watson, Sentiment Analysis

En este último año debido al Covid-19 hemos evidenciado que canales de mensajería como WhatsApp han tenido un auge en esta época para múltiples usos , chatbots de servicio al cliente, marketing, ventas y muchos otros; En este blog les vamos a mostrar cómo usando Twilio Studio, podemos armar chatbots en minutos, desplegarlos en WhatsApp y finalmente integrarlos a APIs externas tales como IBM Watson Tone analyzer.

Prerrequisitos

Esta app usa las siguientes herramientas y tecnologías:

Para poder correr correctamente esta app, vas a necesitar tener Node.js y npm instalados. En el momento en que escribo este blog post, tengo Node v.10.16.3 y npm v6.13.7 instalados

Instalar dependencias

Es momento de inicializar la app. Navega al directorio donde deseas iniciar el proyecto( en este caso lo llamaremos webinar_test) y ejecuta el siguiente comando bash:

npm init

Esto generará un archivo package.json que contendrá toda la información sobre el proyecto. Fácilmente puedes saltarte las indicaciones si no estás interesado en personalizar  la información. Ya con esto listo podemos comenzar a instalar las dependencias que se necesitan para la aplicación.

Ahora instala el módulo de node de Twilio (3.x) :

npm install twilio --save

Se necesita de una URL para que Twilio envíe el HTTP request con el mensaje que queremos analizar en la API de IBM. Para esto se debe construir una aplicación del lado del servidor, en este caso haremos uso del framework Web Express para Node, por consiguiente debemos instalar la dependencia de Express:

npm install express --save

Finalmente para hacer uso de la API de IBM  Tone analyzer serán necesarias las librerías de IBM Watson:

npm install ibm-watson

Ya tenemos nuestro proyecto creado localmente con todas las dependencias que necesitamos

IBM Watson

Crea una instancia del servicio de Tone Analyzer y obtén las credenciales:

Ingresa a tu cuenta en IBM Cloud y ve a la página de Tone Analyzer en tu catálogo, selecciona el plan Lite, dale un nombre a tu instancia del servicio, en nuestro caso  se  llamará “Tone Analyzer-Twilio”, y finalmente dale click en Crear.

Imagen creación de servicio de Tone Analyzer en IBM Cloud

Cuando la instancia se crea correctamente, te aparecerá la siguiente pantalla:

 

Imagen configuración de credenciales servicio de Tone Analyzer

Dirígete a la pestaña de credenciales de servicio y copia los campos APIKEY  y URL, esta información la necesitarás más adelante para autenticación y uso de la API

Imagen de credenciales servicio de Tone Analyzer

La API de Tone analyzer tiene dos Endpoints, el de propósito general /v3/tone y el de  de customer engagement /v3/tone_chat. Para propósitos de este blog vamos a usar el primer endpoint.

Para solicitar un análisis de sentimientos a través de la API de IBM es posible enviar el contenido que se quiere analizar ya sea en formato JSON, texto plano o HTML y va a recibir como parámetros los siguientes:

https://cloud.ibm.com/docs/tone-analyzer?topic=tone-analyzer-utgpe

Uno de los parámetros es Content-Language el cual  define el idioma del texto de entrada a analizar, según la documentación este solo soporta actualmente Inglés(en) y Francés(fr), es por esto que debemos traducir el texto de entrada de Espanol a Inglés antes de enviar el texto a la API de tone analyzer.

Para lo anterior usaremos la API de IBM “Language translator”,para agregar este servicio a la cuenta de IBM Cloud debes buscar en el catálogo “Language Translator”.

Imagen creación de servicio Language Translator en IBM Cloud

De forma similar a la API de tone analyzer, selecciona  el plan lite y crea una instancia del servicio en este caso  lo llamamos “Language Translator- Twilio”.

Después de crear exitosamente el servicio debe aparecerte la siguiente pantalla:

Imagen credenciales servicio Language Translator IBM Cloud

Ve a la opción de Gestionar y copia la clave de API(APIKEY) y la URL de este servicio.

Si vas al menú inicial de IBM Cloud y listas todos los servicios, deberías ver los dos servicios que acabamos de crear y deberían estar en estado activo.

Imagen instancias de servicios IBM Cloud corriendo

Crea un archivo en el directorio que se creó anteriormente y nombrarlo config.js, luego pega el siguiente código

 // config.js
module.exports = {
 URL_TONE: 'https://************',
 APIKEY_TONE: '*****************',
 URL_TRANSLATE: 'https://*******',
 APIKEY_TRANSLATE: '************',
 PORT:  3000
}

Cambiar las APIKEYs y URLs que acabamos de copiar de IBM Cloud, tanto para la API de tone analyzer como la de language translator.

Este archivo tiene otra variable que se llama PORT, este será el puerto por el cual subiremos nuestro web server por defecto esta en 3000.

Crear Web Server con Express

Luego de crear el config.js el cual contiene las variables de entorno,crea un archivo llamado index.js y vas a copiar el siguiente código

const config = require('./config.js');
const express= require('express');
const app=express();
const ToneAnalyzerV3 = require('ibm-watson/tone-analyzer/v3');
const LanguageTranslatorV3 = require('ibm-watson/language-translator/v3');
const { IamAuthenticator } = require('ibm-watson/auth');
app.use(express.json());
app.use(express.urlencoded());

app.get('/sentiment',(req,res) => {

   console.log(req.query.message);

   const languageTranslator = new LanguageTranslatorV3({
       version: '2018-05-01',
       authenticator: new IamAuthenticator({
         apikey: config.APIKEY_TRANSLATE,
       }),
       serviceUrl: config.URL_TRANSLATE,
     });
    
   const translateParams = {
       text: req.query.message,
       modelId: 'es-en',
     };

   const toneAnalyzer = new ToneAnalyzerV3({
       version: '2017-09-21',
       authenticator: new IamAuthenticator({
         apikey: config.APIKEY_TONE,
       }),
       url: config.URL_TONE,
     });

   languageTranslator.translate(translateParams)
     .then(translationResult => {
       console.log(JSON.stringify(translationResult.result.translations[0].translation, null, 2));
       const toneParams = {
           toneInput: { 'text': translationResult.result.translations[0].translation },
           contentType: 'application/json',
           acceptLanguage:'es',
         };
         toneAnalyzer.tone(toneParams)
           .then(toneAnalysis => {
           console.log(JSON.stringify(toneAnalysis, null, 2)); 
           console.log({"sentiment":toneAnalysis.result.document_tone.tones[0].tone_id });
           res.send(toneAnalysis.result.document_tone.tones[0].tone_id );
           })
           .catch(err => {
           console.log('error:', err);
           });
     })
     .catch(err => {
       console.log('error:', err);
     });


 });

app.listen(config.PORT,()=> console.log(`listening on port ${config.PORT}`));

Es momento de correr nuestro web Server, dirígete al terminal y luego al directorio creado anteriormente y ejecuta el siguiente comando node index.js

Node Index.js run on command line

Si el código se ejecuta bien debemos ver algo parecido a la imagen anterior, donde el terminal nos arroja el mensaje de “listening on port 3000” el puerto que definimos anteriormente.

Entendiendo el Código

Este webserver va a recibir el siguiente json:

{"mensaje": *mensaje de whatsapp del usuario"}

Y lo que va a hacer primero es pasar este mensaje a la API de language translator para traducir al idioma inglés y finalmente va a pasar este texto traducido como entrada a la API de tone analyzer para detectar el tono y/o sentimiento del texto. Aquí es importante recalcar que el código de desarrollo es solo para pruebas y demo, por lo que recomendamos que lo modifiquen o mejoren para temas productivos.

La respuesta completa de la API de tone analyzer es parecida a este ejemplo:

{
  "document_tone": {
    "tones": [
      {
        "score": 0.6165,
        "tone_id": "sadness",
        "tone_name": "Sadness"
      },
      {
        "score": 0.829888,
        "tone_id": "analytical",
        "tone_name": "Analytical"
      }
    ]
  },
  "sentences_tone": [
    {
      "sentence_id": 0,
      "text": "Team, I know that times are tough!",
      "tones": [
        {
          "score": 0.801827,
          "tone_id": "analytical",
          "tone_name": "Analytical"
        }
      ]
    },
    {
      "sentence_id": 1,
      "text": "Product sales have been disappointing for the past three quarters.",
      "tones": [
        {
          "score": 0.771241,
          "tone_id": "sadness",
          "tone_name": "Sadness"
        },
        {
          "score": 0.687768,
          "tone_id": "analytical",
          "tone_name": "Analytical"
        }
      ]
    },
    {
      "sentence_id": 2,
      "text": "We have a competitive product, but we need to do a better job of selling it!",
      "tones": [
        {
          "score": 0.506763,
          "tone_id": "analytical",
          "tone_name": "Analytical"
        }
      ]
    }
  ]
}

Esta respuesta es en formato JSON, donde IBM retorna inicialmente el análisis de tono del documento(toda la entrada de texto) y un análisis más específico por cada frase, para cada uno de estos análisis IBM devuelve un array de objetos ToneScore, donde cada objeto tiene un score(probabilidad de que ese tono se perciba en el contenido), tone_id (El identificador único y no localizado del tono) y tone_name (El nombre visible del tono).

El tone_id puede tener los siguientes valores(dependiendo de la versión de la API, en nuestro caso 2017-09-21); angerfearjoy y sadness (tonos emocionales); analyticalconfident, y tentative (tonos de lenguaje). Es importante aclarar que el servicio solo retorna los tonos que tienen un score que cumple con el threshold mínimo de 0.5. Por último, si se quiere la respuesta de la API de IBM tone analyzer en español se debe agregar como parámetro en el request de la API acceptLanguage:’es’.

Por temas de facilidad del demo, lo que hacemos en el código del index.js es coger el primer tono detectado en el array, sin embargo, esta no es una solución escalable y hay que hacer un análisis más exhaustivo de cómo aprovechar y usar la respuesta de la API de IBM tone analyzer para casos de uso más complejos. Para ver más información sobre la API aquí hay más documentación.

Usando Ngrok

Para que Twilio pueda alcanzar tu aplicación para enviar el mensaje de whatsapp debemos exponer nuestro server al internet, esto podemos hacerlo usando ngrok. Aquí hay un gran tutorial sobre como empezar con ngrok. Una vez ya tengas instalado ngrok, haz que escuche a través del puerto de tu server en este caso el puerto 3000 que fue el que definimos en el archivo config.js:

ngrok http 3000

Deberías ver una pantalla que luzca como esta, esta te generara un link que Twilio puede visitar para acceder a tu app de Express, copia la url https:

Imagen URL ngrok

Usando tu nueva URL de ngrok asegurate que configures el webhook en el flujo de Twilio Studio apuntando a la ruta “/sentiment”(ver sección siguiente) . Twilio studio va a hacer un HTTP request a “/sentiment” cuando la conversación a través de WhatsApp pase por ese flujo.

Crear flujo en Twilio Studio  

Twilio Studio es una herramienta poderosa de código mínimo que incluye una interfaz de arrastrar y soltar que se utiliza para crear IVR en varios canales, que incluye Voice, SMS y WhatsApp. Hoy vamos a utilizar Studio para construir nuestro chatbot.

En la consola Twilio, navegue hasta la página de la consola de Studio. Seleccione el botón “Create new Flow”.

Create a new flow in twilio

Dale a tu flujo un nombre descriptivo y selecciona la opción de plantilla "Import from JSON".

Imagen creación de flujo en Twilio Studio

Luego, copie y pegue el JSON en el editor de texto y seleccione el botón “Next”.

¡Felicidades! Ahora tienes tu primer Studio Flow, el cual usarás como un bot sencillo para integrar con la aplicación de IBM Watson. Primero, tienes que hacer algunos cambios pequeños para asociar el flujo con el backend de la aplicación.

Imagen flujo de Twilio Studio

Primero, seleccione el widget "postMessageBody_webhook" y actualice el parámetro REQUEST URL. Reemplace suURLdengrock con la URL que creaste anteriormente en ngrok, luego seleccione el widget de Trigger y copie la URL que está en el campo de WEBHOOK URL. Recuerda en agregar la ruta de /sentiment al final de la URL de ngrok

Imagen configuración flujo de Twilio Studio

Conectar el flujo con WhatsApp Sandbox

Pegue la URL que copió anteriormente del flujo en la consola de Twilio Sandbox for WhatsApp donde dice “WHEN A MESSAGE COMES IN.”

Imagen configuración Sandbox de WhatsApp

Envíe la frase completa que empieza con la palabra “join” al número +1 415 523 8886 en WhatsApp para empezar a mandar y recibir mensajes de WhatsApp. Puedes leer más información sobre el Sandbox y cómo usar el API de WhatsApp en general aquí.

Imagen conexión a Sandbox de WhatsApp

Después de recibir el mensaje de “You are all set!” significa que ya estás conectado al Sandbox de WhatsApp.

Si deseas adquirir un número para tu aplicación productiva debes solicitarlo aca.

Prueba de la aplicación

Ahora es el momento de probar la aplicación. Envía tu nombre al número de WhatsApp Twilio Sandbox para comenzar tu flujo. Deberías recibir un segundo mensaje solicitando tu opinión sobre el pedido. Responde con un mensaje positivo o negativo para recibir diferentes respuestas de tu aplicación.

imagen chat whatsapp prueba sentimiento positivo

imagen prueba whatsapp sentimiento negativo

¿Qué sigue?

¡Sigue construyendo! Puedes modificar fácilmente tu Studio Flow existente para tener opciones más complejas. Puedes optar por conectar a un usuario final con un agente si tiene una mala experiencia, por ejemplo.

Recursos adicionales

Eliana Corradine es Solutions Engineer para Twilio en America latina. Con desarrollo, soporte y experiencia del cliente, ha ayudado a los clientes a crear y construir cosas increíbles para su negocio utilizando la plataforma de Twilio. Anteriormente trabajó en IBM Colombia, en el área de soporte de Software donde aprendió algunas cosas de IBM Watson

Lillian Wakefield comenzó su carrera en consultoría de química ambiental antes de hacer la transición a educación. Más recientemente, comenzó su propio negocio como educadora privada. Cómo Solutions Engineer en Twilio, ahora se enfoca en cómo las comunicaciones basadas en la nube pueden ayudar a empresas a desarrollar mejores relaciones con sus clientes.