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
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:
- 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.
- 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.
- 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:
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 🙂 ):
Y ahora, vamos a hacer una transferencia:
Y ahora, vamos a consultar el saldo y los 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.