Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the acf domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/planetac/desa.planetachatbot.com/wp-includes/functions.php on line 6170

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the all-in-one-seo-pack domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/planetac/desa.planetachatbot.com/wp-includes/functions.php on line 6170

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the wp-user-avatar domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/planetac/desa.planetachatbot.com/wp-includes/functions.php on line 6170

Warning: Cannot modify header information - headers already sent by (output started at /home/planetac/desa.planetachatbot.com/wp-includes/functions.php:6170) in /home/planetac/desa.planetachatbot.com/wp-content/plugins/all-in-one-seo-pack/app/Common/Meta/Robots.php on line 87

Warning: Cannot modify header information - headers already sent by (output started at /home/planetac/desa.planetachatbot.com/wp-includes/functions.php:6170) in /home/planetac/desa.planetachatbot.com/wp-includes/feed-rss2.php on line 8
Jesús Seijas de la Fuente - Planeta Chatbot https://desa.planetachatbot.com Comunidad de expertos en IA Conversacional Mon, 06 Jun 2022 13:22:02 +0000 es hourly 1 https://wordpress.org/?v=7.0.2 https://desa.planetachatbot.com/wp-content/uploads/2021/05/cropped-favicon-32x32.png Jesús Seijas de la Fuente - Planeta Chatbot https://desa.planetachatbot.com 32 32 Empezando con NLP.js https://desa.planetachatbot.com/empezando-con-nlp-js/?utm_source=rss&utm_medium=rss&utm_campaign=empezando-con-nlp-js https://desa.planetachatbot.com/empezando-con-nlp-js/#respond Fri, 23 Oct 2020 09:00:48 +0000 https://desa.planetachatbot.com/?p=295 ¿Alguna vez has querido desarrollar un chatbot y te has encontrado con stopper en el camino relacionados con la privacidad de los datos o los idiomas compatibles? ¿Deseas reducir el tiempo de respuesta del chatbot o ejecutarlos sin tener activa una conexión? Si ese es el caso, o si simplemente por curiosidad y deseas obtener […]

The post Empezando con NLP.js first appeared on Planeta Chatbot.

]]>
¿Alguna vez has querido desarrollar un chatbot y te has encontrado con stopper en el camino relacionados con la privacidad de los datos o los idiomas compatibles? ¿Deseas reducir el tiempo de respuesta del chatbot o ejecutarlos sin tener activa una conexión?

Si ese es el caso, o si simplemente por curiosidad y deseas obtener más información, dale una oportunidad a NLP.js

Procesamiento de lenguaje natural y NLP.js

El procesamiento del lenguaje natural o PLN (en inglés Natural Language Processing o NLP) es un campo que combina la lingüística y la informática, así como la inteligencia artificial. Comprender correctamente el lenguaje natural es fundamental para los asistentes virtuales, chatbots, asistentes de voz y una amplia gama de aplicaciones basadas en una interfaz de voz o texto con una máquina. Estas aplicaciones generalmente incluyen un procesador de lenguaje natural cuyo propósito es extraer las interacciones y la intención (intent), así como la información y los metadatos relacionados, de un fragmento de lenguaje natural simple y traducirlos a algo que una máquina pueda procesar.

NLP.js es un conjunto de más de 70 librerías de código abierto, que se utiliza para abordar y resolver las tres áreas principales del NLP: comprensión del lenguaje natural, generación del lenguaje y reconocimiento de entidades. La característica clave que proporciona NLP.js es una experiencia de usuario mejorada gracias a tener buen tiempo de respuesta, soporte de diversos idiomas y, según algunos puntos de referencia, precisión mejorada a la vez que permite una mayor privacidad de datos y seguridad, al no estar enviando datos a terceros.

¿Por qué tener una librería de NLP?

No es fácil entender cómo los NLP existentes procesan cada frase, como funcionan internamente y cómo toman las decisiones. Este efecto de caja negra, debido a la falta de visibilidad de por qué el chatbot ha respondido de una manera específica sin poder profundizar en el origen del problema, causa frustración a los administradores del chatbot. Tener el NLP como una biblioteca de código abierto proporciona más visibilidad y comprensión del procesamiento del lenguaje natural a bajo nivel. Permite a los técnicos comprender mejor el procesamiento de la conversación para administrar estrategias específicas del idioma para lograr el nivel de precisión esperado. Incluso si tener una estrategia específica por país no es un enfoque obligatorio, es muy recomendable cuando se dirige a los chatbots de alto rendimiento en idiomas distintos a los más utilizados.

Las principales características de NLP.js

1. Soporte de idiomas

NLP.js admite hasta 104 idiomas diferentes con el uso de BERT embeddingsSin BERT, admite de forma nativa 41 idiomas.

2. Stemmers

NLP.js implementa stemmers para mejorar la precisión y requerir menos expresiones de entrenamiento para lograr el mismo resultado. Reduce drásticamente el trabajo manual y la potencia de computación necesarias para entrenar el NLP.

Los stemmers son algoritmos que se utilizan para calcular el “stem” (raíz) de las palabras. Por ejemplo, palabras como “desarrollado”, “desarrollador”, “desarrollando”, “desarrollo” y “desarrolladores”, se clasifican con la misma raíz: “desarroll”. Esto es importante porque cuando preparamos frases para ser entrenadas o clasificadas por un NLP, generalmente tendemos a dividir esas oraciones en características. Algunos NLP usan un tokenizador para dividirlos en palabras, pero el problema con este enfoque es que es probable que debas entrenar al NLP con más frases para incluir las diferentes inflexiones del idioma.

Consideremos por ejemplo que entrenamos al NLP con la frase “¿quién es tu desarrollador?” con la palabra ‘developer’ como la intención, y luego, alguien hace la pregunta: “¿quién te ha desarrollado?”. Sin un stemmer, las palabras “desarrollador” y “desarrollado” no se reconocerían como similares, ya que no se identifican con el mismo token. Este problema es más pronunciado en idiomas con muchas inflexiones como el español o el indonesio, donde la misma palabra puede declinarse para indicar el género o, en el caso de los verbos, el tiempo verbal, la persona, el número…

3. Preguntas abiertas

Como resultado de la integración con BERT, se pueden tener preguntas abiertas sobre textos usando NLP.js. Esto significa que en lugar de entrenar la NLP con oraciones e intenciones, sólo tienes que proporcionar un texto a BERT y luego puedes hacer cualquier pregunta sobre el texto. La integración de NLP.js con BERT hace posible tener una clasificación sin supervisión en la que no es necesario proporcionar las intenciones.

A continuación, puedes ver un ejemplo en el que el texto proporcionado al chatbot es información sobre Harry Potter, con algunas preguntas abiertas posteriormente formuladas sobre el texto:

4. Extracción de entidades

El sistema NLP.js permite la extracción de entidades en varios niveles. Incluye una extracción de entidades enumeradas optimizada que puede buscar y comparar millones de posibilidades en milisegundos.

Además, tiene extracción de entidades doradas (golden entities o builtin entities) para identificar números, correos electrónicos, números de teléfono, medidas, URLs, moneda, etc. Cuando hablamos de identificar un número, puede ser bastante simple cuando la cifra está escrita en dígitos numéricos como ‘ 541 ‘, pero no es tan obvio entender que ‘quinientos cuarenta y uno’ corresponde al mismo número. La extracción de este tipo de entidades más complejas y diferentes en cada idioma es posible para un máximo de 44 idiomas en NLP.js .

NLP.js ayuda a optimizar la experiencia del usuario

La privacidad de los datos, la seguridad y el tiempo de respuesta son pilares clave para mejorar la experiencia del usuario y el sistema de conversacional en general.

Privacidad de datos

La mayoría de los líderes del mercado de NLP son soluciones basadas en la nube, lo que significa que todos los datos se procesan en la nube y, en algunos casos, se administran fuera de la plataforma del cliente. En principio, el procesamiento de datos en la nube no es un gran problema cuando se busca satisfacer las necesidades y requisitos de privacidad de datos de la mayoría de los países. Sin embargo, todavía puede ser un éxito en ciertas regiones, como Alemania, Singapur o Turquía …

Seguridad

La idea de convertir la NLP en una biblioteca permite que la solución general se pueda implementar completamente on-premise si es necesario. Además, NLP.js puede ejecutarse directamente en un smartphone sin necesidad de una conexión de datos. Con las tendencias actuales de globalización y haciendo que todo esté cada vez más conectado, es importante mantener la puerta abierta a soluciones totalmente on-premise para mantener el control sobre los datos.

Tiempo de respuesta

Al eliminar la necesidad de conectividad en la nube, se observa una mejora significativa en términos de latencia y rendimiento, aunque toda llamada a una API tiene una latencia inherente. Esta latencia se puede evitar aún más al incluir NLP.js como una biblioteca incorporada al propio chatbot. Este rendimiento mucho más rápido y esa baja latencia marcan una diferencie frente a otras soluciones del mercado.

Cómo ejecutar NLP.js localmente (ejemplo)

Primero, necesitarás tener Node.js instalado en tu ordenador. Si no lo tienes, puedes descargarlo aquí.

A continuación, crea una carpeta para tu proyecto, inicia un nuevo proyecto de nodo e instala estas dependencias NLP.js: basicexpress-api-serverdirectline-connectorBasic instala los paquetes necesarios para ejecutar NLP.js, express-api-server proporciona un servidor API que utiliza express y la interfaz para el chatbot, y directline-connector proporciona una API para el chatbot como la de Microsoft Directline.

mkdir chatbot
cd chatbot
npm init
npm i @nlpjs/basic @nlpjs/express-api-server @nlpjs/directline-connector

Ahora necesitarás un Corpus, que son los datos de conocimiento para tu chatbot, organizados en intents, y para cada intent, las oraciones a entrenar, así como las respuestas. Puedes acceder a un ejemplo de corpus en inglés aquí. Descárgalo y ponlo dentro de la carpeta donde tienes tu proyecto.

curl -O https://raw.githubusercontent.com/axa-group/nlp.js/master/examples/03-qna-pipelines/corpus.json

Crea un archivo llamado conf.json , este es el archivo de configuración que le dice a NLP.js qué complementos debe incluir y la configuración de cada complemento. Coloca la siguiente información en el archivo conf.json para ejecutar este ejemplo:

{
 "settings": {
 "nlp": {
 "corpora": ["./corpus.json"]
 },
 "api-server": {
 "port": 3000,
 "serveBot": true
 }
 },
 "use": ["Basic", "ExpressApiServer", "DirectlineConnector"]
}

La sección llamada use le indica qué complementos debe incluir y la sección settings es la configuración de cada complemento. En este caso, le estamos diciendo al NLP que cargue la corpora, que consisten en el archivo corpus.json que hemos descargado antes. También le estamos diciendo al servidor API que se inicie en el puerto 3000 y lo configuramos serveBot como verdadero, ya que queremos que el frontend del bot funcione automáticamente.

Ahora que tenemos la configuración, creemos un archivo index.js con el código para que se ejecute:

const { dockStart } = require("@nlpjs/basic");(async () => {
 const dock = await dockStart();
 const nlp = dock.get('nlp');
 await nlp.train();
})();

Y eso es todo lo que necesitamos. Ahora podemos iniciar la aplicación.

Con const dock = await dockStart()le estamos diciendo a NLP.js que se inicialice, cargue el archivo conf.json, cargue los complementos asociados definidos y los instancie con la configuración definida. Devuelve una instancia del objeto dock que es un contenedor con todos los complementos cargados. En la parteconst nlp = dock.get('nlp')es donde recuperamos la instancia del NLP desde este contenedor. Esta instancia de NLP ya contiene el corpus que hemos definido en la configuración, pero aún no está entrenado, así que tenemos que entrenarlo, y eso es lo que hace la líneaawait nlp.train().

Y eso es todo lo que necesitamos. Ahora podemos iniciar la aplicación:

node .

Ya puedes abrir http://localhost: 3000 en el navegador para ver el webchat y hablar con el chatbot.

Demo online

Si lo prefieres puedes probar la versión online, que está desplegada en Glitch , lo que significa que podrás ejecutar la demo, así como hacer tus propias modificaciones en el código y jugar con él.

Para obtener más información, puedes acceder al tutorial completo y a algunos fragmentos de códigos adicionales .

El valor del código abierto

Según Tom Preston-Werner, cofundador de GitHub : “A las personas inteligentes les gusta pasar el rato con otras personas inteligentes. A los desarrolladores inteligentes les gusta pasar el rato con código inteligente. Cuando abres código útil, atraes talento”.

En nuestra ambición de convertirnos en una empresa tech-led, compartir proyectos y bibliotecas de código abierto relevantes es un método excelente para mostrar nuestra tecnología al mundo, extender nuestra colaboración más allá de los muros de nuestra empresa y ampliar nuestras formas de conectarnos con el talento.

NLP.js es el candidato perfecto para el programa de código abierto de AXA. No contiene nada específico del negocio principal de AXA, es lo suficientemente genérico, fácil de reutilizar y creemos que brinda una oportunidad perfecta para participar y contribuir a la comunidad de código abierto.

Entre otros usos y publicaciones, ya se ha utilizado en la Universidad de Goettingen y se presentó en la conferencia Colombia 4.0 AI en 2019.

Si deseas obtener más información sobre el programa y la tecnología de código abierto de AXA, puedes escribir a: opensource@axa.com

The post Empezando con NLP.js first appeared on Planeta Chatbot.

]]>
https://desa.planetachatbot.com/empezando-con-nlp-js/feed/ 0
Benchmark de IAs Conversacionales https://desa.planetachatbot.com/benchmark-de-ias-conversacionales/?utm_source=rss&utm_medium=rss&utm_campaign=benchmark-de-ias-conversacionales https://desa.planetachatbot.com/benchmark-de-ias-conversacionales/#respond Sat, 27 Jul 2019 09:00:59 +0000 https://desa.planetachatbot.com/?p=311 Introducción A la hora de hacer un bot una de las decisiones más importantes es qué inteligencia artificial conversacional utilizar, y para ello hay que evaluar cómo se comportan. Para ello, actualmente, uno de los papers más relevantes es el SIGDIAL22 que propone 3 corpus (conjuntos de datos) para probarlas. El problema con esto es que la […]

The post Benchmark de IAs Conversacionales first appeared on Planeta Chatbot.

]]>
Introducción

A la hora de hacer un bot una de las decisiones más importantes es qué inteligencia artificial conversacional utilizar, y para ello hay que evaluar cómo se comportan. Para ello, actualmente, uno de los papers más relevantes es el SIGDIAL22 que propone 3 corpus (conjuntos de datos) para probarlas. El problema con esto es que la cantidad de datos utilizados para el estudio distan mucho de un caso real. Una descripción de los tres corpus:

  • Chatbot: Entrenamiento con 100 frases clasificadas en 2 intents
  • Ask Ubuntu: Entrenamiento con 53 frases clasificadas en 5 intents
  • Web Applications: Entrenamiento con 30 frases clasificadas en 8 intents

Pero, ¿cómo se comportan ante una situación real?

En nuestro caso hemos evaluado diferentes inteligencias artificiales conversacionales con un chatbot real en el que se entrena con 854 frases (en inglés) clasificadas en 126 intents (127 si contamos el “None” que significa que la frase no se corresponde con ninguno con los intents de entrenamiento), y además un juego de tests de 82 frases reales dichas por usuarios y en las que ninguna está presente en el juego de datos utilizado para entrenar.

Sistemas evaluados

Estos son los sistemas evaluados:

De estos sistemas el único Open Source es NLP.js, mientras que los demás son sistemas propietarios.

También se quería evaluar Amazon LEX pero por la limitación a 100 intents por bot los resultados no se pueden comparar con el resto de proveedores.

Resultados del Corpus

La primera prueba realizada tras entrenar con esas 854 frases hacia los 126 intents, es probar cada una de las 854 frases esperando que el intent devuelto por el sistema sea aquel con el que se entrenó. Para cada uno de los sistemas esta es la cantidad de errores usando las frases de entrenamiento:

  • Microsoft LUIS: falla en 20 de las frases
  • Google Dialogflow: falla en 27 de las frases
  • IBM Watson Assistant: falla en 27 de las frases
  • SAP Conversational AI: falla en 10 de las frases
  • NLP.js: falla en 1 de las frases

Resultados de los Tests

El juego de tests son 82 frases que las inteligencias artificiales utilizadas no han visto jamás, y son frases reales de usuarios, y se comprueba cuántas aciertan o fallan cada uno de los proveedores. Esta es la cantidad de errores de cada uno:

  • Microsoft LUIS: falla en 18 de las frases
  • Google Dialogflow: falla en 19 de las frases
  • IBM Watson Assistant: falla en 6 de las frases
  • SAP Conversational AI: falla en 20 de las frases
  • NLP.js: falla en 3 de las frases

Resultados totales

Estos serían entonces los resultados totales para cada uno:

  • Microsoft LUIS: falla en 20 de las frases de entrenamiento y 18 de las frases de test
  • Google Dialogflow: falla en 27 de las frases de entrenamiento y 19 de las frases de test
  • IBM Watson Assistant: falla en 27 de las frases de entrenamiento y 6 de las frases de test
  • SAP Conversational AI: falla en 10 de las frases de entrenamiento y 20 de las frases de test
  • NLP.js: falla en 1 de las frases de entrenamiento y 3 de las frases de test

Conclusiones

Observando la última gráfica podemos observar que SAP Conversational AI es muy buena ajustándose a los datos de entrenamiento pero no tanto generalizando para casos que no ha visto: esto es lo que se denomina “overfitting”, es decir, se ajusta demasiado a los datos de entrenamiento.

Por su parte a Watson Assistant le ocurre lo contrario: es capaz de generalizar muy bien, pero por el contrario no es capaz de acertar bien con los datos de entrenamiento.

Por otro lado tanto Microsoft LUIS como Dialogflow están bastante equilibrados, pero de media son bastante peores que sus competidores.

Como muestran los números, NLP.js, la solución open-source sorprendentemente da mejor respuesta tanto en el set de entrenamiento como en el de pruebas. Analizando estadísticas del repositorio en Github, podemos ver que está recibiendo mucho apoyo de la comunidad y que las últimas actualizaciones mejoran notablemente el rendimiento.

The post Benchmark de IAs Conversacionales first appeared on Planeta Chatbot.

]]>
https://desa.planetachatbot.com/benchmark-de-ias-conversacionales/feed/ 0
Cómo desarrollar tu propio NLP para Chatbots (I) https://desa.planetachatbot.com/como-desarrollar-nlp-para-chatbots/?utm_source=rss&utm_medium=rss&utm_campaign=como-desarrollar-nlp-para-chatbots https://desa.planetachatbot.com/como-desarrollar-nlp-para-chatbots/#respond Tue, 05 Mar 2019 09:00:28 +0000 https://desa.planetachatbot.com/?p=306 TL; DR: En tan solo 23 líneas de código se puede construir, en javascript, un sistema NLP para detectar el intent de una frase utilizando un stemmer de la librería Natural, y la librería brain.js para la red neuronal. Este NLP daría los siguientes resultados comparándolo con otras herramientas comerciales, siguiendo el paper SIGDIAL22 que […]

The post Cómo desarrollar tu propio NLP para Chatbots (I) first appeared on Planeta Chatbot.

]]>
TL; DR:

En tan solo 23 líneas de código se puede construir, en javascript, un sistema NLP para detectar el intent de una frase utilizando un stemmer de la librería Natural, y la librería brain.js para la red neuronal. Este NLP daría los siguientes resultados comparándolo con otras herramientas comerciales, siguiendo el paper SIGDIAL22 que propone utilizar 3 corpus diferentes para medirlo:

El código se puede ver en el sandbox que está al final del artículo.

Introducción

A la hora de desarrollar un chatbot, una de las piezas fundamentales es el NLP (Natural Language Processing), en concreto cómo conseguir entender qué es lo que quiere el usuario de las múltiples acciones que sabe realizar nuestro chatbot.

Esta parte tan fundamental, normalmente se convierte en una “caja negra” servida por un proveedor como pueden ser DialogFlow (Google), Microsoft LUIS o IBM Watson. Sobre estas “cajas negras” hay desconocimiento de lo que sucede dentro o cómo lo hacen, y esto normalmente causa miedo a implementar uno, o a creer que la implementación realizada sea correcta.

La estructura de este artículo es primero ver la teoría, para más tarde ver el ejemplo práctico con código y cómo medirlo.

Técnicas

Cuando hablamos de NLP, estamos hablando de un área enorme de la Inteligencia Artificial, con multitud de técnicas como LSTM, word2vec, PoS (Part Of Speech),…

En nuestro caso lo vamos a hacer con un clasificador multiclase utilizando una red neuronal. Pero vamos paso por paso.

Qué es un clasificador multiclase

Dentro de NLP hay multitud de ramas y técnicas. En nuestro caso lo que queremos implementar es un clasificador multiclase. Pero, ¿qué significa esto?

Un clasificador es, dentro de la inteligencia artificial, aquella que nos sirve para dado un input clasificarlo hacia la clase (o label) que más se identifique con ese input, siendo estas clases algo discreto y finito… es decir, que es algo enumerable, por ejemplo los colores del arco iris. Si fuese contínuo, por ejemplo que la respuesta fuese un número real entre 0 y 1, entonces ya no sería una clasificación sino una regresión.

Cuando nuestro clasificador tiene dos clases se denomina binario, por ejemplo si tuviésemos un clasificador entrenado para diferenciar entre mails que son spam de los que no lo son, sería binario, dado que hay dos clases: “spam” y “no spam”.

Cuando nuestro clasificador tiene varias clases, se denomina multiclase.

Cómo funciona un clasificador multiclase

Hay varias formas de implementarlo, pero vamos a explicar cómo hacerlo con redes neuronales. El concepto fundamental es entender el perceptrón:

Perceptrón

Un perceptrón no es más que dado un vector de inputs, cada uno de los inputs se multiplica por un número real que se denomina “peso”, y cada input tendrá el suyo. Además, hay un concepto llamado “bias”. Cada input se multiplica por su peso y todos ellos se suman y se les suma el bias, y finalmente ese resultado se pasa a una función llamada “activación”. Con lo cual en cada perceptrón la cantidad de variables que la IA debe calcular es igual al número de inputs (los pesos) más uno (el bias).

En un clasificador multiclase tendremos el mismo escenario, pero en lugar de una salida habrá varias, con lo cual serían tantos perceptrones como clases. Con lo cual la cantidad de variables a calcular será (n+1) * c, siendo n el número de inputs y c el número de clases.

Qué son las clases en un NLP

En un NLP el input es la frase que dice el usuario, pero, ¿y las clases? Las clases son lo que se denomina “intents”, es decir, las acciones que sabe llevar a cabo el bot o a las que sabe responder. Supongamos este ejemplo:

Habría dos clases: Saludar y Viajar. A cada una de las frases se les llama “utterance”.

Cómo construir el input de un NLP

En el ejemplo anterior tenemos diversas frases y los intents con los que se relacionan. Ahora ya sabemos las clases, que serán los intents. Pero, ¿cómo calcular nuestro input? Nuestro input de la red neuronal estará compuesto por “features”, es decir diversas características de la frase que podemos cuantificar de una manera numérica. Vamos a por la manera más fácil de verlo, supongamos que nuestras features son las palabras de cada frase:

En este caso tendríamos 13 features diferentes, una por palabra. Cada línea azul representaría un peso hacia la clase “Saludar”, mientras que cada línea verde representaría un peso hacia la clase “Viajar”. ¿Cómo cuantificar en número el input? La primera y más intuitiva de las maneras es: Si la feature (palabra) está presente en la frase entonces vale 1, y si no lo está vale 0. Por ejemplo la frase “Me quiero ir de vacaciones” tendría los siguientes inputs:

Antes de programar: ¿cómo medir?

Antes de empezar a programar, ¿cómo mediremos que nuestro NLP está actuando de manera correcta? ¿que acierta los intents?

Para ello nos vamos a basar en el siguiente paper, SIGDIAL22: http://www.aclweb.org/anthology/W17-5522

Este paper propone, para probar en inglés, la utilización de 3 corpus diferentes: uno del chatbot de transporte de Munich, otro del foro Ask Ubuntu y otro sobre Web Applications. Ejemplos de frases e intents de cada uno:

Chatbot: i want to go marienplatz (FindConnection); when is the next train in muncher freiheit? (DepartureTime)

AskUbuntu: What software can I use to view epub documents? (Software Recommendation); What does my computer do when I click ‘Shut Down’? (Shutdown computer)

WebApplication: Alternative to Facebook (Find Alternative); How do I delete my Facebook account? (Delete Account)

Para poder medir, he creado la librería evaluate-nlp que se usará durante el ejercicio, y que lo que contiene son los corpus antes mencionados así como las métricas ya obtenidas de otros proveedores.

Importante: cada corpus trae frases y sus intents, pero además una variable que nos indica si es para entrenar o no (training). Las frases con las que se prueba la eficacia del NLP no son las mismas que con las que se entrena.

Tokenizer

Lo primero es construir nuestro tokenizer. Lo haremos primero de la manera más simple, que es cortando el string con split utilizando la expresión regular que nos da los whitespaces.

Aquí tenéis el ejemplo usando codesandbox, que nos permitirá ver el código y a la vez hacer una API para probar nuestro progreso. En la API podemos agregar el query param text con el texto que queramos tokenizar, por ejemplo: https://73l4owjvjq.sse.codesandbox.io?text=esto%20es%20una%20prueba

Programando la Red Neuronal

Para programar la red neuronal hemos escogido brain.js, que nos permite hacer clasificadores de una manera bastante fácil, y con buena performance. Pero podría ser reemplazado por tensorflow.js, pero eso haría el código más complejo, aunque se conseguiría el mismo resultado.

Empezaremos con una función sencilla que nos crea la red neuronal:

El cambio con respecto a cómo la crearía por defecto, es que por defecto crea dos capas ocultas, es decir, calcula features derivadas de las primeras, y eso implica identificar clasificaciones más complejas además de necesitar más computación. Por ahora vamos a dejarlo tal y cómo lo hemos dibujado en puntos anteriores: el input conectado al output y calcular los pesos.

Ahora necesitaremos saber cómo entrenar nuestra red neuronal. Aquí lo complejo es cómo es el tipo de input que le gusta a brain.js, que es un array de objetos con este formato:

Así que primero construiremos una función “utteranceToFeatures” que dado un texto (un utterance) nos construye el objeto de features tal y cómo está en el input. El método chain no es más que un método que recibe un input como primer parámetro y varias funciones, y encadena las funciones, así que en este caso esto sería lo mismo que escribir featuresToDict(tokenize(str)):

Para ello construiremos una función “train” que recibe una red neuronal de brain.js para entrenar, los inputs (xs) y los outputs (ys) ordenados, y devolverá la red ya entrenada. Ojo, es un método asíncrono:

Por último, una función “predict” que dada una red neuronal y un input, nos devuelva la predicción:

Así que tendríamos nuestra primera versión del NLP, en la que el código del NLP ocupa tan sólo 13 líneas de código, vamos a probar qué tal funciona:

Si pintamos los resultados en una gráfica, vemos lo siguiente:

Bueno, no está mal para ser una primera iteración, aun está de último en el global pero porque va muy mal todavía en Web Application… pero vemos que para el corpus de Chatbot ya puntúa mejor que Dialogflow, y para el de Ask Ubuntu ya se sitúa en la mitad.

Trim y minúsculas

¿Cuál sería el primer paso para mejorarlo? Bueno, por un lado, a veces al calcular los tokens nos sale uno en blanco, el cual hay que eliminar. Por otro lado, ni siquiera hemos pasado a minúsculas, así que “Developer” no es lo mismo que “developer” para nuestro sistema. Así que implementamos el pasar a minúsculas y el trim, y los añadimos a nuestra cadena de cálculo de las features:

Los nuevos resultados:

Vemos que se ha mejorado en Web Application pero no en Chatbot ni en Ask Ubuntu. El motivo es sencillo: en los dos primeros las frases ya venían en minúsculas. Por otro lado, ¡ya hemos conseguido superar en el global tanto a DialogFlow como a RASA!

Mejorando la Red Neuronal

Lo siguiente que podemos hacer es mejorar la red neuronal. Vamos a hacer tres cambios: para empezar vamos a cambiar la función de activación. Por defecto la función de activación es la sigmoide. Sin embargo para nuestro problema van a funcionar mejor la tangente hiperbólica o la leaky ReLU.

Por otro lado, vamos a cambiar el umbral de error, que por defecto es 0.005, lo vamos a reducir a 0.00005. Por último, el learning rate por defecto es de 0.3, vamos a reducirlo a 0.1.

Los nuevos resultados:

Vemos que empata ya en primera posición en Chatbot, sigue en la mitad de la tabla en Ask Ubuntu, y empieza a posicionarse en el medio en Web Applicaation. El global ya pasa a estar en mitad de la tabla por encima de DialogFlow, RASA y Recast. Pero con una diferencia: ¡todavía no se ha tenido en cuenta el idioma! En ningún momento hemos tenido en cuenta si el idioma es inglés, español, o qué idioma es, y sin embargo ya está en mitad de la tabla.

Aplicando stemmer

Como hemos dicho al final del punto anterior, todavía ni siquiera hemos tenido en cuenta el idioma utilizado. Hay dos métodos principales: el cálculo del lema o de la raíz. El lema significaría calcular la palabra principal de la familia, por ejemplo de “eres” el lema sería “ser”. El problema del cálculo del lema es que requiere tener diccionarios, con el consiguiente espacio en memoria. Por el otro lado, el cálculo de la raíz, se puede hacer aproximado utilizando algoritmos, usualmente que eliminan y cambian posibles terminaciones para calcular así la raíz. No es perfecto, pero es suficientemente bueno.

Esto de usar stemmers no es algo nuevo dentro del mundo de IT, por ejemplo los gestores documentales los utilizan para hacer búsquedas de documentos, en el caso de lucene y solr el código java de estos es Open Source.

En nuestro caso al ser javascript, utilizaremos el PorterStemmer que viene en la librería Natural. Así que usaremos el PorterStemmer para, de cada token que calculamos una vez pasado a minúsculas, sustituirlo por su raíz:

Y los resultados quedarían así:

Como vemos, nuestro método se posicionaría como primero en el corpus de Chatbot empatado con Recast, primero en el corpus Ask Ubuntu, segundo en el corpus de Web Application empatado con LUIS y solamente superado por Watson, y quedaría primero en la puntuación global, en tan solo 23 líneas de código.

The post Cómo desarrollar tu propio NLP para Chatbots (I) first appeared on Planeta Chatbot.

]]>
https://desa.planetachatbot.com/como-desarrollar-nlp-para-chatbots/feed/ 0
Cómo desarrollar tu propio NLP para Chatbots (II): Rompiendo los records https://desa.planetachatbot.com/como-desarrollar-nlp-para-chatbots-rompiendo-los-records/?utm_source=rss&utm_medium=rss&utm_campaign=como-desarrollar-nlp-para-chatbots-rompiendo-los-records https://desa.planetachatbot.com/como-desarrollar-nlp-para-chatbots-rompiendo-los-records/#respond Tue, 05 Mar 2019 09:00:25 +0000 https://desa.planetachatbot.com/?p=308 Viene de Cómo desarrollar tu propio NLP para Chatbots (I). Introducción En el artículo anterior veíamos cómo con poco código se podía llegar a un NLP tan bueno o mejor que los comerciales, basándonos en el paper SIGDIAL22, que evalúa con tres corpus muy diferentes entre ellos. Sin embargo, ¿por qué quedarse ahí y no […]

The post Cómo desarrollar tu propio NLP para Chatbots (II): Rompiendo los records first appeared on Planeta Chatbot.

]]>
Viene de Cómo desarrollar tu propio NLP para Chatbots (I).

Introducción

En el artículo anterior veíamos cómo con poco código se podía llegar a un NLP tan bueno o mejor que los comerciales, basándonos en el paper SIGDIAL22, que evalúa con tres corpus muy diferentes entre ellos. Sin embargo, ¿por qué quedarse ahí y no seguir mejorándolo hasta que sea mejor en los tres corpus y en el global y rompa todos los records?

Sustitución de Entidades

Ahora mismo para las puntuaciones el resto de NLP cuentan con una ventaja que no se ha aplicado en el nuestro: se han entrenado teniendo en cuenta las entidades. Vamos a ver un ejemplo:

Esta es una de las frases de entrenamiento, podemos ver que tiene una sección en la que le dice qué palabra o palabras de la frase son en realidad una entidad. En este caso está diciendo que “TV Tropes” es la entidad “WebService”. Lo que vamos a hacer ahora es que, cuando durante el entrenamiento, vengan entidades, vamos a sustituir el texto que corresponde a la entidad por una etiqueta que represente a la entidad. Para entenderlo, en nuestro ejemplo, esa frase en realidad serían dos frases para el entrenamiento:

Para conseguirlo creamos una función “augment” que reciba una frase y sus entidades y nos devuelva un array de frases.

También tenemos que cambiar el entrenamiento para que tenga en cuenta que en lugar de una frase ahora tendrá un array de ellas que procederán de la función augment:

El sandbox con el código:

https://codesandbox.io/s/vkjzx0pm3?from-embed

 

Y los resultados:

Apreciamos que nuestro método ya ha mejorado mucho en el corpus de Web Application, y pasa a estar primero en todas las categorías, aunque en Chatbot empatado con Recast y en Web Application empatado con IBM Watson. Pero logramos pasar del 0.927 al 0.934 en el global, ¡que es una mejora muy sustancial!

Sinónimos

Ya hemos llegado muy lejos, pero, ¿qué nos puede faltar? Analizando el corpus vemos que hay partes en las que las expresiones y palabras que se están usando para el test, en algunas ocasiones jamás han sido vistas por el entrenamiento, en especial el empleo de sinónimos. Así vemos que se prueba con “remove” cuando en el entrenamiento solamente ha visto “delete”, se prueba con “junk” referido al “spam” que ha visto entrenando y con “transfer” para referirse a “export”.

Si guardamos un diccionario de sinónimos y por qué palabra se quiere sustituir, y al principio de todo a partir de este diccionario generamos un diccionario de sus stems, podemos añadirlo como paso a la hora de generar las features.

Este sería el código de la generación del diccionario:

Y esta sería la nueva pipeline de generación de las features:

Este sería el sandbox con el código:

Y los resultados:

Vemos que despunta en el corpus de Web Application y con ello en el global ¡rompe totalmente los records!

Conclusión

Siguiendo un proceso lógico y usando redes neuronales se puede lograr entender muy bien el lenguaje humano en el entorno de Chatbots. Cabe preguntarse cómo es posible que empresas con grandes inversiones y grandes profesionales detrás, sin embargo sus Inteligencias Artificiales conversacionales no puntúan igual de bien. Mi opinión personal es que esto es por dos motivos:

  • Por una parte no es su objetivo principal, sino que sirve con ser “suficientemente bueno”
  • Por otra parte, cuando utilizas tu propio NLP tú eres tu único cliente, con lo que tienes toda tu memoria y CPU para tu uso, mientras que en una plataforma como Google DialogFlow, IBM Watson o Microsoft LUIS estamos hablando de miles de clientes y a precios muy bajos o incluso gratis, con lo cual el uso de memoria y de CPU debe ser minimizado al máximo para poder dar servicio a todos los clientes.

The post Cómo desarrollar tu propio NLP para Chatbots (II): Rompiendo los records first appeared on Planeta Chatbot.

]]>
https://desa.planetachatbot.com/como-desarrollar-nlp-para-chatbots-rompiendo-los-records/feed/ 0
Evaluando el NLU para chatbots https://desa.planetachatbot.com/evaluando-nlu-para-chatbots/?utm_source=rss&utm_medium=rss&utm_campaign=evaluando-nlu-para-chatbots https://desa.planetachatbot.com/evaluando-nlu-para-chatbots/#respond Thu, 18 Oct 2018 09:00:15 +0000 https://desa.planetachatbot.com/?p=303 Introducción Cuando queremos construir chatbot inteligentes, una de las decisiones más complicadas es que herramienta o plataforma de NLP (Natural Language Processing) utilizar. Y normalmente solemos llegar a una pregunta: ¿usar una comercial? ¿Una open source on premise? ¿Cuáles aciertan mejor? Uno de los criterios para elegir un NLP u otro suele ser cuán bueno es su […]

The post Evaluando el NLU para chatbots first appeared on Planeta Chatbot.

]]>
Introducción

Cuando queremos construir chatbot inteligentes, una de las decisiones más complicadas es que herramienta o plataforma de NLP (Natural Language Processing) utilizar. Y normalmente solemos llegar a una pregunta: ¿usar una comercial? ¿Una open source on premise? ¿Cuáles aciertan mejor?

Uno de los criterios para elegir un NLP u otro suele ser cuán bueno es su NLU (Natural Language Understanding) relacionando las frases que dicen los usuarios con los intents, es decir, cuán buena es su inteligencia.

En este artículo veremos cómo evaluar un NLU, y además los resultados de la evaluación de varios NLP usuales. Además explicaremos cómo construímos un NLU que se comporta bastante bien, realizado usando javascript.

Cómo evaluar un NLU

Cuando se evaluan varios NLUs, se necesita un corpora, es decir, varias colecciones de frases en los que para cada frase sabemos el intent correcto (cada conjunto recibe el nombre de corpus). Además, algunas de las frases estarán marcadas para ser usadas por el entrenamiento, y otras no, y son las que se usarán para evaluar. Esto se hace así para evitar el overfitting, es decir, evitar que la inteligencia esté aprendiéndose lo que le enseñamos tal cual, en lugar de ser capaz de generalizar los conceptos para ser usados en otras frases.

Uno de los mejores papers sobre este tema es SIGDIAL22 Evaluating Natural Language Understanding Services for Conversational Questions Answering Systems, escrito por Daniel Braun, Adrian Hernandez-Mendez, Florian Matthes y Manfred Langen.

El corpora utilizado tanto en el paper como en este artículo puede encontrase aquí: https://github.com/sebischair/NLU-Evaluation-Corpora

Descripción de cada corpus:

  • Chatbot: 206 preguntas de un chatbot de Telegram usado para el transporte público de Munich
  • AskUbuntu: 190 preguntas y respuestas de https://askubuntu.com
  • WebApplications: 100 preguntas y respuestas de https://webapps.stackexchange.com.

Hay que tener en cuenta también una nota de Daniel Braun, coautor del paper:

Sin embargo, estos resultados son solamente para los corpus que hemos probado y los resultados no son generalizables para otros dominios. El objetivo de nuestro documento no es sugerir un servicio específico, sino alentar a las personas a evaluar las alternativas existentes para su caso de uso y mostrarles cómo podría ser esa evaluación.

Systemas evaluados

Hemos evaluado siete sistemas diferentes:

  • LUIS.ai: Solución en la nube perteneciente a Microsoft.
  • Watson Conversation: Solución en la nube perteneciente a IBM.
  • DialogFlow: Solución en la nube perteneciente a Google.
  • Botfuel: Solución en la nube.
  • Recast.ai: Solución en la nube perteneciente a SAP.
  • RASA: solución on-premise, open source, realizada en python.
  • NLP.js: solución on-premise en forma de librería, open source, hecho en javascript, perteneciente a AXA Shared Services Spain

Resultados Finales

Puedes descargarte el excel con toda la información detallada en el siguiente enlace: https://github.com/axa-group/nlp.js/blob/master/docs/NLU_evaluation.xlsx

Estos son los resultados finales en forma de tabla y las correspondientes gráficas globales y por corpus. Si quieres ver la analítica detallada, con datos desgranados sobre los intents por corpus y plataforma, puedes encontrarlos en el excel citado anteriormente.

Resultados finales ordenados por F1-score

Una nota sobre DialogFlow: se puede comprobar que los resultados de DialogFlow no se corresponden con lo que se esperaría. Esto parece ser debido al umbral de 0.5: mientras otros sistemas devuelven todos los intents o el mejor intent y su probabilidad, DialogFlow tiene un umbral de probabilidad que por defecto es 0.5, y cualquier evaluación de una frase que como resultado devuelva una probabilidad por debajo de ese umbral, devuelve un intent llamado Default Fallback Intent. Así que hemos comprobado por separado NLP.js y DialogFlow utilizando el mismo comportamiento: si el score está por debajo de 0.5, entonces se devuelve un intent por defecto. Los resultados:

El algoritmo detrás de NLP.js explicado

Puedes encontrar NLP.js en github y en npmjs: https://github.com/axa-group/nlp.js

Es open source y está construído usando javascript, soporta 27 idiomas y puede ser usado tanto en Node.js como en el navegador (de hecho es el único NLP de los evaluados que puede ser ejecutado en el navegador). La limitación es que en el navegador el idioma chino no está disponible.

El secreto de lograr una confianza tan buena en los resultados es combinar dos métodos de lograr la respuesta: Logistic Regression Classifier y Binary Relevance Neural Network. La forma de funcionar de este último es tener una red neuronal por cada intent, de forma que se entrena con cada una de las frases de entrenamiento que se corresponden con ese intent con un resultado de 1, y con las que no con un 0, y esto se hace para cada intent. De esta manera, cuando recibimos una frase, pasamos esa frase a cada una de estas redes neuronales, que dan su respuesta por separado. Y además se pasa al Logistic Regression Classifier. Y todos estos resultados se combinan para dar una respuesta más adecuada a lo que se busca.

Para escoger la función de activación y los hiperparámetros, se lanzaron una gran colección de pruebas con diferentes formas de entrenamiento, y probando además contra un corpus más grande que los tres propuestos (328 frases de entrenamiento y 56 intents). Finalmente parece que un learning rate de 0.1 con un umbral de error de 0.0005 entrenado durante 20000 iteraciones parece dar un resultado bastante óptimo en un tiempo aceptable. Y para diferentes funciones de activación se obtienen diferentes resultados:

Podemos aprenciar que la activación con ReLu no es la más adecuada para algunos problemas, seguramente por la exceisva linearidad. Por otro lado, la tangente hiperbólica y leaky-ReLu parecen funcionar muy bien con los diversos problemas, de hecho funcionan incluso mejor de lo esperado. Además tanto hiperparámetros como función de activación pueden escogerse en NLP.js, y si no se utiliza por defecto la configuración antes mencionada. El impacto de escoger una u otra configuración estará también en el tiempo de entrenamiento y la calidad de acierto, y hay que encontrar un balance entre ambos. Dado que el entrenamiento no suele ser algo frecuente, y que además se puede hacer desde otro entorno y luego subir el fichero de pesos generado a otros entornos, suele salir a cuenta tunear correctamente los parámetros para obtener una buena calidad. El tiempo dependerá fundamentalmente de la cantidad de intents, en el caso del corpus con 56 intents y 328 frases de entrenamiento, el tiempo en un portátil normal tarda unos 110 segundos, en los cuales se entrena ambos métodos: Logistic Regression Classifier y Binary Relevance Neural Network.

The post Evaluando el NLU para chatbots first appeared on Planeta Chatbot.

]]>
https://desa.planetachatbot.com/evaluando-nlu-para-chatbots/feed/ 0
Desarrollando chatbots inteligentes https://desa.planetachatbot.com/desarrollando-chatbots-inteligentes/?utm_source=rss&utm_medium=rss&utm_campaign=desarrollando-chatbots-inteligentes https://desa.planetachatbot.com/desarrollando-chatbots-inteligentes/#respond Mon, 27 Aug 2018 09:00:48 +0000 https://desa.planetachatbot.com/?p=298 Introducción Los chatbots están aquí, y han venido para quedarse. Son una nueva manera más natural de interactuar con los usuarios, y además viven en los canales que los usuarios ya usan. Una de las frameworks más famosas para construir chatbots es la Microsoft Bot Framework y uno de los lenguajes que soporta es Node.js. Durante este artículo […]

The post Desarrollando chatbots inteligentes first appeared on Planeta Chatbot.

]]>
Introducción

Los chatbots están aquí, y han venido para quedarse. Son una nueva manera más natural de interactuar con los usuarios, y además viven en los canales que los usuarios ya usan.

Una de las frameworks más famosas para construir chatbots es la Microsoft Bot Framework y uno de los lenguajes que soporta es Node.js. Durante este artículo veremos como construir chatbots inteligentes utilizando ambos.

Canales

Hay muchos canales en los que un chatbot puede vivir, incluyendo aplicaciones móviles, la web o el mail. Y desde luego, los canales de mensajería como Facebook Messenger, Telegram o Slack. El problema con la existencia de tantos canales, es que cada uno tiene una manera diferente de comunicarse, y eso supone que para desplegar un bot en varios hay que hacer mucho desarrollo diferente solamente para adaptarse a la comunicación de cada canal. Esta es una de las ventajas de usar Microsoft Bot Framework: desplegas un único bot, y puedes conectarlo a los canales sin desarrollo extra, y Microsoft es el responsable de conectarse a cada canal y traducir los mensajes a un formato común. Para ello hay que desplegar en Azure un componente llamado Bot Channel Registration, que tiene una interfaz gráfica sencilla para añadir el bot a los diferentes canales:

Dos notas importantes:

  • Mucha gente cree que los bots desarrollados con Microsoft Bot Framework obligatoriamente hay que desplegarlos en Azure. En realidad se pueden desplegar en cualquier plataforma de tu gusto (Google Cloud, AWS, Digital Ocean, Heroku,…) y lo que sí se despliega en Azure es el Bot Channel Registration y se hace que apunte al backend de tu bot.
  • El uso de Bot Channel Registration es gratuito para canales que no sean premium. Los canales premium son aquellos en los que Microsoft no solamente hace de conector sino que también tiene que almacenar trozos de conversación y manejarla, es decir: Web y Direct Line API (genera una API, es la manera ideal de integrar bots en móvil). Los canales premium pueden ser desplegados como F0 (gratuito pero limitado a 10.000 mensajes al mes) o S1 (0.42$ por cada 1000 mensajes. También es importante saber que un mensaje se considera no solamente del usuario al bot, sino también del bot hacia el usuario.

UI, Clickbots, Inteligencia

Los chatbots de hoy en día no son solamente de texto, sino que se han ido añadiendo elementos gráficos para interactuar con el usuario, como botones, imágenes, localización, carruseles,… y estos elementos gráficos siguen evolucionado a día de hoy.

Para probar estos elementos gráficos, puedes probar la web de Adaptative Cards, la propuesta de Microsoft para ser capaces de usar estos elementos de una manera común para diferentes canales.

Pero también hay una manera de añadir inteligencia a tus chatbots: NLP (Natural Language Processing). El NLP se compone de dos partes:

  • NLU: Natural Language Understanding. Es la parte que a partir de una utterance (frases tal y como las dicen los humanos) es capaz de determinar el intent (acción que esa utterance significa). Además es capaz de extraer las entidades mediante algo llamado NER (Named Entity Recognition).
  • NLG: Natural Language Generation. Es la parte para producir frases hacia el usuario. No es solamente devolver una frase y punto, hay que tener en cuenta el género del usuario, los plurales, el nivel de confianza, el contexto de la conversación,…

Lo entenderemos mejor con un ejemplo:

En este ejemplo la utterance es I want to travel to Barcelona tomorrow, que el NLU interpreta como el intent user.travel. Además, debe reconocer dos entidades: la localización a la que se quiere viajar y la fecha. Hay que pensar en el intent como el nombre de la acción que queremos que el chatbot ejecute, y las entidades como los parámetros necesarios para realizar dicha acción.

node-nlp

Hay muchos productos para la parte del NLP, como DialogFlow (Google), Wit.ai (Facebook) o LUIS.ai (Microsoft). Puedes encontrar comparativas por internet, aunque no todas son fiables porque dependen mucho del idioma que se pruebe y de la fecha en la que se haya probado, porque son tecnologías en contínua evolución.

Una de las grandes diferencias que hacen de DialogFlow el líder, es el uso de contextos, de manera que el procesamiento de los intents varía en función de parámetros de la conversación, y da herramientas para definir las respuestas de los usuarios. Esto es muy importante porque por ejemplo otro líder del sector, LUIS.ai, no da contexto ni manera de definir las respuestas, sino solamente los intents, y las respuestas y el contexto los dejan para la parte del desarrollo dentro del código del bot.

También puedes haber oído hablar de QnA Maker. QnA Maker es muy bueno para poder hacer rápidamente bots a partir de una FAQ (Frequently Asked Questions), pero es importante entender que no es un NLP. Cuando usas QnA Maker en profundidad, parece no estar utilizando técnicas de inteligencia artificial para tomar las decisiones, sino más bien algoritmos de distancia de cadenas de texto. En mi caso lo probé entrenándolo con frases en lengua negra, una lengua inventada de El Señor de los Anillos, y el ejemplo funcionaba, con lo cual internamente no tiene en cuenta el idioma utilizado (de hecho nunca lo pregunta).

También existen productos que en lugar de en la nube pueden ser desplegados on premise, como RASA o Snips. La principal razón para no tener un NLP en la nube sino dentro de u compañía, suele ser la seguridad y temas legales: evitar que información confidencial del usuario sea enviada a compañías de terceros. Esto es muy importante sobre todo en chatbots cuya área es la salud: pensad en un chatbot al que el usuario le comunica sus enfermedades, o incluso sus alergias. También puede haber otros motivos para tener tu NLP dentro de tu compañía, como personalización, precio, performance, privacidad…

En mi caso para los ejemplos utilizaré node-nlp, que es una libreía de Node.js basada en Natural. Las razones para usar una libería son varias, pero básicamente lo que nos permite es una total personalización del NLP, integrar el NLG directamente en el contexto del bot para cada conversación, integración sencilla, no tener que desplegar de manera separada y la performance, además de permitirnos hacer entrenamiento del bot en tiempo real.

Sobre la performance, tener el NLP como libería significa que no hay que llamar a ninguna API para resolver la información, sino que está directamente accesible en el programa, así que no hay TTL. Esto es importante porque cuando se envía una respuesta a un usuario, muchas veces para calcularla hay proceso de negocio intermedios que ya tardan un tiempo, así que agregar incluso más tiempo puede hacer esperar al usuario. Una pequeña comparación del mismo bot hecho con node-nlp y con LUIS:

¡Menos de 2 milisegundos para calcular la respuesta!

Creando un bot con node-nlp

Para crear un bot usando node-nlp, básicamente hay que crear un bot como siempre, y utilizar node-nlp para cargar el modelo, bien sea programándolo, desde un fichero de modelo o desde un excel. Es importante que una vez el modelo está entrenado, guardarlo para no tener que volver a perder el tiempo que se tarda en entrenarlo, porque es un proceso que utiliza mucha CPU.

const builder = require('botbuilder');
const express = require('express');
const fs = require('fs');
const { Recognizer } = require('node-nlp');

const modelName = './smalltalk.nlp';
const excelName = './smalltalk.xls';

// Creates a connector for the chatbot
const connector = new builder.ChatConnector({
  appId: process.env.BOT_APP_ID,
  appPassword: process.env.BOT_APP_PASSWORD,
});

// Creates a node-nlp recognizer for the bot
const recognizer = new Recognizer();
if (fs.existsSync(modelName)) {
  recognizer.load(modelName);
} else {
  recognizer.loadExcel(excelName);
  recognizer.save(modelName);
}

// Creates the bot using a memory storage, with a main dialog that
// use the node-nlp recognizer to calculate the answer. 
const bot = new builder.UniversalBot(connector, (session) => {
  recognizer.recognize(session, (err, data) => {
    session.send(data.answer || 'I don\'t understand');
  });
}).set('storage', new builder.MemoryBotStorage());

// Creates the express application
const app = express();
const port = process.env.PORT || 3000;
app.post('/api/messages', connector.listen());
app.listen(port);

Para modificar el comportamiento del bot, simplemente edita el excel que viene con su código. En ese excel podrás cambiar las utterances, intents y respuestas:

Una vez modificado solamente tienes que reentrenar a tu bot con el nuevo excel.

Para probar el bot antes de desplegarlo, te sugiero que uses Microsoft Bot Emulator, que te permitirá usarlo en local y hacer todas las pruebas necesarias. El bot del ejemplo ejcutaría así:

Intents y Diálogos

Si ya has desarrollado chatbots usando Microsoft Bot Framework y LUIS, sabrás que la manera en la que la framework usa el NLP es muy diferente de la que se muestra en el ejemplo. Como LUIS no tiene NLG con lo cual no devuelve la respuesta sino el intent, Microsoft Bot Framework propone trabajar con disparadores: cada mensaje que llega al bot es enviado a LUIS, y si LUIS reconoce el mensaje como un intent, y existe un diálogo marcado como que debe ejecutarse cuando suceda ese intent, entonces se dispara ese diálogo. Un ejemplo de código:

const luisAppId = process.env.LuisAppId;
const luisAPIKey = process.env.LuisAPIKey;
const luisAPIHostName = process.env.LuisAPIHostName || 'westus.api.cognitive.microsoft.com';

// Create a recognizer that gets intents from LUIS, and add it to the bot
bot.recognizer(new builder.LuisRecognizer(`https://${luisAPIHostName}/luis/v2.0/apps/${luisAppId}?subscription-key=${luisAPIKey}`));

bot.dialog('GreetingDialog', (session) => {
  session.send(`You reached the Greeting intent. You said '${session.message.text}'`);
  session.endDialog();
}).triggerAction({ matches: 'Greeting' });

Dentro de node-nlp hay una clase Recognizer que puede ser usada perfectamente en lugar del LUIS Recognizer de Microsoft. Un ejemplo usando node-nlp recognizer:

const builder = require('botbuilder');
const express = require('express');
const { Recognizer } = require('node-nlp');

// Creates a connector for the chatbot
const connector = new builder.ChatConnector({
  appId: process.env.BOT_APP_ID,
  appPassword: process.env.BOT_APP_PASSWORD,
});

// Creates a node-nlp recognizer for the bot
const recognizer = new Recognizer();
recognizer.nlpManager.addLanguage('en');
recognizer.nlpManager.addDocument('en', 'Hello', 'Greeting');
recognizer.nlpManager.addDocument('en', 'Hey', 'Greeting');
recognizer.nlpManager.addDocument('en', 'Hi!', 'Greeting');
recognizer.nlpManager.addDocument('en', 'I need help', 'Help');
recognizer.nlpManager.addDocument('en', 'Help me', 'Help');
recognizer.nlpManager.addDocument('en', 'help', 'Help');
recognizer.nlpManager.addDocument('en', 'I want to cancel', 'Cancel');
recognizer.nlpManager.addDocument('en', 'cancel', 'Cancel');
recognizer.nlpManager.addDocument('en', 'please cancel', 'Cancel');
recognizer.train();

// Creates the bot using a memory storage, with a main dialog that
// use the node-nlp recognizer to calculate the answer. 
const bot = new builder.UniversalBot(connector, (session) => {
  session.send(`You reached the default message handler. You said '${session.message.text}'.`);
}).set('storage', new builder.MemoryBotStorage());

bot.recognizer(recognizer);

bot.dialog('GreetingDialog', (session) => {
  session.send(`You reached the Greeting intent. You said '${session.message.text}'.`);
  session.endDialog();
}).triggerAction({ matches: 'Greeting' });

bot.dialog('HelpDialog', (session) => {
  session.send(`You reached the Help intent. You said '${session.message.text}'.`);
  session.endDialog();
}).triggerAction({ matches: 'Help' });

bot.dialog('CancelDialog', (session) => {
  session.send('You reached the Cancel intent. You said \'%s\'.', session.message.text);
  session.endDialog();
}).triggerAction({ matches: 'Cancel' });

// Creates the express application
const app = express();
const port = process.env.PORT || 3000;
app.post('/api/messages', connector.listen());
app.listen(port);
console.log(`Chatbot listening on port ${port}`);

En este ejemplo hemos entrenado al bot directamente desde el código para enseñar que no solamente se puede hacer desde el excel, y además para enseñar que al poder cambiar programáticamente el NLP, significa que podemos cambiar los intents y respuestas y reentrenar en tiempo real. El bot funcionando:

Híbrido

El problema viene cuando tienes que hacer un chatbot más complejo, en el que tienen que convivir un árbol de diálogos complejo con una inteligencia contextualizada. En esos casos, la integración del NLP es muy complicada usando Microsoft Bot Framework y LUIS. Gran parte del trabajo duro viene causado por el hecho de que el reconocedor está integrado en la lógica core de Microsoft Bot Framework, calculando cual será el siguiente diálogo a mostrar, suponiendo que no se integra ningún NLG para calcular ese enrutado.

Pero hay una manera de cambiar el comportamiento de ese enrutado cambiado un método llamado “disambiguate route”, de manera que se puede reemplazar el comportamiento por defecto de Microsoft Bot Framework con tu propia manera de calcular la ruta basada en la pila de diálogos de la conversación y la información de sesión.

Todo esto que suena complicado, node-nlp ya es capaz de hacerlo internamente, añadiendo la capacidad de tener respuestas, o incluso de que que si la respuesta empieza por / entonces significa que no es una respuesta de texto sino la ruta hacia un diálogo.

Para conseguirlo, en lugar de llamar a bot.recognizer(recognizer) como en el ejemplo anterior, hay que llamar a recognizer.setBot(bot, true, 0.7), que le dirá al recognizer el bot al que debe configurarse, el true significa que active el enrutado del recognizer sustituyendo al de Miccrosoft, y 0.7 es el umbral de certeza que debe tener como mínimo al reconocer el intent para que se intent sea disparado en lugar de considerar que la respuesta pertenece a la ejecución que ya había del diálogo.

Mejor verlo en código:

const builder = require('botbuilder');
const express = require('express');
const fs = require('fs');
const { Recognizer } = require('node-nlp');

const modelName = './hybrid.nlp';
const excelName = './hybrid.xls';

// Creates a connector for the chatbot
const connector = new builder.ChatConnector({
  appId: process.env.BOT_APP_ID,
  appPassword: process.env.BOT_APP_PASSWORD,
});

// Creates a node-nlp recognizer for the bot
const recognizer = new Recognizer();
if (fs.existsSync(modelName)) {
  recognizer.load(modelName);
} else {
  recognizer.loadExcel(excelName);
  recognizer.save(modelName);
}

// Creates the bot using a memory storage, with a main dialog that
// use the node-nlp recognizer to calculate the answer. 
const bot = new builder.UniversalBot(connector, (session) => {
  session.send(`You reached the default message handler. You said '${session.message.text}'.`);
}).set('storage', new builder.MemoryBotStorage());

recognizer.setBot(bot, true);

bot.dialog('/GreetingDialog', (session) => {
  session.send(`You reached the Greeting intent. You said '${session.message.text}'.`);
  session.endDialog();
});

bot.dialog('/HelpDialog', (session) => {
  session.send(`You reached the Help intent. You said '${session.message.text}'.`);
  session.endDialog();
});

bot.dialog('/CancelDialog', (session) => {
  session.send('You reached the Cancel intent. You said \'%s\'.', session.message.text);
  session.endDialog();
});

// Creates the express application
const app = express();
const port = process.env.PORT || 3000;
app.post('/api/messages', connector.listen());
app.listen(port);
console.log(`Chatbot listening on port ${port}`);

El bot ejecutándose:

Conclusión

Es muy importante tener un buen enrutado en el chatbot de manera que ambos mundos, el de los chatbots inteligentes y el de los clickbots, puedan vivir juntos en el mismo bot para lograr la mejor experiencia de usuario.

También es muy importante separar la generación de respuestas del código, porque eso es parte del NLG, y nos permitirá cambiar el coportamiento del bot sin tener que cambiar su código ni desplegarlo de nuevo. Permitir además que desde el NLG podamos controlar la pila y flujo de diálogos es de lo más potente, y es la manera en la que podemos conseguir hacer bots muchísimo más complejos pero que en realidad al usuario le resulten intuitivos.

Código y Librerías:

Todos los ejemplos de código pueden ser encontrados en este repositorio:

  • https://github.com/jseijas/bot-nlp
  • https://github.com/axa-group/nlp.js
  • https://github.com/NaturalNode/natural
  • https://github.com/Microsoft/botbuilder

The post Desarrollando chatbots inteligentes first appeared on Planeta Chatbot.

]]>
https://desa.planetachatbot.com/desarrollando-chatbots-inteligentes/feed/ 0