
Compartir:
Antiguo desarrollador .NET Advocate @Vonage, ingeniero de software poliglota full-stack, AI/ML
Comprensión del lenguaje SMS con LUIS y .NET
¿Cómo se obtienen las entradas del usuario? Apuesto a que si estás construyendo una aplicación web o GUI, probablemente vas a utilizar algún formulario que tu usuario pueda rellenar y enviar. Si estás escribiendo una aplicación de consola, vas a tener alguna serie codificada de entradas y banderas que tu usuario te va a dar. ¿Y si quisieras recibir un mensaje, por ejemplo un SMS, de un usuario y analizar la información procesable de ese SMS?
Tomemos esta frase como ejemplo:
I'd like to have one cheese pizza from Joe's Pizza delivered to 21 Jump Street, Melbourne, FL 32940.Imagine recoger esa información en un formulario web.
Quantity: 1
Item: Pizza
Toppings: cheese
Restaurant: Joe's Pizza
Method: Delivery
street-number: 21
street-name: Jump Street
City: Melbourne
State: FL
Zip: 32940Pero claro, como esta frase no está estructurada, es imposible extraer esta información de ella. Ahí es donde el programa de Microsoft para la comprensión del lenguaje (LUIS) de Microsoft. Con LUIS, podemos construir bots que nos permitan utilizar el lenguaje natural como entrada y entender la intención del usuario incluso a partir de estas frases. Y eso es lo que vamos a aprender en este post-cómo construir la comprensión del lenguaje natural utilizando LUIS y el uso de ese reconocimiento del lenguaje para manejar la entrada de SMS.
Requisitos previos
Visual Studio o Rider (yo estoy usando Visual Studio 2019).
El tiempo de ejecución de .NET Core 3.1
Opcional: ngrok para probar
Vonage API Account
To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.
This tutorial also uses a virtual phone number. To purchase one, go to Numbers > Buy Numbers and search for one that meets your needs.
Algunos Conceptos Importantes en LUIS AI
LUIS considera todas las entradas como "expresiones", o cosas que usted podría decir. Hay dos conceptos clave que debe comprender para empezar a utilizar LUIS. El primero son las intenciones. El segundo concepto son las entidades, que son piezas específicas de información transmitida a través de nuestras expresiones, que podrían corresponder a los datos de un formulario.
Utilizando estos Conceptos básicos, puede detectar la intención de su usuario, casi como si estuviera dirigiendo la solicitud a un punto final. A continuación, puedes extraer la información que te proporciona el usuario para utilizarla en tu aplicación.
Creación de aplicaciones LUIS
Empecemos por ir a la página de la aplicación LUIS página de aplicaciones.
Desde aquí, cree una aplicación haciendo clic en Crear aplicación. Pongámosle un nombre DeliverySample.

Después de crear tu aplicación, serás redirigido al panel de control de tu aplicación. Haz clic en Crear en la barra de pestañas de la parte superior:

Esto te llevará a la interfaz del constructor. Ahora hay dos maneras de construir su aplicación Luis - a través de la API, o con la interfaz gráfica de usuario. Vamos a aprender cómo hacerlo con la GUI.
Añadir algunas entidades
Dirección Entidad
Para añadir algunas entidades a nuestra app, vamos a Activos de la aplicación -> Entidades. Comenzaremos creando una Entidad de Dirección. Dado que una dirección se descompone en varios componentes, empezaremos añadiendo los tipos de entidad de los componentes. Primero, haga clic en Crear nueva Entidad y cree un tipo simple llamado StreetNumber. Repita este paso para StreetName, City, State y ZipCode. Finalmente, podemos crear la entidad compuesta. Haga clic en Crear nueva entidad de nuevo, seleccione tipo compositey añada cada uno de los tipos que acabamos de crear como hijos de ese tipo.

Método Entidad
Ahora también se pueden crear otras entidades, por ejemplo, una entidad "Método" que describa cómo va a conseguir la comida el usuario. En esta, la era de COVID-19, sólo tenemos dos opciones: comida para llevar o entrega a domicilio. Por lo tanto, crearemos Method como una entidad List (una entidad con una lista enumerada de valores), y para esos valores podemos proporcionar sinónimos, por ejemplo, 'para llevar' o 'para llevar'.

Añadir una entidad Food
También podemos añadir una entidad alimentaria. Para ello, vamos a añadir otra simple entidad y llamémosla comida.
Introducir una entidad de dominio simple
La última entidad que añadiremos será la entidad PlaceName Domain-Simple. Haga clic en Añadir entidad de dominio preconstruida y busque RestaurantReservation.PlaceName. Estas entidades pre-construidas vienen junto con cientos de expresiones pre-entrenadas. Por lo tanto, hacen un buen trabajo de comprensión de lo que un nombre de lugar se parece en el contexto. De todos modos, tendremos que entrenar LUIS para entender estos un poco mejor, ya que va a estar buscando en los nombres de restaurantes desde una perspectiva diferente.
Añadir nuestra intención
Las intenciones en LUIS son lo que la frase que le estás proporcionando está pidiendo o diciendo. Así que en nuestro ejemplo, podemos leer la "intención" de la frase como "PedirComida". Así que vamos a hacer precisamente eso. Ir a Activos de la aplicación -> Intents. Esta página es la lista de intentos que busca su aplicación. Todas las aplicaciones LUIS entienden la intención 'Ninguno', que es la intención "No sé" que se registra cuando no se puede entender lo que dice el enunciado. Añadamos nuestra intent de ejemplo 'PedirComida'.
Añadir expresiones a OrderFood Intent
Una vez creada nuestra intent, tenemos que rellenarla con expresiones. Rellenar estos enunciados permite a LUIS reconocer la intent y extraer los datos de ella. La recomendación de Microsoft es que cualquier intención del mundo real va a necesitar un mínimo de 15 expresiones de diferentes longitudes, estructuras y tiempos antes de que LUIS pueda empezar a predecir y extraer información con precisión.
Para añadir expresiones a una intent, haga clic en la intent y accederá a la página de la intent. En esta página, hay una sección que dice "Introduce un ejemplo de lo que un usuario podría decir y pulsa Intro", sigue estas instrucciones para introducir una expresión. Aquí tienes algunas con las que yo empecé:
Quiero que me envíen un pedido de patatas fritas de discoteca a 14 Seventh Ave, New York New York, 10001
¿Puedo obtener un burrito de pollo de Chipotle entregado a 15 Yemen Road, Cedar Rapids Iowa, 52227
Me gustaría coger un General Tsao's Chicken de Hop Bo's.
Entidades de etiquetado
Lo que acabamos de hacer permitirá a LUIS extraer la intención del usuario a partir de esas frases. Pero eso es sólo la mitad de lo que hace potente a LUIS. Donde LUIS se vuelve poderoso es que le permite extraer datos directamente de las expresiones del usuario utilizando las entidades que definimos anteriormente. Pero, para que pueda hacer eso, primero debe etiquetar las entidades dentro de los enunciados para tenerlos identificados. Para ello, haga clic en las palabras individuales dentro de la expresión que son relevantes para la entidad. Vea cómo lo hice en el siguiente GIF.

Poner a prueba nuestras intenciones
Con las 3 o más entidades que hemos introducido y marcado hasta ahora, ahora podemos ir a jugar con LUIS para ver cómo lo hace (pista: no lo hará muy bien con sólo 3 enunciados). Haga clic en el botón de tren en la esquina superior derecha de la pantalla. Esto hace LUIS tren en contra de todas las entidades / intentos / enunciados que ha proporcionado hasta el momento.
Cuando Luis termine el entrenamiento, puedes probarlo en la interfaz web. Haz clic en el botón Prueba que abrirá la ventana de chat. Haga clic en el botón de flecha en la parte superior derecha para expandir el panel de detalles. Ahora podemos introducir frases y ver lo que hace LUIS. Voy a empezar con "Enviar alitas de pollo a 7287 North Cottage Ave. Camden, NJ 08105 de Popeye's." Esto va a funcionar bastante mal porque LUIS no ha visto nada estructurado de esta manera todavía. Así que podemos abrir el panel de detalles y editar la intención para que refleje lo que debería haber sido la intención. Si establecemos la intención en el panel de detalles, la expresión pasará a la lista de expresiones para esa intención. A partir de ahí, podemos marcar las diferentes entidades de la intent.

Añadir patrones
Si mira la frase "Enviar alitas de pollo a 7287 North Cottage Ave. Camden, NJ 08105 de Popeye's" con todas las entidades resaltadas tendrá este aspecto:

Esto forma algo llamado un patrón, que es casi como una regex para LUIS. Usted puede agregar esto como un patrón marcando la casilla junto a la expresión, y haciendo clic en "añadir como patrón" en la parte superior. Después de hacer esto, pulse entrenar de nuevo para obtener LUIS para incorporar el nuevo enunciado y el patrón a su modelo.
Extracción de entidades a partir de consultas
Ahora que hemos entrenado LUIS un poco mejor, vamos a pasar de nuevo "Enviar alitas de pollo a 7287 North Cottage Ave. Camden, NJ 08105 de Popeye's." Esto va a producir un resultado sustancialmente diferente. Por un lado, ahora es 100% seguro que la intención era pedir comida. Y lo que es más importante, además de determinar la intención del enunciado, extrae información útil del mismo. Por ejemplo, sabemos que el método es "Enviar", que forma parte de la sublista de entrega, por lo que sabemos que quieren que se les entreguen las alitas de pollo. Sabemos que la comida que quieren es "Alitas de pollo". Sabemos que quieren las alitas de pollo de Popeye's, ¡y sabemos dónde entregarlas! Cuando consultemos esto más tarde desde nuestra aplicación C#, veremos que los datos vuelven a nosotros en un objeto JSON que podremos analizar fácilmente.

Publicación de la demo
Para publicar su aplicación LUIS, simplemente pulse el botón publicar en la parte superior derecha de la pantalla, seleccione la opción Producción y siga las instrucciones. Es posible que desee habilitar la corrección ortográfica de Bing o tal vez incluso el análisis de sentimiento si desea extraer el sentimiento de las solicitudes. Esto publicará la aplicación en un punto final de Azure. Primary Keyel Endpoint Urly, por supuesto, su AppId en las páginas Azure Resources y Application Information. Los necesitarás más adelante.
Crear nuestra aplicación .NET
Para esta demostración, vamos a crear una sencilla aplicación SMS API de entrada/salida en ASP.NET Core. Así que vamos a encender Visual Studio:
Haga clic en Crear nuevo
Aplicación web ASP.NET Core
Nombre
LuisVonageDemoHaga clic en Crear
Seleccione API para el tipo
Haga clic en Crear
Añadir una nueva clase
LuisQueryHaga clic con el botón derecho en el directorio Controladores y vaya a Añadir -> Controladory cree un nuevo Controlador API -> Vacío
SmsControllerAñade una nueva clase llamada
Dispatcheral proyecto
Añadir paquetes
Añade los siguientes paquetes al proyecto:
Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime (Estoy usando 3.0.0)
Nexmo.Csharp.Client (Estoy usando 4.3.1)
Añadir variables de entorno
Puedes decidir cómo vas a introducir tus credenciales en tu aplicación. A mí me gusta usar inyección de dependencias de configuración o variables de entorno. El uso de variables de entorno es un poco más simple en este caso, así que vamos a seguir adelante y utilizar eso para la demostración. Haga clic derecho sobre el proyecto y vaya a propiedades. En el menú Depuración desplácese hasta variables de entorno y añada lo siguiente:
| Variable | Description |
|---|---|
| NEXMO_API_KEY | Your API Key from the dashboard |
| NEXMO_API_Secret | Your API Secret from the dashboard |
| LUIS_PREDICTION_KEY | This is the key from LUIS |
| LUIS_ENDPOINT_NAME | The endpoint URL from LUIS e.g. https://westus.api.cognitive.microsoft.com |
| LUIS_APP_ID | the Guid App ID from Luis |
Consulta Luis
Así que ahora vamos a consultar el LUIS Endpoint desde nuestra aplicación. Abre la clase LuisQuery y añade las siguientes sentencias using en la parte superior:
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime;
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime.Models;
using System;
using System.Threading.Tasks;A continuación, dentro de la clase añade los siguientes campos:
// Use Language Understanding (LUIS) prediction endpoint key
// to create authentication credentials
private static string _predictionKey = Environment.GetEnvironmentVariable("LUIS_PREDICTION_KEY");
// Endpoint URL example value = "https://YOUR-RESOURCE-NAME.api.cognitive.microsoft.com"
private static string _predictionEndpoint = Environment.GetEnvironmentVariable("LUIS_ENDPOINT_NAME");
// App Id example value e.g. "df67dcdb-c37d-46af-88e1-8b97951ca1c2"
private static string _appId = Environment.GetEnvironmentVariable("LUIS_APP_ID");A continuación, vamos a crear el cliente mediante la generación de un conjunto de credenciales de nuestra clave de predicción, y el uso de esas credenciales junto con nuestro punto final. Vamos a crear un cliente en un método estático.
private static LUISRuntimeClient CreateClient()
{
var credentials = new ApiKeyServiceClientCredentials(_predictionKey);
return new LUISRuntimeClient(credentials, new System.Net.Http.DelegatingHandler[] { })
{
Endpoint = _predictionEndpoint
};
}Lo último que hay que hacer aquí es crear un método que utilice nuestro cliente de predicción para crear una predicción. Este método toma una cadena queryobtiene un cliente de predicción y añade nuestra consulta a nuestro punto final de predicción.
public static async Task<PredictionResponse> GetPredictionAsync(string query)
{
using (var luisClient = CreateClient())
{
var requestOptions = new PredictionRequestOptions
{
PreferExternalEntities = true
};
var predictionRequest = new PredictionRequest
{
Query = query,
Options = requestOptions
};
return await luisClient.Prediction.GetSlotPredictionAsync(
Guid.Parse(_appId),
slotName: "production",
predictionRequest,
verbose: true,
showAllIntents: true,
log: true);
}
}
Añadir código despachador
Nuestro Dispatcher va a gestionar la lógica de negocio de lo que queremos hacer con nuestros intents. Por lo tanto lo primero que hay que establecer es el enum para nuestros intents. Añade lo siguiente a tu clase Dispatcher clase:
public enum Intent
{
None,
OrderFood
}A continuación, añada las siguientes sentencias using al archivo Dispatcher archivo.
using Newtonsoft.Json.Linq;
using Nexmo.Api;
using System;A continuación, vamos a añadir una función, ExecuteQuerypara ejecutar la consulta, crear un mensaje de respuesta a partir del resultado de la consulta y enviar ese mensaje de vuelta al endpoint. Tomará el mensaje SMS entrante de nuestro endpoint controlador (que construiremos a continuación), extraerá el mensaje y lo enviará a través de nuestra clase LuisQuery clase. Si la consulta detecta una intención None, crea un mensaje que dice: "No lo he entendido bien. Si no, extrae el nombre de la comida y del restaurante del mensaje y responde al cliente que su comida está en camino.
public static async void ExecuteQuery(SMS.SMSInbound inbound)
{
try
{
var query = inbound.text;
var apiKey = Environment.GetEnvironmentVariable("NEXMO_API_KEY");
var apiSecret = Environment.GetEnvironmentVariable("NEXMO_API_SECRET");
var message = string.Empty;
//Get prediction
var pred = await LuisQuery.GetPredictionAsync(query);
var intent = Enum.Parse(typeof(Intent), pred.Prediction.TopIntent);
Console.WriteLine($"Top intent was {pred.Prediction.TopIntent}");
switch (intent)
{
case Intent.None:
message = "I didn't quite get that. Can you please specify what you would like to do?";
break;
case Intent.OrderFood:
var food = (pred.Prediction.Entities["Food"] as JArray)?[0];
var restaraunt = (pred.Prediction.Entities["RestaurantReservation.PlaceName"] as JArray)?[0];
message = $"We'll have that {food} from {restaraunt} send over straight away!";
break;
}
Console.WriteLine($"Message: {message}");
//Send the SMS back
var client = new Client(new Nexmo.Api.Request.Credentials { ApiKey = apiKey, ApiSecret = apiSecret });
client.SMS.Send(new SMS.SMSRequest { to = inbound.msisdn, from = inbound.to, text = message });
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
} Recepción y envío de SMS
Vamos a recibir mensajes SMS en nuestro endpoint SmsController consulta a LUIS, y responder a los SMS entrantes. Para ello, vamos a entrar en nuestra clase SmsController clase. Lo primero que vamos a hacer es eliminar el atributo Route del atributo SmsController. Entonces aquí vamos a añadir un método:
[HttpGet("webhooks/inbound")]
public IActionResult Get([FromQuery]SMS.SMSInbound inbound)
{
Dispatcher.ExecuteQuery(inbound);
return NoContent();
}Para ello deberá importar el espacio de nombres Nexmo.Api para ello.
Y ese es todo el código que vamos a necesitar.
Pruebas con IIS Express y ngrok
Sólo vamos a estar probando esto en IIS express, así que vamos a ir a la pestaña de depuración de la página de propiedades del proyecto. Voy a deshabilitar SSL en IIS Express y tomar nota del número de puerto en el que está alojado. A continuación, voy a ejecutar el siguiente comando en el símbolo del sistema:
Eso arrancará ngrok y producirá algo como:

Tome nota de la identificación única por delante de la ngrok.io en la URL. Deje que esto sea e inicie la aplicación en modo de depuración en IIS Express.
Configurar Webhooks
Ahora todo lo que queda por hacer es ir a la página de configuración en el panel de control y cambiar la URL de los mensajes entrantes a http://UNIQUE_NGROK_ENDPOINT.ngrok.io/webhooks/inbound. Sustituya UNIQUE_NGROK_ENDPOINT por el conjunto aleatorio de caracteres producido por ngrok. En el ejemplo anterior, el endpoint sería http://dc0feb1d.ngrok.io/webhooks/inbound. Esto apunta a Vonage en nuestro servidor IIS Express y nos permite recibir mensajes en nuestro punto final de SMS.
Hora de probar
Ahora sólo queda hacer una prueba. La aplicación debería estar lista y funcionando; todo lo que tienes que hacer es enviar un mensaje de texto con tu pedido de entrega a cualquier número habilitado para SMS que hayas adquirido a través del panel de la API de Vonagey el pedido se procesará por ti.
Próximos pasos
Esta demo era un ejemplo básico de cómo trabajar con LUIS. LUIS es una plataforma robusta con mucha flexibilidad. Sin embargo, como sin duda habrás observado, requiere pensar mucho en cómo vas a construir la base de conocimientos para que sea realmente útil.
Hay un montón de canales que las API de Vonage te permiten usar para hablar con LUIS a través de ellos. Puedes usar la Messages APIque admite Facebook Messenger, WhatsApp y Viber, además de SMS. LUIS también le permite trabajar con el habla directamente, por lo que potencialmente podría construir un bot que escucha el habla de una llamada PSTN a través de Vonage de API de Websocket.
Recursos
Puede encontrar el código de ejemplo completo en GitHub
Si quieres saltarte la construcción del modelo e importar el que construí para fines de demostración, está disponible aquí.
Hay mucha documentación sobre cómo trabajar con Luis en el sitio de documentación de Microsoft de Microsoft.
