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 Cómo construir un asistente de voz con herramientas de código abierto como Rasa y Mozilla first appeared on Planeta Chatbot.
]]>Con plataformas como Google Assistant y Alexa que son cada vez más populares, los asistentes de voz están destinados a ser la próxima herramienta para las interacciones con los clientes en varias industrias. Sin embargo, a menos que utilices soluciones comerciales alojadas, el desarrollo de asistentes de voz viene con un conjunto completamente nuevo de desafíos que van más allá de la NLU y la gestión del diálogo; además de esos temas, debes ocuparte de la transcripción del habla a texto, componentes de texto a voz, la interfaz… Tocamos el tema de la voz hace algún tiempo cuando experimentamos con la construcción de un Google Assistant con tecnología Rasa. Aprovechar plataformas como Google Assistant elimina el obstáculo de implementar el procesamiento de voz y los frontend components, pero obliga a comprometer la seguridad de tus datos y la flexibilidad de las herramientas que utilizas. Entonces, ¿qué opciones tienes si deseas crear un asistente de voz que se ejecute localmente y garantice la seguridad de tus datos? Bueno, descubrámoslo. En este post, aprenderás cómo puedes crear un asistente de voz utilizando solo herramientas de código abierto, desde el backend hasta la interfaz.
El objetivo de esta publicación es mostrarte cómo puedes crear tu propio asistente de voz utilizando solo herramientas de código abierto. En general, hay cinco componentes principales que son necesarios para construir un asistente de voz:

Si bien Rasa de código abierto es una opción bastante obvia para NLU y la gestión de diálogo, decidir sobre STT y TTS es una tarea más difícil simplemente porque no hay muchos marcos de código abierto para elegir. Después de explorar las opciones disponibles actualmente: CMUSphinx, Mozilla DeepSpeech, Mozilla TTS, Kaldi, decidimos utilizar las herramientas de Mozilla : Mozilla DeepSpeech y Mozilla TTS . Esto es porque:
¿Qué es Mozilla DeepSpeech y Mozilla TTS? Mozilla DeepSpeech es un marco de voz a texto que toma la entrada del usuario en un formato de audio y utiliza el aprendizaje automático para convertirlo a un formato de texto que luego puede ser procesado por la NLU y el sistema de diálogo. Mozilla TTS se encarga de lo contrario: toma la entrada (en nuestro caso, la respuesta del asistente producido por un sistema de diálogo) en un formato de texto y utiliza el aprendizaje automático para crear una representación de audio.
Los componentes de NLU, gestión de diálogo y procesamiento de voz cubren el backend del asistente de voz, ¿qué pasa con la interfaz? Bueno, aquí es donde radica el mayor problema: si buscas los widgets de interfaz de voz de código abierto, es muy probable que termines sin resultados. ¡Al menos esto es lo que nos pasó y es por eso que desarrollamos nuestra propia interfaz de voz Rasa que utilizamos para este proyecto y estamos felices de compartirla con la comunidad!
Para resumir, aquí están los ingredientes del asistente de voz de código abierto:
Para este proyecto, vamos a utilizar un asistente de Rasa existente: Sara . Es un asistente de código abierto impulsado por Rasa que puede responder varias preguntas sobre el marco Rasa y ayudarte a comenzar. A continuación se muestra un ejemplo de conversación con Sara:

Estos son los pasos sobre cómo configurar Sara en su entorno de desarrollo:
git clone https://github.com/RasaHQ/rasa-demo.git cd rasa-demo
2. Instala las dependencias necesarias:
pip install -e .
3. Capacitar a la NLU y los modelos de diálogo:
rasa train --augmentation 0
4. Prueba Sara en tu terminal:
docker run -p 8000:8000 rasa/duckling rasa run actions --actions demo.actions make run-cmdline
Para convertir a Sara en un asistente de voz, tendremos que editar algunos de los archivos del proyecto en las etapas posteriores de la implementación. Antes de hacer eso, implementamos los componentes TTS y STT.
Implementemos el componente de voz a texto: modelo Mozilla DeepSpeech. Echa un vistazo a esta publicación del blog de Rouben Morais para obtener más información sobre cómo funciona Mozilla DeepSpeech bajo el capó. Mozilla DeepSpeech viene con algunos modelos previamente entrenados y te permite entrenar el tuyo. En aras de la simplicidad, utilizamos un modelo previamente capacitado para este proyecto. Estos son los pasos para configurar STT en tu entorno de desarrollo:
pip3 install deepspeech
2. Descarga un modelo de texto a voz previamente capacitado y descomprímelo en el directorio de su proyecto:
wget https://github.com/mozilla/DeepSpeech/releases/download/v0.5.1/deepspeech-0.5.1-models.tar.gz tar xvfz deepspeech-0.5.1-models.tar.gz
3. Prueba el modelo.
La mejor manera de verificar si el componente se configuró correctamente es probar el modelo en algunas entradas de audio de muestra. El siguiente script te ayudará a hacer eso:
Ejecuta el script usando el comando a continuación y una vez que veas el mensaje ‘ Grabando… ‘ pronuncia una oración con la que te gustaría probar el modelo:
python deepspeech_test_prediction.py
En la siguiente parte de este post, aprenderás cómo configurar la tercera parte del proyecto: el componente de texto a voz.
Para permitir que el asistente responda con voz en lugar de texto, tenemos que configurar el componente de texto a voz que tomará la respuesta generada por Rasa y la convertirá en un sonido. Para eso, utilizamos Mozilla TTS . Al igual que Mozilla DeepSpeech, viene con modelos previamente entrenados, pero también puedes entrenar tus propios modelos utilizando datos personalizados. Esta vez también utilizaremos un modelo TTS pre-entrenado. Aquí se explica cómo configurar el componente TTS en tu entorno de desarrollo:
git clone https://github.com/mozilla/TTS.git cd TTS git checkout db7f3d3
2. Instala el paquete:
python setup.py develop
3. Descarga el modelo:
En tu directorio de Sara, crea una carpeta llamada tts_model y coloca los archivos de modelo descargados desde aquí (solo necesitas config.json y best_model.th.tar )
4. Prueba el componente:
Puedes usar el siguiente script para probar el componente de texto a voz. Esto es lo que hace el script:
Puedes cambiar la variable de oración con una entrada personalizada en la que te gustaría probar el modelo. Una vez que el script deja de ejecutarse, el resultado se guardará en el archivo test_tts.wav que puedes escuchar para probar el rendimiento del modelo.
import os
import sys
import io
import torch
from collections import OrderedDict
from TTS.models.tacotron import Tacotron
from TTS.layers import *
from TTS.utils.data import *
from TTS.utils.audio import AudioProcessor
from TTS.utils.generic_utils import load_config
from TTS.utils.text import text_to_sequence
from TTS.utils.synthesis import synthesis
from utils.text.symbols import symbols, phonemes
from TTS.utils.visual import visualize
# Set constants
MODEL_PATH = './tts_model/best_model.pth.tar'
CONFIG_PATH = './tts_model/config.json'
OUT_FILE = 'tts_out.wav'
CONFIG = load_config(CONFIG_PATH)
use_cuda = False
def tts(model, text, CONFIG, use_cuda, ap, OUT_FILE):
waveform, alignment, spectrogram, mel_spectrogram, stop_tokens = synthesis(model, text, CONFIG, use_cuda, ap)
ap.save_wav(waveform, OUT_FILE)
return alignment, spectrogram, stop_tokens
def load_model(MODEL_PATH, sentence, CONFIG, use_cuda, OUT_FILE):
# load the model
num_chars = len(phonemes) if CONFIG.use_phonemes else len(symbols)
model = Tacotron(num_chars, CONFIG.embedding_size, CONFIG.audio['num_freq'], CONFIG.audio['num_mels'], CONFIG.r, attn_windowing=False)
# load the audio processor
# CONFIG.audio["power"] = 1.3
CONFIG.audio["preemphasis"] = 0.97
ap = AudioProcessor(**CONFIG.audio)
# load model state
if use_cuda:
cp = torch.load(MODEL_PATH)
else:
cp = torch.load(MODEL_PATH, map_location=lambda storage, loc: storage)
# load the model
model.load_state_dict(cp['model'])
if use_cuda:
model.cuda()
model.eval()
model.eval()
model.decoder.max_decoder_steps = 1000
align, spec, stop_tokens = tts(model, sentence, CONFIG, use_cuda, ap, OUT_FILE)
if __name__ == '__main__':
sentence = "Hello, how are you doing? My name is Sara"
load_model(MODEL_PATH, sentence, CONFIG, use_cuda, OUT_FILE)
En este punto, debes tener todos los componentes más importantes ejecutándose en el entorno de desarrollo: el asistente Rasa, componentes de voz a texto y de texto a voz. Todo lo que queda por hacer es juntar todos estos componentes y conectar el asistente a la interfaz de voz Rasa. Aprende cómo puedes hacerlo en el siguiente paso de este post.
Para juntar todas las piezas y poner el asistente de voz en acción, necesitamos dos cosas:
Primero configuremos la interfaz de voz Rasa. Aquí esos dejo cómo hacerlo:
git clone https://github.com/RasaHQ/rasa-voice-interface.git cd rasa-voice-interface
3. Instala el componente:
npm install
4. Pruébalo:
npm run serve
Una vez que ejecutes el comando anterior, abre un navegador y entra en https: //localhost: 8080 para verificar si la interfaz de voz se está cargando. Una pelota que salta indica que se ha cargado correctamente y está esperando la conexión.

Para conectar el asistente a la interfaz, necesitas un conector. El conector también determinará qué sucede cuando el usuario dice algo y cómo la respuesta de audio se devuelve al frontend component. Para crear un conector, podemos usar un conector socketio existente y actualizarlo con algunos componentes nuevos:
A continuación, puede encontrar un código completo del conector actualizado:
import logging
import uuid
from sanic import Blueprint, response
from sanic.request import Request
from socketio import AsyncServer
from typing import Optional, Text, Any, List, Dict, Iterable
from rasa.core.channels.channel import InputChannel
from rasa.core.channels.channel import UserMessage, OutputChannel
import deepspeech
from deepspeech import Model
import scipy.io.wavfile as wav
import os
import sys
import io
import torch
import time
import numpy as np
from collections import OrderedDict
import urllib
import librosa
from TTS.models.tacotron import Tacotron
from TTS.layers import *
from TTS.utils.data import *
from TTS.utils.audio import AudioProcessor
from TTS.utils.generic_utils import load_config
from TTS.utils.text import text_to_sequence
from TTS.utils.synthesis import synthesis
from utils.text.symbols import symbols, phonemes
from TTS.utils.visual import visualize
logger = logging.getLogger(__name__)
def load_deepspeech_model():
N_FEATURES = 25
N_CONTEXT = 9
BEAM_WIDTH = 500
LM_ALPHA = 0.75
LM_BETA = 1.85
ds = Model('deepspeech-0.5.1-models/output_graph.pbmm', N_FEATURES, N_CONTEXT, 'deepspeech-0.5.1-models/alphabet.txt', BEAM_WIDTH)
return ds
def load_tts_model():
MODEL_PATH = './tts_model/best_model.pth.tar'
CONFIG_PATH = './tts_model/config.json'
CONFIG = load_config(CONFIG_PATH)
use_cuda = False
num_chars = len(phonemes) if CONFIG.use_phonemes else len(symbols)
model = Tacotron(num_chars, CONFIG.embedding_size, CONFIG.audio['num_freq'], CONFIG.audio['num_mels'], CONFIG.r, attn_windowing=False)
num_chars = len(phonemes) if CONFIG.use_phonemes else len(symbols)
model = Tacotron(num_chars, CONFIG.embedding_size, CONFIG.audio['num_freq'], CONFIG.audio['num_mels'], CONFIG.r, attn_windowing=False)
# load the audio processor
# CONFIG.audio["power"] = 1.3
CONFIG.audio["preemphasis"] = 0.97
ap = AudioProcessor(**CONFIG.audio)
# load model state
if use_cuda:
cp = torch.load(MODEL_PATH)
else:
cp = torch.load(MODEL_PATH, map_location=lambda storage, loc: storage)
# load the model
model.load_state_dict(cp['model'])
if use_cuda:
model.cuda()
#model.eval()
model.decoder.max_decoder_steps = 1000
return model, ap, MODEL_PATH, CONFIG, use_cuda
ds = load_deepspeech_model()
model, ap, MODEL_PATH, CONFIG, use_cuda = load_tts_model()
class SocketBlueprint(Blueprint):
def __init__(self, sio: AsyncServer, socketio_path, *args, **kwargs):
self.sio = sio
self.socketio_path = socketio_path
super(SocketBlueprint, self).__init__(*args, **kwargs)
def register(self, app, options):
self.sio.attach(app, self.socketio_path)
super(SocketBlueprint, self).register(app, options)
class SocketIOOutput(OutputChannel):
@classmethod
def name(cls):
return "socketio"
def __init__(self, sio, sid, bot_message_evt, message):
self.sio = sio
self.sid = sid
self.bot_message_evt = bot_message_evt
self.message = message
def tts(self, model, text, CONFIG, use_cuda, ap, OUT_FILE):
import numpy as np
waveform, alignment, spectrogram, mel_spectrogram, stop_tokens = synthesis(model, text, CONFIG, use_cuda, ap)
ap.save_wav(waveform, OUT_FILE)
wav_norm = waveform * (32767 / max(0.01, np.max(np.abs(waveform))))
return alignment, spectrogram, stop_tokens, wav_norm
def tts_predict(self, MODEL_PATH, sentence, CONFIG, use_cuda, OUT_FILE):
align, spec, stop_tokens, wav_norm = self.tts(model, sentence, CONFIG, use_cuda, ap, OUT_FILE)
return wav_norm
async def _send_audio_message(self, socket_id, response, **kwargs: Any):
# type: (Text, Any) -> None
"""Sends a message to the recipient using the bot event."""
ts = time.time()
OUT_FILE = str(ts)+'.wav'
link = "http://localhost:8888/"+OUT_FILE
wav_norm = self.tts_predict(MODEL_PATH, response['text'], CONFIG, use_cuda, OUT_FILE)
await self.sio.emit(self.bot_message_evt, {'text':response['text'], "link":link}, room=socket_id)
async def send_text_message(self, recipient_id: Text, message: Text, **kwargs: Any) -> None:
"""Send a message through this channel."""
await self._send_audio_message(self.sid, {"text": message})
class SocketIOInput(InputChannel):
"""A socket.io input channel."""
@classmethod
def name(cls):
return "socketio"
@classmethod
def from_credentials(cls, credentials):
credentials = credentials or {}
return cls(credentials.get("user_message_evt", "user_uttered"),
credentials.get("bot_message_evt", "bot_uttered"),
credentials.get("namespace"),
credentials.get("session_persistence", False),
credentials.get("socketio_path", "/socket.io"),
)
def __init__(self,
user_message_evt: Text = "user_uttered",
bot_message_evt: Text = "bot_uttered",
namespace: Optional[Text] = None,
session_persistence: bool = False,
socketio_path: Optional[Text] = '/socket.io'
):
self.bot_message_evt = bot_message_evt
self.session_persistence = session_persistence
self.user_message_evt = user_message_evt
self.namespace = namespace
self.socketio_path = socketio_path
def blueprint(self, on_new_message):
sio = AsyncServer(async_mode="sanic")
socketio_webhook = SocketBlueprint(
sio, self.socketio_path, "socketio_webhook", __name__
)
@socketio_webhook.route("/", methods=['GET'])
async def health(request):
return response.json({"status": "ok"})
@sio.on('connect', namespace=self.namespace)
async def connect(sid, environ):
logger.debug("User {} connected to socketIO endpoint.".format(sid))
print('Connected!')
@sio.on('disconnect', namespace=self.namespace)
async def disconnect(sid):
logger.debug("User {} disconnected from socketIO endpoint."
"".format(sid))
@sio.on('session_request', namespace=self.namespace)
async def session_request(sid, data):
print('This is sessioin request')
if data is None:
data = {}
if 'session_id' not in data or data['session_id'] is None:
data['session_id'] = uuid.uuid4().hex
await sio.emit("session_confirm", data['session_id'], room=sid)
logger.debug("User {} connected to socketIO endpoint."
"".format(sid))
@sio.on('user_uttered', namespace=self.namespace)
async def handle_message(sid, data):
output_channel = SocketIOOutput(sio, sid, self.bot_message_evt, data['message'])
if data['message'] == "/get_started":
message = data['message']
else:
##receive audio
received_file = 'output_'+sid+'.wav'
urllib.request.urlretrieve(data['message'], received_file)
path = os.path.dirname(__file__)
fs, audio = wav.read("output_{0}.wav".format(sid))
message = ds.stt(audio, fs)
await sio.emit(self.user_message_evt, {"text":message}, room=sid)
message_rasa = UserMessage(message, output_channel, sid,
input_channel=self.name())
await on_new_message(message_rasa)
return socketio_webhook
Guarda este código en el directorio de tu proyecto como socketio_connector.py.
Lo último que debe configurarse antes de que puedas darle un giro es la configuración del conector, ya que creamos un conector personalizado, tenemos que decirle a Rasa que use este conector personalizado para recibir las entradas del usuario y enviar las respuestas. Para hacerlo, crea un archivo credentials.yml en el directorio del proyecto de Sara y proporciona los siguientes detalles (aquí socketio_connector es el nombre del módulo donde se implementa el conector personalizado, mientras que SocketIOInput es el nombre de la clase de entrada del conector personalizado):
socketio_connector.SocketIOInput: bot_message_evt: bot_uttered session_persistence: true user_message_evt: user_uttered
¡Eso es! Todo lo que queda por hacer es iniciar el asistente y tener una conversación con él. Aquí te explico cómo hacerlo:
rasa run --enable-api -p 5005
2. Inicia el servidor de acciones personalizadas Rasa:
rasa run actions --actions demo.actions
3. Uno de los componentes de Sara es el componente DucklingHTTPExtractor . Para usarlo, inicia un servidor:
docker run -p 8000:8000 rasa/duckling
4. Inicia un servidor http simple para enviar los archivos de audio al cliente:
python3 -m http.server 8888
Si actualizas la interfaz de voz Rasa en tu navegador, deberías ver que el asistente está listo para hablar:

¡Haz clic en Inicio y mantén una conversación con un asistente de voz creado utilizando solo herramientas de código abierto!
6. ¿Qué sigue?
El desarrollo de asistentes de voz viene con un conjunto completamente nuevo de desafíos: ya no se trata solo de la buena NLU y el diálogo, necesita buenos componentes STT y TTS y tu NLU debe ser lo suficientemente flexible como para compensar los errores cometidos por STT. Si replicas este proyecto, notarás que el asistente no es perfecto y que hay mucho margen de mejora, especialmente en la etapa STT y NLU. ¿Cómo puedes mejorarlo? Aquí hay algunas ideas:
7. Resumen y recursos
En Rasa, buscamos constantemente formas de superar los límites de las herramientas y el software que permiten a los desarrolladores construir grandes cosas. Al compilar este proyecto, queríamos mostrarte que puedes usar Rasa para construir no solo texto, sino también asistentes de voz e inspirarlo para crear aplicaciones excelentes sin comprometer la seguridad y la flexibilidad de las herramientas que usa. ¿Has construido un asistente de voz con Rasa? ¿Qué herramientas usaste? Comparte tu experiencia con nosotros publicando al respecto en el foro de la comunidad Rasa.
The post Cómo construir un asistente de voz con herramientas de código abierto como Rasa y Mozilla first appeared on Planeta Chatbot.
]]>The post Más allá de ‘Ok Google’: construyendo un asistente de Google impulsado por Rasa first appeared on Planeta Chatbot.
]]>En este post, te mostraremos cómo puedes habilitar tu Asistente de Google para manejar conversaciones más profundas y más naturales al integrarlo con Rasa Stack. Hay una serie de razones por las que los desarrolladores eligen Rasa Stack para crear asistentes de conversación:
⦁ Es de código abierto, lo que permite la personalización completa del marco y garantiza que tenga la propiedad completa de los datos de su aplicación.
⦁ Utiliza el aprendizaje automático para dirigir el diálogo: aprende los patrones a partir de los datos conversacionales reales. Escala mucho mejor en producción que las reglas predefinidas o las máquinas de estado.
⦁ Puedes ejecutar tu asistente Rasa AI a través de múltiples canales, lo que significa que tu asistente puede ser accesible a través de diferentes plataformas de mensajería y voz.
Al combinar Rasa Stack con las poderosas capacidades de voz a texto de Google Assistant y una interfaz ampliamente utilizada, puedes llevar a tu asistente de AI a un nivel completamente nuevo. La integración de Rasa con interfaces de voz como el Asistente de Google es una función muy solicitada por nuestra Comunidad de Rasa , ¡así que sigue leyendo y aprende cómo realizar la integración tu mismo! Este es un ejemplo de lo que puedes lograr al seguir este tutorial:
1. El asistente de Rasa AI.
2. Inicializando la habilidad personalizada de Google Assistant.
3. Creando la acción personalizada de Google Assistant.
4. Creando el Rasa Connector para el Asistente de Google.
5. Poniendo todas las piezas juntas.
Estas son las herramientas y el software que necesitarás para crear un Asistente de Google basado en Rasa:
El objetivo principal de este tutorial es mostrarte cómo puedes conectar un agente de Rasa a Google Assistant y hacerlo más conversacional. Hay dos opciones de cómo puedes seguir este tutorial: puedes usar tu asistente Rasa personalizado o puedes tomar nuestro asistente de búsqueda de lugares preconstruido llamado Place Finder
y usarlo para hacer la integración.
Si eliges la primera opción, puedes ir al paso dos de este tutorial. Si eliges el segundo, ahora es el mejor momento para capturar el Place Finder mediante la clonación de este repositorio.
El asistente consta de los siguientes archivos:
⦁ data/nlu_data.md es un archivo que contiene los datos de entrenamiento para el modelo Rasa NLU. Estos datos consisten en ejemplos de consultas de usuarios junto con los intents y las entidades correspondientes.
⦁ El archivo config.yml contiene la configuración del canal de capacitación Rasa NLU. Define cómo se analizarán las entradas del usuario, cómo se extraerán las características y qué modelo de aprendizaje automático se usará para entrenar el modelo.
⦁ data/stories.md es un archivo que contiene datos de entrenamiento para el modelo Rasa Core. Estos datos consisten en historias: conversaciones reales entre un usuario y un asistente escritas en ⦁ formato Rasa , donde las entradas del usuario se expresan como intenciones y entidades correspondientes, y las respuestas del asistente se expresan como acciones.
⦁ domain.yml es un archivo que contiene la configuración del dominio del asistente. Se compone de las siguientes piezas:
⦁ Intenciones y entidades que se definen en los ejemplos de datos de capacitación de Rasa NLU;
⦁ Ranuras que funcionan como marcadores de posición para guardar los detalles que el asistente debe recordar durante la conversación;
⦁ Plantillas que definen las respuestas de texto que un asistente debe devolver cuando se pronostican las expresiones correspondientes
⦁ Acciones que el asistente debe poder predecir y ejecutar.
⦁ Actions.py es un archivo que contiene el código de la acción personalizada donde el asistente realiza una llamada a la API para recuperar los detalles sobre la ubicación actual del usuario y buscar el lugar especificado dentro del radio solicitado por el usuario. El asistente luego usa los detalles devueltos para generar la respuesta y almacena algunos de los detalles recuperados como espacios para que el asistente los use en las últimas etapas de la conversación.
⦁ Endpoints.yml contiene la configuración de webhook de acciones personalizadas.
⦁ Credentials.yml es un archivo para almacenar la clave de la API de Google Places.
Todos estos archivos están listos para su uso, todo lo que tienes que hacer es proporcionar tu clave API de Google Places al archivo credentials.yml y capacitar a los modelos. Entrena al modelo NLU usando el comando que encontrarás a continuación y que se encargará de llamar a la función NLU de Rasa, pasará los datos de entrenamiento y procesará los archivos de configuración de la pipeline, y guardará el modelo dentro del directorio models/current/nlu_model:
python -m rasa_nlu.train -c config.yml — data data/nlu_data.md -o models — fixed_model_name nlu_model — project current — verbose
Una vez que se haya capacitado al modelo NLU, adiestra el modelo Rasa Core utilizando el comando que verás a continuación y que llamará a la función de Rasa Core, pasará los datos de las historias y los archivos de dominio y guardará el modelo entrenado dentro del directorio de models/current/ dialogue:
python -m rasa_core.train -d domain.yml -s data/stories.md -o models/current/dialogue — epochs 200
Al capacitar a los modelos Rasa NLU y Rasa Core, crearás el cerebro de tu asistente de IA. Estos dos modelos serán responsables de comprender lo que dice el usuario y decidir cómo debe responder el asistente. Ahora es el momento de crear el oído y la boca del asistente utilizando el Asistente de Google.
La acción personalizada de Google Assistant empaquetará a tu agente Rasa como una habilidad personalizada y te permitirá utilizar el servicio de voz a texto de Google Assistant para habilitar la comunicación de voz con tu asistente. Primero, tienes que inicializar la acción personalizada de Google Assistant. Aquí sabrás como podrás hacerlo:

2. Establece el nombre de tu proyecto y eligue el idioma que deseas que use tu asistente. Haz click en ‘Crear proyecto’.

3. Una vez que se haya creado el proyecto, se te pedirá que ingreses a una página donde puedes elegir la categoría de tu proyecto. Desplázate hasta la parte inferior de la página y eligue la opción ‘Acciones SDK’. Al hacerlo, le dice a tu Asistente de Google que implementará su propia acción personalizada con un sistema personalizado de gestión de diálogos y PNL.

4. Dentro de la ventana que se abrió después de seleccionar Actions SDK, encontrarás la guía Google Actions SDK y una función gactions que usarás más adelante para implementar la acción personalizada. Copia la función proporcionada o toma nota del valor del parámetro — proyecto y haz clic en Aceptar.

5. Ahora puedes elegir una categoría de proyecto u omitir este paso seleccionando “Omitir” en la parte superior de la página.

6. En la página de configuraciones del proyecto, puedes especificar cómo deseas que se invoque tu habilidad personalizada. Puedes hacerlo haciendo click en “Decidir cómo se invoca tu acción” en un panel de “Configuración rápida”.

7. Aquí puedes seleccionar el Nombre para mostrar: el nombre que el Asistente de Google busca para comenzar tu habilidad personalizada. Por ejemplo, si estableces el nombre para mostrar en ‘Localizador de lugares’, para comenzar esta habilidad personalizada tendrá que decir algo como ‘Hola Google, hable con un Localizador de lugares’. También puedes elegir la voz que deseas que use tu asistente de Google y una vez que estés satisfecho con las configuraciones, selecciona ‘Guardar’.

En esta etapa, has inicializado la acción personalizada de Google Assistant. Ahora es el momento de definir cómo debe comportarse el Asistente de Google cuando el usuario invoca esta acción y qué debe hacer cuando el usuario comienza a usar la habilidad.
Dado que la fuente abierta Rasa Stack se encargará de la comprensión del lenguaje natural y la gestión del diálogo, la acción personalizada de Google Assistant será responsable de solo dos cosas: comprender que un usuario invocó la acción personalizada y pasar todas las entradas del usuario a Rasa después de invocar la habilidad. Para lograr esto, tendrá que definir los intentos para estos dos comportamientos y cumplimientos: cosas que el Asistente de Google tendrá que hacer una vez que estos intentos coincidan después de realizar la voz a texto en las entradas de voz del usuario. Aquí está cómo hacerlo:
gactions init
3. Abre el archivo actions.json que se inicializó después de ejecutar el comando anterior. Este archivo tiene la configuración básica de la acción de invocación de habilidad personalizada. Se compone de tres partes principales:
⦁ nombre — define el tipo de intento
⦁ intención — corresponde a lo que se trata la acción
⦁ cumplimiento: un webhook al que el Asistente de Google debe enviar la solicitud una vez que coincida la intención correspondiente.
Todas las habilidades personalizadas de Google Assistant necesitan una acción de invocación, por lo que todo lo que tienes que hacer es proporcionar los detalles necesarios a la configuración anterior:
{
"actions": [
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "<INSERT YOUR CONVERSATION NAME HERE>"
},
"intent": {
"name": "actions.intent.MAIN",
"trigger": {
"queryPatterns": [
"talk to <INSERT YOUR NAME HERE>"
]
}
}
}
],
"conversations": {
"<INSERT YOUR CONVERSATION NAME HERE>": {
"name": "<INSERT YOUR CONVERSATION NAME HERE>",
"url": "<INSERT YOUR FULLFILLMENT URL HERE>"
}
},
"locale": "en"
}
⦁ conversationName que funcionará como un conector entre la intención y un cumplimiento correspondiente. Para la acción de invocación de habilidad, un nombre de conversación podría ser algo así como “bienvenido”
⦁ queryPatterns: una frase de ejemplo que un usuario podría decir. Para la acción de invocación de habilidad, un patrón de consulta podría ser algo así como ‘Talk to Place Finder’.
Una vez que se configura la acción de invocación, todo lo que tienes que agregar es otra acción que pasará todas las entradas del usuario a la Pila Rasa después de invocar la habilidad personalizada. Para esto, tendrás que definir una nueva intención con el nombre ‘TEXTO’ que capturará todas las entradas del usuario después de que se realice el servicio de voz a texto y pasarlo a Rasa Stack utilizando el webhook que definirás en el próximo paso. A continuación se muestra la configuración completa de la acción personalizada de Google Assistant:
{
"actions": [
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "welcome"
},
"intent": {
"name": "actions.intent.MAIN",
"trigger": {
"queryPatterns":["talk to Place Finder"]
}
}
},
{
"description": "Rasa Intent",
"name": "TEXT",
"fulfillment": {
"conversationName": "rasa_intent"
},
"intent": {
"name": "actions.intent.TEXT",
"trigger": {
"queryPatterns":[]
}
}
}],
"conversations": {
"welcome": {
"name": "welcome",
"url": "...",
"fulfillmentApiVersion": 2
},
"rasa_intent": {
"name": "rasa_intent",
"url": "...",
"fulfillmentApiVersion": 2
}
}
}
Para pasar las entradas de los usuarios a Rasa, el Asistente de Google necesita un URL de webhook que se utilizará para establecer la conexión entre los dos. En el siguiente paso, escribirás un conector personalizado para conectar Rasa a Google Assistant.
De manera predeterminada, Rasa viene con un montón de conectores precompilados para las plataformas de mensajería más populares, pero como el conector de Google Assistant aún no está incluido, ¡aprenderás cómo crear uno! Aquí están los pasos de cómo hacerlo:
1. En el directorio de tu proyecto, crea un nuevo archivo llamado ‘ga_connector.py’. En este archivo, escribirás el código.
2. Abre el archivo ga_connector.py y comienza importando las bibliotecas necesarias que incluyen:
⦁ future(por la cordura del código).
⦁ logging(para la depuración)
⦁ flask(para crear el webhook)
⦁ Algunas clases de Rasa Core (para crear el conector personalizado)
⦁ json
import logging import json from sanic import Blueprint, response from sanic.request import Request from typing import Text, Optional, List, Dict, Any from rasa.core.channels.channel import UserMessage, OutputChannel from rasa.core.channels.channel import InputChannel from rasa.core.channels.channel import CollectingOutputChannel logger = logging.getLogger(__name__)
3. Crea una clase llamada GoogleAssistant que hereda la clase InputChannel del núcleo rasa. Esta clase constará de dos funciones: nombre y plano:
class GoogleAssistant(InputChannel): @classmethod def name(cls): def blueprint(self, on_new_message):
4. La función de nombre definirá tu prefijo de URL de webhook. Llámalo google_assistant:
@classmethod def name(cls) return ‘google_assistant’
5. Ahora vamos a completar la función de plano. Esta función definirá el webhook que Google Assistant usará para pasar las entradas del usuario a Rasa Core, recopilar las respuestas y enviarlas de vuelta a Google Assistant. Comienza por inicializar el nombre de webhook:
def blueprint(self, on_new_message):
google_webhook = Blueprint('google_webhook', __name__)
@google_webhook.route("/", methods=['GET'])
async def health(request):
return response.json({"status": "ok"})
⦁ Una vez que se recibe la solicitud POST, el conector toma la carga útil de la solicitud.
⦁ La carga útil contiene los detalles sobre la entrada del usuario enviada por el Asistente de Google. Estos detalles incluyen la identificación del usuario, la intención (es una solicitud de inicio o un mensaje regular) y el mensaje real en un formato de texto. Todos estos detalles se extraen de la carga útil y se asignan a las variables correspondientes.
⦁ Si la intención es una solicitud de lanzamiento de habilidad, el Asistente responderá con un mensaje introductorio “Bienvenido a la habilidad Asistente de Google potenciada por Rasa. Puedes empezar diciendo hola “.
⦁ Si la intención es una entrada de usuario regular, entonces tiene que inicializar el canal de salida (CollectingOutputChannel es una buena opción para devolver las respuestas generadas por Rasa Core) y pasarlo a Rasa junto con la entrada del usuario y la identificación del remitente. Rasa Core hará una predicción de cómo debería responder el asistente y te permitirá recuperar el mensaje de respuesta del canal de salida.
⦁ Finalmente, el mensaje producido se incorpora a una respuesta json que se envía de vuelta a Google Assistant.
@google_webhook.route("/webhook", methods=['POST'])
async def receive(request):
payload = request.json
intent = payload['inputs'][0]['intent']
text = payload['inputs'][0]['rawInputs'][0]['query']
if intent == 'actions.intent.MAIN':
message = "Hello! Welcome to the Rasa-powered Google Assistant skill. You can start by saying hi."
else:
out = CollectingOutputChannel()
await on_new_message(UserMessage(text, out))
responses = [m["text"] for m in out.messages]
message = responses[0]
r = {
"expectUserResponse": 'true',
"expectedInputs": [
{
"possibleIntents": [
{
"intent": "actions.intent.TEXT"
}
],
"inputPrompt": {
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": message,
"displayText": message
}
}
]
}
}
}
]
}
return response.json(r)
A continuación se muestra el código completo de la clase de conector Asistente de Google:
import logging
import json
from sanic import Blueprint, response
from sanic.request import Request
from typing import Text, Optional, List, Dict, Any
from rasa.core.channels.channel import UserMessage, OutputChannel
from rasa.core.channels.channel import InputChannel
from rasa.core.channels.channel import CollectingOutputChannel
logger = logging.getLogger(__name__)
class GoogleConnector(InputChannel):
"""A custom http input channel.
This implementation is the basis for a custom implementation of a chat
frontend. You can customize this to send messages to Rasa Core and
retrieve responses from the agent."""
@classmethod
def name(cls):
return "google_assistant"
def blueprint(self, on_new_message):
google_webhook = Blueprint('google_webhook', __name__)
@google_webhook.route("/", methods=['GET'])
async def health(request):
return response.json({"status": "ok"})
@google_webhook.route("/webhook", methods=['POST'])
async def receive(request):
payload = request.json
intent = payload['inputs'][0]['intent']
text = payload['inputs'][0]['rawInputs'][0]['query']
if intent == 'actions.intent.MAIN':
message = "Hello! Welcome to the Rasa-powered Google Assistant skill. You can start by saying hi."
else:
out = CollectingOutputChannel()
await on_new_message(UserMessage(text, out))
responses = [m["text"] for m in out.messages]
message = responses[0]
r = {
"expectUserResponse": 'true',
"expectedInputs": [
{
"possibleIntents": [
{
"intent": "actions.intent.TEXT"
}
],
"inputPrompt": {
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": message,
"displayText": message
}
}
]
}
}
}
]
}
return response.json(r)
return google_webhook
Y eso es. ¡Acabas de escribir un conector personalizado de Google Assistant para Rasa! Ahora es el momento de juntar todas las piezas y probar al asistente.
Todo lo que queda por hacer es iniciar el servidor Rasa Core, que utilizará el conector personalizado para conectarse a Google Assistant. Puedes hacerlo utilizando el código siguiente que cargará el agente de Rasa Core utilizando el modelo Rasa NLU como intérprete e iniciará el webhook que escuchará las entradas del usuario entrante:
from rasa_core.agent import Agent
from rasa_core.interpreter import RasaNLUInterpreter
from custom import GoogleConnector
from rasa_core.utils import EndpointConfig
action_endpoint = EndpointConfig(url="http://localhost:5055/webhook")
nlu_interpreter = RasaNLUInterpreter('./models/current/nlu_model')
agent = Agent.load('./models/current/dialogue', interpreter = nlu_interpreter, action_endpoint=action_endpoint)
input_channel = GoogleConnector()
agent.handle_channels([input_channel], 5004, serve_forever=True)
Guarda este código dentro de un archivo llamado run_app.py y ejecútalo. Iniciará el servidor en el puerto 5004 y establecerá el webhook de GoogleConnector.
Como tu asistente Rasa se ejecuta localmente y Google Assistant se ejecuta en la nube, necesitarás un servicio de tunelización para exponer a tu asistente local Rasa al mundo exterior. Ngrok es una buena opción para eso, así que inicia ngrok en el mismo puerto en el que se está ejecutando el agente de Rasa: 5004. Ahora puedes conectarlo a Google Assistant pasando la URL de webhook a los cumplimientos de tu acción personalizada de Google Assistant. Para hacer eso, copia la url generada por ngrok (será diferente a la que obtuvimos para el siguiente ejemplo), adjunta el sufijo ‘/webhooks/google_assistant/webhook’, regresa al archivo action.json y proporciona la url a la parte de conversaciones del archivo de configuración:
{
"actions": [
{
"description": "Default Welcome Intent",
"name": "MAIN",
"fulfillment": {
"conversationName": "welcome"
},
"intent": {
"name": "actions.intent.MAIN",
"trigger": {
"queryPatterns":["talk to Place Finder"]
}
}
},
{
"description": "Rasa Intent",
"name": "TEXT",
"fulfillment": {
"conversationName": "rasa_intent"
},
"intent": {
"name": "actions.intent.TEXT",
"trigger": {
"queryPatterns":[]
}
}
}],
"conversations": {
"welcome": {
"name": "welcome",
"url": "https://145f1bf4.ngrok.io/webhooks/google_assistant/webhook",
"fulfillmentApiVersion": 2
},
"rasa_intent": {
"name": "rasa_intent",
"url": "https://145f1bf4.ngrok.io/webhooks/google_assistant/webhook",
"fulfillmentApiVersion": 2
}
}
}
python -m rasa_core_sdk.endpoint --actions actions
Ahora, todo lo que queda por hacer es implementar tu habilidad personalizada de Google Assistant y habilitar las pruebas. Puedes implementar la habilidad personalizada de Google Assistant ejecutando el siguiente comando. Aquí, PROJECT_ID es un valor del parámetro — proyecto del cual tomó nota en el paso 2 de este tutorial.
gactions update --action_package action.json --project PROJECT_ID
Una vez que se carga la acción, habilita la prueba de la acción ejecutando el siguiente comando:
gactions test --action_package action.json --project PROJECT_ID
Sugerencia: si olvidaste tomar nota de tu ID de proyecto, puedes encontrarla dentro de la configuración de proyectos en la consola de Google Actions:

¡Felicidades! ¡Acabas de crear una habilidad personalizada de Google Assistant con Rasa Stack!
¡Ahora puedes continuar y probarlo en tu altavoz inteligente de Google Home o en tu aplicación Google Assistant (asegúrate de iniciar sesión con la misma cuenta de Google que usaste para desarrollar la habilidad personalizada en la consola de acciones de Google)!
Estamos deseando ver lo que puedes construir. Comparte tus proyectos en el Foro de la Comunidad de Rasa y publica cualquier pregunta que tengas sobre la integración de Rasa en el Asistente de Google.
The post Más allá de ‘Ok Google’: construyendo un asistente de Google impulsado por Rasa first appeared on Planeta Chatbot.
]]>The post Construyendo asistentes contextuales con Rasa Forms first appeared on Planeta Chatbot.
]]>Este proceso es fácil con nuestra última novedad de FormPolicy. Esta es una característica nueva que implementa el slot filling de una manera fácil y efectiva. ¿Cómo? FormPolicy te permite cubrir todos los caminos felices con una sola historia. Los formularios también te permiten alterar la lógica en un camino feliz, sin necesidad de cambiar los datos de entrenamiento.
Entonces, ¿cómo implementar esta nueva técnica? Me alegra que hayas preguntado. Aquí te indicamos cómo hacer que FormPolicy lo haga todo por ti.
2. Construyendo un asistente de búsqueda de restaurantes usando los nuevos formularios:
3. Resumen
4. Recursos útiles.
La presentación de slots es un proceso de recopilación de información importante para cumplir con la solicitud del usuario. Se trata de tener datos relevantes a mano que pueden ser útiles en una conversación determinada.
Tomemos como ejemplo un asistente de búsqueda de restaurantes para ilustrarlo. Antes de que el asistente pueda realizar una acción de búsqueda en un restaurante, debe conocer las preferencias de los usuarios, como el tipo de restauración, el rango de precios, la ubicación, etc., para poder hacer una sugerencia útil.
Para almacenar dicha información, Rasa Core utiliza ranuras (slots). En casos simples, puede implementar el slot filling utilizando solo ranuras (slots), pero las cosas se complican rápidamente una vez que la complejidad de las conversaciones crece. Con más detalles, vienen más posibles giros de diálogo, lo que crea mayores y mayores requisitos de datos de capacitación. Aquí es donde FormAction viene al rescate. Te permite imponer una lógica estricta en el proceso de recopilación de información y reducir considerablemente la cantidad de datos de capacitación necesarios para construir un buen modelo de diálogo.
En la parte restante de este tutorial, aprenderás cómo usar la nueva FormPolicy en la realidad. Este tutorial se basa en un asistente de búsqueda de restaurantes llamado formbot. Puedes encontrar todo el código dentro del repositorio de Rasa Core GitHub :
git clone https://github.com/RasaHQ/rasa_core.git
cd rasa_core/examples/formbot
Al seguir este tutorial y usar el código dentro del repositorio, construirás un asistente divertido, capaz de sugerir restaurantes según las preferencias del usuario, como el tipo de cocina, el número de personas, el lugar que prefieres y otros requisitos posibles. Aquí puedes encontrar una recreación de una conversación real con el chatbot:

Antes de almacenar información importante como ranuras, el asistente debe extraerlas de las entradas del usuario.
Para que tu asistente pueda hacer eso, es necesario entrenar el modelo NLU que clasificará la intención de las entradas del usuario y extraerá detalles importantes como entidades.
El ejemplo de Formbot ya viene con ejemplos de entrenamiento que puedes usar para entrenar el modelo NLU. Utilizando los ejemplos de capacitación proporcionados, puedes enseñar a tu asistente a comprender entradas como saludos, consultas de búsqueda de restaurantes, entradas para suministrar la información solicitada, etc., y luego extraer entidades como tipo de restaurante, cantidad de personas, requisitos adicionales, etc. Puedes encontrar la capacitación de NLU ejemplos dentro del archivo data/nlu_data.md del ejemplo formbot.
Para entrenar el modelo, ejecuta el siguiente comando. Este comando es un comando de shell de acceso directo que llamará a la función Rasa NLU train, pasará los datos de entrenamiento y los archivos de configuración del modelo y guardará el modelo dentro del directorio models / nlu / current de su directorio de trabajo:
make train-nlu
Nota: si eres nuevo en Rasa NLU y deseas obtener más información al respecto, asegúrate de consultar la documentación de Rasa NLU.
Una vez que el asistente es capaz de comprender las entradas del usuario, es hora de construir un modelo de gestión de diálogo. Al usar Formularios para rellenar espacios, es mejor comenzar por entrenar al modelo para manejar los caminos felices, situaciones en las que el usuario proporciona toda la información requerida y le permite al asistente dirigir la conversación.
Lo mejor de las nuevas formas es que el asistente aprende a manejar todos los caminos felices de una sola historia de entrenamiento. Mira el video de abajo para ver la ilustración:
Una vez que restaurant_form predice la “acción de formulario”, el asistente sigue pidiendo los detalles necesarios hasta que se configuren todos los espacios requeridos. No hay restricciones sobre la forma en que el usuario debe proporcionar los detalles: si un usuario especifica todas las preferencias en la solicitud inicial del restaurante, por ejemplo, “Reserve una mesa para dos en el restaurante chino”, el asistente omitirá las preguntas sobre la cocina y número de personas.
Si el usuario no especifica ninguno de estos detalles en una solicitud inicial, el asistente pregunta todos los detalles en las preguntas de seguimiento hasta que se proporcionen todos ellos. Ambas situaciones representan dos conversaciones diferentes (puede haber más de dos), pero al usar FormsPolicy, ambas se aprenderán usando la misma historia. A continuación se muestra un fragmento de la historia de entrenamiento utilizada para modelar todos los caminos felices en un ejemplo de formbot:
## happy path
* greet
- utter_greet
* request_restaurant
- restaurant_form
- form{"name": "restaurant_form"}
- form{"name": null}
- utter_slots_values
* thankyou
- utter_noworries
Consulte el archivo data/stories.md del ejemplo de Formbot para investigar las historias de capacitación con más detalle.
Para entrenar el modelo de gestión de diálogos con Rasa Core, también necesitas definir el dominio . Aquí es donde puedes especificar qué detalles extraídos deben almacenarse como ranuras.
Hay tres cosas importantes que debes considerar al definir el dominio para un asistente con el llenado de espacios:
A continuación se muestra un fragmento del dominio utilizado en un ejemplo de formbot:
entities: - cuisine - num_people - number - feedback - seatingslots: cuisine: type:unfeaturized auto_fill:false num_people: type: unfeaturized auto_fill: false outdoor_seating: type: unfeaturized auto_fill: false preferences: type: unfeaturized auto_fill: false feedback: type: unfeaturized auto_fill: false requested_slot: type: unfeaturizedforms: - restaurant_form
El siguiente paso es implementar la FormAction que, una vez predicha, manejará el llenado de la ranura. Puedes implementar todas las FormActions en el archivo actions.py donde implementarías cualquier otra acción personalizada que te gustaría que tu asistente maneje. Vamos a definir la formAction para el relleno de la ranura auxiliar restaurante paso a paso (echa un vistazo a la actions.py archivo del ejemplo formbot para ver un código completo):
Consejo profesional: la función required_slots es un gran lugar para introducir alguna lógica de ranura personalizada. Por ejemplo, podría tener sentido incluir la opción de asientos al aire libre solo para los restaurantes de una cocina específica. Puedes lograr esto introduciendo una lógica simple como en el ejemplo que te muestro a continuación, donde la ranura outdoor_seating solo será necesaria cuando los usuarios piden restaurantes que sirven comida griega:
Y ahí lo tienen, una implementación simple de FormAction. Hay mucho más que puedes agregar para permitir que tu asistente maneje casos aún más avanzados. Veamos esto en el siguiente paso de este tutorial.
Algunas ranuras necesarias pueden provenir de entradas de usuario muy diferentes. Por ejemplo, el usuario podría responder a la pregunta “¿Te gustaría sentarte afuera?” Con las siguientes respuestas:
Cada una de estas respuestas corresponde a diferentes intenciones o tiene diferentes entidades importantes, pero dado que proporcionan una respuesta viable a la pregunta, un asistente debe poder aceptarlo y establecer un espacio para avanzar.
Aquí es donde entra en juego la función slot_mappings en una FormAction: define cómo extraer valores de slot de las posibles respuestas de los usuarios y los asigna a un slot específico. A continuación se muestra un ejemplo de la función slot_mappings para la outdoor_seating comentada anteriormente . De acuerdo con la lógica definida, la outdoor_seating se rellenará utilizando:
seating.Puedes encontrar más ejemplos de asignación de ranura dentro de la slot_mappings función del actions.py archivo del ejemplo formbot.
def slot_mappings(self):
# type: () -> Dict[Text: Union[Dict, List[Dict]]]
"""A dictionary to map required slots to
- an extracted entity
- intent: value pairs
- a whole message or a list of them, where a first
match will be picked"""
return { "outdoor_seating": [self.from_entity(entity="seating"),
self.from_intent(intent='affirm',
value=True),
self.from_intent(intent='deny',
value=False)]}
Otra cosa útil que puedes hacer con FormAction es la validación de espacios. Por ejemplo, antes de permitir que tu asistente continúe con las preguntas, es posible que desees verificar el valor de la ranura con los valores posibles en tu base de datos o verificar si el valor está en el formato correcto. Puedes lograrlo creando una función llamada validaren su clase de FormAction. De forma predeterminada, comprueba si se extrajo la ranura solicitada, pero puedes agregar tanta lógica adicional como sea necesario. A continuación se muestra un ejemplo de la función de validación que primero verifica si la ranura solicitada se completó y luego verifica si el número de personas proporcionado está en el formato correcto: si el número es un número entero, el asistente usará el valor proporcionado, si no responderá con un mensaje que indica que el formato del valor de la ranura no es válido, establece la ranura en Ninguno y solicítalo nuevamente.
def validate(self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: Dict[Text, Any]) -> List[Dict]:
"""Validate extracted requested slot
else reject the execution of the form action
"""
# extract other slots that were not requested
# but set by corresponding entity
slot_values = self.extract_other_slots(dispatcher, tracker, domain)
# extract requested slot
slot_to_fill = tracker.get_slot(REQUESTED_SLOT)
if slot_to_fill:
slot_values.update(self.extract_requested_slot(dispatcher,
tracker, domain))
if not slot_values:
# reject form action execution
# if some slot was requested but nothing was extracted
# it will allow other policies to predict another action
raise ActionExecutionRejection(self.name(),
"Failed to validate slot {0}"
"with action {1}"
"".format(slot_to_fill,
self.name()))
# we'll check when validation failed in order
# to add appropriate utterances
for slot, value in slot_values.items():
if slot == 'num_people':
if not self.is_int(value) or int(value) <= 0:
dispatcher.utter_template('utter_wrong_num_people',
tracker)
# validation failed, set slot to None
slot_values[slot] = None
Puedes encontrar más ejemplos de la validación ranura (comprobación de la base de datos, cadena coincidente) en el actions.py archivo del ejemplo formbot.
La idea principal detrás del relleno de ranuras con FormAction es que se aplica una lógica estricta para recopilar las piezas importantes de información y manejar el camino feliz, mientras que el aprendizaje automático normal se utiliza para manejar con gracia las desviaciones del camino feliz. Estas desviaciones pueden ser algunos mensajes de chat en medio de la sesión de acción de formulario o las situaciones en las que los usuarios se niegan a proporcionar todos los detalles necesarios. Para manejar situaciones como esta, tienes que escribir las historias que representan esos giros de conversación.
Por ejemplo, la historia a continuación representa la situación en la que el usuario decidió dejar de proporcionar la información en medio de la sesión de acción de formulario, pero luego regresó para proporcionar los detalles necesarios:
## stop but continue path
* request_restaurant
- restaurant_form
- form{"name": "restaurant_form"}
* stop
- utter_ask_continue
* affirm
- restaurant_form
- form{"name": null}
- utter_slots_values
* thankyou
- utter_noworries
Para permitir que tu asistente maneje casos aún más avanzados, necesitas recopilar más historias como esta para cubrir diferentes turnos de diálogo. En algunas situaciones, es posible que desees manejar las rutas infelices de manera diferente según la ranura que el usuario solicite actualmente. Para lograrlo, dentro del archivo de dominio debe configurarse requested_slot categórico. Esto permitirá que las predicciones de la próxima respuesta se vean influenciadas según la ranura que se solicite actualmente.
Consulta el archivo data/stories.md del ejemplo de formbot para ver más posibles historias de ruta infelices.
Ya has aprendido mucho sobre la implementación de FormAction y has definido todos los bits necesarios del modelo de gestión de diálogo. Ahora es el momento de la parte más emocionante: ¡probar al asistente!
Primero, entrena el modelo de gestión de diálogos utilizando el siguiente comando que llamará a la función de tren de Rasa Core, te pasará el dominio y los archivos de datos, y almacenará el modelo entrenado dentro del directorio de modelos / diálogo de tu directorio de trabajo:
make train-core
Una vez que el modelo está entrenado, ¡es hora de cargarlo junto con el modelo NLU previamente entrenado, y probar cómo funciona el robot de búsqueda de restaurantes!
Primero, en un nuevo terminal, inicia un servidor patito ejecutando el siguiente comando:
docker run -p 8000:8000 rasa/duckling
Inicia tu asistente ejecutando el siguiente comando que activará el servidor local para acciones personalizadas y cargará el asistente para que pueda chatear:
make run
Para ver mejor cómo funciona FormAction, dedica un tiempo a probar cómo se desempeña el asistente en diferentes caminos felices e infelices.
Construir buenos asistentes contextuales no es fácil. La combinación de FormAction con el ML tradicional te permite crear asistentes que pueden manejar conversaciones más profundas sin tener que escribir muchas historias de entrenamiento para manejar el camino feliz. Además de esto, FormAction hace que sea mucho más fácil realizar cambios en el código y el diálogo de tu asistente, ya que las ranuras solicitadas no se utilizan directamente en las historias de capacitación.
¡Prueba los nuevos formularios en tus propios conjuntos de datos y comparte tus comentarios con nosotros uniéndote a la discusión en este hilo del Foro de la Comunidad Rasa!
The post Construyendo asistentes contextuales con Rasa Forms first appeared on Planeta Chatbot.
]]>The post Cómo migrar tu Chatbot de Google DialogFlow a Rasa first appeared on Planeta Chatbot.
]]>Estas son las razones principales por las que los desarrolladores eligen Rasa Stack sobre las plataformas alojadas:
Es de código abierto.
Gestión de diálogo con motor de aprendizaje automático.
La migración de DialogFlow a Rasa es una de las solicitudes más comunes de la comunidad Rasa . En esta publicación veremos paso a paso cómo migrar un asistente DialogFlow existente a Rasa.
Puedes encontrar el código del asistente de ejemplo utilizado en este tutorial.
Como dijimos, el objetivo de esta publicación es mostrar un proceso paso a paso sobre cómo migrar un asistente DialogFlow existente a Rasa.
Para ilustrar el proceso, vamos a usar un ejemplo: un asistente de búsqueda personalizado llamado place_finder, capaz de buscar lugares como restaurantes, tiendas, bancos dentro del radio especificado por el usuario, y proporcionar detalles sobre el entorno como dirección, clasificación y horario de apertura del lugar. El asistente obtiene todos estos detalles utilizando un webhook para realizar llamadas a la API de Google Places.
A continuación hay una conversación de ejemplo con el asistente de place_finder:

Si deseas replicar este tutorial, puedes encontrar los archivos de datos y el código webhook del asistente place_finder dentro del directorio dialog-assistant del repositorio de este tutorial. Alternativamente, puedes seguir esta guía utilizando tu propio chatbot y ajustar que verás a continuación.
Cualquiera que sea la opción que elijas, en este punto deberías tener tu asistente de DialogFlow: ¡ahora es el momento de migrarlo a Rasa!
Consejo: si quieres jugar con el asistente de place_finder, debes obtener una clave API de Google Places y colocarla dentro del archivo credentials.yml de estos repositorios.
Recomendamos comenzar con la migración de la parte NLU del asistente DialogFlow.
Para migrarlo a Rasa, lo único que tienes que hacer es exportar los archivos del proyecto y usarlos para capacitar al modelo Rasa NLU; no se necesitan datos ni cambios de formato. Está diseñado para ser lo má fácil posible.

2. En la pestaña ‘Exportar e Importar’, elije la opción ‘Exportar como ZIP’. Esto exportará los datos del proyecto como un archivo zip y lo descargará en tu ordenador.

3. Una vez descargado, puedes descomprimir el paquete e inspeccionar los archivos. El directorio del proyecto DialogFlow consta de los siguientes archivos y directorios:

Estos archivos se pueden usar directamente para entrenar el modelo Rasa NLU. Solo necesitas definir un archivo de configuración de canalización NLU y pasarlo al script de tren Rasa NLU. Eso se soluciona en el paso que veremos a continuación. Consulta el siguiente paso de este tutorial para ver las instrucciones detalladas.
Rasa NLU permite la personalización completa de los modelos. Antes de entrenar el modelo NLU, debes definir una configuración de tu pipeline. Una canalización de proceso define cómo se analizan los ejemplos de formación y cómo se extraen las características. La configuración debe guardarse como un archivo .yml dentro del directorio del proyecto. A continuación te muestro un ejemplo de pipeline que podrías emplear en tu proyecto:
Archivo: rasa-assistant / config.yml
language: "en"pipeline: - name: "nlp_spacy" - name: "tokenizer_spacy" - name: "ner_crf" - name: "intent_featurizer_spacy" - name: "intent_classifier_sklearn" - name: "ner_duckling" dimensions: ['number']
Una vez que hayas definido la canalización, puedes entrenar el modelo NLU siguiendo los pasos que muestro a continuación:
python -m rasa_nlu.train -c config.yml — data data/place_finder -o models — project current — verbose
Puedes probar el modelo entrenado ejecutándolo como un servidor Rasa que puedes ejecutar utilizando el siguiente comando:
python -m rasa_nlu.server --path ./models
La función anterior iniciará un servidor local en un puerto 5000.
2. Ahora puedes emular los resultados del modelo Rasla NLU enviando solicitudes como la siguiente. Pasará el mensaje ‘Hello’ al modelo Rasa NLU y devolverá la respuesta.
curl 'localhost:5000/parse?q=Hello&project=current'
La respuesta del modelo Rasla NLU incluye los resultados de la clasificación de intención y la extracción de entidad. Por ejemplo, el mensaje “Hello” se clasificó como una intención “Default Welcome Intent” con la confianza de 0,83. Aquí hay una respuesta completa devuelta por el modelo NLU:
{
"intent":{
"name":"Default Welcome Intent",
"confidence":0.8342492802420313
},
"entities":[
],
"intent_ranking":[
{
"name":"Default Welcome Intent",
"confidence":0.8342492802420313
},
{
"name":"thanks",
"confidence":0.09805256693160122
},
{
"name":"goodbye",
"confidence":0.05392708191432759
},
{
"name":"address",
"confidence":0.003986386948676723
},
{
"name":"place_search",
"confidence":0.0037102872949153686
},
{
"name":"rating",
"confidence":0.003059348479049656
},
{
"name":"opening_hours",
"confidence":0.0030150481893980153
}
],
"text":"Hello",
"project":"current",
"model":"model_20180827-110057"
}
¡Y LISTO! ¡Acabas de migrar la parte NLU del asistente de DialogFlow a Rasa!
Consejo: El formato de datos exportado por DialogFlow es diferente del que utiliza Rasa NLU . Si deseas mejorar su modelo Rasa NLU después de la migración, puedes tomar un archivo de datos producido dentro del directorio del modelo después de que finalice la capacitación inicial (en este ejemplo, la ruta a este archivo es rasa-assistant / models / current / model_xxxxxxx / trainingdata.json), agrega nuevos ejemplos y vuelva a entrenar el modelo NLU que señala la train fuction del archivo.
Nota: Si tu asistente DialogFlow personalizado no usa contextos o webhooks, puedes omitir esta parte del tutorial e ir directamente al punto cuatro.
Pero si los usas, tendrás que seguir los siguientes pasos:

Para convertir esta conversación en una historia de entrenamiento de Rasa Core, debes convertir las entradas del usuario a las intenciones y entidades correspondientes, mientras que las respuestas del agente deben expresarse como acciones. Así es como se vería la conversación anterior como una historia de Rasa:
Archivo: rasa-assistant / data / stories.md
## story_01
* Default Welcome Intent
utter_greet
* place_search{“query”:”restaurant”, “radius”:”600”}
action_place_search
slots{“place_match”:”one”}
slots{“address”:”Ars Vini in Sredzkistraße 27, Hagenauer Straße
1, Berlin”}
slots{“rating”:”4.4”}
slots{“opening_hours”:”true”}
* opening_hours
utter_opening_hours
* rating
utter_rating
Para entrenar el modelo necesitarás algunas historias adicionales que representen diferentes turnos de conversación.
2. Crea el dominio de tu asistente que define todos los intentos, entidades, ranuras, plantillas y acciones con las que el asistente debe estar familiarizado. Por ejemplo, las plantillas del asistente de place_finder se ven así:
Archivo: domain.yml
templates:
utter_greet:
— “Hello! How can I help?”
utter_goodbye:
— “Talk to you later!”
utter_thanks:
— “You are very welcome.”
utter_what_radius:
— “Within what radius?”
utter_rating:
— “The rating is {rating}.”
utter_address:
— “The address is {address}.”
utter_opening_hours:
— “The place is currently {opening_hours}.”
utter_no_results:
— “Sorry, I couldn’t find anything.”
Consejo: Todos los intentos y entidades definidos en el archivo de dominio deben coincidir con los nombres definidos en los ejemplos de capacitación.
3. Define acciones personalizadas. Si bien podemos escribir respuestas de texto simples dentro del archivo de dominio (al igual que en el fragmento de archivo de dominio anterior), las acciones más complicadas, como realizar una llamada API o conectarse a la base de datos para recuperar algunos datos, deben incluirse como una clase de acción personalizada. En DialogFlow, place_finder tenía un webhook para recuperar los datos de la API de Google Places, por lo que para migrarlo a Rasa, debes convertirlo en una clase de acción personalizada como la siguiente:
Esta clase asigna el nombre a esta acción personalizada, realiza la llamada API, recupera los datos solicitados, genera una respuesta que debe enviarse de vuelta al usuario y establece los detalles que deben mantenerse a lo largo de la conversación como espacios.
from rasa_sdk import Action, Tracker
from rasa_sdk.events import SlotSet, AllSlotsReset
import requests
import json
from random import randint
import datetime
import os
import yaml
class ActionPlaceSearch(Action):
def name(self):
#define the name of the action
return 'action_place_search'
def run(self, dispatcher, tracker, domain):
#retrieve slot values
query = tracker.get_slot('query')
radius = tracker.get_slot('number')
#retrieve google api key
with open("./ga_credentials.yml", 'r') as ymlfile:
cfg = yaml.load(ymlfile)
key = cfg['credentials']['GOOGLE_KEY']
#get user's current location
get_origin = requests.post(
"https://www.googleapis.com/geolocation/v1/geolocate?key={}".format(key)).json()
origin_lat = get_origin['location']['lat']
origin_lng = get_origin['location']['lng']
#look for a place using all the details
place = requests.get('https://maps.googleapis.com/maps/api/place/nearbysearch/json?location={},{}&radius={}&type={}&key={}'.format(origin_lat, origin_lng, radius, query, key)).json()
if len(place['results'])==0:
dispatcher.utter_message("Sorry, I didn't find anything")
return [SlotSet('location_match', 'none')]
else:
for i in place['results']:
if 'rating' and 'vicinity' in i.keys():
name = i['name']
rating = i['rating']
address = i['vicinity']
if i['opening_hours']['open_now']==True:
opening_hours = 'open'
else:
opening_hours = 'closed'
break
speech = "I found a {} called {} based on your specified parameters.".format(query, name)
dispatcher.utter_message(speech) #send the response back to the user
return [SlotSet('location_match', 'one'), SlotSet('rating', rating), SlotSet('address', address), SlotSet('opening_hours', opening_hours)] #set returned details as slots
4. Eso es todo lo que necesitas para entrenar el modelo Rasa Core que predecirá cómo debe responder el asistente a las entradas del usuario. ¡Ahora es el momento de entrenarlo!
Puedes entrenarlo utilizando el siguiente comando que llamará a la train fuction de rasa, cargará los archivos de datos de entrenamiento de dominio e historias y almacenará el modelo entrenado dentro del proyecto ‘actual’:
python -m rasa_core.train -d domain.yml -s data/stories.md -o models/current/dialogue --epochs 200
5. Y esto es todo: ¡has migrado con éxito un asistente de DialogFlow a Rasa! Ahora puedes probarlo localmente. Al ejecutar el siguiente comando, iniciará las acciones personalizadas webhook:
python -m rasa_core_sdk.endpoint — actions actions
Ahora, puedes cargar el agente usando el siguiente comando que cargará los modelos Rasa NLU y Rasa Core e inicie el asistente en la consola para que pueda chatear:
python -m rasa_core.run -d models/current/dialogue -u models/current/nlu_model --endpoints endpoints.yml
Como se suele decir, “Sky is the limit” si hablamos de las posibildiades que ofrece Rasa a la hora de desarrollar tus chatbots. Puedes personalizar los modelos, integrar componentes adicionales o conectarlo al mundo exterior utilizando los conectores de las plataformas de mensajería más populares. ¡Incluso puedes conectarlos a otros marcos y herramientas geniales para hacerlo aún más divertido!
Si has migrado tu asistente a Rasa, ¡nos encantaría conocer tu experiencia! ¡Únete al foro de la comunidad de Rasa y cuéntanos tu experiencia!
The post Cómo migrar tu Chatbot de Google DialogFlow a Rasa first appeared on Planeta Chatbot.
]]>