根据验证重复对话步骤
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;
希望得到帮助!
我目前正在使用 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;
希望得到帮助!