根据验证重复对话步骤

Repeating a dialog step based on validation

我目前正在使用 Bot Framework v4 构建配置机器人,并且我已将其与 Microsoft Graph 集成。

Microsoft Graph 用于验证用户输入,因此在这种情况下,它会检查组名是否已存在。但是,我 运行 遇到的问题是让机器人在验证发现该组存在时重复上一步。

我浏览了论坛并看到了许多解决方案,尤其是我遇到了 step.activeDialog.state['stepIndex']-2 方法,但一直无法使它起作用。这是在 NodeJS 中返回一个步骤的可行解决方案,还是我应该考虑另一种方法?

async nameStep(step) {
        // User selected a group type and now is required to enter the name of the group
        step.values.sitetype = step.result.value;
        return await step.prompt(NAME_PROMPT, 'What do you want to name it');
    }

    async ownerStep(step) {
        // Retrieve the value from the previous step and check against the Microsoft Graph to see if the name has been used previously
        step.values.name = step.result;
        const getToken =
            await axios.post(TOKEN_ENDPOINT, qs.stringify(postData))
            .then(response => {
                return {
                    headers: {
                        'Authorization': 'Bearer ' + response.data.access_token
                    }
                }
            })
            .catch(error => {
                console.log(error);
            });

        const graphCall =
            await axios.get("https://graph.microsoft.com/v1.0/groups?$filter=startswith(displayName,'" + `${step.result}` + "')", getToken)
            .then((response) => {
                if (response.data.value[0] != null) {
                    return true;
                }
            })
            .catch((error) => {
                console.log(error);
            })

        if (!graphCall) {
            return await step.prompt(NAME_PROMPT, 'What is your email address');
        } else {
            await step.context.sendActivity("Group already exists");
            return await step.activeDialog.state['stepIndex']-2
        }
    }

提前致谢

您可以使用 component dialog 来实现。本质上,您将要重复的步骤外推到一个单独的对话框中,该对话框仅从当前 (parent) 对话框中调用。在 parent 中,您进行检查。当检查失败时,再次调用组件对话框。如果成功,parent 对话框将继续。

在下面的代码中,我的 parent 对话框立即调用组件对话框进行第一次传递,向用户提供两个选项。每个都将发送一个 pre-determined 文本值,检查该值是否存在 LUIS 意图。

第一个选项 "Hello" 将成功找到意图。然后重新启动 parent 对话框。 parent 对话框以文本 "You have a choice to make in life..." 开始,当 parent 对话框再次开始时,它将 re-display。

第二个选项将失败,returns用户到组件对话框再试一次。组件对话框以 "Text me something! I'll see if my maker setup a LUIS intent for it." 开头 此文本将在单击任一按钮时显示,因为在这两种情况下组件对话框都是 运行。但是,当 LUIS 找不到意图并重新启动组件对话框时,只会显示此文本。

旁注 - 本例中的 parent 对话框实际上是我的主对话框的组件对话框,这就是它在最后导出的原因。所以,是的,您可以在组件对话框中包含组件对话框。

Parent对话:

const { ComponentDialog, WaterfallDialog } = require('botbuilder-dialogs');
const { LuisRecognizer } = require('botbuilder-ai');

const { ChoiceDialogSub, CHOICE_DIALOG_SUB } = require('./choiceDialog_Sub');
const CHOICE_DIALOG = 'choiceDialog';

class ChoiceDialog extends ComponentDialog {
    constructor(id) {
        super(id);

        this.addDialog(new ChoiceDialogSub(CHOICE_DIALOG_SUB));
        this.addDialog(new WaterfallDialog(CHOICE_DIALOG, [
            this.welcomeStep.bind(this),
            this.choiceLuisStep.bind(this)
        ]));

        this.initialDialogId = CHOICE_DIALOG;

        try {
            this.recognizer = new LuisRecognizer({
                applicationId: process.env.LuisAppId,
                endpointKey: process.env.LuisAPIKey,
                endpoint: `https://${ process.env.LuisAPIHostName }`
            }, {}, true);
        } catch (err) {
            console.warn(`LUIS Exception: ${ err } Check your LUIS configuration`);
        }
    }

    async welcomeStep(stepContext) {
        await stepContext.context.sendActivity('You have a choice to make in life...');
        return await stepContext.beginDialog(CHOICE_DIALOG_SUB);
    }

    async choiceLuisStep(stepContext) {
        if (stepContext.context.activity.text) {
            const stepResults = stepContext.context.activity.text;
            const recognizerResult = await this.recognizer.recognize(stepContext.context);
            const intent = await LuisRecognizer.topIntent(recognizerResult);

            if (intent === 'Greeting') {
                await stepContext.context.sendActivity(`'${ stepResults }' identified in the {${ intent }} intent.`);
                return await stepContext.beginDialog(CHOICE_DIALOG);
            } else {
                await stepContext.context.sendActivity(`No LUIS intent was found for '${ stepResults }'.`);
                return await stepContext.beginDialog(CHOICE_DIALOG_SUB);
            }
        } else {
            await stepContext.context.sendActivity('I need text, fool!');
            return await stepContext.next();
        }
    }
}

module.exports.ChoiceDialog = ChoiceDialog;
module.exports.CHOICE_DIALOG = CHOICE_DIALOG;

组件对话框:

const { ChoicePrompt, ChoiceFactory, ComponentDialog, WaterfallDialog } = require('botbuilder-dialogs');

const CHOICE_DIALOG_SUB = 'choiceDialogSub';
const CHOICE_DIALOG_SUB_PROMPT = 'choicePromptSub';

class ChoiceDialogSub extends ComponentDialog {
    constructor(id) {
        super(id);

        this.addDialog(new ChoicePrompt(CHOICE_DIALOG_SUB_PROMPT))
            .addDialog(new WaterfallDialog(CHOICE_DIALOG_SUB, [
                this.choiceStep.bind(this)
            ]));

        this.initialDialogId = CHOICE_DIALOG_SUB;
    }

    async choiceStep(stepContext) {
        const choices = ['Hello', 'No soup for you!'];
        return await stepContext.prompt(CHOICE_DIALOG_SUB_PROMPT, {
            prompt: "Text me something! I'll see if my maker setup a LUIS intent for it.",
            choices: ChoiceFactory.toChoices(choices)
        });
    }
}

module.exports.ChoiceDialogSub = ChoiceDialogSub;
module.exports.CHOICE_DIALOG_SUB = CHOICE_DIALOG_SUB;

希望得到帮助!