Этого можно добиться, используя диалоговые окна компонентов .
В следующем примере у меня есть одно диалоговое окно компонентов, которое «слушает» пользовательский ввод.В этом случае пользователю нужно ввести что-то, связанное с получением имени пользователя.Если есть совпадение, он делает вызов QnA, чтобы получить ответ / ответ.Как только ответ получен и отображен, бот затем начинает промежуточное (дочернее) диалоговое окно, прежде чем вернуться в главное диалоговое окно.
Сначала создайте диалоговое окно компонента, к которому вы хотите направить отслеживание любых успешных ответов QnA.Я назвал этот файл 'getUserNameDialog.js'.
const {
TextPrompt,
ComponentDialog,
WaterfallDialog
} = require('botbuilder-dialogs');
const GET_USER_NAME_DIALOG = 'GET_USER_NAME_DIALOG';
const TEXT_PROMPT = 'TEXT_PROMPT';
const WATERFALL_DIALOG = 'WATERFALL_DIALOG';
class GetUserNameDialog extends ComponentDialog {
constructor() {
super(GET_USER_NAME_DIALOG);
this.addDialog(new TextPrompt(TEXT_PROMPT));
this.addDialog(new WaterfallDialog(WATERFALL_DIALOG, [
this.getNameStep.bind(this),
this.displayNameStep.bind(this)
]));
this.initialDialogId = WATERFALL_DIALOG;
}
async getNameStep(stepContext) {
return await stepContext.prompt(TEXT_PROMPT, "Let's makeup a user name for fun. Enter something.");
// return stepContext.next();
}
async displayNameStep(stepContext) {
const stepResults = stepContext.result;
await stepContext.context.sendActivity(`${ stepResults } is a fine name!`);
return stepContext.endDialog();
}
}
module.exports.GetUserNameDialog = GetUserNameDialog;
module.exports.GET_USER_NAME_DIALOG = GET_USER_NAME_DIALOG;
Затем создайте диалог QnA (я назвал его qnaResponseDialog.js).Мои учетные данные QnA хранятся в файле .env, откуда они получены.Обратите внимание, что мне требуется файл 'getUserNameDialog', который я только что создал.
Когда есть совпадение / ответ от QnA (я ищу ссылку на «имя пользователя»), тогда я вызываю beginDialog ()который запускает дочерний диалог.Я делаю это, отображая вопросы, возвращенные в ответе QnA, и сопоставляя их с пользовательским вводом.Если в любом из вопросов есть «пользователь» и / или «имя», я возвращаю «истина».Если это правда, тогда я возвращаю ответ QnA и начинаю дочерний диалог.
Этот процесс сопоставления довольно прост и предназначен для демонстрации, но если он работает для вас, тогда отлично.Тем не менее, я бы рекомендовал вам использовать LUIS , чтобы соответствовать намерениям пользователя.Это сделает этот процесс намного чище и проще в обслуживании.
const { ComponentDialog } = require('botbuilder-dialogs');
const { QnAMaker } = require('botbuilder-ai');
const { GetUserNameDialog, GET_USER_NAME_DIALOG } = require('./getUserNameDialog');
class QnAResponseDialog extends ComponentDialog {
constructor() {
super(GET_USER_NAME_DIALOG);
this.addDialog(new GetUserNameDialog());
try {
this.qnaMaker = new QnAMaker({
knowledgeBaseId: process.env.QnAKnowledgebaseId,
endpointKey: process.env.QnAAuthKey,
host: process.env.QnAEndpointHostName
});
} catch (err) {
console.warn(`QnAMaker Exception: ${ err } Check your QnAMaker configuration in .env`);
}
}
async onBeginDialog(innerDc, options) {
const result = await this.interrupt(innerDc);
if (result) {
return result;
}
return await super.onBeginDialog(innerDc, options);
}
async onContinueDialog(innerDc) {
const result = await this.interrupt(innerDc);
if (result) {
return result;
}
return await super.onContinueDialog(innerDc);
}
async interrupt(innerDc) {
if (innerDc.context.activity.type === 'message') {
const text = innerDc.context.activity.text.toLowerCase();
const stepResults = innerDc.context;
let qnaResults = await this.qnaMaker.getAnswers(stepResults);
console.log(qnaResults[0]);
stepResults.qna = qnaResults[0];
if (qnaResults[0]) {
let mappedResult = null;
const includesText = qnaResults[0].questions.map((question) => {
if (text.includes('user') || text.includes('name')) {
mappedResult = true;
} else {
mappedResult = false;
}
console.log('RESULTS: ', mappedResult);
});
console.log('MAPPED: ', mappedResult);
switch (mappedResult) {
case true:
let answer = stepResults.qna.answer;
await innerDc.context.sendActivity(answer);
return await innerDc.beginDialog(GET_USER_NAME_DIALOG);
}
}
}
}
}
module.exports.QnAResponseDialog = QnAResponseDialog;
Наконец, в диалоге основного или верхнего уровня, включите следующее:
const { QnAResponseDialog } = require('./qnaResponseDialog');
class MainDialg extends QnAResponseDialog {
[...]
}
На этом этапе, есливсе настроено правильно, когда пользователь вводит фразу, которую QnA распознает и принимает, она должна прервать текущее диалоговое окно, отобразить ответ QnA, начать диалоговое окно дочернего компонента и, после завершения, вернуться к родительскому диалоговому окну.