Diciembre de 2016
Volumen 31, número 13
Microsoft Bot Framework: use Bot Framework para acceder a datos de la aplicación en cualquier momento y lugar
En el último número, presenté Microsoft Bot Framework y describí cómo puede aprovecharlo para superar un reto al que se enfrentan muchas organizaciones actualmente, que es dar a los clientes un acceso interactivo a sus servicios a través de voz y texto (msdn.com/magazine/mt788623). En el artículo, describía un escenario empresarial que implicaba la consolidación de información de distintas aplicaciones de línea de negocio implementadas en una organización proveedora de seguros, con tecnologías como Microsoft Flow y Azure Logic Apps. El contenido, que incluye datos estructurados y no estructurados, se indexa con Azure Search y, después, se pone a disposición de las aplicaciones cliente para que lo consuman.
La Figura 1, que también aparecía en el artículo anterior, representa la arquitectura de la solución que implementa el escenario.
Figura 1 Arquitectura de la solución
En este artículo, voy a generar e implementar una aplicación bot que pueda consumir la información recopilada a través de Azure Search. La aplicación bot se implementará como aplicación web de Azure y se publicará a través del servicio Microsoft Bot Framework Connector. A través del servicio Connector, se podrá obtener acceso a la aplicación bot desde el canal de Skype, que proporcionará a los clientes acceso al estado de sus solicitudes de póliza de seguro y les permitirá descargar los documentos de la póliza emitidos, programar visitas de inspección de sitios, etc. Los consumidores podrán identificarse en el bot con la cuenta de Microsoft con la que se registraron al solicitar una póliza de seguro y podrán usar la mensajería del cliente de Skype o comandos de voz para interactuar con el bot. La aplicación bot se integra con el servicio LUIS, uno de los distintos servicios disponibles en Azure Cognitive Services, para interpretar conversaciones del consumidor y ejecutar consultas en Azure Search.
Los pasos requeridos para compilar la solución se explican en la secuencia siguiente. Los fragmentos de código se obtienen de la solución Visual Studio 2015, que se puede descargar con este artículo. Desde este punto, siga estos pasos:
- Cree y publique un modelo LUIS que capture las distintas conversaciones que se deben admitir en el bot mediante la UI que proporciona el servicio LUIS.
- Use la plantilla de Visual Studio 2015 para crear una aplicación bot nueva. Después, puede agregar los bloques de código de la solución proporcionada con este artículo o seguir el resto del artículo haciendo referencia al archivo de solución descargado. El archivo MessageController.cs es el punto de entrada a la aplicación bot, que es un tipo especial de aplicación MVC de .NET.
- Integre la funcionalidad de LUIS en el bot mediante el cuadro de diálogo de LUIS disponible en Framework SDK del bot. Esto se implementa en el archivo PolicyInfoDialog.cs en la solución.
- Use el SDK de Azure Search, implemente el código que invoca a las Azure Search API y ejecute las solicitudes de búsqueda que el servicio LUIS interpreta. Esto se implementa en el archivo SearchService.cs de la solución.
- Implemente un cuadro de diálogo FormFlow para capturar la cuenta de Microsoft del usuario en el canal de Skype de modo interactivo, cuando se realice una solicitud de usuario por primera vez. Esto se implementa en el archivo SigninForm.cs de la solución que lo acompaña.
- Use el SDK de Azure Search para recuperar la información de perfil del usuario a partir de la cuenta de Microsoft que se captura cuando el usuario accede al bot por primera vez. Esto también se implementa en SearchService.cs
- Use el servicio Bot State para conservar la información de perfil del usuario. La información de contacto y la dirección del usuario del bot, que se almacena en el servicio Bot State, se usa al programar una visita de inspección del sitio. Esto también se implementa en el archivo PolicyInfoDialog.cs.
- Para probar la aplicación bot, ejecútela localmente como servicio en la máquina de desarrollo y use Bot Framework Channel Emulator para evaluar la interacción del usuario con el servicio.
- Después de probar la aplicación bot localmente, impleméntela en una aplicación web en Azure directamente desde Visual Studio.
- Registre la aplicación bot con el servicio Microsoft Bot Framework Connector y configúrela en la dirección URL de la aplicación bot implementada en Azure.
- Agregue el nombre de la aplicación bot, el id. de aplicación y la información secreta obtenida durante el registro del bot en la solución Visual Studio y vuelva a publicarla en Azure.
- Habilite la aplicación bot para obtener acceso a ella desde canales como Skype y Slack desde el portal para desarrolladores de bots.
Puede descargar la solución de Visual Studio 2015 para la aplicación bot y una exportación de archivo del modelo LUIS que se usa en esta aplicación desde el repositorio GitHub: bit.ly/2cOfANh.
Crear y entrenar el modelo LUIS para distintos casos prácticos
La Figura 2 muestra la forma en que asigné cómo podía conversar un usuario potencialmente (mediante una declaración LUIS) con el bot y cómo debía interpretarse como una intención o acción LUIS que se debía realizar a través de Azure Search y cómo extraer palabras clave (entidades de LUIS) de la declaración LUIS para usarlas como parámetros de consulta al realizar la búsqueda.
Figura 2 Asignación de declaraciones e intenciones
Declaraciones o conversación | Acciones o intenciones asignadas | Calificadores o parámetros |
Algo que LUIS no puede interpretar (o para lo que no está entrenado). | Ninguno (valor por defecto) | No aplicable |
Obtener (o mostrar) todas mis solicitudes de póliza. | GetPolicyRequests | Implícitos para el usuario de bot con sesión iniciada |
Tengo una solicitud de póliza activa o ¿se ha aprobado mi solicitud de póliza? | GetPendingPolicyRequests | Implícitos para solicitudes de póliza con un estado distinto de aprobado |
Obtener los detalles del número de solicitud de póliza VehPolicy001. | GetPolicyRequestDetails | Id. de solicitud de póliza: VehPolicy001 |
Obtener el estado de mi solicitud de póliza de seguro de vida. | GetPolicyRequestStatusByType | Tipo de solicitud de póliza: vida |
Obtener número de documento de póliza Policy0101 emitida este año. | GetPolicyDocument | Nombre de archivo: Policy0101 y lastmoddate: año actual |
Programar una visita de inspección del sitio mañana. | ScheduleSiteVisit | Fecha de inspección: mañana |
El servicio LUIS proporciona una aplicación web en luis.ai en la que se puede crear un modelo de aplicación LUIS visualmente para el problema en cuestión. En la Figura 3 se muestra el modelo LUIS configurado para este escenario.
Figura 3 Modelo LUIS para mi escenario
Las intenciones, entidades y declaraciones identificadas en el paso anterior se pueden crear en la aplicación LUIS. Use el menú Intents (Intenciones) para agregar las intenciones y el menú Entities (Entidades) para crear las entidades. Tenga en cuenta que hay dos tipos especiales de entidades:
- Entidades jerárquicas: en este caso, la "póliza de seguro" se crea como entidad jerárquica, el elemento principal, con varios tipos como elementos secundarios: vida, vehículo, hogar, etc.
- Entidades pregeneradas: he usado una entidad pregenerada que proporciona LUIS denominada Datetime. El motor de LUIS asignará los parámetros de entrada, como el año en que se generó un documento de póliza o la fecha en que se programó una visita de inspección del sitio, con estos tipos de entidad pregenerada.
La entidad denominada "Keyword" se usará para realizar una búsqueda de texto completo en el índice de documentos de la póliza de Azure Search.
Ahora, seleccione la pestaña New utterances (Nuevas declaraciones) y cree declaraciones para cada una de las conversaciones identificadas previamente. A continuación, etiquételas.
Para cada declaración, identifique o etiquete la intención y las entidades asociadas. Por ejemplo, en la Figura 3, asigné la declaración "obtener el estado de mi solicitud de póliza de seguro de vida" a la intención "GetPolicyRequestStatusByType" y asigné el texto "Seguro de vida" a la entidad jerárquica "Insurance:life".
Repita este paso para agregar otras variaciones; por ejemplo, si el tipo de póliza es vehículo, hogar o general. Además, considere variaciones en que se podría hacer de otra forma la misma solicitud. Sin embargo, no tiene que capturar todas las permutaciones y combinaciones de formas de expresar el mismo mensaje. Por ejemplo, si agrego una declaración nueva con la frase "mostrar el estado..." como se muestra en la Figura 4, LUIS podría interpretarla correctamente como una variación de la anterior: "obtener el estado…". LUIS hizo las sugerencias correctas en la intención y las entidades asociadas a pesar de que la pregunta se formuló de otra forma.
Figura 4 Etiquetado de declaraciones LUIS y control de variaciones
Después de capturar las declaraciones, la aplicación LUIS ofrece la opción de entrenar al modelo. Como resultado, el motor AI de LUIS, genera modelos optimizados que pueden usar las aplicaciones cliente. Este paso se debe repetir cuando se etiqueten declaraciones nuevas o se apliquen cambios a las existentes.
La publicación del modelo LUIS permite a las aplicaciones del lado cliente invocarlo mediante una API de REST. El cuadro de diálogo de publicación de la aplicación también permite probar el modelo para asegurarse de que funciona como se espera. En la Figura 5 se muestra cómo probar rápidamente el modelo LUIS. Para ello, se pasa una frase de conversación y se visualiza la salida en el explorador. (Para mayor comodidad, en la Figura 5 se muestran instantáneas de tres invocaciones distintas de declaraciones y los resultados correspondientes junto a ellas).
Figura 5 Probar el modelo LUIS
Observe que la intención que recomienda LUIS tiene el máximo valor de probabilidad asignado y aparece en primer lugar en la lista. Las entidades extraídas de la frase también se devuelven en la respuesta. Si hay varias entidades identificadas en la declaración, también se devuelven. Puede ver cómo el modelo LUIS interpreta términos como "este año" en la frase de la declaración, lo asigna a la entidad pregenerada "Datetime" y devuelve el valor "2016", que la aplicación cliente puede usar directamente.
Creación de la aplicación bot
Ahora que el modelo LUIS está listo, se puede usar en una aplicación bot. Descargue la plantilla de Visual Studio 2015 desde aka.ms/bf-bc-vstemplate para crear la aplicación. (Visite bit.ly/2dYrwyW para obtener información para compilar una aplicación bot y sobre cómo usar un emulador de bot para compilar y probar el bot localmente).
El proyecto creado al usar esta plantilla es una variante de un proyecto MVC. El punto de entrada al proyecto es MessageController.cs, que procesa mensajes entrantes de canales como Skype o Slack y devuelve las respuestas.
LUISDialog para Bot Framework se usa para pasar mensajes implícitamente del bot al modelo LUIS. Para cada intención implementada en el modelo LUIS, se implementa un método correspondiente que se puede llamar directamente cuando se ejecuta la aplicación bot. Esto obvia la necesidad de código personalizado para llamar a las API de REST de LUIS para interpretar la conversación e identificar la intención y las entidades.
El id. de aplicación de LUIS y los valores secretos se usan para decorar los atributos de nivel de clase, es decir, LuisModel. El atributo LuisIntent se usa en el método que proporciona la implementación si la intención se encuentra en la solicitud del usuario. Esto es todo lo que se necesita para que funcione la integración de LUIS en el bot. En la Figura 6 se representa cómo se implementa en código.
Figura 6 Implementar la integración de LUIS
[LuisModel("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")]
[Serializable]
public class PolicyInfoDialogs : LuisDialog<object>
{
[LuisIntent("")]
public async Task None(IDialogContext context, LuisResult result)
{
// Called when the incoming utterance is not recognized (default bin)
}
[LuisIntent("GetPolicyRequests")]
public async Task GetPolicyRequests(IDialogContext context, LuisResult result)
{
//
}
----------------------
}
En este punto, la implementación de cada uno de los métodos puede ser simple; puedo devolver un mensaje que identifique la implementación de LuisIntent que se invocó.
En MessageController.cs, agregue el siguiente fragmento de código para capturar el mensaje entrante del usuario de bot y proporcionárselo a LuisDialog:
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new PolicyInfoDialog());
}
Ejecute la aplicación bot, inicie Bot Framework Channel Emulator, que se puede descargar desde aka.ms/bf-bc-emulator. Escriba las declaraciones para las que entrenó al modelo LUIS y compruebe que el mensaje de respuesta indica que se invocó el método correcto asignado a la intención de LUIS.
Integración de la búsqueda
Ahora agregaré el SDK de Azure Search para .NET a la solución de Visual Studio con el Administrador de paquetes NuGet. El archivo SearchService.cs de la solución usa este SDK y encapsula toda la integración con el servicio Azure Search. Implementa métodos que ejecutan consultas en Azure Search, devuelven el valor de UserProfile del cliente y recuperan PolicyRequests y PolicyDocuments.
Los comandos de búsqueda de los distintos escenarios se compilan con la sintaxis de consulta Lucene, que se implementa en el archivo PolicyInfoDialog.cs. Estos son algunos ejemplos:
Recuperar todas las solicitudes de póliza para el usuario de bot en la conversación:
command += "CustomerId:(" + msftid + ")";
Retrieve all policy requests for the bot user that haven’t yet been approved:
command += "CustomerId:(" + msftid + ") -PolicyStatus:(Approved)";
Query policy requests for the bot user based on the policy request Id:
public async Task GetPolicyRequestDetails(IDialogContext context, LuisResult result)
{
----------------------
string command += "CustomerId:(" + msftid + ") AND PolicyRequestId:(" +
result.Entities[0].Entity + ")";
----------------------
}
El fragmento de código anterior muestra cómo el motor de LUIS pasa la entidad PolicyRequestId (los parámetros de entrada para ejecutar las consultas de búsqueda) a través de LuisResult (resultado).
En la Figura 7 se muestra cómo implementar la búsqueda basada en propiedades y la de texto completo para los documentos.
Para vincular los valores y nombres de propiedad del código de la Figura 7, consulte mi artículo anterior. Además, puede descargar el esquema de todas las tablas usadas en la base de datos que acompaña a este artículo con los vínculos que se proporcionan en secciones posteriores.
Figura 7 Implementar la búsqueda basada en propiedades y la de texto completo para los documentos
foreach (EntityRecommendation curEntity in request.Entities)
{
switch (curEntity.Type)
{
case "PolicyNumber": // Look for documents with this filename
{
command += " filename:(" + request.Entities[0].Entity + ") ";
break;
}
case "keyword": // Search within documents for this keyword expression
{
command += " " + request.Entities[0].Entity + " ";
break;
}
case "builtin.datetime.date":
// Retrieve based on the year a document was generated
{
char[] delimiterChars = { '.', ':' };
List<string> allvalues = curEntity.Resolution.Values.ToList<string>();
string val = allvalues[0];
string[] vals = val.Split(delimiterChars);
command += " lastmoddate:(" + vals[0] + ") ";
break;
}
default:
{
break;
}
}
}
Dar formato a la respuesta para el usuario
Puede dar formato al texto del mensaje de respuesta que devuelve el bot para definir su estilo, agregar hipervínculos o contenido multimedia, etc. De este modo, la aplicación bot resulta más fácil de usar. A continuación se incluyen algunos ejemplos...
Para definir el estilo de fuente negrita, solo para los datos dinámicos que se devuelven de Azure Search, escríbalos entre asteriscos dobles (**):
foreach (SearchResult<PolicyRequest> result in eachGroup)
{
searchResponse += (counter) + ". **" + result.Document.PolicyRequestId + "**" +
" on the insured :**" + result.Document.InsuredIdentifier + "**
for an amount of :**" +
result.Document.Currency + " " + result.Document.AssessedValue + "**
has status: **" +
result.Document.PolicyStatus + "**\n\n";
counter++;
}
Para agregar un hipervínculo a un documento de póliza que devuelva Azure Search, agregue el atributo Link a la dirección URL del documento:
foreach (SearchResult<PolicyDocument> result in results)
{
searchResponse += counter + ". Link: [" + result.Document.filename + "](" +
result.Document.fileurl + ") \n";
counter++;
}
Identificar al usuario bot
Bot Framework proporciona el id. de canal del usuario y el nombre para mostrar del contexto de la conversación, pero no proporciona el nombre de usuario usado para iniciar sesión en el canal; por ejemplo, el de Skype. Por lo tanto, esta información se debe obtener explícitamente cuando un usuario empieza a interactuar con el bot. El cuadro de diálogo FormFlow descrito antes se usa para solicitar al usuario esta información. La información del perfil de usuario se recupera de Azure Search a partir del nombre de cuenta.
Para garantizar que el usuario que interactúa con el bot es el propietario del nombre de cuenta de Microsoft compartido en FormDialog, puede integrar un inicio de sesión interactivo en la página de inicio de sesión de la cuenta de Microsoft y proporcionar acceso al bot solo después de la autenticación y la validación. Esto queda fuera del ámbito del artículo. En lugar de ello, simplemente solicite al usuario el nombre de cuenta mediante el cuadro de diálogo SigninForm y suponga que el usuario es quien dice ser:
public static IForm<SigninForm> BuildForm()
{
return new FormBuilder<SigninForm>()
.Message("I would need some information before we get started.")
.Field(nameof(MicrosoftAccount))
.Build();
}
Almacenar el perfil de usuario en el estado del bot
Una vez identificado el usuario al principio de una conversación en el bot, se recupera un objeto de perfil de usuario de Azure Search. Esta información se almacena en el estado del bot para usarla, por ejemplo, cuando el usuario solicita que se programe una inspección del sitio. La dirección y el número de contacto del usuario se comprueba durante la confirmación de la visita de inspección.
Bot Framework proporciona una API para almacenar esta información en el contexto privateConversationData, por usuario y conversación, como se muestra en la Figura 8.
Figura 8 Almacenar el perfil de usuario
private async Task SignUpComplete(IDialogContext context, IAwaitable<SigninForm> result)
{
----------------------------------------------
----------------------------------------------
UserProfile profile =
await LoadBotUserState(profileIdentityForm.MicrosoftAccount);
if (profile == null)
{
message = $"Sorry, I could not locate your profile in our system.
Please retry with the right Microsoft Account";
}
else
{
context.PrivateConversationData.SetValue<bool>("ProfileComplete", true);
context.PrivateConversationData.SetValue<string>(
"FirstName", profile.FirstName);
context.PrivateConversationData.SetValue<string>("LastName", profile.LastName);
context.PrivateConversationData.SetValue<string>("Address", profile.Address);
context.PrivateConversationData.SetValue<string>("Phone", profile.Phone);
context.PrivateConversationData.SetValue<string>(
"CustomerId", profile.CustomerId);
message = $"Thanks {profile.LastName},{profile.FirstName}
for identifying yourself! \n\n
Let me know how I could assist you.";
}
await context.PostAsync(message);
}
context.Wait(MessageReceived);
}
Para cada solicitud, la aplicación bot comprueba el estado del bot para garantizar que la identidad del usuario que emite la solicitud se comprueba y que la información de perfil de usuario está disponible.
Uso del emulador Bot Channel Emulator localmente
La aplicación bot requiere el espacio de nombres de Azure Search, la clave de acceso y el nombre del índice que se usarán para ejecutar las solicitudes del usuario. Estos parámetros se almacenan en el archivo SearchParameters.cs y sus valores se definen a partir del archivo web.config cuando se ejecuta la aplicación bot. Ahora ya puede ejecutar la solución de Visual Studio.
Inicie Bot Channel Emulator y escriba las conversaciones para las que entrenó al modelo LUIS. En la Figura 9 se captura un escenario de interacción de usuario típico. Una vez ejecutada correctamente la aplicación bot en el entorno local, se puede publicar en una aplicación web de Azure.
Figura 9 Ejecutar el bot desde un emulador
Implementar el bot en Azure
Cree una aplicación web en Azure desde Azure Portal. Después en la configuración de la aplicación, agregue las claves y valores de appSetting del archivo web.config de la solución de Visual Studio.
Antes de publicar la aplicación bot en una aplicación web de Azure, debe registrar el bot en dev.botframework.com/bots/new. Este proceso genera un id. de bot, un id. de aplicación de Microsoft y un secreto. Agregue estos valores al archivo web.config de la aplicación bot en Visual Studio 2015 y vuelva a publicar la aplicación en Azure.
Durante el proceso de registro, para el parámetro de URL de redireccionamiento, use la dirección URL con SSL habilitada o la aplicación bot de Azure y agregue el sufijo "/api/messages".
Habilitar el bot entre canales
En el registro del bot, en dev.botframework.com/bots, puede habilitar el bot en otros canales. En la Figura 10 muestra la aplicación bot habilitada en los canales de Skype y Slack. Para habilitar la aplicación bot para Slack, se necesitan algunos pasos adicionales. Al elegir agregar el bot a este canal, se inicia un asistente que le guía a lo largo de los pasos adecuados.
Figura 10 Registrar el bot en varios canales
En la Figura 11 muestra la aplicación bot cuando se accede a ella desde Skype.
Figura 11 Acceder al bot desde Skype
Resumen
Microsoft Bot Framework y otras tecnologías complementarias como LUIS y Azure Search proporcionan la base adecuada para crear aplicaciones bot intuitivas que permiten a los clientes interactuar con las aplicaciones de línea de negocio. La forma de encajar estos servicios en la arquitectura general de la solución garantiza que los componentes individuales se puedan desarrollar o mejorar independientemente del resto. Por ejemplo, el modelo LUIS se puede modificar para admitir más declaraciones que los usuarios podrían usar para interactuar con el bot, sin necesidad de cambiar la aplicación bot principal ni el contenido de Azure Search. Una vez implementada y sin necesidad de más cambios en el código, una aplicación bot se puede habilitar para que se pueda obtener acceso a ella desde varios canales y también se pueden agregar más canales con el tiempo para aumentar el alcance y el uso de la aplicación bot.
Srikantan Sankaran es evangelista técnico en el equipo de DX de India, con sede fuera de Bangalore. Trabaja con muchos ISV en India y les ayuda a diseñar e implementar sus soluciones en Microsoft Azure. Puede ponerse en contacto con él a través de la dirección sansri@microsoft.com.
Gracias a los siguientes expertos técnicos de Microsoft por revisar este artículo: Sandeep Alur y Hemanth Kathuria
Sandeep Alur es evangelista técnico jefe de DX en India con sede en Bangalore.
Hemanth Kathuria es consultor senior en el equipo de servicios de India