IA Generativa para hacer chatbots con RASA CALM

0
123

En el primer tutorial de Rasa hicimos un ejemplo basado en Rasa Open Source que utiliza NLU (Natural Language Understanding) para gestionar las intenciones y entidades como ya vimos. Este tipo de modelos no escala muy bien porque necesita gran cantidad de información para el entrenamiento de cada uno de los intents y no entiende el contexto de la conversación.
Rasa Pro utiliza un enfoque diferente, llamado Dialogue Understanding, que resumiendo mucho, utiliza LLM para interpretar qué es lo que el usuario quiere, generando comandos que inician o finalizan flujos de negocio, conservan o borran información que proporciona el usuario, recuperan información personalizada o simplemente charlan con el usuario.

Incorpora además mecanismos para redirigir la conversación de manera automática, lo que hace especialmente sencillo manejar los flujos alternativos.

También es bastante sencillo preparar la herramienta para responder a los usuarios de manera más natural y personalizada.

Y por último (entre otras muchas cosas), es muy fácil preparar la herramienta para aumentar las capacidades del asistente con mecanismos de RAG (Retrieval-Augmented Generation).

Todo este se traduce en que con Rasa Pro es mucho más fácil y más rápido crear asistentes conversacionales y con capacidades mucho mayores gracias a su cambio de paradigma.

Para demostrarlo, en este tutorial replicaremos el ejemplo que hicimos en el primer tutorial, pero utilizando las capacidades de Rasa Pro y veremos si es verdad o no.

Antes de nada, os dejo todo el código fuente de este tutorial en este repositorio de GitHub.

Índice

  1. Entorno
  2. Preparando el entorno
  3. El ejemplo
  4. Conclusiones

1. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 15″ (Intel Core i9, 32GB, 1TB SSD).
  • Sistema Operativo: macOS Sonoma 14.6.1
  • IntelliJ IDEA (2024.1.6) con el plugin de Python

2. Preparando el entorno

Lo primero, la licencia del producto. Aunque Rasa Pro es de pago para usar en producción, podemos solicitar una licencia de desarrollador para probarlo.

Necesitamos también un LLM para trabajar. Por defecto viene configurado para usar OpenAI (gtp-4) y en este tutorial es lo que haremos, pero se pueden configurar otros LLM.
Si no tienes API Key, aquí puedes conseguir una: licencia de OpenAI (ojo, esto cuesta dinero).

Una vez que tengas la licencia y la API Key, las configuramos como variables de entorno. Para ello, ejecutamos los siguientes comandos en la terminal en la que vayas a ejecutar rasa:

export OPENAI_API_KEY="your-api-key"
export RASA_PRO_LICENSE="your-rasa-pro-license-key"

Si quieres que estas variables se carguen automáticamente cada vez que inicies la terminal, puedes usar direnv.

Usaremos virtualenv para crear un entorno virtual con python 3.10:

virtualenv -p /usr/local/Cellar/python@3.10/3.10.13_1/bin/python3.10 venv
source env/bin/activate

Y tal como dice la documentación, instalamos Rasa Pro usando uv para reducir el tiempo de descarga de Rasa Pro:

uv pip install rasa-pro --extra-index-url=https://europe-west3-python.pkg.dev/rasa-releases/rasa-pro-python/simple/

Si todo ha ido bien, deberías poder ejecutar el siguiente comando para comprobar que Rasa Pro está instalado correctamente:

> rasa --version

Rasa Version      :         3.9.10
Minimum Compatible Version: 3.7.0
Rasa SDK Version  :         3.9.1
Python Version    :         3.10.13
Operating System  :         macOS-14.6.1-x86_64-i386-64bit
Python Path       :         .../venv/bin/python3

Al igual que en el primer tutorial, podemos utilizar el comando init para crear una estructura o incluso el tutorial que se proporciona:

    rasa init --template tutorial

Os recomiendo hacer el tutorial (y probarlo) y luego ir modificándolo para completar el mismo ejercicio que hicimos en el anterior tutorial:

3. El ejemplo

Nuestro asistente virtual será capaz de realizar las siguientes operaciones:

  • Mostrar el saldo, ya sea de nuestra cuenta o de nuestra tarjeta
  • Recuperar los últimos movimientos de nuestra cuenta o de nuestra tarjeta
  • Realizar una transferencia

Lo primero que haremos será, en el fichero domain.yml añadir los slots necesarios para almacenar la información que el usuario nos proporcione, pero esta vez el mapeo lo hará el generador de comandos basado en LLM:

...
slots:
  product_type:
    type: text
    mappings:
      - type: from_llm

  transfer_amount:
    type: float
    mappings:
      - type: from_llm

  transfer_account_number:
    type: text
    mappings:
      - type: from_llm

  balance:
    type: float
    mappings:
      - type: custom
        action: action_balance

  last_transactions:
    type: text
    mappings:
      - type: custom
        action: action_last_transactions
    ...

También en el mismo fichero, definimos las acciones personalizadas que ejecutarán las diferentes operaciones que el usuario solicite:

...
actions:
  - action_balance
  - action_last_transactions
  - action_transfer
...

Si habéis seguido el tutorial anterior, veréis que la estructura es similar, pero ya no aparecen ni intents ni entidades, ni formularios.

Ahora, para definir los flujos, no usaremos rules ni stories, sino que usaremos flows. Veamos el fichero flows.yml:

...
flows:
  balance_inquiry:
    description: Este flujo permite a los usuarios consultar el saldo un tipo de producto.
    steps:
      - collect: product_type
        description: El tipo de producto para el que se consulta el saldo que puede ser cuenta o tarjeta.
      - action: action_balance
      - action: utter_balance

  last_transactions_inquiry:
    description: Este flujo permite a los usuarios consultar los últimos movimientos de su cuenta o de su tarjeta.
    steps:
      - collect: product_type
        description: El tipo de producto para el que se consulta los últimos movimientos que puede ser cuenta o tarjeta.
      - action: action_last_transactions
      - action: utter_last_transactions

  transfer_money:
    description: Este flujo permite a los usuarios enviar dinero a otras cuentas.
    steps:
      - collect: transfer_account_number
        description: El número de cuenta al que se enviará el dinero.
      - collect: transfer_amount
        description: La cantidad en euros que se enviará a la cuenta.
      - action: action_transfer
      - action: utter_transfer_completed
...

Si prestamos atención, y comparamos con lo que teníamos que hacer antes para gestionar la lógica de negocio, podemos destacar entre otras cosas que:

  1. Ahora no necesitamos entrenar el modelo con ejemplos de conversaciones, sino que simplemente describimos cada flujo y será el LLM el que haga el trabajo duro.
  2. Hay flujos que nos podemos ahorrar y dejar que el framework con el soporte del LLM se encargue (si queremos) de todas aquellas conversaciones que se desvíen del camino feliz.
  3. La recuperación de información es mucho más sencilla con el uso de collect.

Hay muchas más mejoras que se pueden ver en la documentación, como la posibilidad de enlazar o embeber flujos, usar condiciones para controlar la lógica de los flujos.

Además, la herramienta está preparada para mantener la convivencia con flujos de negocio tradicionales, por lo que no es necesario migrar todo a flows o porque no, definir algunos a la forma antigua para ahorrarnos unos eurillos y no acudir al LLM.

Las acciones personalizadas son prácticamente las mismas que teníamos antes y las responses se han reducido mucho, ya que no necesitamos tantas para gestionar los flujos alternativos:

...
responses:
  utter_ask_product_type:
    - text: "¿Desea consultar su cuenta o su tarjeta?"

  utter_ask_transfer_account_number:
    - text: "¿A qué cuenta quieres enviar el dinero?"

  utter_ask_transfer_amount:
    - text: "¿Cuánto dinero quieres enviar?"

  utter_transfer_completed:
    - text: "Se ha realizado una transferencia de {transfer_amount} EUR a la cuenta {transfer_account_number}."

  utter_balance:
    - text: "El saldo actual de tu {product_type} es de {balance} EUR.?"

  utter_last_transactions:
    - text: "Los últimos movimientos en tu {product_type} han sido: \n {last_transactions}."
...

Las que empiezan por utter_ask_ son una convención para las respuestas de los collect.

Y ahora vamos a configurar a personalizar algunos de los patrones predefinidos que trae la herramienta en el fichero patterns.yml:

...
  pattern_chitchat:
    description: Conversation repair flow for off-topic interactions that won't disrupt the main conversation. should not respond to greetings or anything else for which there is a flow defined
    name: pattern chitchat
    steps:
      - action: utter_free_chitchat_response
...

Vamos a dejarle que de rienda suelta a las respuestas de cuando el usuario esté charlando (esto es configurable y totalmente desactivable, ya que no suele ser algo deseado en un asistente empresarial).

Y por último, vamos a configurar nuestro asistente para que hagas dos cositas que os van a gustar:

La primera, le vamos a decir que queremos que sepa buscar información personalizada (RAG) de algunos productos de los que disponemos, en este caso, hipotecas que tiene nuestro banco. He copiado información de un banco cualquiera y la he añadido en un fichero llamado hipotecas.txt a un directorio llamado docs:

disponemos de cuatro tipos de hipotecas: hipoteca variable, hipoteca fija, hipoteca joven...

la hipoteca variable se adapta a las fluctuaciones del mercado, contratando productos como seguros, ...
...

No debemos olvidar configurar el componente de búsqueda en el fichero config.yml:

...
policies:
    ...
    - name: EnterpriseSearchPolicy
...

Y segundo, vamos a configurar que el LLM para quemejore las respuestas definiendo un prompt personalizado, y además que lo haga en español y que a veces sea algo irreverente, a ver qué pasa :).

The following is a conversation with an AI assistant.
The assistant is helpful, creative, clever, and very friendly, but sometimes it is a little irreverent.
Rephrase the suggest AI response staying close to the original message and retaining its meaning. Use simple spanish.
Context / previous conversation with the user:
{{history}}
{{current_input}}
Suggested AI Response: {{suggested_response}}
Rephrased AI Response:

Configuramos el componente en el fichero endpoints.yml:

...
nlg:
  type: rephrase
  rephrase_all: True
  prompt: prompts/response-rephraser-template.jinja2
...

Bueno, pues ya está todo listo para entrenar el modelo y probarlo. Vamos a ello:

 > rasa train
  ... rasa.engine.training.hooks  - Finished training component 'SingleStepLLMCommandGenerator'.
  ... rasa.model_training  - [info     ] Your Rasa model is trained and saved at 'models/...-ordered-agent.tar.gz'. event_key=mod

No olvidemos arrancar el servidor de acciones en otra shell:

  > rasa run actions
  ...
    ...rasa_sdk.endpoint  - Starting plugins...
    ...rasa_sdk.endpoint  - Action endpoint is up and running on http://0.0.0.0:5055
  ...

Y por último, usemos otra de las maravillas que incluye Rasa pro, el inspector para probar nuestro asistente:

  > rasa intent

Esperamos que nos abra una ventana en el navegador y a jugar.

Empecemos saludando y charlando con él, a ver qué nos cuenta:
El asistente responde al saludo

Preguntemos por alguna hipoteca, a ver si sabe algo (he imaginado que aún tengo 30 años, no creo que a nadie le importe 🙂 ):
El asistente retorna información relevante cuando se le solicita información de hipotecas

Y ahora, vamos a hacer una transferencia:
El asistente facilita una operación de envío de dinero

Y ahora, vamos a consultar el saldo y los movimientos:
El asistente muestra el saldo y los últimos movimientos

La verdad es que no está nada mal.

4. Conclusiones

Desde la aparición de las redes neuronales en el siglo pasado, la IA ha avanzado a pasos agigantados, especialmente estos últimos años con su resurgimiento en las redes neuronales profundas gracias especialmente al aumento de la capacidad de cómputo con las GPU y las TPU y la aparición de los Transformers que han revolucionado el campo del procesamiento del lenguaje. Muchos han sabido aprovechar la situación y para, con un enfoque diferente, basado en LLM, crear nuevas aplicaciones o mejorar las existentes.

Es el caso de RASA, que con la evolución hacia CALM ha sabido dotar a su asistente virtual de capacidades mucho mayores con mucho menos esfuerzo. Ahora nos centraremos principalmente en gestionar el happy path de la conversación y proporcionar las acciones personalizadas que permitan interactuar con nuestros sistemas transaccionales, sin preocuparnos de todos los flujos alternativos en la que la conversación puede derivar. Sin duda alguna, la mejora es espectacular con respecto a la versión anterior.

Espero que os haya gustado este tutorial y que os sigáis animando a explorar este increíble mundo de la inteligencia artificial aplicada a los asistentes virtuales.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad