Primer chatbot con Dialogflow y Nodejs
Primer chatbot con Dialogflow y Nodejs
Después de estar unos días trasteando con Dialogflow y con Nodejs, he creado un pequeño chatbot que te dice la temperatura de cualquier lugar del mundo.
El ejemplo es muy sencillo pero muestra la gran potencia que tiene Dialogflow.
Comenzaremos creando un Agente, que para este ejemplo he usado el nombre de Curso01.
En este ejemplo usaremos para el nombre del Agente Curso01, pero podemos usar cualquier nombre.
Para el idioma y la zona horaria, usaremos la que nos corresponda. Finalmente para el proyecto Google, podemos crear uno nuevo (recomendado) o usar un proyecto existente.
A continuación crearemos un Intent, que llamaremos para esta prueba El tiempo
Ahora toca el momento de empezar añadir las frases para entrenar a nuestro agente.
En mi caso estoy haciendo una prueba de una aplicación para saber el tiempo de cualquier punto geográfico, así que usare diferentes formas de preguntar el tiempo.
Como en este ejemplo solo quiero que me diga la temperatura del día actual, únicamente usare como parámetro el nombre de la ubicación.
Dentro de acciones y parámetros nos vamos a centrar en 3 partes. La primera es parameter name, ese valor es el que nos interesa para este ejemplo ya que sera el que se
enviara en el JSON a nuestro fichero en el servidor. Entity es una herramienta potente que se utiliza para extraer los valores de los parámetros de entrada.
En la frase «¿Que temperatura hace en Madrid?, Madrid es nuestro parámetro y en este ejemplo uso del tipo any aunque lo correcto debería ser city, geo-city, etc..
Para finalizar el Value, aunque en este ejemplo no lo vamos a usar, este valor lo usamos dentro de response para personalizar la respuesta.
A continuación un ejemplo de como sería el flujo:
- Pregunta: ¿Que tiempo hace en Londres?
- Respuesta: En $any (Londres) hace una temperatura de…. (Aquí añadimos las diferentes respuesta que necesitemos para conseguir una apariencia lo mas humana posible)
Como decía antes, en este ejemplo no vamos hacer uso de responses desde Dialogflow, usaremos nuestro script externo (webhook).
Para poder gestionar desde fuera de dialogflow una respuesta es necesario añadir un webhook y activar en la parte de fulfillment el uso de webhook para este intent.
Integrando nuestro bot
Yo voy a usar Slack por comodidad
Accedemos a la parte de integración
Configuramos Slack para hacer la integración del bot
Ahora un video de como funciona el bot en Slack:
En el video uso varias localizaciones validas e invalidas para comprobar el comportamiento del bot.
Usando nuestro servicio externo
Ahora vamos a la parte de Fulfillment
En el campo URL añadiremos la url donde esta nuestro servicio que usara el JSON que envía dialogflow y que para este ejemplo sera el único campo que usemos.
Ahora el flujo de dialogflow:
- Añadimos una frase de prueba para comprobar que respuesta nos da dialogflow
- Nos muestra la frase que hemos usado
- Aparece la respuesta (en este caso de un servicio externo). Si usamos el propio dialogflow nos respondería con el texto ubicado en response
- El intent que esta usando
- El parámetro y el valor del parámetro (definido en la parte de parámetros y acciones)
- Mostrar el json que genera dialogflow
- Contenido del json
Hasta este punto todo lo que hemos hecho ha sido con dialogflow, ahora toca crear el código que gestionara esos datos y que en la parte de Fulfillment definimos.
Creando nuestro servicio con Node
Aunque la finalidad de este articulo es tener una idea básica de Dialogflow, voy a explicar de forma sencilla como montar una pequeña API REST con Node para poder ver el comportamiento de dialogflow con un servicio externo.
Para el servicio externo podemos usar cualquier lenguaje de lado del servidor (Node, PHP, Java, etc…).
Lo primero que necesitamos es instalar Node y npm.
Una vez instalado podemos comprobar si funciona usando los siguientes comandos, node -v para ver la versión de node y npm -v para comprobar la versión de npm.
Creamos la carpeta donde vamos a crear el script y ejecutamos el siguiente comando: npm init -y, con este comando estamos generando el fichero package.json con los valores por defecto.
El fichero package.json es un fichero que contiene la configuración del proyecto en Node
Para este ejemplo necesitamos los siguiente paquetes y que instalaremos de la siguiente forma
- npm i -D express
- npm i -D body-parser
- npm i -D request
- npm i -D google-translate-api
Comenzamos con el código del servicio en Node:
servicio.js
'use strict'; // Libreria express para crear un api rest const express = require("express"); const bodyParser = require("body-parser"); // Para hacer peticiones http de forma simple const request = require('request'); // Para usar express dentro de Node const app = express(); // Definimos el puerto const port = process.env.PORT || 8899; // Traducción en tiempo real const translate = require('google-translate-api'); // Middleware de análisis del cuerpo de Node.js app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // Métodos de ruta (VERBOS HTTP: POST, GET, PUT, DELETE, etc...). Endpoint app.post("/api/tiempo", (req, res) => { // JSON QUE ENVIA DIALOGFLOW let ubicacion = req.body.result.parameters["any"]; // Valor de kelvin para hacer la transformación a centígrados let kelvin = 273.15; // URL del API para la consulta de la temperatura por la posición geográfica let url = `http://api.openweathermap.org/data/2.5/forecast?q=${ubicacion}&APPID=apikey`; // Realizamos la petición request(url, function(error, response, body) { // Convertimos a JSON, la respuesta del servicio let _body = JSON.parse(body); // Que no de error el servicio externo if (_body.cod === '200') { // Pequeñas conversiones let meses = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]; let mesTxt = meses[parseInt(_body.list[0].dt_txt.split(" ")[0].split("-")[1]) - 1]; let fecha = `${_body.list[0].dt_txt.split(" ")[0].split("-")[2]} de ${mesTxt} de ${_body.list[0].dt_txt.split(" ")[0].split("-")[0]}`; let temperatura = _body.list[0].main.temp - kelvin; // Formamos la respuesta que enviaremos a Dialogflow let _response = new Object(); // DEFAULT RESPONSE EN DIALOGFLOW _response.speech = `La temperatura prevista para el día ${fecha} (${_body.list[0].dt_txt.split(" ")[1]}) en ${_body.city.name} es de ${temperatura.toFixed(1)} grados `; _response.displayText = _response.speech; _response.source = "webhook"; // Enviamos la respuesta res.status(_body.cod).send(_response); } else { // ERROR!!! translate(_body.message, { to: 'es' }).then(resTra) => { let _response = new Object(); _response.speech = resTra.text; _response.displayText = resTra.text; _response.source = "webhook"; res.status(200).send(_response); }).catch(err) => { console.error(err); }); } }); }); // Escuchando nuestro servidor Node app.listen(port, () => { console.log(`API REST en el puerto: http://localhost:${port}`); });
Cuando este creado el fichero con el código, solo quedaría ejecutar node servicio.js.
En ese momento deberíamos tener en el puerto 8899 nuestro servidor corriendo a la espera de los datos.
Nuestro primer bot funcionando
Para poder ejecutar este ejemplo y que se puede comprobar su funcionamiento, además de la integración con slack voy a crear una integración web para ejecutar directamente desde esta entrada.
Aunque casi todo el trabajo esta hecho en dialogflow, como siempre dejo el enlace a github con el código.
Recordad que para este ejemplo únicamente he usado dos tipos de variaciones para solicitar la temperatura, que tiempo hace…. y que temperatura hace…
Hola Franklin muchas gracias por compartir tus conocimientos, quisiera saber si te puedeo contactar a traves de algun correo, y que me puedas brindar una asesoria, ya que quiero implementar algo muy parecido a este articulo, y logico el costo que tendria la misma,
Muchas gracias
Puedo conectar dialogflow con una base de datos?
Buenas, usando un webhook puedes conectarte a un servicio creado por ejemplo con NodeJs, JAVA, PHP, etc… y desde allí hacer lo que necesites, en tu caso conectarte a una base de datos y almacenar la información que necesite o quieras.