O entendimento de linguagem conversacional (CLU), um recurso do Azure AI Language, é a versão atualizada do LUIS.
Para obter mais informações sobre o suporte à compreensão de linguagem no Bot Framework SDK, consulte Compreensão de linguagem natural.
A capacidade de entender o que seu usuário significa conversacional e contextualmente pode ser uma tarefa difícil, mas pode fornecer ao seu bot uma sensação de conversa mais natural. O Language Understanding (LUIS) é um serviço de API baseado em nuvem que permite que você faça exatamente isso para que seu bot possa reconhecer a intenção das mensagens do usuário, permitir uma linguagem mais natural do usuário e direcionar melhor o fluxo de conversa.
Este tópico orienta você pela adição do LUIS a um aplicativo de reserva de voos para reconhecer diferentes intenções e entidades contidas na entrada do usuário.
Nota
Os SDKs JavaScript, C# e Python do Bot Framework continuarão a ser suportados, no entanto, o Java SDK está sendo desativado com suporte final de longo prazo terminando em novembro de 2023.
Os bots existentes construídos com o Java SDK continuarão a funcionar.
Conhecimento básico de bots e processamento de linguagem natural.
Sobre este exemplo
Este exemplo de bot principal mostra um exemplo de um aplicativo de reserva de voo de aeroporto. Ele usa um serviço LUIS para reconhecer a entrada do usuário e retornar a intenção LUIS reconhecida superior.
O modelo de linguagem contém três intenções: Book Flight, Cancel, e None. O LUIS usará essas intenções para entender o que o usuário quis dizer quando enviar uma mensagem para o bot. O modelo de linguagem também define entidades que o LUIS pode extrair da entrada do usuário, como o aeroporto de origem ou de destino.
Após cada processamento de entrada do usuário, DialogBot salva o estado atual de ambos e ConversationStateUserState . Uma vez reunidas todas as informações necessárias, a amostra de codificação cria uma reserva de voo de demonstração. Neste artigo, abordaremos os aspetos LUIS deste exemplo. No entanto, o fluxo geral da amostra é:
OnMembersAddedAsync é chamado quando um novo usuário está conectado e exibe um cartão de boas-vindas.
OnMessageActivityAsync é chamada para cada entrada de usuário recebida.
O OnMessageActivityAsync módulo executa a caixa de diálogo apropriada através do método de extensão de Run diálogo. Em seguida, a caixa de diálogo principal chama o auxiliar do LUIS para encontrar a intenção do usuário com melhor pontuação. Se a intenção superior para a entrada do usuário retornar "BookFlight", o auxiliar preenche as informações do usuário que o LUIS retornou. Depois disso, a caixa de diálogo principal inicia o BookingDialog, que adquire informações adicionais conforme necessário do usuário, tais como:
Origin a cidade de origem
TravelDate a data para reservar o voo
Destination a cidade de destino
Após cada processamento de entrada do usuário, dialogBot salva o estado atual de ambos e conversationStateuserState . Uma vez reunidas todas as informações necessárias, a amostra de codificação cria uma reserva de voo de demonstração. Neste artigo, abordaremos os aspetos LUIS deste exemplo. No entanto, o fluxo geral da amostra é:
onMembersAdded é chamado quando um novo usuário está conectado e exibe um cartão de boas-vindas.
OnMessage é chamada para cada entrada de usuário recebida.
O onMessage módulo executa o , que reúne a mainDialogentrada do usuário.
Em seguida, a caixa de diálogo principal chama o auxiliar FlightBookingRecognizer do LUIS para encontrar a intenção do usuário com melhor pontuação. Se a intenção superior para a entrada do usuário retornar "BookFlight", o auxiliar preenche as informações do usuário que o LUIS retornou.
Após a resposta de volta, mainDialog preserva as informações para o usuário retornadas pelo LUIS e inicia.bookingDialogbookingDialog adquire informações adicionais, conforme necessário, do utilizador, tais como:
destination a cidade de destino.
origin a cidade de origem.
travelDate a data para reservar o voo.
Após cada processamento de entrada do usuário, DialogBot salva o estado atual de ambos e ConversationStateUserState .
Uma vez reunidas todas as informações necessárias, a amostra de codificação cria uma reserva de voo de demonstração.
Neste artigo, abordaremos os aspetos LUIS deste exemplo. No entanto, o fluxo geral da amostra é:
onMembersAdded é chamado quando um novo usuário está conectado e exibe um cartão de boas-vindas.
onMessageActivity é chamada para cada entrada de usuário recebida.
O onMessageActivity módulo executa a caixa de diálogo apropriada através do método de extensão de run diálogo. Em seguida, a caixa de diálogo principal chama o auxiliar do LUIS para encontrar a intenção do usuário com melhor pontuação. Se a intenção superior para a entrada do usuário retornar "BookFlight", o auxiliar preenche as informações do usuário que o LUIS retornou. Depois disso, a caixa de diálogo principal inicia o BookingDialog, que adquire informações adicionais conforme necessário do usuário, tais como:
Origin a cidade de origem
TravelDate a data para reservar o voo
Destination a cidade de destino
Após cada processamento de entrada do usuário, DialogBot salva o estado atual de ambos e conversation_stateuser_state . Uma vez reunidas todas as informações necessárias, a amostra de codificação cria uma reserva de voo de demonstração. Neste artigo, abordaremos os aspetos LUIS deste exemplo. No entanto, o fluxo geral da amostra é:
on_members_added_activity é chamado quando um novo usuário está conectado e exibe um cartão de boas-vindas.
on_message_activity é chamada para cada entrada de usuário recebida.
O on_message_activity módulo executa a caixa de diálogo apropriada através do método de extensão de run_dialog diálogo. Em seguida, a caixa de diálogo principal chama LuisHelper para encontrar a intenção do usuário com melhor pontuação. Se a intenção superior para a entrada do usuário retornar "BookFlight", a função auxiliar preenche as informações do usuário que o LUIS retornou. Depois disso, a caixa de diálogo principal inicia o BookingDialog, que adquire informações adicionais conforme necessário do usuário, tais como:
destination a cidade de destino.
origin a cidade de origem.
travel_date a data para reservar o voo.
Este artigo aborda como adicionar LUIS a um bot. Para obter informações sobre como usar caixas de diálogo ou estado, consulte como coletar a entrada do usuário usando um prompt de diálogo ou salvar dados do usuário e da conversa, respectivamente.
Escolha o arquivo FlightBooking.json na pasta CognitiveModels do exemplo.
Digite FlightBooking como o nome opcional do aplicativo e selecione Concluído.
O site pode exibir Como criar um aplicativo LUIS eficaz e Atualizar suas caixas de diálogo de entidades compostas. Você pode descartar essas caixas de diálogo e continuar.
Treine seu aplicativo e, em seguida, publique-o no ambiente de produção .
Para obter mais informações, consulte a documentação do LUIS sobre como treinar e publicar um aplicativo.
Porquê utilizar entidades
As entidades LUIS permitem que seu bot compreenda eventos além das intenções padrão. Isso permite que você colete informações adicionais dos usuários, para que seu bot possa fazer perguntas e responder de forma mais inteligente. Juntamente com as definições para as três intenções do LUIS 'Reservar voo', 'Cancelar' e 'Nenhuma', o arquivo FlightBooking.json também contém um conjunto de entidades, como 'From.Airport' e 'To.Airport'. Estas entidades permitem ao LUIS detetar e devolver informação adicional contida na entrada original do utilizador quando este solicita uma nova reserva de viagem.
Obter valores para ligar à sua aplicação LUIS
Assim que seu aplicativo LUIS for publicado, você poderá acessá-lo a partir do seu bot. Você precisará registrar vários valores para acessar seu aplicativo LUIS de dentro do seu bot. Você pode recuperar essas informações usando o portal LUIS.
Recuperar informações do aplicativo do portal LUIS.ai
O arquivo de configurações (appsettings.json, .env ou config.py) atua como o local para reunir todas as referências de serviço em um só lugar. As informações recuperadas serão adicionadas a este arquivo na próxima seção.
Selecione seu aplicativo LUIS publicado em luis.ai.
Com a aplicação LUIS publicada aberta, selecione o separador GERIR .
Selecione a guia Configurações no lado esquerdo e registre o valor mostrado para ID do aplicativo como <YOUR_APP_ID>.
Selecione Recursos do Azure e, em seguida , Recurso de Previsão. Registre o valor mostrado para Localização como YOUR_REGION e Chave Primária como <YOUR_AUTHORING_KEY>.> <
Como alternativa, você pode usar a região e a chave primária para seu recurso de criação.
Adicione as informações necessárias para acessar seu aplicativo LUIS, incluindo ID do aplicativo, chave de criação e região no appsettings.json arquivo. Na etapa anterior, você recuperou esses valores do seu aplicativo LUIS publicado. O nome do host da API deve estar no formato <your region>.api.cognitive.microsoft.com.
Adicione as informações necessárias para acessar seu aplicativo LUIS, incluindo ID do aplicativo, chave de criação e região no .env arquivo. Na etapa anterior, você recuperou esses valores do seu aplicativo LUIS publicado. O nome do host da API deve estar no formato <your region>.api.cognitive.microsoft.com.
Adicione as informações necessárias para acessar seu aplicativo LUIS, incluindo ID do aplicativo, chave de criação e região no application.properties arquivo. Na etapa anterior, você recuperou esses valores do seu aplicativo LUIS publicado. O nome do host da API deve estar no formato <your region>.api.cognitive.microsoft.com.
Adicione as informações necessárias para acessar seu aplicativo LUIS, incluindo ID do aplicativo, chave de criação e região no config.py arquivo. Na etapa anterior, você recuperou esses valores do seu aplicativo LUIS publicado. O nome do host da API deve estar no formato <your region>.api.cognitive.microsoft.com.
Certifique-se de que o pacote Microsoft.Bot.Builder.AI.Luis NuGet está instalado para o seu projeto.
Para se conectar ao serviço LUIS, o bot extrai as informações adicionadas ao arquivo appsetting.json. A FlightBookingRecognizer classe contém código com suas configurações do arquivo appsetting.json e consulta o serviço LUIS chamando RecognizeAsync o método.
FlightBookingRecognizer.cs
public class FlightBookingRecognizer : IRecognizer
{
private readonly LuisRecognizer _recognizer;
public FlightBookingRecognizer(IConfiguration configuration)
{
var luisIsConfigured = !string.IsNullOrEmpty(configuration["LuisAppId"]) && !string.IsNullOrEmpty(configuration["LuisAPIKey"]) && !string.IsNullOrEmpty(configuration["LuisAPIHostName"]);
if (luisIsConfigured)
{
var luisApplication = new LuisApplication(
configuration["LuisAppId"],
configuration["LuisAPIKey"],
"https://" + configuration["LuisAPIHostName"]);
// Set the recognizer options depending on which endpoint version you want to use.
// More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
var recognizerOptions = new LuisRecognizerOptionsV3(luisApplication)
{
PredictionOptions = new Bot.Builder.AI.LuisV3.LuisPredictionOptions
{
IncludeInstanceData = true,
}
};
_recognizer = new LuisRecognizer(recognizerOptions);
}
}
// Returns true if luis is configured in the appsettings.json and initialized.
public virtual bool IsConfigured => _recognizer != null;
public virtual async Task<RecognizerResult> RecognizeAsync(ITurnContext turnContext, CancellationToken cancellationToken)
=> await _recognizer.RecognizeAsync(turnContext, cancellationToken);
public virtual async Task<T> RecognizeAsync<T>(ITurnContext turnContext, CancellationToken cancellationToken)
where T : IRecognizerConvert, new()
=> await _recognizer.RecognizeAsync<T>(turnContext, cancellationToken);
}
O FlightBookingEx.cs contém a lógica para extrair From, To e TravelDate, estende a classe FlightBooking.cs parcial usada para armazenar resultados LUIS ao chamar FlightBookingRecognizer.RecognizeAsync<FlightBooking> do MainDialog.cs.
CognitiveModels\FlightBookingEx.cs
// Extends the partial FlightBooking class with methods and properties that simplify accessing entities in the luis results
public partial class FlightBooking
{
public (string From, string Airport) FromEntities
{
get
{
var fromValue = Entities?._instance?.From?.FirstOrDefault()?.Text;
var fromAirportValue = Entities?.From?.FirstOrDefault()?.Airport?.FirstOrDefault()?.FirstOrDefault();
return (fromValue, fromAirportValue);
}
}
public (string To, string Airport) ToEntities
{
get
{
var toValue = Entities?._instance?.To?.FirstOrDefault()?.Text;
var toAirportValue = Entities?.To?.FirstOrDefault()?.Airport?.FirstOrDefault()?.FirstOrDefault();
return (toValue, toAirportValue);
}
}
// This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.
// TIMEX is a format that represents DateTime expressions that include some ambiguity. e.g. missing a Year.
public string TravelDate
=> Entities.datetime?.FirstOrDefault()?.Expressions.FirstOrDefault()?.Split('T')[0];
}
Para usar o LUIS, seu projeto precisa instalar o pacote botbuilder-ai npm.
Para se conectar ao serviço LUIS, o bot usa as informações que você adicionou ao .env arquivo. A flightBookingRecognizer.js classe contém o código que importa suas configurações do .env arquivo e consulta o serviço LUIS chamando recognize() o método.
diálogos/flightBookingRecognizer.js
class FlightBookingRecognizer {
constructor(config) {
const luisIsConfigured = config && config.applicationId && config.endpointKey && config.endpoint;
if (luisIsConfigured) {
// Set the recognizer options depending on which endpoint version you want to use e.g v2 or v3.
// More details can be found in https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
const recognizerOptions = {
apiVersion: 'v3'
};
this.recognizer = new LuisRecognizer(config, recognizerOptions);
}
}
get isConfigured() {
return (this.recognizer !== undefined);
}
/**
* Returns an object with preformatted LUIS results for the bot's dialogs to consume.
* @param {TurnContext} context
*/
async executeLuisQuery(context) {
return await this.recognizer.recognize(context);
}
getFromEntities(result) {
let fromValue, fromAirportValue;
if (result.entities.$instance.From) {
fromValue = result.entities.$instance.From[0].text;
}
if (fromValue && result.entities.From[0].Airport) {
fromAirportValue = result.entities.From[0].Airport[0][0];
}
return { from: fromValue, airport: fromAirportValue };
}
getToEntities(result) {
let toValue, toAirportValue;
if (result.entities.$instance.To) {
toValue = result.entities.$instance.To[0].text;
}
if (toValue && result.entities.To[0].Airport) {
toAirportValue = result.entities.To[0].Airport[0][0];
}
return { to: toValue, airport: toAirportValue };
}
/**
* This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.
* TIMEX is a format that represents DateTime expressions that include some ambiguity. e.g. missing a Year.
*/
getTravelDate(result) {
const datetimeEntity = result.entities.datetime;
if (!datetimeEntity || !datetimeEntity[0]) return undefined;
const timex = datetimeEntity[0].timex;
if (!timex || !timex[0]) return undefined;
const datetime = timex[0].split('T')[0];
return datetime;
}
}
A lógica para extrair From, To e TravelDate é implementada como métodos auxiliares dentro do flightBookingRecognizer.js. Esses métodos são usados após a chamada flightBookingRecognizer.executeLuisQuery() de mainDialog.js
Certifique-se de que o pacote com.microsoft.bot.bot-ai-luis-v3 foi adicionado ao seu arquivo pom.xml.
Para se conectar ao serviço LUIS, o bot extrai as informações adicionadas ao arquivo application.properties. A FlightBookingRecognizer classe contém código com suas configurações do arquivo application.properties e consulta o serviço LUIS chamando recognize o método.
FlightBookingRecognizer.java
/**
* The constructor of the FlightBookingRecognizer class.
*
* @param configuration The Configuration object to use.
*/
public FlightBookingRecognizer(Configuration configuration) {
Boolean luisIsConfigured = StringUtils.isNotBlank(configuration.getProperty("LuisAppId"))
&& StringUtils.isNotBlank(configuration.getProperty("LuisAPIKey"))
&& StringUtils.isNotBlank(configuration.getProperty("LuisAPIHostName"));
if (luisIsConfigured) {
LuisApplication luisApplication = new LuisApplication(
configuration.getProperty("LuisAppId"),
configuration.getProperty("LuisAPIKey"),
String.format("https://%s", configuration.getProperty("LuisAPIHostName"))
);
// Set the recognizer options depending on which endpoint version you want to use.
// More details can be found in
// https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-migration-api-v3
LuisRecognizerOptionsV3 recognizerOptions = new LuisRecognizerOptionsV3(luisApplication);
recognizerOptions.setIncludeInstanceData(true);
this.recognizer = new LuisRecognizer(recognizerOptions);
}
}
/**
* Runs an utterance through a recognizer and returns a generic recognizer result.
*
* @param turnContext Turn context.
* @return Analysis of utterance.
*/
@Override
public CompletableFuture<RecognizerResult> recognize(TurnContext turnContext) {
return this.recognizer.recognize(turnContext);
}
O FlightBookingRecognizer.cs contém a lógica para extrair From, To e TravelDate, e é chamado a MainDialog.java partir do para decodificar os resultados do resultado da consulta Luís.
FlightBookingRecognizer.java
/**
* Gets the From data from the entities which is part of the result.
*
* @param result The recognizer result.
* @return The object node representing the From data.
*/
public ObjectNode getFromEntities(RecognizerResult result) {
String fromValue = "", fromAirportValue = "";
if (result.getEntities().get("$instance").get("From") != null) {
fromValue = result.getEntities().get("$instance").get("From").get(0).get("text")
.asText();
}
if (!fromValue.isEmpty()
&& result.getEntities().get("From").get(0).get("Airport") != null) {
fromAirportValue = result.getEntities().get("From").get(0).get("Airport").get(0).get(0)
.asText();
}
ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
ObjectNode entitiesNode = mapper.createObjectNode();
entitiesNode.put("from", fromValue);
entitiesNode.put("airport", fromAirportValue);
return entitiesNode;
}
/**
* Gets the To data from the entities which is part of the result.
*
* @param result The recognizer result.
* @return The object node representing the To data.
*/
public ObjectNode getToEntities(RecognizerResult result) {
String toValue = "", toAirportValue = "";
if (result.getEntities().get("$instance").get("To") != null) {
toValue = result.getEntities().get("$instance").get("To").get(0).get("text").asText();
}
if (!toValue.isEmpty() && result.getEntities().get("To").get(0).get("Airport") != null) {
toAirportValue = result.getEntities().get("To").get(0).get("Airport").get(0).get(0)
.asText();
}
ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
ObjectNode entitiesNode = mapper.createObjectNode();
entitiesNode.put("to", toValue);
entitiesNode.put("airport", toAirportValue);
return entitiesNode;
}
/**
* This value will be a TIMEX. And we are only interested in a Date so grab the first result and
* drop the Time part. TIMEX is a format that represents DateTime expressions that include some
* ambiguity. e.g. missing a Year.
*
* @param result A {link RecognizerResult}
* @return The Timex value without the Time model
*/
public String getTravelDate(RecognizerResult result) {
JsonNode datetimeEntity = result.getEntities().get("datetime");
if (datetimeEntity == null || datetimeEntity.get(0) == null) {
return null;
}
JsonNode timex = datetimeEntity.get(0).get("timex");
if (timex == null || timex.get(0) == null) {
return null;
}
String datetime = timex.get(0).asText().split("T")[0];
return datetime;
}
Certifique-se de que o pacote botbuilder-ai PyPI está instalado para o seu projeto.
Para se conectar ao serviço LUIS, o bot usa as informações que você adicionou ao config.py arquivo. A FlightBookingRecognizer classe contém o código que importa suas configurações do config.py arquivo e consulta o serviço LUIS chamando recognize() o método.
flight_booking_recognizer.py
class FlightBookingRecognizer(Recognizer):
def __init__(self, configuration: DefaultConfig):
self._recognizer = None
luis_is_configured = (
configuration.LUIS_APP_ID
and configuration.LUIS_API_KEY
and configuration.LUIS_API_HOST_NAME
)
if luis_is_configured:
# Set the recognizer options depending on which endpoint version you want to use e.g v2 or v3.
# More details can be found in https://docs.microsoft.com/azure/cognitive-services/luis/luis-migration-api-v3
luis_application = LuisApplication(
configuration.LUIS_APP_ID,
configuration.LUIS_API_KEY,
"https://" + configuration.LUIS_API_HOST_NAME,
)
self._recognizer = LuisRecognizer(luis_application)
@property
def is_configured(self) -> bool:
# Returns true if luis is configured in the config.py and initialized.
return self._recognizer is not None
async def recognize(self, turn_context: TurnContext) -> RecognizerResult:
return await self._recognizer.recognize(turn_context)
A lógica para extrair From, To e travel_date é implementada como métodos auxiliares da LuisHelper classe dentro luis_helper.pydo . Esses métodos são usados após a chamada LuisHelper.execute_luis_query() de main_dialog.py
ajudantes/luis_helper.py
class LuisHelper:
@staticmethod
async def execute_luis_query(
luis_recognizer: LuisRecognizer, turn_context: TurnContext
) -> (Intent, object):
"""
Returns an object with preformatted LUIS results for the bot's dialogs to consume.
"""
result = None
intent = None
try:
recognizer_result = await luis_recognizer.recognize(turn_context)
intent = (
sorted(
recognizer_result.intents,
key=recognizer_result.intents.get,
reverse=True,
)[:1][0]
if recognizer_result.intents
else None
)
if intent == Intent.BOOK_FLIGHT.value:
result = BookingDetails()
# We need to get the result from the LUIS JSON which at every level returns an array.
to_entities = recognizer_result.entities.get("$instance", {}).get(
"To", []
)
if len(to_entities) > 0:
if recognizer_result.entities.get("To", [{"$instance": {}}])[0][
"$instance"
]:
result.destination = to_entities[0]["text"].capitalize()
else:
result.unsupported_airports.append(
to_entities[0]["text"].capitalize()
)
from_entities = recognizer_result.entities.get("$instance", {}).get(
"From", []
)
if len(from_entities) > 0:
if recognizer_result.entities.get("From", [{"$instance": {}}])[0][
"$instance"
]:
result.origin = from_entities[0]["text"].capitalize()
else:
result.unsupported_airports.append(
from_entities[0]["text"].capitalize()
)
# This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop
# the Time part. TIMEX is a format that represents DateTime expressions that include some ambiguity.
# e.g. missing a Year.
date_entities = recognizer_result.entities.get("datetime", [])
if date_entities:
timex = date_entities[0]["timex"]
if timex:
datetime = timex[0].split("T")[0]
result.travel_date = datetime
else:
result.travel_date = None
except Exception as exception:
print(exception)
return intent, result
O LUIS agora está configurado e conectado para seu bot.
Execute a amostra localmente na sua máquina. Se você precisar de instruções, consulte o README arquivo para o Exemplo de C#, Exemplo de JS ou Exemplo de Python.
No emulador, digite uma mensagem como "viajar para Paris" ou "Ir de Paris para Berlim". Use qualquer enunciado encontrado no arquivo FlightBooking.json para treinar a intenção "Reservar voo".
Se a intenção principal retornada do LUIS resolver para "Reservar voo", seu bot fará mais perguntas até ter informações suficientes armazenadas para criar uma reserva de viagem. Nesse momento, ele retornará essas informações de reserva de volta ao seu usuário.
Neste ponto, a lógica do bot de código será redefinida e você poderá continuar a criar mais reservas.
Informações adicionais
Para obter mais informações sobre o LUIS, consulte a documentação do LUIS: