0
votes

I have been working on customizing corebot example of botframework (https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/13.core-bot)

After trying to make it work i realized that the example provided was not handling user answer that were not associated to Luis intent.

For example, i would like the bot to prompt the user to repeat when he says "blabla".

enter image description here

Below the code of main dialog. When i say "blabla" (which is obviously not recognized by Luis), the bot stops and restart from scratch.

// Call LUIS and gather any potential booking details. (Note the TurnContext has the response to the prompt.)
            var luisResult = await _luisRecognizer.RecognizeAsync<FlightBooking>(stepContext.Context, cancellationToken);
            switch (luisResult.TopIntent().intent)
            {
                case FlightBooking.Intent.BookFlight:
                    await ShowWarningForUnsupportedCities(stepContext.Context, luisResult, cancellationToken);

                    // Initialize BookingDetails with any entities we may have found in the response.
                    var bookingDetails = new BookingDetails()
                    {
                        // Get destination and origin from the composite entities arrays.
                        Destination = luisResult.ToEntities.Airport,
                        Origin = luisResult.FromEntities.Airport,
                        TravelDate = luisResult.TravelDate,
                    };

                    // Run the BookingDialog giving it whatever details we have from the LUIS call, it will fill out the remainder.
                    return await stepContext.BeginDialogAsync(nameof(BookingDialog), bookingDetails, cancellationToken);

                case FlightBooking.Intent.GetWeather:
                    // We haven't implemented the GetWeatherDialog so we just display a TODO message.
                    var getWeatherMessageText = "TODO: get weather flow here";
                    var getWeatherMessage = MessageFactory.Text(getWeatherMessageText, getWeatherMessageText, InputHints.IgnoringInput);
                    await stepContext.Context.SendActivityAsync(getWeatherMessage, cancellationToken);
                    break;

                default:
                    // Catch all for unhandled intents
                    var didntUnderstandMessageText = $"Sorry, I didn't get that. Please try asking in a different way (intent was {luisResult.TopIntent().intent})";
                    var didntUnderstandMessage = MessageFactory.Text(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
                    await stepContext.Context.SendActivityAsync(didntUnderstandMessage, cancellationToken);
                    break;
            }

            return await stepContext.NextAsync(null, cancellationToken);
        }

Is there a way i can handle these? It could be really useful and i could leave the loop with any other intents.


EDIT


Based on the answer from @billoverton, i am trying to add this if before the switch.

if (luisResult.TopIntent().score < 0.5) 
{ FlightBooking.Intent = FlightBooking.Intent.None; } 

but it says that FlightBooking.Intent is a type and not a variable.

1
I haven't used that nomenclature before, but as in my example, I would completely bypass it. Try assigning the top intent to a variable and then switch on that. E.g. var topIntent = luisResult.TopIntent().intent. I'd still put that if statement underneath: if (luisResult.TopIntent().score < 0.5) { topIntent = FlightBooking.Intent.None; }. I'm not 100% sure that assignment will work (I assign mine to just the text intent name 'None'), but I'd give that a go and see how it works.billoverton

1 Answers

1
votes

I'm curious why LUIS isn't returning None for you. I thought that was standard behavior. But regardless it may be because you're trying to switch on the LUIS result directly. I save the intent to a variable and switch on that. I'm using nodejs but you should be able to follow and implement something similar in C#. So here is my call to LUIS and intent switching.

const results = await this.luisRecognizer.recognize(context);
var topIntent = LuisRecognizer.topIntent(results);
if (results.intents[topIntent].score < 0.5) {
    topIntent = 'None';
}

if (!dc.context.responded) {
    switch (dialogResult.status) {
        case DialogTurnStatus.empty:
            switch (topIntent) {
                case Intent1:
                    break;
                case Intent2:
                    break;
                deafult:
                    break;
            }
        case DialogTurnStatus.waiting:
            break;
        case DialogTurnStatus.complete:
            break;
        default:
            await dc.cancelAllDialogs();
            break;
    }
}

The one additional thing I'm doing here is manually setting the intent to None if the confidence is low. I'd rather have the bot not understand than kick off a dialog off of 20% confidence.