Я пытаюсь создать систему требований для диалогов заказов в нашем боте, чтобы мы могли повторно использовать основную структуру для различных процедур.
enum DialogIds {
// Necessary Ids
oauthPrompt = "oauthPrompt",
// Requirement dialogs
itemWaterfallDialog = "itemWaterfallDialog",
// Reset Dialogs
summaryWaterfallDialog = "summaryWaterfallDialog",
// All other prompts
unrecognizedItemPrompt = "unrecognizedItemPrompt",
beneficiaryConfirmPrompt = "beneficiaryConfirmPrompt",
askBeneficiaryPrompt = "askBeneficiaryPrompt",
reasonPrompt = "reasonPrompt",
orderConfirm = "orderConfirm"
}
export class OrderDialog extends ComponentDialog {
private responseManager: ResponseManager;
private requirementManager: RequirementManager;
private luisResult: RecognizerResult | undefined = undefined;
// TODO: get userState and ConversationState
constructor(
private service: BotServices,
telemetryClient: BotTelemetryClient
) {
super(OrderDialog.name);
this.initialDialogId = OrderDialog.name;
// Response manager serving OrderResponses.json
this.responseManager = new ResponseManager(["fr-fr"], [OrderResponses]);
const routeWaterfallDialog: ((
sc: WaterfallStepContext
) => Promise<DialogTurnResult>)[] = [
this.route.bind(this)
];
this.telemetryClient = telemetryClient;
this.addDialog(
new WaterfallDialog(this.initialDialogId, routeWaterfallDialog)
);
/**
* Order specific dialogs and requirements
*/
const itemWaterfallDialog: WaterfallDialog = new WaterfallDialog(
DialogIds.itemWaterfallDialog,
[this.itemStep.bind(this), this.itemEndStep.bind(this)]
);
this.addDialog(itemWaterfallDialog);
const reqs = [
new Requirement<string>("claimant", false, undefined),
new Requirement<string>(
"item",
true,
undefined,
itemWaterfallDialog,
DialogIds.itemWaterfallDialog
),
];
// Create requirement manager for this dialog
this.requirementManager = new RequirementManager(reqs);
// Add all the prompt
this.addDialog(new ConfirmPrompt(DialogIds.beneficiaryConfirmPrompt));
this.addDialog(new TextPrompt(DialogIds.unrecognizedItemPrompt));
this.addDialog(new TextPrompt(DialogIds.askBeneficiaryPrompt));
this.addDialog(new TextPrompt(DialogIds.reasonPrompt));
this.addDialog(new ConfirmPrompt(DialogIds.orderConfirm));
}
/**
* We save the token, query graph is necessary and
* execute the next dialog if any, if not we'll
* execute the summary waterfallDialog.
* @param sc context
*/
async route(sc: WaterfallStepContext): Promise<DialogTurnResult> {
this.requirementManager.set("claimant", 'nothing');
let next = this.requirementManager.getNext();
while (next) {
await sc.beginDialog(next.dialogId!);
// Execute summary if there are no elements left
if (!this.requirementManager.getNextBool()) {
await sc.beginDialog(DialogIds.summaryWaterfallDialog);
}
next = this.requirementManager.getNext();
}
return sc.endDialog();
}
/**
* ITEM
* @param sc
*/
async itemStep(sc: WaterfallStepContext): Promise<DialogTurnResult> {
// Couldn't recgonize any item
if (this.luisResult!.entities.length === 0) {
await sc.context.sendActivity(
this.responseManager.getResponse(
OrderResponses.itemNotRecognized
)
);
// prompt user for the item again
return await sc.prompt(
DialogIds.unrecognizedItemPrompt,
this.responseManager.getResponse(OrderResponses.rePromptItem)
);
}
const entities = this.luisResult!.entities as generalLuis["entities"];
if (entities.PhoneItem || entities.ComputerItem) {
const item = entities.PhoneItem
? entities.PhoneItem
: entities.ComputerItem;
if (item) {
this.requirementManager.set("item", item[0][0]);
}
}
return await sc.next();
}
async itemEndStep(sc: WaterfallStepContext): Promise<DialogTurnResult> {
// Save result from itemStep(prompt triggered) if any
if (sc.result) {
await sc.context.sendActivity(
this.responseManager.getResponse(OrderResponses.thanksUser)
);
// retrieve item from result and save it
const item = sc.result as string;
this.requirementManager.set("item", item);
}
return sc.endDialog();
}
}
Строка
const result = await sc.beginDialog(next.dialogId!);
Запускает WaterfallDialog, объявленный в конструкторе Dialog, и метод route также находится внутри общего waterfallDialog.
Проблема в том, что когда один из дочерних диалоговых окон запрашивает пользователя, код не дождитесь ответа пользователя, и из-за того, как работает маршрут, он снова вызовет тот же диалог (если значение объекта не заполнено, он вызовет указанное диалоговое окно, что и делает менеджер требований).
Если при сохранении возврата из этой строки мы видим, что статус «ждет», как я могу это исправить или я должен создать независимые диалоги для каждого требования, а не только waterfallDialogs?
Спасибо.