Adding prompts to a Microsoft bot

Introduction

In recent posts I have covered the basics of creating a bot. One of the last features that was added was the ability to remove a team from a competition. In a normal desktop or web application, basic user experience rules would have us ensure that the user was prompted to confirm such a decision. Our bot didn’t have this feature, which would increase the possibility of users mistakenly deleting data. In todays post we are going to look at adding prompts to our bot.

Basic yes or no questions

The first prompt we will look at is a basic confirmation. This prompt will allow the user to respond with Yes or No. As some of the channels we can connect our bot into allow for buttons, we will automatically get these displayed. We will see these in the image from our emulator later in the post, but we need to remember that depending on channel used (i.e. SMS) this may not be available to the user.

To implement our prompt we call PromptDialog.Confirm. We need to provide the context, the name of a suitable Action and also some options for how we what we will display in the prompt. In this example, for the options we just provide a caption for the dialog. In the example later in the post we will create a more complete set of PromptOptions.

private string TeamName;

[LuisIntent("RemoveTeam")]
public async Task RemoveTeam(IDialogContext context, LuisResult result)
{
    EntityRecommendation rec;
    if (result.TryFindEntity("TeamName", out rec))
    {
        TeamName = rec.Entity;
        if (champs.DoesTeamExist(TeamName))
        {
            PromptDialog.Confirm(context, RemoveTeamPromptAsync, 
                    $"Are you sure you want to delete the team { TeamName }?");
        }
        else
        {
            await context.PostAsync($"The team {TeamName} was not found.");
            context.Wait(MessageReceived);
        }
    }
    else
    {
        await context.PostAsync("An error occured. We were unable to remove the team.");
        context.Wait(MessageReceived);
    }

}

In the RemoveTeamPromptAsync method we created we need to add the code for handling the users response. For a confirm dialog the result is always going to be a bool, so we can await this result and use that to determine the action to carry out. If the user selects or states No then no action is taken and the user is informed of this. At the end of the method we have the IDialogContext await the next message.

private async Task RemoveTeamPromptAsync(IDialogContext context, IAwaitable<bool> result)
{
    if (await result)
    {
        champs.RemoveTeam(TeamName);
        await context.PostAsync($"{TeamName} has been removed from the championships.");
    }
    else
    {
        await context.PostAsync($"OK, we have not deleted them.");
    }
    context.Wait(MessageReceived);
}

We can test our code now in the Emulator and see how the prompt is displayed to the users.

Simple Prompt

Custom prompts

Although Yes/No prompts are great, sometimes you want to provide a more specific set of options. Imaging creating a booking application and the user asks to book an appointment. You would not respond back with a yes or no question of if they want to book unless you had more details. So rather than requiring the user to specify a time initially, you could offer them a list of available times via a prompt.

In the example below I have added a new feature to my Championships class that returns the top three teams. This is a simple example, but provides enough to show the necessary steps. The LUIS application has also been updated to have a new Intent called RemoveGoodTeam. This allows the user to inform the bot to “Remove a good team” and the bot will return a list of the top three teams and ask the user which it should remove.

Outside of the bot code, I have called the GetTopThreeTeams from my sample app and assigned to result to a List this will be used in the prompt options. We now create PromptOptions object which we will use with our PromptDialog. Within these options we can provide a number of settings. In this example not only do I provide the prompt for the user as in we did in our earlier example, but I also provide messages for incorrect entries, too many attempts, the list of options to display (taken from our GetTopThreeTeamsMethod) and finally how many attempts the user gets.

The final line of the code calls the PromptDialog but this time instead of Confirm we call Choice.

[LuisIntent("RemoveGoodTeam")]
public async Task RemoveGoodTeam(IDialogContext context, LuisResult result)
{
    List goodTeams = champs.GetTopThreeTeams();
    PromptOptions options = new PromptOptions("Select which of the top teams to remove",
            "Sorry please try again", "I give up on you", goodTeams, 2);
    PromptDialog.Choice(context, RemoveGoodTeamAsync, options);
}

The code for our action is pretty much the same as our first example, with the notable exception that we are awaiting a string and not a bool. The string value will be one of the options we provided earlier. The bot will only return one of our specified options, so we don’t have to worry as much about invalid entries as we would have done if the user had sent the request themselves.

private async Task RemoveGoodTeamAsync(IDialogContext context, IAwaitable<string> result)
{
    string res = await result;
    if (champs.DoesTeamExist(res))
    {
        champs.RemoveTeam(res);
        await context.PostAsync($"{res} has been removed from the championships.");
    }
    else
    {
        await context.PostAsync($"The team {res} was not found.");
    }
    context.Wait(MessageReceived);
}

When we test this in the emulator we can see the options now displayed instead of the Yes/No prompts. If we typed in a team name that was not on the options list, the bot would return the message we entered for incorrect entries. After the specified number of attempts had failed, the user would have to re ask the bot to remove a good team.

CustomPrompt

What next?

So far in the last three posts we have created a basic bot, added natural language support with LUIS and now provided prompts and questions. Our next stage is to deploy our bot outside of our local environment and connect up to some of the channels available.

Author: Dave Green

Software developer focusing on Microsoft Technologies, MCSD in Windows Store Apps, full time developer at a real job, part time writer and terrible golf player. Follow on twitter @IntelligentLabs

Leave a Reply

Your email address will not be published. Required fields are marked *