根据验证重复对话步骤 [英] Repeating a dialog step based on validation

查看:49
本文介绍了根据验证重复对话步骤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我已经阅读了整个论坛并看到了许多解决方案,特别是,我遇到了 step.activeDialog.state ['stepIndex']-2 方法,但是无法得到它的工作.这是退后NodeJS的可行解决方案,还是我应该考虑另一种方法?

 异步nameStep(步骤){//用户选择了一个组类型,现在需要输入该组的名称step.values.sitetype = step.result.value;返回await step.prompt(NAME_PROMPT,'你想给它起什么名字');}异步ownerStep(step){//从上一步中获取值,然后对照Microsoft Graph进行检查,以查看该名称是否先前已被使用过step.values.name = step.result;const getToken =等待axios.post(TOKEN_ENDPOINT,qs.stringify(postData)).then(response => {返回 {标头:{'授权':'承载者'+ response.data.access_token}}}).catch(错误=> {console.log(错误);});const graphCall =等待axios.get("https://graph.microsoft.com/v1.0/groups?$filter=startswith(displayName,'" +`$ {step.result}`+')",getToken).then((response)=> {if(response.data.value [0]!= null){返回true;}}).catch((错误)=> {console.log(错误);})如果(!graphCall){返回等待步骤提示(NAME_PROMPT,您的电子邮件地址是什么");} 别的 {等待step.context.sendActivity(组已存在");返回等待step.activeDialog.state ['stepIndex']-2}} 

先谢谢您

解决方案

您可以通过使用

希望有帮助!

I'm currently building a provisioning bot using v4 of the Bot Framework and I've integrated it with the Microsoft Graph.

The Microsoft Graph is being used to validate user inputs, so in this scenario, it's checking to see if the group name already exists. However, the issue I'm running into is getting the bot to repeat the previous step if the validation finds the group exists.

I've read through the forum and seen a number of solutions, particularly, I have come across the step.activeDialog.state['stepIndex']-2 approach, but have been unable to get it to work. Is this a viable solution for going back a step in NodeJS or should I be looking at another approach?

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
        }
    }

Thanking you in advance

解决方案

You can achieve this by use of a component dialog. Essentially, you extrapolate the steps you would like to repeat into a separate dialog that is called only from within the current (parent) dialog. In the parent, you institute your checks. When a check fails, the component dialog is called again. If it succeeds, the parent dialog continues on.

In the code below, my parent dialog immediately calls the component dialog for a first pass thru presenting the user with two options. Each will send a pre-determined text value which is checked to see if a LUIS intent exists for it.

The first option, "Hello", will succeed with an intent having been found. It then restarts the parent dialog. The parent dialog starts with the text "You have a choice to make in life..." which will re-display as the parent dialog begins again.

The second option will fail and returns the user to the component dialog to try again. The component dialog starts with "Text me something! I'll see if my maker setup a LUIS intent for it." This text will display when either button is clicked because the component dialog is run in both instances. However, only this text will display when LUIS fails to find an intent and restarts the component dialog.

Side note - the parent dialog in this example is, in fact, a component dialog to my main dialog which is why it is exported at the end. So, yes, you can have component dialogs within component dialogs.

Parent Dialog:

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;

Component 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;

Hope of help!

这篇关于根据验证重复对话步骤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆