
Compartilhar:
Steve é um ex-membro da equipe da Vonage. Ele atuou como Developer Advocate .NET na Vonage, engenheiro de software full-stack poliglota, especializado em IA/ML
Compreensão de linguagem em SMS com o LUIS e o .NET
Como você faz para obter as entradas do usuário? Aposto que, se estiver desenvolvendo um aplicativo web ou uma interface gráfica (GUI), provavelmente usará algum formulário que o usuário possa preencher e enviar. Se estiver criando um aplicativo de console, terá uma série de entradas e parâmetros codificados que o usuário fornecerá. E se você quisesse receber uma mensagem, digamos, um SMS, de um usuário e extrair informações úteis desse SMS?
Veja esta frase, por exemplo:
I'd like to have one cheese pizza from Joe's Pizza delivered to 21 Jump Street, Melbourne, FL 32940.Imagine coletar essas informações por meio de um formulário na 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: 32940Mas, é claro, como essa frase não está estruturada, é impossível extrair essa informação dela. É aí que entra o Language Understanding da Microsoft (LUIS) da Microsoft entra em cena. Com o LUIS, podemos criar bots que nos permitem usar a linguagem natural como entrada e compreender a intenção do usuário mesmo a partir dessas frases. E é isso que vamos aprender neste post: como criar compreensão de linguagem natural usando o LUIS e como utilizar esse reconhecimento de linguagem para processar entradas de SMS.
Pré-requisitos
Visual Studio ou Rider (estou usando o Visual Studio 2019)
O runtime do .NET Core 3.1
Opcional: ngrok para testar
Alguns conceitos importantes no LUIS AI
O LUIS considera todas as entradas como “enunciados”, ou seja, coisas que você poderia dizer. Há dois Concepts-chave que você precisa entender para começar a usar o LUIS. O primeiro é a intenção. A intenção é o objetivo da expressão — portanto, no nosso exemplo, você poderia chamar essa intenção de “OrderFood”. O segundo conceito são as entidades, que são informações específicas transmitidas por meio de nossas expressões e que podem corresponder aos dados em um formulário.
Usando esses conceitos fundamentais, você pode identificar a intenção do usuário, quase como se estivesse direcionando a solicitação para um endpoint. Em seguida, você pode extrair as informações que o usuário está fornecendo para utilizá-las em seu aplicativo.
Criação de aplicativos LUIS
Vamos começar acessando a página de inscrição do LUIS da aplicação LUIS.
A partir daqui, crie um aplicativo clicando em “Criar aplicativo”. Vamos chamá-la de DeliverySample.

Depois de criar seu aplicativo, você será redirecionado para o painel do seu aplicativo. Clique em “Build” na barra de abas na parte superior:

Isso levará você à interface do construtor. Agora, há duas maneiras de criar seu aplicativo Luis: por meio da API ou com a interface gráfica (GUI). Vamos aprender a fazer isso usando a interface gráfica (GUI).
Adicionar algumas entidades
Entidade de endereço
Para adicionar algumas entidades ao nosso aplicativo, acessamos Recursos do aplicativo -> Entidades. Vamos começar criando uma entidade de endereço. Como um endereço se divide em vários componentes, vamos começar adicionando os tipos de entidade dos componentes. Primeiro, clique em Criar nova entidade e crie um simple tipo chamado Número da Rua. Repita isso para Nome da Rua, Cidade, Estado e CEP. Por fim, podemos criar a entidade composta. Clique em “Criar nova entidade” novamente, selecione o tipo compositee adicione cada um dos tipos que acabamos de criar como filhos desse tipo.

Entidade de Método
Agora você também pode criar outras entidades — por exemplo, uma entidade “Método” que descreva como o usuário receberá a comida. Nesta época da COVID-19, temos apenas duas opções: para viagem ou entrega. Assim, criaremos “Método” como uma List entidade (uma entidade com uma lista enumerada de valores), e para esses valores podemos fornecer sinônimos, por exemplo, “para viagem” ou “entregue em casa”.

Adicionando uma entidade “Alimento”
Também podemos adicionar uma entidade de alimento. Para isso, vamos adicionar outra simple entidade e chamá-la de “alimento”.
Incorporar uma entidade do tipo “Domain-Simple”
A última entidade que vamos adicionar será a entidade “PlaceName Domain-Simple”. Clique em “Adicionar entidade de domínio pré-construída” e procure RestaurantReservation.PlaceName. Essas entidades pré-construídas vêm acompanhadas de centenas de expressões pré-treinadas. Assim, elas conseguem compreender razoavelmente bem como um nome de lugar se apresenta no contexto. De qualquer forma, precisaremos treinar o LUIS para compreendê-las um pouco melhor, já que ele analisará nomes de restaurantes sob uma perspectiva diferente.
Incorporando nossa intenção
As intenções no LUIS correspondem ao que a expressão que você está fornecendo está solicitando ou dizendo. Portanto, no nosso exemplo, podemos interpretar a “intenção” da frase como `OrderFood`. Então, vamos fazer exatamente isso. Acesse Recursos do aplicativo -> Intents. Essa página exibe a lista de intenções que seu aplicativo procura. Todo aplicativo do LUIS reconhece uma intenção “None”, que é a intenção “Não sei”, registrada quando ele não consegue entender o que a fala está dizendo. Vamos adicionar nossa intenção de exemplo, “OrderFood”.
Adicionar frases à intenção “OrderFood”
Depois de criada a intenção, precisamos preenchê-la com expressões. O preenchimento dessas expressões permite que o LUIS reconheça a intenção e extraia os dados dela. A recomendação da Microsoft é que qualquer intenção do mundo real precise de, no mínimo, 15 expressões de diferentes comprimentos, estruturas e tempos verbais antes que o LUIS possa começar a prever e extrair informações com precisão.
Para adicionar expressões a uma intenção, clique na intenção, o que o levará à página da intenção. Nessa página, há uma seção que diz: “Digite um exemplo do que um usuário poderia dizer e pressione Enter”. Siga essas instruções para inserir uma expressão. Aqui estão algumas com as quais comecei:
Gostaria de pedir uma porção de batatas fritas “disco” para ser entregue no endereço 14 Seventh Ave, Nova York, Nova York, 10001
Será que posso pedir um burrito de frango do Chipotle para entrega no endereço 15 Yemen Road, Cedar Rapids, Iowa, 52227?
Gostaria de comprar um Frango do General Tsao no Hop Bo's
Entidades de rotulagem
O que acabamos de fazer permitirá que o LUIS extraia a intenção do usuário dessas frases. Mas isso é apenas metade do que torna o LUIS tão poderoso. O que torna o LUIS realmente poderoso é o fato de ele permitir que você extraia dados diretamente das falas do usuário usando as entidades que definimos anteriormente. Mas, para que isso aconteça, você precisa primeiro rotular as entidades dentro das falas para que elas sejam identificadas. Para fazer isso, clique nas palavras individuais dentro da fala que sejam relevantes para a entidade. Veja como eu fiz isso no GIF abaixo.

Testando nossas intenções
Com as cerca de 3 entidades que inserimos e marcamos até agora, já podemos começar a experimentar o LUIS para ver como ele se sai (dica: ele não vai se sair muito bem com apenas 3 expressões). Clique no botão “treinar” no canto superior direito da tela. Isso faz com que o LUIS seja treinado com todas as entidades, intenções e expressões que você forneceu até agora.
Quando o Luis terminar o treinamento, você poderá testá-lo na interface da web. Clique no botão “Testar” , o que abrirá a janela de bate-papo. Clique no botão de seta no canto superior direito para expandir o painel de detalhes. Agora podemos digitar frases e ver o que o LUIS faz. Vou começar com “Envie asas de frango para 7287 North Cottage Ave., Camden, NJ 08105, do Popeye’s”. Esse comando terá um desempenho bem ruim, pois o LUIS ainda não viu nada estruturado dessa maneira. Portanto, podemos abrir o painel de detalhes e editar a intenção para que ela reflita o que deveria ter sido. Definir a intenção no painel de detalhes irá inserir essa expressão na lista de expressões para essa intenção. A partir daí, podemos marcar as diferentes entidades da intenção.

Adicionando padrões
Se você observar a frase “Envie asas de frango para 7287 North Cottage Ave., Camden, NJ 08105, do Popeye’s” com todas as entidades destacadas, ficará assim:

Isso forma o que chamamos de padrão, que é quase como uma expressão regular para o LUIS. Você pode adicioná-lo como padrão marcando a caixa ao lado da expressão e clicando em “adicionar como padrão”, na parte superior. Depois disso, clique em “treinar” novamente para que o LUIS incorpore a nova expressão e o padrão ao seu modelo.
Extração de entidades de consultas
Agora que treinamos o LUIS um pouco melhor, vamos passar para ele novamente: “Envie asas de frango para 7287 North Cottage Ave., Camden, NJ 08105, do Popeye’s”. Isso vai gerar um resultado substancialmente diferente. Para começar, agora há 100% de certeza de que a intenção era pedir comida. Além disso, e mais importante ainda, além de determinar a intenção da fala, ele extraiu informações úteis dela. Por exemplo, sabemos que o método é “Enviar”, que faz parte da sublista de entregas; portanto, sabemos que a pessoa quer que as asinhas de frango sejam entregues. Sabemos que a comida que ela quer são “Asinhas de frango”. Sabemos que a pessoa quer as asas de frango do Popeye’s e sabemos para onde entregá-las! Quando consultarmos isso mais tarde em nosso aplicativo C#, veremos que os dados nos serão retornados em um objeto JSON que poderemos analisar facilmente.

Publicação da demonstração
Para publicar seu aplicativo LUIS, basta clicar no botão “Publicar” no canto superior direito da tela e selecionar o Produção e siga as instruções. Você pode ativar a verificação ortográfica do Bing ou até mesmo a análise de sentimento, caso queira extrair o sentimento das solicitações. Isso publicará o aplicativo em um endpoint do Azure — anote o Primary Key, o Endpoint Urle, é claro, seu AppId nas páginas de Recursos do Azure e Informações das Applications. Você precisará deles mais tarde.
Criação do nosso aplicativo .NET
Para esta demonstração, vamos criar um aplicativo simples de SMS API de entrada e saída no ASP.NET Core. Então, vamos abrir o Visual Studio:
Clique em Criar novo
Aplicativo Web ASP.NET Core
Diga o nome
LuisVonageDemoClique Criar
Selecione a API para o tipo
Clique Criar
Adicionar uma nova classe
LuisQueryClique com o botão direito do mouse no diretório “Controllers” e acesse Adicionar -> Controlador, crie um novo Controlador de API -> Vazio
SmsControllerAdicione uma nova classe chamada
Dispatcherao projeto
Adicionar pacotes
Adicione os seguintes pacotes ao projeto:
Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime (estou usando a versão 3.0.0)
Nexmo.Csharp.Client (estou usando a versão 4.3.1)
Adicionar variáveis de ambiente
Você pode decidir como vai inserir suas credenciais no seu aplicativo. Eu prefiro usar injeção de dependência de configuração ou variáveis de ambiente. Usar variáveis de ambiente é um pouco mais simples neste caso, então vamos usar isso para a demonstração. Clique com o botão direito do mouse no projeto e acesse as propriedades. Na guia , role a tela até “Variáveis de ambiente” e adicione o seguinte:
| 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 |
Pergunte ao Luis
Então, agora vamos fazer uma consulta ao Endpoint do LUIS a partir do nosso aplicativo. Abra a LuisQuery classe e adicione as seguintes instruções `using` no início:
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime;
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime.Models;
using System;
using System.Threading.Tasks;Em seguida, dentro da classe, adicione os seguintes 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 seguir, vamos criar o cliente gerando um conjunto de credenciais a partir da nossa chave de previsão e utilizando essas credenciais juntamente com nosso endpoint. Criaremos um cliente em um método estático.
private static LUISRuntimeClient CreateClient()
{
var credentials = new ApiKeyServiceClientCredentials(_predictionKey);
return new LUISRuntimeClient(credentials, new System.Net.Http.DelegatingHandler[] { })
{
Endpoint = _predictionEndpoint
};
}A última coisa a fazer aqui é criar um método que utilize nosso cliente de previsão para gerar uma previsão. Esse método recebe uma string query, obtém um cliente de previsão e envia nossa consulta ao nosso endpoint de previsão.
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);
}
}
Adicionar código do despachante
Nosso Dispatcher vai gerenciar a lógica de negócios do que queremos fazer com nossas intenções. Portanto, a primeira coisa a definir é a enumeração para nossas intenções. Adicione o seguinte à sua Dispatcher classe:
public enum Intent
{
None,
OrderFood
}Em seguida, adicione as seguintes instruções `using` ao Dispatcher arquivo.
using Newtonsoft.Json.Linq;
using Nexmo.Api;
using System;A seguir, vamos adicionar uma função, ExecuteQuerypara executar a consulta, criar uma mensagem de resposta a partir do resultado da consulta e enviar essa mensagem de volta ao endpoint. Ela receberá nossa mensagem SMS de entrada do endpoint do controlador (que criaremos a seguir), extrairá o conteúdo da mensagem e o passará pela nossa LuisQuery classe. Se a consulta detectar uma intenção “None”, ela criará uma mensagem dizendo: “Não entendi muito bem. Você poderia especificar o que gostaria de fazer?”. Caso contrário, ela extrairá o nome do prato e do restaurante da mensagem e responderá ao cliente que o pedido está a caminho.
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());
}
} Recebimento e envio de SMS
Vamos receber mensagens SMS em nosso SmsController endpoint, consultar o LUIS e responder às mensagens SMS recebidas. Para fazer isso, vamos acessar nossa SmsController classe. A primeira coisa que faremos é remover o Route atributo do SmsController. Em seguida, vamos adicionar um método aqui:
[HttpGet("webhooks/inbound")]
public IActionResult Get([FromQuery]SMS.SMSInbound inbound)
{
Dispatcher.ExecuteQuery(inbound);
return NoContent();
}Você precisará importar o Nexmo.Api namespace para isso.
E esse é todo o código de que vamos precisar!
Testes com o IIS Express e o ngrok
Vamos testar isso apenas no IIS Express, então vamos para a aba “Depuração” da página de propriedades do projeto. Vou desativar o SSL no IIS Express e anotar o número da porta em que ele está sendo hospedado. Em seguida, vou executar o seguinte comando no prompt de comando:
Isso iniciará o ngrok e exibirá algo como:

Anote o ID exclusivo que aparece antes de “ngrok.io” na URL. Deixe-o como está e inicie o aplicativo no modo de depuração no IIS Express.
Configurar Webhooks
Agora, tudo o que resta fazer é acessar a página de configurações no painel e alterar a URL das mensagens recebidas para http://UNIQUE_NGROK_ENDPOINT.ngrok.io/webhooks/inbound. Substitua UNIQUE_NGROK_ENDPOINT pelo conjunto aleatório de caracteres gerado pelo ngrok. No exemplo acima, o endpoint seria http://dc0feb1d.ngrok.io/webhooks/inbound. Isso direciona o Vonage para o nosso servidor IIS Express e nos permite receber mensagens em nosso endpoint de SMS.
Hora do teste
Agora só falta fazer um teste. O aplicativo já deve estar funcionando; basta enviar uma mensagem de texto com seu pedido de entrega para qualquer número compatível com SMS que você tenha obtido por meio do painel da API da Vonage, e o pedido será processado para você.
Próximos passos
Esta demonstração foi um exemplo básico de como trabalhar com o LUIS. O LUIS é uma plataforma robusta e com grande flexibilidade. No entanto, como você sem dúvida observou, é preciso refletir bastante sobre como construir a base de conhecimento para que ela seja realmente útil.
Existem inúmeros canais que as APIs da Vonage permitem que você utilize para se comunicar com o LUIS. Você pode usar a Messages API, que oferece suporte ao Facebook Messenger, WhatsApp e Viber, além de SMS. O LUIS também permite que você trabalhe diretamente com áudio, de modo que você poderia, potencialmente, criar um bot que escute a voz de uma chamada PSTN por meio da API Websocketda Vonage.