Construye un bot con el nuevo Bot Framework Composer

Compartir esta publicación

Como los chatbots de asistencia son cada vez más útiles, precisos y predecibles, no es de extrañar que ganen en popularidad. Pueden guiar a los clientes, sugerir acciones, actuar como un FAQ interactivo e incluso ayudar a incorporar nuevos empleados a las aplicaciones internas de las empresas. Entonces, ¿qué se necesita para desarrollar uno en Azure? En el siguiente post, nos sumergiremos de lleno en el nuevo Bot Framework Composer v2 de Microsoft y crearemos un simple Bot, mientras comprobamos algunas de las características y capacidades más populares del Composer.

¿Qué es el Bot Framework Composer?

El Bot Framework Composer es un IDE construido sobre el SDK del Bot Framework de Microsoft, con el objetivo de proporcionar una herramienta potente pero intuitiva para desarrollar y desplegar bots a un ritmo más rápido. Su diseñador de tipo flujo es fácil de entender y de empezar, mientras que el aspecto de la personalización no se siente comprometido – el código fuente, ya sea C# o JavaScript, se puede editar y ampliar directamente.

Si bien el Composer estaba disponible desde finales de 2019, en 2021 se lanzó su versión 2.0, que aporta un buen número de nuevas funcionalidades, lo que podría incluso convencer a los desarrolladores, que tal vez encontraron las iteraciones anteriores de las capacidades del Composer deficientes, para darle otra oportunidad.

Por supuesto, todavía es posible construir bots directamente con el SDK, sin depender del Composer.

Poniendo en marcha nuestro proyecto

Después de instalar la aplicación, podemos optar por utilizar una plantilla para poner en marcha nuestro proyecto:

Screenshot 2021 07 09 at 13.43.32

Para nuestros propósitos, la plantilla Empty Bot será suficiente, sin embargo, la elección de una plantilla más completa puede ahorrar un tiempo valioso si nuestro objetivo era construir un bot para el uso de producción. Bajando por la lista, cada plantilla puede hacer lo mismo que la anterior, solo que añadiendo capacidades por encima – las plantillas Enterprise incluso se integran con Office 365 y Active Directory a través de la Graph API.

Aparte del bot vacío, todas las plantillas requieren el aprovisionamiento de algunos recursos adicionales de Azure, ya sea un servicio lingüístico cognitivo o un QnA Maker (aunque para fines de demostración y exploración, hay niveles gratuitos disponibles).

Después de seleccionar una plantilla, también tendremos que especificar el tiempo de ejecución de nuestro Bot, ya sea un App Service o Azure Functions.

Bloques de construcción de un Bot

Antes de empezar a construir nuestro Bot, tenemos que entender los fundamentos de los componentes que conforman un Bot.

El punto de entrada principal de nuestro Bot es un Dialog. Siempre hay un único diálogo principal, sin embargo podemos construir cualquier número de diálogos child adicionales (u optar por poner toda nuestra lógica dentro del diálogo principal). Cada diálogo puede ser visto como un contenedor de funcionalidad independiente. A medida que aumenta la complejidad de nuestro Bot, se añadirán más y más diálogos hijos – para los Bots del mundo real más sofisticados, tener cientos de diálogos no es raro.
Cada diálogo contiene uno o más handlers, llamados Triggers. Un trigger tiene una condición y una lista de Acción a ejecutar, siempre que se cumpla la condición definida. Un disparador puede ser cuando el Bot reconoce la intención del usuario, un evento en su diálogo (eventos del ciclo de vida), actividades (por ejemplo, el usuario se unió, el usuario está escribiendo) y así sucesivamente. Por supuesto, hay varios tipos de acciones que podríamos tomar, tal vez queremos llamar a una API externa, establecer algunas propiedades/variables internas del usuario actualmente conectado, hacer preguntas de seguimiento, o simplemente responder con un simple texto.

  Poda de dependencias en el desarrollo de software

Creando nuestras primeras interacciones

Es bastante razonable esperar que nuestro Bot nos salude, cuando abrimos por primera vez su ventana de chat. Esta es una actividad (el usuario se unió) en nuestro diálogo principal, por lo tanto vamos a añadir un nuevo disparador en el diálogo principal:

Screenshot 2021 07 09 at 13.44.48

El Composer nos pedirá entonces que especifiquemos el tipo de este activador (Actividades) y luego el tipo de actividad exacta sobre la que nos gustaría activar (Saludo).

De entrada, se genera un flujo con un bucle y una sentencia if, que contiene algunos valores por defecto:

Screenshot 2021 07 09 at 14.08.59

Aunque puede parecer un poco más complicado de lo esperado (después de todo, sólo queremos enviar un mensaje de «Hola»), no hay mucho que hacer aquí, sólo tareas domésticas. Queremos centrarnos en la tarjeta «Enviar una respuesta», donde podemos definir el mensaje con el que el Bot debe saludar a cada usuario. Para hacer nuestro Bot un poco más emocionante, podemos añadir algunas alternativas, de las cuales el Bot escogerá una al azar:

Screenshot 2021 07 09 at 14.28.42

Por defecto, el único idioma de nuestro Bot será el inglés, sin embargo, si navegáramos a nuestros archivos fuente, veríamos que bajo el capó, el Compositor guardó nuestras plantillas con una identificación a su idioma, como BotDemo.en-us.lg. En los ajustes, podemos añadir nuevos idiomas, lo que generaría una copia de los archivos .lg donde podemos personalizar las respuestas en consecuencia.

Ejecutando el Bot, el protocolo Direct Line

La aplicación Composer viene con un gestor de tiempo de ejecución integrado con el que podemos ejecutar nuestro Bot en localhost. Para comunicarnos con el Bot, podemos optar por utilizar el Chat Web también integrado, sin embargo, su fiabilidad a día de hoy podría no ser tan buena como la de ejecutar localmente una instancia del Emulador del Framework del Bot.

Screenshot 2021 07 09 at 14.32.33

La razón por la que potencialmente tenemos que instalar otra aplicación sólo para ejecutar el Bot localmente es el protocolo de comunicación que utiliza bajo el capó: Direct Line (o Direct Line Speech), un protocolo HTTPS estándar. En aras de la precisión técnica, el emulador utiliza en realidad el cliente JavaScript para Direct Line, que también utiliza el Chat Web. El Chat Web es una forma bastante personalizable de integrar Bots en aplicaciones frontales existentes – incluso ofrece un componente para React.

Después de conectarnos al Bot, como era de esperar, nos saluda:

Screenshot 2021 07 09 at 14.33.00

Para validar que el bot cambia su saludo aleatoriamente, podemos reiniciar la conversación y ver finalmente nuestro saludo alternativo de «¡Hola!».

Expresiones, funciones, generación de lenguaje

Quizás queramos saludar a nuestro usuario de manera más formal, con un «Buenos días», «Buenas tardes» o «Buenas noches». Para ello, tendremos que evaluar una expresión para determinar la hora actual del día, y luego cambiar entre las respuestas, dependiendo de la hora actual.

Tenemos acceso a un conjunto de funciones pre-construidas, de las cuales necesitaremos dos: utcNow, para obtener la fecha y hora actuales, así como getTimeOfDay, que espera una marca de tiempo como parámetro y devuelve ‘mañana’, ‘tarde’, ‘noche’ o ‘medianoche’. Como sólo necesitaremos tres de estos valores, tendremos que procesar un poco más nuestra respuesta.

Para respuestas más complejas, es una buena idea extraer la lógica del paso «Enviar respuesta» a la sección «Respuestas del bot» y editarlas directamente allí.

Screenshot 2021 07 09 at 14.34.02

Para acceder a las variables y funciones dinámicas/incorporadas, utilizaremos la interpolación de cadenas: si ponemos ${utcNow()} como valor, el Bot lo evaluará primero y responderá con la salida.

Ahora podemos definir una sentencia if para que sólo responda con nuestros tres saludos como tal:

- IF: ${getTimeOfDay(utcNow()) == 'morning'}
   - Good morning!
- ELSEIF: ${getTimeOfDay(utcNow()) == 'afternoon'}
   - Good afternoon!
- ELSE:
   - Good evening!

Por último, sólo tenemos que asegurarnos de que nuestro paso «Enviar respuesta» devuelva el valor de nuestra nueva plantilla: sólo hay que eliminar los valores codificados anteriormente y utilizar el icono del Bot – todas las plantillas en el ámbito serán seleccionables:

  Integración continua en iOS usando Fastlane y Jenkins
Screenshot 2021 07 09 at 14.34.44

El editor también tiene un resaltador de sintaxis decente, lo que hace que sea bastante fácil escribir plantillas aún más complejas: las funciones se pueden combinar, los parámetros se pueden pasar a lo largo y así sucesivamente, como veremos más adelante.

Botones de acción sugeridos, tarjetas

Junto a una respuesta de texto, podemos enviar elementos adicionales con nuestra respuesta, los más utilizados para mejorarla con sugerencias, botones u opciones de seguimiento.

Screenshot 2021 07 09 at 14.35.30

La forma más sencilla es una acción sugerida. En la interfaz de usuario, se mostrará como una burbuja separada en la que se puede hacer clic y que desencadenará una acción diferente; en nuestro caso, pondremos «¡Cuéntame un chiste!» como texto para la acción sugerida. Para poder responder con un chiste, tendremos que hacer que nuestro bot reconozca e interprete el texto entrante de «¡Cuéntame un chiste!» del usuario – en nuestro diálogo principal, podemos seleccionar el tipo Default, Regular Expression o Custom para su reconocedor. Para nuestro caso, el de expresiones regulares será suficiente.

Después de esta configuración, podemos crear nuestro nuevo disparador, que esta vez se basará en la intención del usuario, donde el patrón RegEx debe coincidir con nuestro texto de sugerencia «¡Cuéntame un chiste!».

En cuanto a las acciones bajo el nuevo disparador, será necesario otro «Enviar respuesta», con nuestra broma de elección – esto es todo lo que se necesita para crear y manejar las sugerencias.

Screenshot 2021 07 09 at 14.35.59

Además de los botones de sugerencia, también podemos adjuntar tarjetas con nuestra respuesta de texto, ya sea para pedir al usuario que se registre en algún sitio, una miniatura, un audio o un vídeo. Un buen caso de uso para las tarjetas podría ser si el usuario estuviera buscando productos: si se reconoce la intención, devolver más detalles con acciones de seguimiento sobre el producto sería una mejor experiencia para el usuario, en lugar de simplemente devolver un enlace:

[HeroCard
 title = Medicine at Midnight
 subtitle = by Foo Fighters
 text = Medicine at Midnight is the tenth studio album by American rock band Foo Fighters. It was released through RCA and Roswell Records on February 5, 2021​.
 images = https://upload.wikimedia.org/wikipedia/en/thumb/2/2f/Medicine_at_Midnight.jpeg/1000px-Medicine_at_Midnight.jpeg
 buttons = Buy a Copy
]
Screenshot 2021 07 09 at 14.36.43

Consumir una API externa

En el mundo real, llamar a una o más APIs sería probablemente un requisito bastante temprano. En nuestro caso, cuando el usuario pregunte por los libros más populares del momento, llamaremos a la API de libros del New York Times para obtener los cinco libros juveniles más vendidos.

En un nuevo trigger sobre una nueva y reconocida intención de usuario, podemos elegir el paso ‘Enviar una petición HTTP’:

Screenshot 2021 07 09 at 14.43.00

Cabe destacar aquí la opción de inicio de sesión OAuth: en caso de que la API externa lo requiera, esa opción proporcionaría un botón de inicio de sesión al usuario para que se identifique de antemano.
Si tuviéramos que llamar a otros servicios en nuestra suscripción de Azure, la autenticación podría haberse realizado a través de identidades gestionadas o principales de servicio después de desplegar nuestro Bot.
Dado que la API de NYTimes utiliza una clave api, no es necesario que configuremos nada más, aparte de asegurarnos de no consignar nuestra clave api en el control de versiones – si fuéramos a desplegarlo en producción, inyectar datos sensibles desde una Key Vault durante el pipeline de CI/CD habría sido una opción.

  Las 5 principales tendencias tecnológicas para 2022

Después de rellenar el método HTTP, la URL y las cabeceras necesarias, tendremos que almacenar el resultado de la llamada en una variable a la que acceder en los siguientes pasos – para ello, podemos crear una nueva variable en nuestro diálogo, dialog.nyt_api_response.
Como la petición HTTP ha fallado o ha tenido éxito, pondremos un bloque If después de nuestro paso Send HTTP request. En él, comprobaremos el código de estado: dialog.nyt_api_response.statusCode == 200. Para ambos casos, verdadero y falso, se coloca un bloque Send response para responder al usuario. En este momento, nuestra acción debería tener el siguiente aspecto:

Screenshot 2021 07 09 at 14.43.31

Después de validar que todo funciona como se espera, podemos empezar a procesar el resultado de la llamada exitosa. En primer lugar, sólo necesitaremos el título y el autor de la respuesta, por lo que utilizaremos la función incorporada select (dividida para una mejor legibilidad):

${select(
    dialog.nyt_api_response.content.results.books,
    book,
    book.title
}

Esto sería el equivalente en LINQ de:

dialog.nyt_api_response.content.results.books.select(book => book.title);

Como queremos mostrar también los autores, en lugar de devolver sólo book.title, devolveremos

book.title + ' ' + book.contributor

No queremos abrumar al usuario con una cadena larga, por lo que podemos envolver la selección en una función take, especificando cuántos elementos incluir en nuestro resultado:

${take(
    select(
        dialog.nyt_api_response.content.results.books,
        book,
        book.title + ' ' + book.contributor)
    , 5)}

Como take devuelve un array, tendremos que concatenar los elementos en una sola cadena: utilizaremos la función join:

${join(
    take(
        select(
            dialog.nyt_api_response.content.results.books,
            book,
            book.title + ' ' + book.contributor)
        , 5),
    ', ')}

Al final, esto sería equivalente en LINQ a:

string.Join(‘, ‘, dialog.nyt_api_response.content.results.books.select(book => book.title + ' ' + book.contributor).take(5))

Como ya sabemos cómo adjuntar una tarjeta a nuestra respuesta, también podemos pedir al usuario el enlace de Amazon al best seller número 1:

[ThumbnailCard
 title = ${dialog.nyt_api_response.content.results.books[0].title}
 subtitle = ${dialog.nyt_api_response.content.results.books[0].contributor}
 text = ${dialog.nyt_api_response.content.results.books[0].description}
 image = ${dialog.nyt_api_response.content.results.books[0].book_image}
 buttons = ${cardActionTemplate('Buy on Amazon', dialog.nyt_api_response.content.results.books[0].amazon_product_url)}
]

Donde cardActionTemplate se define como una plantilla en Bot Responses:

[CardAction
title = ${title}
type = 'link'
value = ${value}
]

Finalmente, terminamos con la siguiente respuesta, con un botón que funciona:

Screenshot 2021 07 09 at 14.44.34

Desplegando nuestro Bot, integrándolo con React

Podemos iniciar el despliegue de nuestro Bot en Azure desde la opción Publish del Composer. Podemos crear nuevos recursos, utilizar los existentes o generar una solicitud que podemos reenviar a alguien que tenga acceso a aprovisionar los recursos, en caso de que tengamos roles limitados.

Para nuestro sencillo Bot, sólo será necesario un Registro de App, Azure Service Web Apps para el alojamiento y un Registro de Canales de Microsoft Bot. Después de unos minutos, los recursos se despliegan y podemos confirmar nuestra intención de empujar el origen de nuestro Bot a la nube.

A partir del 2 de julio de 2021, la integración del despliegue dentro de un pipeline CI/CD en Azure DevOps está en Preview, por lo que aún no está listo para producción. No obstante, los pasos del pipeline serían reconocibles para quien haya creado alguna vez un pipeline para aplicaciones web .NET (dotnet build, publish y tareas de AzureWebApp).
Una vez completado el despliegue, podemos integrar el Bot a, por ejemplo, nuestra app React existente, a través del paquete npm de Web Chat botframework-webchat. Para autenticarse con nuestro Bot, sólo será necesario un simple token, que podemos generar nosotros mismos directamente en el Azure Portal desde el menú Channels de la Web App Bot desplegada.

Lectura adicional, referencias:

Plantillas

Diálogos

Triggers

Generación de idioma

Tipos de respuesta

Lista completa de funciones preconstruidas

Llamadas HTTP de los bots

Publicar un bot

Repo de github de WebChat

Repositorio de Github de DirectLineJS

Author

  • DanielAgg 1

    Full stack developer, with 6+ years of experience, building back-, and frontends with various technologies, designing and developing scalable infrastructures on Microsoft Azure.

    Ver todas las entradas

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Suscríbete a nuestro boletín de noticias

Recibe actualizaciones de los últimos descubrimientos tecnológicos

¿Tienes un proyecto desafiante?

Podemos trabajar juntos

apiumhub software development projects barcelona
Secured By miniOrange