Use multiple LUIS and QnA models

APPLIES TO: yesSDK v4 no SDK v3

If a bot uses multiple LUIS models and QnA Maker knowledge bases (KBs), you can use Disptach tool to determince which LUIS model or QnA Maker KB best maches the user input. The dispatch tool does this by creating a single LUIS app to route user input to the corrrect model. For more information about the Disptach, including the CLI commands, refer to the README.

Prerequisites

About this sample

This sample is based on a predefined set of LUIS and QnA Maker Apps.

Code sample logic flow

OnMessageActivityAsync is called for each user input received. This module finds the the top scoring user intent and passes that result on to DispatchToTopIntentAsync. DispatchToTopIntentAsync, in turn, calls the appropriate app handler

  • ProcessSampleQnAAsync - for bot faq questions.
  • ProcessWeatherAsync - for weather queries.
  • ProcessHomeAutomationAsync - for home lighting commands.

The handler calls the LUIS or QnA Maker service and returns the generated result back to the user.

Create LUIS apps and QnA KB

Before you can create the dispatch model, you'll need to have your LUIS apps and QnA KBs created and published. In this article, we'll publish the following models that are inculded with the NLP With Dispatch sample in the \CognitiveModels folder:

Name Description
HomeAutomation A LUIS app that recognizes a home automation intent with associated entity data.
Weather A LUIS app that recognizes weather related intents with location data.
QnAMaker A QnA Maker KB that provides answers to simple questions about the bot.

Create LUIS apps

  1. Log into the LUIS web portal. Under section My apps select the Tab Import new app. The following Dialog Box will appear:

Import LUIS json file

  1. Select the button Choose app file, navigate to the CognitiveModel folder of your sample code and select the file 'HomeAutomation.json'. Leave the optional name field blank.

  2. Select Done.

  3. Once LUIS opens up your Home Automation app, select the Train button. This will train your app using the set of utterances you just imported using the 'home-automation.json' file.

  4. When training is complete, select the Publish button. The following Dialog Box will appear:

Publish LUIS app

  1. Choose the 'production' environment and then select the Publish button.

  2. Once your new LUIS app has been published, select the MANAGE Tab. From the 'Application Information' page, record the values Application ID as "app-id-for-app" and Display name as "name-of-app". From the 'Key and Endpoints' page, record the values Authoring Key as "your-luis-authoring-key" and Region as "your-region". These values will later be used within your 'appsetting.json' file.

  3. Once completed, Train and Publish both your LUIS weather app and your LUIS dispatch app by repeating the above steps for 'Weather.json' file.

Create QnA Maker KB

The first step to setting up a QnA Maker KB is to set up a QnA Maker service in Azure. To do that, follow the step-by-step instructions found here.

Once your QnA Maker Service has been created in Azure, you need to record the Cognitive Services Key 1 provided for your QnA Maker service. This will be used as <azure-qna-service-key1> when adding qna to your dispatch application. The following steps provide you with this key:

Select Cognitive Service

  1. From within your Azure Portal, select your QnA Maker cognitive service.

Select Cognitive Service Keys

  1. Select the Keys icon found under the Resource Management section on the left-hand menu.

Select Cognitive Service Key1

  1. Copy the value of Key 1 to your clipboard and save this locally. this will later be used for the (-k) key value <azure-qna-service-key1> when adding qna to your dispatch application.

Now log into the QnAMaker web portal. Move down to Step 2

Create QnA Step 2

and select

  1. Your Azure AD account.
  2. Your Azure subscription name.
  3. The name you created for your QnA Maker service. (If your Azure QnA service does not initially appear in this pull down list, try refreshing the page.)

Move to Step 3

Create QnA Step 3

Provide a name for your QnA Maker knowledgebase. For this example we will be using the name 'sample-qna'.

Move to Step 4

Create QnA Step 4

select the option + Add File, navigate to the CognitiveModel folder of your sample code, and select the file 'QnAMaker.tsv'

There is an additional selection to add a Chit-chat personality to your knowledgebase but our example does not include this option.

Move to Step 5

select Create your KB.

Once a knowledgebase has been created from your uploaded file, select Save and train and when finished select the PUBLISH Tab and publish your app.

Once your QnA Maker app is published, select the SETTINGS Tab, and scroll down to 'Deployment details'. Record the following values from the Postman Sample HTTP request.

POST /knowledgebases/<knowledge-base-id>/generateAnswer
Host: <your-hostname>  // NOTE - this is a URL.
Authorization: EndpointKey <qna-maker-resource-key>

The full URL string for your hostname will look like "https://< >.azure.net/qnamaker".

These values will later be used within your appsettings.json or .env file.

Note the LUIS app and QnA Maker knowledge base names and IDs. Also note your LUIS authoring key and your Cognitive Services subscription key. You will need all this information to complete this process.

Create the dispatch model

The CLI interface for the dispatch tool creates the model for dispatching to the correct service.

  1. Open a command prompt or terminal window, and change directories to the CognitiveModels directory

  2. Make sure you have the current version of npm and the Dispatch tool.

    npm i -g npm
    npm i -g botdispatch
    
  3. Use dispatch init to initialize create a .dispatch file for your dispatch model. Create this usinga filename you will recognize.

    dispatch init -n <filename-to-create> --luisAuthoringKey "<your-luis-authoring-key>" --luisAuthoringRegion <your-region>
    
  4. Use dispatch add to add your LUIS apps and QnA Maker knowledge bases to the .dispatch file.

    dispatch add -t luis -i "<app-id-for-weather-app>" -n "<name-of-weather-app>" -v <app-version-number> -k "<your-luis-authoring-key>" --intentName l_Weather
    dispatch add -t luis -i "<app-id-for-home-automation-app>" -n "<name-of-home-automation-app>" -v <app-version-number> -k "<your-luis-authoring-key>" --intentName l_HomeAutomation
    dispatch add -t qna -i "<knowledge-base-id>" -n "<knowledge-base-name>" -k "<azure-qna-service-key1>" --intentName q_sample-qna
    
  5. Use dispatch create to generate a dispatch model from the .dispatch file.

    dispatch create
    
  6. Publish the dispatch LUIS app using the generated dispatch model JSON file.

Use the dispatch model

The generated model defines intents for each of the apps and knowledge bases, as well as a none intent for when the utterance doesn't have a good fit.

  • l_HomeAutomation
  • l_Weather
  • None
  • q_sample-qna

Note that these services need to be published under the correct names for the bot to run properly.

The bot needs information about the published services, so that it can access those services.

Installing packages

Prior to running this app for the first time ensure that several nuget packages are installed:

Microsoft.Bot.Builder

Microsoft.Bot.Builder.AI.Luis

Microsoft.Bot.Builder.AI.QnA

Manually update your appsettings.json file

Once all of your service apps are created, the information for each needs to be added into your 'appsettings.json' file. The initial C# Sample code contains an empty appsettings.json file:

appsettings.json

 "MicrosoftAppId": "",
 "MicrosoftAppPassword": "",

 "QnAKnowledgebaseId": "",
 "QnAAuthKey": "",
 "QnAEndpointHostName": "",

 "LuisAppId": "",
 "LuisAPIKey": "",
 "LuisAPIHostName": "",

For each of the entities shown below, add the values you recorded earlier in these instructions:

appsettings.json

"MicrosoftAppId": "",
"MicrosoftAppPassword": "",
  
"QnAKnowledgebaseId": "<knowledge-base-id>",
"QnAAuthKey": "<qna-maker-resource-key>",
"QnAEndpointHostName": "<your-hostname>",

"LuisAppId": "<app-id-for-dispatch-app>",
"LuisAPIKey": "<your-luis-authoring-key>",
"LuisAPIHostName": "<your-dispatch-app-region>",

When all changes are inplace, save this file.

Connect to the services from your bot

To connect to the Dispatch, LUIS, and QnA Maker services, your bot pulls information from the settings you have previously provided.

In BotServices.cs, the information contained within configuration file appsettings.json is used to connect your dispatch bot to the Dispatch and SampleQnA services. The constructors use the values you provided to connect to these services.

BotServices.cs

public BotServices(IConfiguration configuration)
{
    // Read the setting for cognitive services (LUIS, QnA) from the appsettings.json
    Dispatch = new LuisRecognizer(new LuisApplication(
        configuration["LuisAppId"],
        configuration["LuisAPIKey"],
        $"https://{configuration["LuisAPIHostName"]}.api.cognitive.microsoft.com"),
        new LuisPredictionOptions { IncludeAllIntents = true, IncludeInstanceData = true },
        true);

    SampleQnA = new QnAMaker(new QnAMakerEndpoint
    {
        KnowledgeBaseId = configuration["QnAKnowledgebaseId"],
        EndpointKey = configuration["QnAAuthKey"],
        Host = configuration["QnAEndpointHostName"]
    });
}

Call the services from your bot

For each input from your user, the bot logic checks user input against the combined Dispatch model, finds the top returned intent, and uses that information to call the appropriate service for the input.

In the DispatchBot.cs file whenever the OnMessageActivityAsync method is called, we check the incoming user message against the Dispatch model. We then pass the Dispatch Model's topIntent and recognizerResult on to the correct method to call the service and return the result.

DispatchBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    // First, we use the dispatch model to determine which cognitive service (LUIS or QnA) to use.
    var recognizerResult = await _botServices.Dispatch.RecognizeAsync(turnContext, cancellationToken);
    
    // Top intent tell us which cognitive service to use.
    var topIntent = recognizerResult.GetTopScoringIntent();
    
    // Next, we call the dispatcher with the top intent.
    await DispatchToTopIntentAsync(turnContext, topIntent.intent, recognizerResult, cancellationToken);
}

Work with the recognition results

When the model produces a result, it indicates which service can most appropriately process the utterance. The code in this bot routes the request to the corresponding service, and then summarizes the response from the called service. Depending on the intent returned from Dispatch, this code uses the returned intent to route to the correct LUIS model or QnA service.

DispatchBot.cs

private async Task DispatchToTopIntentAsync(ITurnContext<IMessageActivity> turnContext, string intent, RecognizerResult recognizerResult, CancellationToken cancellationToken)
{
    switch (intent)
    {
        case "l_HomeAutomation":
            await ProcessHomeAutomationAsync(turnContext, recognizerResult.Properties["luisResult"] as LuisResult, cancellationToken);
            break;
        case "l_Weather":
            await ProcessWeatherAsync(turnContext, recognizerResult.Properties["luisResult"] as LuisResult, cancellationToken);
            break;
        case "q_sample-qna":
            await ProcessSampleQnAAsync(turnContext, cancellationToken);
            break;
        default:
            _logger.LogInformation($"Dispatch unrecognized intent: {intent}.");
            await turnContext.SendActivityAsync(MessageFactory.Text($"Dispatch unrecognized intent: {intent}."), cancellationToken);
            break;
    }
}

If method ProcessHomeAutomationAsync or ProcessWeatherAsync are invoked, they are passed the results from the dispatch model within luisResult.ConnectedServiceResult. The specified method then provides user feedback showing the dispatch model top intent, plus a ranked listing of all intents and entities that were detected.

If method q_sample-qna is invoked, it uses the user input contained within the turnContext to generate an answer from the knowledgebase and display that result to the user.

Note

If this were a production application, this is where the selected LUIS methods would connect to their specified service, pass in the user input, and process the returned LUIS intent and entity data.

Test your bot

Using your development environment, start the sample code. Note the localhost address shown in the address bar of the browser window opened by your App: "https://localhost:<Port_Number>" After opening your Bot Framework Emulator, select the blue test outlined below create new bot configuration.

Create new configuration

Enter the localhost address you recorded, adding '/api/messages' to the end: "https://localhost:<Port_Number>/api/messages"

Connect the Emulator

Now click the Save and connect button to access your running bot. For your reference, here are some of the questions and commands that are covered by the services built for your bot:

  • QnA Maker
    • hi, good morning
    • what are you, what do you do
  • LUIS (home automation)
    • turn on bedroom light
    • turn off bedroom light
    • make some coffee
  • LUIS (weather)
    • whats the weather in redmond washington
    • what's the forecast for london
    • show me the forecast for nebraska

Additional information

Once your bot is running, it is possible to improve the bot's performance by removing similar or overlapping utterances. For example, let's say that in the Home Automation LUIS app requests like "turn my lights on" map to a "TurnOnLights" intent, but requests like "Why won't my lights turn on?" map to a "None" intent so that they can be passed on to QnA Maker. When you combine the LUIS app and the QnA Maker service using dispatch, you need to do one of the following:

  • Remove the "None" intent from the original Home Automation LUIS app, and instead add the utterances from that intent to the "None" intent in the dispatcher app.
  • If you don't remove the "None" intent from the original LUIS app, you will instead need to add logic into your bot to pass the messages that match your "None" intent on to the QnA maker service.

Either of the above two actions will reduce the number of times that your bot responds back to your users with the message, 'Couldn't find an answer.'

To update or create a new LUIS model

This sample is based on a preconfigured LUIS model. Additional information to help you update this model, or create a new LUIS model, can be found here.

To delete resources

This sample creates a number of applications and resources that you can delete using the steps listed below, but you should not delete resources that any other apps or services rely on.

To delete LUIS resources:

  1. Sign in to the luis.ai portal.
  2. Go to the My Apps page.
  3. Select the apps created by this sample.
    • Home Automation
    • Weather
    • NLP-With-Dispatch-BotDispatch
  4. Click Delete, and click Ok to confirm.

To delete QnA Maker resources:

  1. Sign in to the qnamaker.ai portal.
  2. Go to the My knowledge bases page.
  3. Click the delete button for the Sample QnA knowledge base, and click Delete to confirm.

Best practice

To improve services used in this sample, refer to best practice for LUIS, and QnA Maker.