Search code examples
azurebotframeworkdirect-line-botframework

Adding multiple dialogs to Microsoft botframework dialog stack


According to Microsoft's Botframework Documentation here, by using triggerAction with onSelectAction, you can add dialogs to the top of the stack if a user's utterance includes a matched phrase.

However, if the user's utterance includes TWO matched phrases, how can you add multiple dialogs to the stack?

For example, if a user said...

I want a burger and fries

I would like to add the burgers dialog and the fries dialog to the stack, so we can ask questions about both of them.

I've tried something like this:

bot.dialog('burgers', require('./burgers'))
    .triggerAction({
        matches: [/burger/i],
            onSelectAction: (session, args, next) => {
                session.beginDialog(args.action, args);
            }
    });

bot.dialog('fries', require('./fries'))
    .triggerAction({
        matches: [/fries/i],
            onSelectAction: (session, args, next) => {
                session.beginDialog(args.action, args);
            }
    });

Here's an example of the burgers dialog (the fries dialog is the same):

var builder = require('botbuilder');
var Store = require('./store');

module.exports = [
    // Destination
    function (session) {
        session.send('Burger dialog test');
        builder.Prompts.text(session, 'I am just testing the burger dialog');
    },
    function (session, results, next) {
        session.send('Now we should go to the next dialog in the stack', results.response);
        session.endDialog();
    },

];

However, only one of the dialogs gets invoked... and then it's game over!

Any help is appreciated!


Solution

  • As you've found, only one dialog will be triggered at one time, so as a workaround to trigger multiple dialogs, we can trigger one dialog first and analyses the user input to call different child dialog.

    For example:

    bot.dialog('addOrder', (session, args)=>{
        var text = session.message.text;
        var found = text.match(/burger/i);
        if(found!=null){
            session.beginDialog('burger');
        }
        var found = text.match(/fries/i);
        if(found!=null){
            session.beginDialog('fries');
        }    
    }).triggerAction({
        matches: [/burger/i, /fries/i]
    });
    
    bot.dialog('burger',(session)=>{
        session.send("burgers");
        //logic of 'burger' dialog
        session.endDialog();
    });
    
    bot.dialog('fries', (session)=>{
        session.send("fries!");
        //logic of 'fries' dialog
        session.endDialog();
    }); 
    

    As you can see here, we can use a regular expression array to trigger the addOrder dialog first and then call other dialogs inside this addOrder dialog.

    Or you may train a LUIS and use it in your bot like this:

    const LuisModelUrl = 'YOUR-BOT-ENDPOINT';
    var recognizer = new builder.LuisRecognizer(LuisModelUrl);
    var intents = new builder.IntentDialog({recognizers:[recognizer]})
    .matches('MyOrder',(session, args)=>{
       var entities = args.entities;
       //handle entities
    });
    
    bot.dialog('/',intents);
    

    I create a intent named MyOrder and two entities named MyOrder.Burgers and MyOrder.Fries like this:

    enter image description here