Using LUIS -Language Understanding Intelligent Service (MS Bot Framework V4 Edition)

Oct 3

Written by:
10/3/2018 6:09 PM  RssIcon

image

The Microsoft Bot Framework V4 allows you to create intelligent bots that interact naturally wherever your users are (text/SMS to Skype, Slack, Office 365 mail and other popular services). The Bot Builder V4 SDK offers new features and is extensible with a pluggable middleware model.

In this article we will build on the example started in the following article: Using Dialogs (MS Bot Framework V4 Edition). In this article we will cover integrating LUIS (Language Understanding Intelligent Service) into your Bot. Using Language Understanding Intelligent Service (LUIS) in your Bot allows you to create chat bots that are easier for your end-users to interact with.

Tutorial Series

Other articles in this series:

Requirements

 

Why Use LUIS?

The Microsoft Language Understanding Intelligent Service (LUIS) allows you to create intelligent applications that allow your end-users to use natural language to perform actions.

The Language Understanding Intelligent Service (LUIS), allows developers to create language understanding models that are specific to their problem domain. To use LUIS, developers log into the LUIS website, enter a few utterances and their labels, and then deploy a model to an HTTP endpoint on Azure.

The utterances sent to the endpoint are logged and labeled. The website allows the developer (or any application administrator) to train the application by identifying issues, which can be resolved by either adding more labels or by giving hints to the machine learner in the form of features.

A developer can create and deploy a model in minutes, and then maintain and train it as the usage of the application grows.

 

Create The LUIS Application

image

To get started, go to: https://www.luis.ai, create an account, and sign in with your Azure account.

image

Select Create new app.

image

Give the app a name and click Done.

image

Select Intents then Add prebuilt domain intent.

image

Search for help and select Utilities.Help and click Done.

We are basically creating a LUIS app to detect when a person is asking for help.

image

Click Train.

image

Publish the app.

image

On the Keys and Endpoints page and copy and save the Subscription Key and the URI Location (you will need them later).

Note: Only use this Subscription Key for development, for Production see: Creating Endpoint Keys using Azure

image

Go to the Manage page and copy and save the Application ID (you will also need it later).

Update The Bot Code

image

Open the project created in the article: Using Dialogs (MS Bot Framework V4 Edition) in Visual Studio 2017 (or higher).

Right-click on the project node and select Manage NuGet Packages.

image

Search for Microsoft.Bot.Builder.Ai.LUIS.

Click on Microsoft.Bot.Builder.Ai.LUIS, then click the Install button.

(accept any other screens that appear and fully install the package)

image

Open the Startup.cs file.

Add the following using statement to the top of the file:

 
using Microsoft.Bot.Builder.AI.Luis;

 

Add the following code at the end of ConfigureServices method (but still inside the method):

 

            // Create and register a LUIS recognizer.
            services.AddSingleton(sp =>
            {
                // Set up Luis
                var luisApp = new LuisApplication(
                    applicationId: "** Your Application ID **",
                    endpointKey: "** Your Subscription Key **",
                    endpoint: "** service endpoint **");
                // Specify LUIS options. These may vary for your bot.
                var luisPredictionOptions = new LuisPredictionOptions
                {
                    IncludeAllIntents = true,
                };
                return new LuisRecognizer(
                    application: luisApp,
                    predictionOptions: luisPredictionOptions,
                    includeApiResults: true);
            });

 

Note:

  • Enter the Application ID you saved earlier where it indicates ** Your Application ID ** (it must be between the quotes)
  • Enter the Subscription Key you saved earlier where it indicates ** Your Subscription Key ** (it must be between the quotes)
  • Enter the URI Location you saved earlier where it indicates ** service endpoint ** (it must be between the quotes). Only use the first part, for example: https://westus.api.cognitive.microsoft.com/

 

This code returns a LuisRecognizer that will them be injected into the main code (in the EchoBot.cs file) using dependency injection.

 

image

Open the EchoBot.cs file.

Add the following using statements to the top of the file:

 

using Microsoft.Bot.Builder.AI.Luis;

 

Add the following global property to the class:

 

private LuisRecognizer Recognizer { get; } = null;

 

Alter the constructor for the class to the following to pass in the LuisRecognizer (using dependency injection):

 

public EchoWithCounterBot(EchoBotAccessors accessors, LuisRecognizer luis)

 

Inside the constructor ad the following code to set the value of the global variable:

 

            // The incoming luis variable is the LUIS Recognizer we added above.
            this.Recognizer = luis ?? throw new System.ArgumentNullException(nameof(luis));

 

Next, alter the OnTurnAsync method to the following to pass any user inputs to the LUIS model. If there is a match above 0.95 it returns: “<here’s some help>”:

 

        public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken
            cancellationToken = default(CancellationToken))
        {
            if (turnContext.Activity.Type == ActivityTypes.Message)
            {
                // Check LUIS model
                var recognizerResult = await this.Recognizer.RecognizeAsync(turnContext, cancellationToken);
                var topIntent = recognizerResult?.GetTopScoringIntent();
                // Get the Intent as a string
                string strIntent = (topIntent != null) ? topIntent.Value.intent : "";
                // Get the IntentScore as a double
                double dblIntentScore = (topIntent != null) ? topIntent.Value.score : 0.0;
                // Only proceed with LUIS if there is an Intent 
                // and the score for the Intent is greater than 95
                if (strIntent != "" && (dblIntentScore > 0.95))
                {
                    switch (strIntent)
                    {
                        case "None":
                            await turnContext.SendActivityAsync("Sorry, I don't understand.");
                            break;
                        case "Utilities_Help":
                            await turnContext.SendActivityAsync("<here's some help>");
                            break;
                        default:
                            // Received an intent we didn't expect, so send its name and score.
                            await turnContext.SendActivityAsync(
                                $"Intent: {topIntent.Value.intent} ({topIntent.Value.score}).");
                            break;
                    }
                }

 

 

To handle the situations where LUIS does not return an Intent with a high enough score, change the remaining code in the method to the following to wrap it into an else block:

 

                else
                {
                    // Get the conversation state from the turn context.
                    var state = await _accessors.CounterState.GetAsync(turnContext, () => new CounterState());
                    // Bump the turn count for this conversation.
                    state.TurnCount++;
                    if (!state.SaidHello)
                    {
                        // Handle the Greeting
                        string strMessage = $"Hello World! {System.Environment.NewLine}";
                        await turnContext.SendActivityAsync(strMessage);
                        // Set SaidHello
                        state.SaidHello = true;
                    }
                    else
                    {
                        // Get the user state from the turn context.
                        var user = await _accessors.UserProfile.GetAsync(turnContext, () => new UserProfile());
                        if (user.Name == null)
                        {
                            // Run the DialogSet - let the framework identify the current state of the 
                            // dialog from the dialog stack and figure out what (if any) is the active dialog.
                            var dialogContext = 
                                await _dialogs.CreateContextAsync(turnContext, cancellationToken);
                            var results = 
                                await dialogContext.ContinueDialogAsync(cancellationToken);
                            // If the DialogTurnStatus is Empty we should start a new dialog.
                            if (results.Status == DialogTurnStatus.Empty)
                            {
                                await dialogContext.BeginDialogAsync("details", null, cancellationToken);
                            }
                        }
                        else
                        {
                            // Echo back to the user whatever they typed.
                            var responseMessage =
                                $"Turn {state.TurnCount}: {user.Name} you said '{turnContext.Activity.Text}'\n";
                            await turnContext.SendActivityAsync(responseMessage);
                        }
                    }
                    // Set the property using the accessor.
                    await _accessors.CounterState.SetAsync(turnContext, state);
                    // Save the new turn count into the conversation state.
                    await _accessors.ConversationState.SaveChangesAsync(turnContext);
                    // Save the user profile updates into the user state.
                    await _accessors.UserState.SaveChangesAsync(turnContext, false, cancellationToken);
                }
            }

 

 

Run The Updated Code

image

We can now run the application and connect to it with the Bot Framework Emulator (V4) (see: Creating a Hello World! Bot (MS Bot Framework V4 Edition) for information on how to do that).

 

image

 

Links

Azure Bot Service Documentation for the v4 SDK

How your bot gets messages from LUIS

Using LUIS for Language Understanding

Conversational AI: Best Practices for Building Bots

 

Download

You can download the code from the Download page