intent:afirmar
- sí
- si claro
- por supuesto
- ok
- afirmativo
- así es
- sin duda
intent:negar
- No
- para nada
- no me gusta
- Nunca
- Claro que no
- jamás
- no no no
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 6170all-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 6170wp-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 6170The post Aprende a usar los “forms” de RASA: un sencillo chatbot de ejemplo first appeared on Planeta Chatbot.
]]>En las partes anteriores demostré los conceptos básicos necesarios para construir chatbots con el framework Rasa, tales como los archivos requeridos, su estructura, y las principales características que ofrece.
En esta ocasión revisaremos los forms, que a mi parecer son de los componentes más útiles y versátiles que ofrece Rasa. Los forms son un conjunto de slots que deberán llenarse durante la conversación para finalmente ejecutar una tarea en específico, lo cual es muy útil cuando se busca obtener información puntual sobre el usuario.
Si bien en los casos anteriores no fue necesario mucho código, en Rasa, el concepto de los forms o formularios involucra el uso del rasa_sdk, que es la misma librería de Python utilizada para construir las acciones personalizadas.
Este chatbot es la traducción al español del formbot, un bot que Rasa provee como ejemplo en su repositorio de GitHub.
Para utilizar este bot debes instalar RASA y descargar el modelo de español de Spacy, puedes utilizar pip para hacerlo.
Puedes ver todo el código original en mi repositorio.
Nota:
Si deseas usar RASA 2.0, visita la guía de migración. Dado que esta versión aún se encuentra en sus etapas iniciales, seguiré usando la versión 1.10.
El objetivo del formbot de Rasa es demostrar la versatilidad de los formularios, y el ejemplo se trata de desarrollar un chatbot que pida al usuario los datos suficientes para realizar una búsqueda de restaurantes. Los datos que el usuario podrá ingresar son los siguientes:
Un extracto de los datos de entrenamiento para el lenguaje natural es el siguiente:
El intentsolicitar_restaurante tiene el objetivo de comunicar que el usuario desea buscar un restaurante, mientras que informar proporciona información sobre la búsqueda más en específico. En ambos casos se proporcionan entities que corresponden a los slots que serán requeridos por el formulario.
El intent charla contiene frases que no son relevantes para la conversación o que no están contempladas en el alcance del chatbot. Más adelante usaremos este intent.
El formato para las historias de entrenamiento de la conversación se verá de la siguiente forma:
## camino feliz
* saludar
- utter_saludar
* solicitar_restaurante
- restaurante_form
- form{"name": "restaurante_form"}
- form{"name": null}
- utter_valores_slots
* gracias
- utter_denada
## charla, detenerse pero continuar
* solicitar_restaurante
- restaurante_form
- form{"name": "restaurante_form"}
* charla
- utter_charla
- restaurante_form
* detener
- utter_ask_continuar
* afirmar
- restaurante_form
- form{"name": null}
- utter_valores_slots
* gracias
- utter_denada
En primera instancia analicemos cómo se incluyen los formularios en las historias de entrenamiento. Tenemos este fragmento:
* solicitar_restaurante
- restaurante_form
- form{"name": "restaurante_form"}
- form{"name": null}
El anterior extracto indica que cuando se detecte el intentsolicitar_restaurante, se correrá la acción de restaurante_form, la cual activará el formulario del mismo nombre, y una vez que se llenen todos los campos necesarios, el formulario se desactivará.
El formulario por sí solo se encargará de pedir los valores al usuario y de extraer la información, sin embargo, el formulario se puede interrumpir con otros intents y se puede regresar al formulario nuevamente, como en el siguiente fragmento:
* solicitar_restaurante
- restaurante_form
- form{"name": "restaurante_form"}
* charla
- utter_charla
- restaurante_form
* detener
- utter_ask_continuar
* afirmar
- restaurante_form
- form{"name": null}
- utter_valores_slots
* gracias
- utter_denada
En este ejemplo, el formulario se ve interrumpido por el intent charla, sin embargo se retoma la ejecución del formulario. Más adelante, se detiene con el intentdetener, se pregunta si se desea continuar, y ante la afirmación, se continua y finaliza la ejecución del formulario.
Ahora veremos cómo deben ser los archivos de dominio y configuración para poder hacer uso de los formularios en Rasa. En primer lugar, en el archivo domain.yml debemos declarar los slots que llenará nuestro formulario. Estos deben ser de tipo unfeaturized y con auto_fill en falso. Asimismo, se deben añadir respuestas con nombres de la forma utter_ask_{slot} para cada slot que llene el formulario.
entities:
- cocina
- asiento
- comentarios
- number # duckling
slots:
cocina:
type: unfeaturized
auto_fill: false
numero_personas:
type: unfeaturized
auto_fill: false
asiento_exterior:
type: unfeaturized
auto_fill: false
preferencias:
type: unfeaturized
auto_fill: false
comentarios:
type: unfeaturized
auto_fill: false
requested_slot:
type: unfeaturized
responses:
utter_ask_cocina:
- text: "¿Qué tipo de cocina?"
utter_ask_numero_personas:
- text: "¿Para cuántas personas?"
utter_ask_asiento_exterior:
- text: "¿Quieres un asiento en el exterior?"
utter_ask_preferencias:
- text: "Por favor proporciona preferencias adicionales"
utter_ask_comentarios:
- text: "Por favor proporciona comentarios sobre tu experiencia hasta ahora"
forms:
- restaurante_form
Tomando como ejemplo el anterior fragmento, tenemos el slot cocina, entonces agregamos el utter_ask_cocina. Estas respuestas se mostrarán automáticamente cuando el formulario necesite los llenar los slots.
Es importante mencionar que se debe agregar el slotrequested_slot, que es en donde se almacenará el nombre del slot que se buscará llenar en el formulario. También se deben agregar todos los formularios que se vayan a usar bajo el apartado forms.
En el archivo config.yml debemos incluir FormPolicy en las policies para poder hacer uso de los formularios.
language: es
pipeline:
- name: SpacyNLP
- name: SpacyTokenizer
- name: SpacyFeaturizer
- name: RegexFeaturizer
- name: DucklingHTTPExtractor
url: http://localhost:8000
dimensions:
- number
- name: DIETClassifier
epochs: 100
- name: EntitySynonymMapper
policies:
- name: FallbackPolicy
- name: MemoizationPolicy
- name: FormPolicy
- name: MappingPolicy
El último paso para poder hacer uso de nuestro formulario es agregar el código para controlar su comportamiento, haciendo uso del rasa_sdk, el cual es sumamente flexible.
El siguiente código muestra la implementación de un FormAction para nuestro formulario.
from typing import Dict, Text, Any, List, Union, Optional
from rasa_sdk import Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormAction
class RestaurantForm(FormAction):
def name(self) -> Text:
return "restaurante_form"
@staticmethod
def required_slots(tracker: Tracker) -> List[Text]:
return ["cocina", "numero_personas", "asiento_exterior", "preferencias", "comentarios"]
def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
return {
"cocina": self.from_entity(entity="cocina", not_intent="chitchat"),
"numero_personas": [
self.from_entity(
entity="number", intent=["informar", "solicitar_restaurante"]
),
],
"asiento_exterior": [
self.from_entity(entity="asiento"),
self.from_intent(intent="afirmar", value=True),
self.from_intent(intent="negar", value=False),
],
"preferencias": [
self.from_intent(intent="negar", value="Sin preferencias adicionales"),
self.from_text(not_intent="afirmar"),
],
"comentarios": [self.from_entity(entity="comentarios"), self.from_text()],
}
@staticmethod
def cocina_db() -> List[Text]:
return [
"caribeña",
"china",
"francesa",
"griega",
"india",
"italiana",
"mexicana",
]
@staticmethod
def is_int(string: Text) -> bool:
try:
int(string)
return True
except ValueError:
return False
def validate_cocina(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
if value.lower() in self.cocina_db():
return {"cocina": value}
else:
dispatcher.utter_message(template="utter_cocina_equivocada")
return {"cocina": None}
def validate_numero_personas(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
if self.is_int(value) and int(value) > 0:
return {"numero_personas": value}
else:
dispatcher.utter_message(template="utter_numero_personas_equivocada")
return {"numero_personas": None}
def validate_asiento_exterior(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
if isinstance(value, str):
if "afuera" in value:
return {"asiento_exterior": True}
elif "adentro" in value:
return {"asiento_exterior": False}
else:
dispatcher.utter_message(template="utter_asiento_exterior_equivocado")
return {"asiento_exterior": None}
else:
return {"asiento_exterior": value}
def submit(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> List[Dict]:
dispatcher.utter_message(template="utter_submit")
return []
¡Vaya! Tal vez parece mucho código pero su funcionamiento es muy sencillo. Veamos paso a paso qué es lo que hace este código.
Primero importamos las clases necesarias y declaramos una nueva clase RestaurantForm que hereda de FormAction. Una vez hecho esto, definiremos una serie de métodos para esta clase:
def validate_cocina(
self,
value: Text,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any],
) -> Dict[Text, Any]:
if value.lower() in self.cocina_db():
return {"cocina": value}
else:
dispatcher.utter_message(
template="utter_cocina_equivocada")
return {"cocina": None}
Si el tipo de cocina solicitado no se encuentra en la “base de datos” de cocinas, se arroja un mensaje al usuario y se volverá a preguntar por el tipo de cocina. En el caso contrario, se acepta la entrada y se continúa con el flujo.
Una vez listos todos los archivos, podemos proceder a probar nuestro chatbot.
En este bot haremos uso de Duckling para extraer datos numéricos (notarás que no incluimos datos de entrenamiento para este caso), entonces primero debemos correr una instancia local de este servicio con:
docker run -p 8000:8000 -d rasa/duckling
Ahora, para poder hacer uso de las acciones que escribimos, corramos un servidor de acciones de Rasa con el comando:
rasa run actions &
Y finalmente podremos interactuar con el chatbot. Con el comando siguiente podremos iniciar una sesión de conversación en la terminal:
rasa shell
Aquí tenemos un ejemplo de un “camino feliz”:

Demostrando la flexibilidad de los formularios:

Finalmente un “camino infeliz”:

Espero que este tutorial te haya sido de utilidad, si tienes algún problema con el tutorial, por favor, escríbeme y con gusto te ayudaré.
Recuerda que todo el código se encuentra en mi GitHub:
Arctic Code…github.com
The post Aprende a usar los “forms” de RASA: un sencillo chatbot de ejemplo first appeared on Planeta Chatbot.
]]>The post Crea un chatbot de Pokémon en español con RASA first appeared on Planeta Chatbot.
]]>En la primera parte de los tutoriales de RASA en español construimos un chatbot muy sencillo cuyo propósito era demostrar la estructura de los archivos que utiliza el framework, así como sus principales características.
Aquel bot no tiene mayor utilidad, por lo que en esta segunda parte introduciremos nuevos conceptos y al mismo tiempo crearemos un proyecto más complejo, utilizando la PokéApi.
El objetivo será desarrollar un chatbot que permita al usuario buscar información acerca de cualquier Pokémon, ya sea proporcionando su nombre o su número.
Pokébot en acción
Para utilizar este bot debes instalar RASA y descargar el modelo de español de Spacy, puedes utilizar pip para hacerlo. Personalmente utilizo la versión 1.10.1, pero no debería haber problema con las versiones, al menos para este ejemplo.
De igual manera he preparado un Dockerfile con lo necesario para ejecutar este bot. Puedes ver todo el código original en mi repositorio.
Nota:
Si deseas usar RASA 2.0, visita la guía de migración. Dado que esta versión aún se encuentra en etapa de pre-release, seguiré usando la versión 1.10.
¿Cómo va a saber el chatbot qué buscar? De alguna manera necesitamos almacenar ya sea el nombre o el número del Pokémon a buscar para poder utilizarlo en el PokéApi. RASA soporta métodos de Reconocimiento de Entidades, los cuales serán útiles para esta tarea.
Partiremos del archivo config.yml del anterior tutorial. Antes que nada, habilitaremos el Reconocimiento de Entidades en el componente DIETClassifier:
Ahora debemos enseñar al chatbot cómo reconocer un nombre o un número de Pokémon, para lo cual nos dirigiremos al archivo nlu.md. Veamos el siguiente ejemplo:
Únicamente tenemos dos intents: saludo y buscar_pokemon. Si te fijas, en los ejemplos de buscar_pokemon hay ciertas palabras marcadas, así es como se etiquetan las entidades para el entrenamiento del chatbot:
- buscar a [Electabuzz](nombre_pokemon) - buscar al pokemon [88](numero_pokemon)
De esta manera se indica que Electabuzz es una entidad de tipo nombre_pokemon, así como 88 es una entidad de tipo numero_pokemon.
Además, se agregó una expresión regular para numero_pokemon, ya que se puede modelar como un número de máximo tres dígitos, y de esta manera mejorar el reconocimiento de esta entidad.
Ahora que hemos indicado al chatbot cómo reconocer entidades, ¿dónde las almacena? RASA cuenta con los llamados slots, que son valores almacenados en la memoria del bot durante la conversación. Para comenzar a utilizar slots, debemos agregarlos en domain.yml.
Hemos declarado los entities para reconocer nombre_pokemon y numero_pokemon, así como los slots para almacenar nombre_pokemon y numero_pokemon. Si un slot lleva el mismo nombre que un entity, el valor identificado de la entidad se asigna automáticamente a ese slot.
Además de lo anterior, agregamos el mensaje utter_info_pokemon para desplegar la información encontrada a través del PokéApi, en este caso el número, el nombre, los tipos y una imagen. Más adelante revisaremos cómo llenar estos campos.
Habrás notado que en domain.yml también hay un apartado llamado actions, donde he listado action_buscar_pokemon. Los actions en RASA son piezas de código en Python que se ejecutan durante la conversación. Estas acciones pueden contener funciones de todo tipo: ejecutar solicitudes a APIs, operaciones sobre bases de datos, cálculos, modificación de la conversación misma, etc.
Antes de ver a detalle el action para este chatbot, definamos en qué punto de la conversación se va ejecutar. Para esto, escribamos el archivo stories.md.
En las historias expresaremos que un usuario proporcionó el valor de un entity en un dado intent con la notación siguiente:
* intent{"entity": "valor"}
Entonces, en las historias hemos definido que se ejecute action_buscar_pokemon en cuando se proporcione un nombre_pokemon o un numero_pokemon.
Los actions son ejecutados desde un action server, el cual requiere de un archivo llamado actions.py, donde estará el código correspondiente para cada uno.
Para desarrollar un action, haremos uso de la librería Rasa SDK, incluida en la instalación de RASA. Un action debe ser una clase que hereda de rasa_sdk.Action y que implementa el método run.
El siguiente es el archivo actions.py que desarrollé para el PokéBot (he omitido las variables POKEAPI_URL y POKEMON_TIPOS por simplicidad):
Dentro de la acción, para obtener los valores almacenados en los slots haremos uso del tracker, que es el objeto que contiene toda la información de la conversación actual.
Según el slot que encontremos, ya sea numero_pokemon o nombre_pokemon, haremos una petición al PokéApi, con ayuda del módulo requests.
Finalmente, extraemos la información necesaria del JSON que obtuvimos como respuesta a la petición, para presentarla en el mensaje utter_info_pokemon.
El tipo de dato que el método run debe devolver es una lista de events, en este caso únicamente borraremos la información almacenada en los slots, para poder almacenar nuevos valores.
Por último, debemos indicar a RASA dónde buscar las acciones, esto se hará a través del archivo endpoints.yml:
Con todos los componentes listos, podemos proceder a probar nuestro chatbot. Como siempre, empezaremos por entrenarlo.
rasa train
Una vez finalizado el entrenamiento ejecutaremos tanto el servidor de acciones como el de RASA, lo cual recomiendo hacer en diferentes terminales.
Para ejecutar el servidor de acciones, ejecuta el siguiente comando:
rasa run actions
Para ejecutar el chatbot, en otra terminal, ejecuta el este comando:
rasa shell
Ahora podrás hablar con el chatbot a través de la línea de comandos. Podrás interactuar con el bot de esta forma:
Pokébot en Rasa shell
El chatbot es capaz de reconocer el nombre o número de un Pokémon y obtener su información a través de la PokéApi. Hay que mencionar que el entrenamiento no ha sido intensivo ni hemos hecho muchos ajustes, por lo cual es posible que no funcione correctamente con algunos nombres de Pokémon.
Espero que este tutorial te haya sido de utilidad, si tienes algún problema con el tutorial, por favor, escríbeme y con gusto te ayudaré.
Más tutoriales de RASA en español por venir. Por lo pronto, visita mi GitHub:
Arctic Code…github.com
The post Crea un chatbot de Pokémon en español con RASA first appeared on Planeta Chatbot.
]]>The post Construyendo un Chatbot en español usando RASA — Moodbot first appeared on Planeta Chatbot.
]]>Sabía que se tiene que procesar el texto y producir un mensaje con base en esto, pero desconocía las técnicas apropiadas.
Teniendo conocimientos de Python, investigué las opciones disponibles para la creación de asistentes en dicho lenguaje, y entonces encontré Rasa.
Rasa es un framework para la creación de asistentes y chatbots, escrito en Python y de código abierto. Basa su funcionamiento en dos componentes principales, NLU y Core:
Ambos elementos utilizan técnicas de aprendizaje de máquina.
Si tienes experiencia en aprendizaje de máquina será más fácil que comprendas los pasos siguientes, de lo contrario, no te asustes, no tendrás que escribir código, Rasa es muy fácil de configurar.
Para utilizar este bot debes instalar RASA, puedes utilizar pip para hacerlo. Personalmente utilizo la versión 1.10.1, pero no debería haber problema con las versiones, al menos para este ejemplo.
De igual manera he preparado un Dockerfile con lo necesario para ejecutar este bot. Puedes ver todo el código original en mi repositorio.
Aunque no lo creas, este primer bot será creado con tan sólo 4 archivos. Sí, no es broma, para la creación de este chatbot básico (al que Rasa llama Moodbot) necesitaremos 4 archivos. Cada uno de ellos nos ayudará a entender mejor el funcionamiento de Rasa.
En este primer archivo describiremos la manera en la que el bot comprenderá el texto. Aquí enlistaremos los intents, que son las intenciones o propósitos que buscaremos captar del usuario, por ejemplo, el mensaje “buenos días” tiene como intención “saludar”, mientras que el mensaje “¿cómo estará el clima mañana?” tiene la intención “consultar clima”.
Para cada intent que se busque clasificar se deberán proporcionar textos de ejemplo, a través de los cuales el bot se entrenará. El formato a utilizar es el siguiente:
En este archivo se escriben las interacciones entre el bot y el usuario con las que se entrenará el asistente. Se deben incluir múltiples ejemplos de “historias”, con el objetivo de que el bot pueda decidir cuál es la mejor acción a tomar después de una interacción con el usuario.
Los intents del usuario se colocan con asteriscos (*), mientras que las acciones o mensajes del bot se escriben con guiones (-). Las historias pueden tener títulos, sin embargo estos no afectarán el entrenamiento. El archivo debe mantener el siguiente formato:
En este archivo debemos registrar todos los intents que buscaremos captar del usuario, así como los mensajes (utterances) y acciones (actions) que el bot realizará. Aquí es donde definiremos el texto que contendrán los mensajes que incluimos en las interacciones de stories.md. A continuación un ejemplo de este archivo:
Si te das cuenta, incluso se pueden incluir imágenes en las respuestas que proporcionará el bot.
Por último tenemos el archivo de configuración. Aquí se definirá el pipeline, que son los procesos que se le aplicarán al texto de entrada para que el bot pueda usarlo. Cada parte del pipeline es un componente diferente que ayuda en las tareas de Lenguaje Natural, por ejemplo:
De igual manera, en este archivo se listan las políticas (policies) bajo las cuales se regirá la conversación. Cada política tiene un principio de funcionamiento diferente, y la combinación de ellas hace que el bot sea más robusto y pueda tomar mejores decisiones. Ejemplos de policies son los siguientes:
Con estos 4 archivos listos, podemos proceder a utilizar el bot por primera vez. Empezaremos por entrenar el bot.
rasa train
Con este comando entrenarás tanto la parte NLU como la parte Core del chatbot. Después de un momento, cuando finalice el entrenamiento, podrás usar el siguiente comando:
rasa shell
Con este último podrás interactuar con el chatbot a través de la línea de comandos. Puedes experimentar un poco y ver qué responde ante respuestas diferentes, aunque toma en cuenta que este ejemplo es muy simple.
Si te interesa ejecutar el chatbot en Docker, he creado en el repositorio para este tutorial un archivo Dockerfile.
La imagen de la cual partimos es una que yo he creado, la cual contiene el modelo de lenguaje de español, que es útil para obtener features en el pipeline. Los pasos restantes son añadir los archivos y entrenar el modelo.
Puedes construir la imagen con el comando:
docker build -t moodbot-es .
Y ejecutarlo con:
docker run -it --entrypoint rasa moodbot-es shell
Aquí puedes encontrar la segunda parte de este tutorial.
Espero que este tutorial te haya sido de utilidad. Escribiré más tutoriales de RASA en español en el futuro. Por lo pronto, visita mi GitHub:
github.com
The post Construyendo un Chatbot en español usando RASA — Moodbot first appeared on Planeta Chatbot.
]]>