How to use LUIS in Microsoft Bot Framework

mbf-luis-cover

In one of the previous articles, I have talked about how to start building a bot with Microsoft Bot Framework (MBF). It was a simple bot that asks a companion to do simple math exercises. The bot application works great but the process of conversation looks not very natural as the app understands only two phrases: the standard utterance for starting the conversation and answering the question with a number.
slack-bot
Also in the LUIS article, I have spoken about the human-computer interaction and one of the main problem of this process – understanding human language by computer. The solution for this problem was a service called LUIS. Let’s take a look at how we can combine both services to create a bot that will understand human language better.

Integration LUIS in MBF application
As a basis for our new bot, we will use MBF and LUIS applications from the previous articles and create a new dialog which will understand commands for managing temperature of the air conditioner. The good news is that MBF has built-in support for LUIS application which means that you don’t have to handle HTTP requests manually.

Steps:
1) To start working with LUIS we need to inherit our dialog from LuisDialog<object> and add LuisModel attribute.

[LuisModel("{model_id}", "subscription_key")]
[Serializable]
public class ConditionerDialog : LuisDialog<object>
{
 
}

2) To get model_id and subscription_key we need to login to LUIS portal and open our app. Then click publish and copy values from URL.
luis-endpoint
3) Then we can add two methods to our dialog and mark them with LuisIntent attribute. In our case LUIS will call ChangeTemperature method when phrase received from a user will be the part of “Change temperature” intent. The method that is marked with empty LuisIntent attribute will be a handler from all non-recognized utterances.

[LuisModel("81910f1b-af4a-4f13-9029-88f8a4c1e561", "48e5df8c9d3c41a39faa7cef422a4241")]
[Serializable]
public class ConditionerDialog : LuisDialog<object>
{
    [LuisIntent("Change temperature")]
    public async Task ChangeTemperature(IDialogContext context, LuisResult result)
    {
    }
 
    [LuisIntent("")]
    public async Task None(IDialogContext context, LuisResult result)
    {
    }
}

4) The result from LUIS with entities, intents and query is available in the result parameter. We write some code to add some logic to our dialog.

[LuisModel("81910f1b-af4a-4f13-9029-88f8a4c1e561", "48e5df8c9d3c41a39faa7cef422a4241")]
[Serializable]
public class ConditionerDialog : LuisDialog<object>
{
    private ConditionerState _conditionerState;
 
    [LuisIntent("Change temperature")]
    public async Task ChangeTemperature(IDialogContext context, LuisResult result)
    {
        if (_conditionerState == null)
            _conditionerState = new ConditionerState();
 
        var temperatureEntity = result.Entities.SingleOrDefault(e => e.Type == "builtin.number");
        double temperature;
 
        if (temperatureEntity == null || !double.TryParse(temperatureEntity.Entity, out temperature))
            await context.PostAsync("I can't find the temperature. Please enter a valid value.");
        else
        {
            _conditionerState.Temperature = temperature;
            var temperatureScaleEntity = result.Entities.SingleOrDefault(e => e.Type == "Temperature scale");
            var temperatureScale = _conditionerState.TemperatureScale;
 
            if (temperatureScaleEntity != null && !Enum.TryParse(temperatureScaleEntity.Entity, true, out temperatureScale))
                await context.PostAsync($"I didn't understand the {temperatureScaleEntity.Entity} temperature scale. Try to use Celsius or Fahrenheit.");
            else
            {
                _conditionerState.TemperatureScale = temperatureScale;
                await context.PostAsync($"Please wait a few minutes while AC will reach {_conditionerState.Temperature} {_conditionerState.TemperatureScale}");
            }
        }
 
        context.Wait(MessageReceived);
    }
 
    [LuisIntent("")]
    public async Task None(IDialogContext context, LuisResult result)
    {
        await context.PostAsync("Sorry I didn't understand that");
        context.Wait(MessageReceived);
    }
 
    [Serializable]
    public class ConditionerState
    {
        public double Temperature { get; set; }
        public TemperatureScale TemperatureScale { get; set; }
    }
 
    public enum TemperatureScale
    {
        Celsius,
        Fahrenheit
    }
}

5) The dialog is ready so let’s see how it works in Bot Framework Emulator.
bot-framework-emulator
You can see the utterances in LUIS portal. Also, you can review and fix LUIS suggestions. The more utterances you submit the more accurately LUIS recognizes your phrases.
luis-suggestions

Summary
With the help of Microsoft Bot Framework, you can create powerful bots that can be integrated into a lot of services like Skype, Facebook, Slack, etc. You can use LUIS service to help your bots understand a user better and become smarter with a time. Also, it’s great that MBF supports LUIS from the box and you just need to use it without care of manually handling HTTP requests.

Posted by Andriy Koval

Andriy is a founder and CEO at Westcoup. Contact him anytime at andriy.koval@westcoup.com

Comments