Cookie usage policy

The website of the University Carlos III of Madrid use its own cookies and third-party cookies to improve our services by analyzing their browsing habits. By continuing navigation, we understand that it accepts our cookie policy. "Usage rules"

CharlieBOT: Mejorando la Comunicación Digital con Inteligencia Artificial Generativa

Imagen ilustrativa del servicio de chat con inteligencia artificial

En el último año, la inteligencia artificial generativa  (IAGen) ha irrumpido en el escenario tecnológico con promesas de transformación y avances sin precedentes. Entre sus múltiples aplicaciones, los bots conversacionales basados en modelos de procesamiento de lenguaje natural han demostrado ser particularmente eficaces, frente a las tecnologías anteriores,  para mejorar la interacción usuario-servicio, ofreciendo respuestas inmediatas y personalizadas a las consultas  de los usuarios en base a la información de servicio de la propia  institución. El Servicio de Informática y Comunicaciones de la Universidad Carlos III de Madrid, dentro de su línea de innovación, acaba de poner en servicio un nuevo bot conversacional basado en ChatGPT.

Este artículo se propone explorar qué tecnologías forman parte de esta implementación   y  cuáles han sido las decisiones que han dirigido el desarrollo del mismo al escenario actual así como posibles  líneas de evolución.

Elección del modelo

La primera decisión clave a la hora de desarrollar un bot conversacional es qué modelo va a ser el corazón del mismo. Existen actualmente múltiples modelos disponibles, pero por calidad y velocidad nos centraremos en los modelos que nos ofrece la empresa OpenAI.

  Modelos antiguos Nuevos modelos
GPT-4 Turbo GPT-4 8K Input: $0.03 Output: $0.06 GPT-4 32K Input: $0.06 Output: $0.12 GPT-4 Turbo 128K Input: $0.01 Output: $0.03
GPT-3.5 Turbo GPT-3.5 Turbo 4K Input: $0.0015 Output: $0.002 GPT-3.5 Turbo 16K Input: $0.003 Output: $0.004 GPT-3.5 Turbo 16K Input: $0.001 Output: $0.002

Con los precios a día de la redacción de este artículo, una interacción media de un usuario con el bot tiene un coste aproximado de 0,30€ con GPT-4-Turbo y de 0,03€ con GPT-3.5-Turbo. Uno de los objetivos clave que nos marcamos a la hora de desarrollar el bot de ayuda es que fuera escalable y su coste asumible. Puesto que no hay grandes diferencias en las respuestas entre GPT-4 Turbo y GPT-3.5-Turbo siempre y cuando se le entregue un contexto adecuado a la pregunta del usuario, nos hemos decantado por GPT-3.5-Turbo.

La mayor limitación de GPT-3.5 frente a GPT-4 es la “ventana” de tokens que puede tratar. Actualmente GPT-3.5 ha subido su limitación a 16.000 tokens pero GPT-4 tiene una ventana de 128.000 tokens. Los tokens son las unidades básicas que ayudan a estos sistemas a descomponer y analizar las preguntas y declaraciones de los usuarios para que puedan proporcionar respuestas precisas y útiles. Típicamente un token es igual a una palabra. 

Está claro que al usar GPT-3.5 tenemos que enfrentarnos a un reto importante, mantener el contexto de la conversación. En cada interacción del usuario con el modelo, se sube al mismo toda la conversación, la actual y la pasada, de manera que el modelo siempre tiene claro cuál es el contexto de la conversación. El problema es que según van aumentando las interacciones del usuario van aumentando el número de palabras simultáneas que el modelo tiene que manejar y nos acercamos, inexorablemente, al límite de tokens del modelo, momento en el cuál ya no será posible continuar la conversación. Más adelante en este artículo trataremos como hemos bordeado este problema para minimizarlo y mantener el contexto fresco pero limitando el número de palabras manejadas por el modelo.

Generando el contexto para el modelo

Llegados a este punto tenemos un bot que ya puede “hablar” con el usuario, pero no contesta a las preguntas que nosotros queremos que conteste. Por ejemplo, si le preguntamos por “¿cuáles son los SSID del wifi de la Universidad?” no será capaz de dar una respuesta válida ya que el modelo no dispone de ese conocimiento. ¿Cómo dotamos al modelo de ese conocimiento? Pues hay varias aproximaciones posibles.


Entrenamiento: Consiste en entrenar un modelo a medida basado en alguno de los que ofrece OpenAI para que adquiera el conocimiento con el que se le entrena. Los inconvenientes de esta solución son varios:

  • Los modelos disponibles para entrenar en OpenAI son antiguos y lentos, es decir, no podríamos usar GPT-3.5-Turbo como modelo de base. 
  • Por otro lado el entrenamiento es caro y, en caso de que cambie la información, requiere que el modelo sea entrenado de nuevo con el consiguiente gasto económico ya que entrenar un modelo ad hoc no es barato actualmente por lo que esta vía se descartó rápidamente.

Tecnología de incrustación (embeddings): Cuando escuchamos la palabra "embedding" en el contexto de la tecnología de inteligencia artificial, podríamos pensar que se refiere a algún concepto complicado y esotérico. Sin embargo, la idea detrás de los embeddings es, en realidad, bastante sencilla y extremadamente útil para ayudar a las inteligencias artificiales a entender nuestro lenguaje. Un "embedding" es, básicamente, una representación numérica compacta de un objeto, como una palabra, una frase, un párrafo o una imagen. Imagina que cada palabra de nuestro idioma es un punto en un mapa grande y multidimensional. Las palabras con significados similares están más cerca entre sí en este mapa, mientras que las que tienen menos en común están más lejos. Esta es la esencia de un embedding de palabras. La tecnología de embeddings no es muy diferente de cómo un ser humano entiende las palabras por el contexto y las relaciones con otras palabras. Por ejemplo, "manzana" y "fruta" están más relacionadas entre sí que "manzana" y "bicicleta". Los embeddings capturan esta relación en forma de vectores, que son esencialmente listas de números. En este caso lo que se hace es extraer todo el conocimiento que debe tener el bot en archivos de texto plano mediante diversas técnicas dependiendo de la fuente del conocimiento. Una vez que obtenemos los archivos con el conocimiento que necesita tener el bot debemos procesarlos para obtener ese mapa de vectores que, posteriormente, nos va a permitir hacer búsquedas para obtener justamente los párrafos relevantes donde esté la información necesaria que necesita el modelo para contestar con precisión al usuario. Para convertir los textos en vectores utilizamos los modelos ADA de OpenAI. Esto tiene un coste algo más bajo que el de un entrenamiento de un modelo y tiene la ventaja de que podemos cambiar el modelo base sin afectar el resto del conocimiento (embeddings). Una vez que obtenemos el campo vectorial, procedemos a almacenarlo en una base de datos, en este caso usamos la tecnología PostgreSQL. PostgreSQL es un sistema de gestión de base de datos relacional que es famoso por su robustez y flexibilidad. Para almacenar embeddings en PostgreSQL, se utiliza un campo especial llamado "vector", que puede almacenar grandes listas de números (vectores) eficientemente.


El proceso es el siguiente:

  1. Generación de Embeddings: Primero, utilizamos el modelo de lenguaje para convertir palabras o frases en vectores embeddings. Cada palabra o frase se procesa a través de ADA, produciendo un vector único.
  2. Almacenamiento de Vectores: Estos vectores se almacenan luego en una base de datos PostgreSQL. Cada vector es un campo en una fila de una tabla, asociado con la palabra o frase correspondiente.
  3. Búsqueda y Análisis: Cuando queremos encontrar palabras o frases similares o realizar cualquier otro análisis, podemos buscar en estos vectores usando funciones especiales que PostgreSQL ofrece para trabajar con datos de tipo vector.
  4. Una vez obtenidos los párrafos relevantes con la información necesaria para contestar al usuario se lo damos al modelo dentro del “contexto” donde también le indicamos cómo se debe comportar y a que debe contestar y a qué no. Básicamente, cuando el usuario realiza una pregunta al bot, se manda al modelo la pregunta del usuario, toda la conversación anterior, siempre y cuando no supere el número de tokens máximo, y un contexto donde va el resultado de la búsqueda semántica y una definición de cómo debe comportarse el bot. Lo último que queremos es que nuestro bot se posicione políticamente o haga respuestas indebidas sobre temas delicados. En nuestro caso el bot está limitado al ámbito de las respuestas técnicas y resolución de dudas en cualquier ámbito del Servicio de Informática y Comunicaciones.

La Sinergia entre Embeddings y Búsquedas Contextuales

Con todo lo anterior, CharlieBOT ya está preparado para dar respuestas bastante acertadas. En principio nuestra intención era poner en funcionamiento una primera versión beta con las funcionalidades explicadas hasta aquí, pero observamos que la respuestas basadas en embeddings en muchas ocasiones se quedan algo cortas. Se echaba de menos que el bot te diera URLs de referencia donde poder consultar más información sobre lo que el usuario había preguntado. Por ello decidimos dar otro paso más y darle aún más contexto al modelo. ¿cómo?: Búsquedas Contextuales. 

Para ello hacemos uso de un buscador de Google Personalizado que busca en todas las páginas del SDIC. En primer lugar probamos con darle al buscador directamente la cadena introducida por el usuario. Por ejemplo, si el usuario pregunta a CharlietBOT por “¿Cómo me instalo FlipApp?”, esa era la cadena que le dábamos al buscador de Google. ¿Qué ocurría? En primer lugar, muchas veces nos devolvía que no encontraba nada o las búsquedas eran lentas. Estaba claro que era necesario un procesamiento sintáctico para convertir la entrada del usuario en términos relevantes de búsqueda. Para ello hacemos un análisis de la entrada del usuario usando la librería “compromise”, de esta manera descomponemos la cadena de entrada en sustantivos, verbos y resto de componentes. Para construir los términos de búsqueda nos quedamos con los verbos en infinitivo y los sustantivos de manera que la entrada del usuario “¿Cómo me instalo FlipApp?” se convierte en “instalar FlipApp” a la hora de realizar la búsqueda. De esta manera el buscador de Google nos da rápidamente los resultados más relevantes. A partir de aquí se guardan los 3 primeros enlaces proporcionados por el buscador y se abre el primer resultado y se busca en el interior el párrafo más significativo a partir de la cadena de búsqueda usando un sistema de ponderación por pesos. 

Ahora ya tenemos el contexto obtenido por el embedding más 3 urls de apoyo más el párrafo relevante contenido en el primer resultado de la búsqueda. Todo este contexto se entrega al modelo para que construya su respuesta. 

¿Qué problema tenemos con proporcionar tanto contexto? La posibilidad de alcanzar muy rápidamente el límite de tokens del modelo. Cabe recordar que, a día de la publicación de este artículo, GPT-3.5-Turbo soporta una ventana de 8000 tokens. ¿Cómo podemos sortear esta limitación? A continuación lo explicamos.

La Optimización del Contexto y la poda

Una de las mayores limitaciones del modelo de base que se usa para dar vida a CharlieBOT es su limitado número de tokens (palabras) simultáneas que puede manejar. Para evitar la sobrecarga de información y la pérdida de relevancia en las conversaciones, CharlieBOT emplea una estrategia de poda dinámica. Si la conversación se empieza a aproximar a los límites del modelo se empiezan a desechar las interacciones más antiguas. También se desechan siempre los contextos pasados y sólo se usa el contexto de la última interacción del usuario con el bot. Pero esto puede ser un gran problema porque si el usuario pregunta primero “¿Qué es flipApp?” y luego pregunta “¿Cómo lo instalo?”, la segunda interacción da como cadena de búsqueda “instalar” que es demasiado genérica y el contexto obtenido no tendrá nada que ver con lo que el bot necesita para dar la respuesta y su respuesta será incorrecta. ¿Cómo corregimos esto? Almacenando los últimos sustantivos utilizados de manera que la pregunta del usuario “¿cómo lo instalo?” se convierte en la cadena “instalar FlipApp” ya que el último sustantivo almacenado es “Flipapp” y como tenemos un pronombre personal “lo” en la frase lo podemos reemplazar por el último sustantivo ya que hace referencia a este. Ahora si que la nueva búsqueda semántica y contextual tendrá éxito y el modelo dará una respuesta válida. Con esto nos ahorramos tener que mantener una gran cantidad de contexto que haría que se alcanzase el límite muy rápido.

Interacción y Mejora Continua

Uno de los mayores retos de los modelos de lenguaje natural es que parecen humanos pero, realmente, están lejos de serlo. En muchas ocasiones nos encontramos que información que para nosotros es clara y perfectamente entendible, cuando se la damos como contexto al modelo, acaba produciendo respuestas no deseadas o no del todo correctas. De hecho con la popularización de estos modelos ha aparecido un nuevo rol que toma una gran relevancia que es el de ingeniero de prompts o “prompt engineer” qué es el especialista en saber qué decir para que la IA ofrezca el mejor resultado.. ¿Y cómo hacemos para mejorar los resultados de CharlieBOT? Hagamos partícipes a los propios usuarios. Para ello hemos implementado un sistema sencillo de votación de manera que los usuarios pueden votar como positiva o negativa la interacción con CharlieBOT. Cada conversación que se tiene con el BOT tiene asignada un ID aleatorio y totalmente anónimo y se almacena en la base de datos PostgreSQL. En el prompt de CharlieBOT que define su comportamiento una de las cosas que se le pide hacer es que, cuando vaya finalizar la conversación, solicite al usuario que vote su desempeño como positivo o negativo. De esta manera recogemos un feedback que es fundamental para aplicar la mejora continua. 

De manera semanal recogemos la conversaciones que han sido votadas como negativas y se analizan de la siguiente forma:

  • Análisis de la entrada del usuario: Ver en que ha convertido el análisis sintáctico la cadena de entrada y cuál es la cadena de búsqueda resultante a partir de la pregunta de partida por si fuera necesario optimizar la librería que realiza esta tarea.
  • Si la cadena es correcta comprobamos cual es el contexto que ha manejado el modelo a la hora de dar la respuesta y se intenta encontrar donde puede estar el “fallo” para intentar modificar el embedding o la información contenida en la web de manera que sigua siendo entendible por los usuarios pero también sea útil para el modelo. Aquí es donde se necesitan la dotes del ingeniero de prompts para optimizar el contexto de manera que el modelo responda lo que se espera de él. 
  • También puede darse el caso de que no haya contexto porque no está recogida de forma correcta la información necesaria para darle la respuesta al usuario. En este caso se puede igualmente modificar o añadir información a la web o añadir nuevos artículos que enriquezcan la búsqueda semántica o expliquen conceptos que no quedan suficientemente claros para la IA del modelo.

Conclusión

La implementación de CharlieBOT en el Servicio de Informática y Comunicaciones de la  Universidad Carlos III de Madrid es un testimonio del poder transformador de la inteligencia artificial en la comunicación digital. Este bot, alimentado por GPT-3.5-Turbo de OpenAI, representa un importante avance en la prestación de servicios de asistencia virtual, demostrando la eficacia de los modelos generativos de lenguaje para la mejora continua de la interacción usuario-servicio. A pesar de los retos inherentes, como la gestión del contexto y la optimización de costes, CharlieBOT se erige como un modelo escalable y económico, capaz de adaptarse y evolucionar con el entorno digital. La sinergia entre la tecnología de embeddings y las búsquedas contextuales ha permitido que CharlieBOT ofrezca respuestas acertadas y enriquecidas con información actualizada, manteniendo un diálogo coherente. Por otro lado, la participación activa de los usuarios en la mejora continua aseguran que este bot conversacional seguirá creciendo en eficacia, convirtiéndose en un activo valioso para la Universidad y un modelo a seguir en la innovación de los asistentes virtuales.

10 de noviembre de 2023
Servicio de Informática y Comunicaciones
Universidad Carlos III de Madrid

  • Alimentado por GPT-3.5-Turbo de OpenAI
  • Modelo escalable y económico
  • Interactúa con CharlieBOT en la esquina inferior derecha de la web SDIC