Search code examples
c#botframeworkazure-language-understanding

Dynamic Prompt with Bot Framework C# v4


I am building a chatbot to schedule meetings with people, As of now, I have built a simple waterfall model. Where the 1st query finds the intent and the following finish the task

  1. What time?
  2. With Who?
  3. What is the Subject?

But this feels like the person is filling up a form. I also had built a basic bot without the waterfall model, but the user had to include all of the above information in a single query.

Eg, "Schedule a meeting with Aditya and Jhon at 10:30 AM Tomorrow as Breakfast"

My goal is to ask a dynamic prompt based on what is missing from the first query Eg, "Schedule a meeting Tomorrow at 10:30 AM", would prompt for Name and Subject. Or "Schedule meeting with Aditya for Breakfast" would prompt for a Time.

I am calling Luis for each response from the user to as it is better than Hardcode, and also "Tomorrow at 10:30 AM" would give me back a DateTime Formate for the same and I don't have to figure out Date of tomorrow based on Today.


Solution

  • Aditya, Setup a state object for the entities you need. These would be who, what and when I guess? It looks like you're already training Luis, so make sure you're also training it to pick up the entities from the utterances. When Luis comes back with your new appointment intent, it will also have the entities it was able to extract. Save the found entities in your state objects. Now, as you go through your waterfall steps, check the state object first. If the you already have that entity skip the prompting. If you don't, proceed with the prompt. Take a look at this sample on github. It's fairly complicated but shows what I am talking about. Specifically pay attention to the 'GetAllRequiredPropertiesAsync' method. That's where the samepl is doing what I first described. You are 100% on the right track and this should get you where you want to go.

    I'm editing to add some sample code.

    In the code from github, the constructor declares two waterfall steps:

    var waterfallSteps = new WaterfallStep[]
    {
        GetAllRequiredPropertiesAsync,
        BookTableAsync,
    };
    

    The method 'GetAllRequiredPropertiesAsync' is checking each piece of the required data to book a table. The method is really long so I'm going to only show a small, relevant bit of code.

    After a bunch of setup this piece of code ultimately prompt the user for any pieces missing from the table reservation

     var options = new PromptOptions()
        {
            Prompt = MessageFactory.Text(reservationResult.NewReservation.GetMissingPropertyReadOut()),
        };
        // Start the prompt with the first missing piece of information.
        return await stepContext.PromptAsync(GetLocationDateTimePartySizePrompt, options);
    

    Now, take a look at 'GetLocationDateTimePartySizePrompt'. This dialog is declared on the same page around line 53. It checks if the reservation is complete, if it isn't, it reads out what it already knows, then asks for the rest. This happens around like 101, then line 109 at this code snipped await promptValidatorContext.Context.SendActivityAsync(newReservation.GetMissingPropertyReadOut());

    That method is declared here. This is really simple to understand. It gets called repeatedly until it returns empty string signifying that all properties have been filled in.

    I hope this helps