首页 > 解决方案 > 使用 MS Bot Framework V4 时如何从虚拟助手取消技能对话框

问题描述

我们正在使用 bot-framework 版本 4.x

"botbuilder": "4.11.0",
"botbuilder-ai": "4.11.0",
"botbuilder-applicationinsights": "4.11.0",
"botbuilder-azure": "4.11.0",
"botbuilder-dialogs": "4.11.0",
"botbuilder-lg": "4.11.0",
"botbuilder-testing": "4.11.0",
"botframework-config": "4.11.0",
"botframework-connector": "4.11.0"

案子

我们需要在虚拟助手中启动一个对话框并取消任何正在进行的技能对话框(如果有)

例子

LiveChat - 虚拟助手的一部分 CreateIncidentDialog - 技能的一部分

假设我们在 CreateIncidentDialog 的中间,并且用户想要启动 LiveChat。我们应该启动 LiveChat 并取消当前的 CreateIncidentDialog。

示例代码

MainDialog.ts in Virtual Assistant

如果当前对话框是技能的一部分,我们将启动一个以activity.type 作为技能事件的对话框。

switch (gIntent) {
 case 'Escalate': {
       // Checking if current Dialog is a part of Skill
       if (isSkill) {
            const activity: Activity = innerDc.context.activity;
            if ((activity.value === null || activity.value === undefined)) {
                 activity.value = { userState: userProfile };
            };
            activity.type = ActivityTypes.Event;
            activity.name = "liveChat";
            const skillDialogArgs: BeginSkillDialogOptions = {
                 activity: activity as Activity
            };
            await innerDc.beginDialog(EvaConfig.LUIS_DEFAULT_INTENT, skillDialogArgs);
       } else {
            await innerDc.cancelAllDialogs();
       }

       // code for starting LiveChat goes here

       // .....
       // .....
       // .....
  }

MainDialog.ts in Skill

如果 activity.type 是 EVENT 并且名称是 'liveChat',则取消对话。

protected async onContinueDialog(innerDc: DialogContext): Promise<DialogTurnResult> {

    try {
        let activity = innerDc.context.activity;
        if (innerDc.context.activity.type === ActivityTypes.Message) {
             // .....
             // .....
             // .....
        } else if (activity.type === ActivityTypes.Event) {
            const ev = activity;
            if (ev.name !== undefined && ev.name.trim().length > 0) {
                switch (ev.name) {
                    case 'liveChat': {
                        await innerDc.cancelAllDialogs(true);
                        return await innerDc.endDialog();
                    }
                }
            }
        }
        return await super.onContinueDialog(innerDc);
    } catch (e) {
        console.log(`Error onContinueDialog ---> ${e} `);
        return await this.hanldeException(innerDc);
    }
}

问题

上面的代码无法正确取消技能的对话。如果我们在取消技能对话后尝试启动一个新对话,它会再次向 Skill 中 MainDilaog.ts 的 routeStep 方法发送一个 activity.type 为 EVENT 的活动。请在下面找到相同的示例代码。

routeStep method of MainDialog.ts in Skill

protected async routeStep(stepContext: WaterfallStepContext): Promise<DialogTurnResult> {
    console.log('skill routeStep');
    if (activity.type === ActivityTypes.Message && activity.text !== undefined && activity.text.trim().length > 0) {
         // .....
         // .....
         // .....
    } else if (activity.type === ActivityTypes.Event) {
            const ev = activity;
            if (ev.name !== undefined && ev.name.trim().length > 0) {
                switch (ev.name) {
                    case 'SampleAction': {
                    // .....
                        // .....
                        // .....
                    }
                }
            } else {

                // If we try to start a new dialog, control comes here

                await stepContext.context.sendActivity({
                    type: ActivityTypes.Trace,
                    text: 'An event with no name was received but not processed.'
                });
            }
        }
    } else {
        await this.responder.replyWith(stepContext.context, MainResponses.responseIds.dontHavePermissionServiceNow);
        await this.complete(stepContext);
    }
    return await stepContext.next();

}

复制步骤

步骤 1. 在技能中启动对话 步骤 2. 在技能中结束对话并在 VA 中启动对话 步骤 3. 开始新对话

谢谢。爱德华

标签: botframeworkbotschatbotdirect-line-botframework

解决方案


推荐阅读