Повторение шага диалога на основе проверки - PullRequest
1 голос
/ 05 мая 2020

В настоящее время я создаю бота для подготовки с использованием v4 Bot Framework и интегрировал его с 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
        }
    }

Заранее благодарю

1 Ответ

1 голос
/ 09 мая 2020

Этого можно добиться с помощью диалогового окна компонента . По сути, вы экстраполируете шаги, которые хотите повторить, в отдельный диалог, который вызывается только из текущего (родительского) диалога. В родительском учреждении вы устанавливаете свои чеки. В случае сбоя проверки снова вызывается диалоговое окно компонента. В случае успеха родительский диалог продолжается.

В приведенном ниже коде мой родительский диалог немедленно вызывает диалоговое окно компонента для первого прохода, представляя пользователю два варианта. Каждый отправит заранее определенное текстовое значение, которое проверяется, чтобы увидеть, существует ли для него намерение LUIS.

Первый вариант, «Hello», будет успешным, если намерение было найдено. Затем он перезапускает родительский диалог. Родительский диалог начинается с текста "You have a choice to make in life...", который будет повторно отображаться, когда родительский диалог начнется снова.

Второй вариант завершится ошибкой и вернет пользователя в диалоговое окно компонента, чтобы повторить попытку. Диалог компонента начинается с "Text me something! I'll see if my maker setup a LUIS intent for it.". Этот текст будет отображаться при нажатии любой кнопки, поскольку диалоговое окно компонента запускается в обоих случаях. Однако только этот текст будет отображаться, когда LUIS не может найти намерение и перезапускает диалоговое окно компонента.

Боковое примечание - родительский диалог в этом примере фактически является диалоговым окном компонента для моего основного диалога, поэтому он экспортируется в конце. Итак, да, вы можете иметь диалоговые окна компонентов внутри диалоговых окон компонентов.

Родительский диалог:

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;

enter image description here

Надеюсь на помощь!

...