如何最好地使用Microsoft Bot Framework(v3)模块化对话框?

时间:2019-10-27 11:35:27

标签: node.js botframework

我刚刚得到一个项目,在该项目中我需要学习和处理Microsoft Bot Framework 3.2版(这是我正在修改的旧项目)。

我正在研究示例,并试图了解对话框流程的工作方式以及如何最好地对其进行模块化。

据我了解,当您像这样创建机器人时

// CODE SAMPLE 1
const bot = new builder.UniversalBot(connector, [
    function (session) {
        session.send("Welcome to the dinner reservation.");
        session.beginDialog('askForDateTime');
    },
   /*
   functions omitted for brevity 
   */
]).set('storage', inMemoryStorage); // Register in-memory storage 

创建bot时必须给出构成“默认对话框”的功能数组-也就是说,您不能在以后添加或更改默认对话框。正确吗?

然后,如果以后要对对话框结构进行模块化,则可以有类似的内容(请参见上面的代码)

// CODE SAMPLE 2 (in same file as code above)
bot.dialog('askForDateTime', [
    function (session) {
        builder.Prompts.time(session, "Please provide a reservation date and time (e.g.: June 6th at 5pm)");
    },
    function (session, results) {
        session.endDialogWithResult(results);
    }
]);

那么,bot.dialog是否正在向机器人注册此对话框以供以后使用?也就是说,在运行时(在对话过程中)会进行某种形式的查找,该字符串基于将第一个代码示例中的session.beginDialog('askForDateTime');与在{第二个代码示例?

当我查看SDK参考时,我发现bot.dialog('askForDateTime')接受beginDialog

IAddress

上面写着

  

事件的地址路由信息。地址是双向的   意味着它们可用于处理传入和传出事件。   它们也是特定于连接器的,这意味着连接器可以自由   在地址中添加自己的字段。

因此,通过字符串进行的“注册”基本上是一种事件注册系统,类似于function beginDialog(address: IAddress, dialogId: string, dialogArgs?: any, done?: (err: Error) => void) ,但在这种情况下,它不是在注册动作本身,而是在对话框?

最后两个问题:

一个人可以从addEventListener内部呼叫session.beginDialog吗?也就是说,是否有嵌套的对话框树?就这样,唯一的例子是从默认对话框嵌套,但是我不知道它是否可以更深入。

最后,如何将对话框模块化到单独的节点模块中,即将子对话框移动到单独的文件中?我想到了这样的东西:

bot.dialog

但看不到如何在我的主应用程序中使用

// askForDateTime.js
module.exports = bot => 
     bot.dialog('askForDateTime', [
        function (session) {
            builder.Prompts.time(session, "Please provide a reservation date and time (e.g.: June 6th at 5pm)");
        },
        function (session, results) {
            session.endDialogWithResult(results);
        }
    ]);

感谢您的帮助!我意识到使用版本4可能会更容易,但是我需要使用更早的版本。

1 个答案:

答案 0 :(得分:1)

首先,请注意,Botbuilder V3即将终止,支持将在2019年底结束。您可以详细了解此主题here以及从v3迁移到v4的选项here

关于默认对话框,另一种方法是仅将连接器传递到适配器中,然后在发生conversationUpdate时启动对话框。使用conversationUpdate时可能会遇到一些挑战,因此在继续之前,我将仔细阅读this博客文章。

var bot = new builder.UniversalBot(connector)

bot.on('conversationUpdate', function (message) {
    if (message.membersAdded) {
        message.membersAdded.forEach(function (identity) {
            if (identity.id === message.address.bot.id) {
                bot.beginDialog(message.address, '/main');
            }
        });
    }
});


// ----greetings.js -----
bot.dialog('/main', [
    function (session, args, next) {
        session.send("Glad you could join.");
        session.beginDialog('/nextDialog');
    }
]);

关于beginDialog()注册/寻址,没有发生任何预注册。调用对话框时,它实际上就像其他函数一样被调用。该地址或多或少用于管理对话框状态(即机器人在对话中的位置)-是将对话框添加到堆栈中,正在使用中还是从对话框中弹出。

关于在另一个对话框中调用一个对话框,是的,这是可行的,如this示例中所示:

lib.dialog('/', [

    [...other functions...]

    function (session, args) {
        session.dialogData.recipientPhoneNumber = args.response;
        session.beginDialog('validators:notes', {
            prompt: session.gettext('ask_note'),
            retryPrompt: session.gettext('invalid_note')
        });
    },

    [...other functions...]

]);

最后,关于模块化,是的,这也是可行的。查看这两个样本中的任何一个。 core-MultiDialogs不太复杂,但是demo-ContosoFlowers也是一个很好的例子。

希望有帮助!