hckr.fyi // thoughts

Adding LUIS to your Bot for the Microsoft Bot Framework

by Michael Szul on

I've been doing a series of videos on working with the Microsoft Bot Framework, and over the first few, I give some working examples. I'll be using all of the examples in an upcoming speaking engagement at the edUi Conference this September. One in particular deals with using cognitive services--specifically Microsoft's LUIS--for natural language processing (NLP). Although using an NLP might seem intimidating, it's actually drop dead simple in the Bot Framework when using one of their SDK's.

Let's assume you have a bot all set up and ready to go, and you want to add LUIS to the mix. Find the code where you initialize your bot. For example, this is pulled from the GitHub project:

var bot = new builder.UniversalBot(conn, (sess) => {
            if(sess.message.text.toLowerCase() === "hello") {
                sess.send("Hello. Welcome to the edUi bot. You can learn about the conference schedule and speakers here.");
            }
            else {
                sess.send("Sorry, I don't understand what you said.");
            }
    });
    

Right after this, it's a simple one line edit to hook up a LUIS recognizer:

bot.recognizer(new builder.LuisRecognizer(process.env.LUIS_MODEL_URL));
    

This sets up your bot to push messages from the user to your LUIS application (on LUIS.ai). The process.env.LUIS_MODEL_URL pulls the URL of your LUIS application from the environment variables--whether local, through your Azure app setup, or using a .env file. For running this locally, I'm using a .env file, and including the following line at the top of my bot code to import the variables:

require("dotenv-extended").load();
    

After the LUIS recognizer is set up. You can capture user intents by matching the trigger action:

bot.dialog("location", [
            (sess, args, next) => {
                ...
            },
            (sess, results) => {
                ...
            }
        ]).triggerAction({
            matches: "location"
    });
    

In this example, the triggerAction is set to associate this dialog (named "location") with any response from LUIS that has been flagged as a "location" intent. The value of the matches property is the same as the name of the intent created in the LUIS app. This allows you to construct a potential series of waterfall functions that handle multiple user interactions after a particular intent has been identified.

In the first function of the waterfall array, the args variable will contain the intent, as well as associated entities--if found in the user's message. You can access these entities with args.intent.entities. This data is being returned by the LUIS application using the JSON data structure that it builds based on the user's intent.

You may be thinking that this is all great, and now you can add LUIS to your bot, but what exactly are intents and entities, and how do you set them up?

If you log into LUIS.ai with your Microsoft account, you can create a new "app" for natural language processing. When you have your new app, you create intents, which are named collections of phrases that you use to train your app.

LUIS Intents

Entities, on the other hand, are ways of identifying generic placements of variable data that represent specific objects of the user's intent. What does this mean?

LUIS Entities

Imagine you have a phrase like what time does the train arrive in Philadelphia today? This phrase might be tied to an intent that you've named "arrivals" because you want your bot to be able to answer user questions about train arrivals and departures. This phrase is very specific since it has Philadelphia in it. In your LUIS app, you can create entities (or use existing, pre-defined ones). If you were starting from scratch, you might create an entity called "city" for use in your intents. Once created, when you add the phrase above to your intent, you can click on the word "Philadelphia" in your phrase, and the LUIS interface will allow you to replace it with the city entity. By doing this, you've created a generic phrase for train arrivals, and when LUIS pings back to your bot (that has a trigger action of "arrivals"), it will pass it a collection of entities. In this instance, it would contain `args.intent.entities.city, allowing you to look up the specific arrival times of trains in Philadelphia.

Once you've created your entities and intents, you can train your app to see how well it matches certain types of phrases, and then, finally, you can publish your app (this will require you to sign up on Azure for some keys you can plug into your LUIS app).