我们有一个使用对话框的简单机器人,它可以正常工作,但是我最近将其更改为使用CosmosDB进行状态存储,现在我们注意到dialogStack为空。
该机器人的大部分代码都来自samples repo中的BotFramework示例。
每个消息的用户状态正在准确更新,初始化代码如下:
this.dialogState = conversationState.createProperty(DIALOG_STATE_PROPERTY);
this.dialogAccessor = userState.createProperty(DIALOG_PROPERTY);
this.dialogs = new DialogSet(this.dialogState);
this.dialogs.add(new GreetingDialog(GREETING_DIALOG, this.dialogAccessor));
this.dialogs.add(new PharmacyOrderDialog(PHARMACY_DIALOG, this.dialogAccessor));
this.conversationState = conversationState;
this.userState = userState;
我们在onTurn结束时调用saveChanges函数:
await this.conversationState.saveChanges(context);
我什至找不到关于dialogStack对象中应该包含的内容的任何信息,也没想到我认为是我们代码中的错误的解决方案。
感谢您的帮助。
编辑,添加了onTurn函数以提高清晰度:
public onTurn = async (context: TurnContext) => {
if (context.activity.type === ActivityTypes.Message) {
if (context.activity.value) {
let useridFromCard = context.activity.value.useridList;
if (context.activity.value.useridList) {
useridFromCard = context.activity.value.useridList;
}
await this.dialogAccessor.set(context, new DialogDetails(useridFromCard));
}
let dialogResult: DialogTurnResult;
const dc = await this.dialogs.createContext(context);
const results = await this.luisRecognizer.recognize(context);
const topIntent = LuisRecognizer.topIntent(results);
const dialogDetails: DialogDetails = await this.dialogAccessor.get(context);
if (!dialogDetails) {
await this.dialogAccessor.set(context, new DialogDetails(ENVIRONMENT.USERID, results));
} else {
dialogDetails.luisResults = results;
await this.dialogAccessor.set(context, dialogDetails);
}
const interrupted = await this.isTurnInterrupted(dc, results);
if (interrupted) {
if (dc.activeDialog !== undefined) {
await dc.repromptDialog();
}
} else {
dialogResult = await dc.continueDialog();
}
if (!dc.context.responded) {
switch (dialogResult.status) {
case DialogTurnStatus.empty:
switch (topIntent) {
case GREETING_INTENT:
await dc.beginDialog(GREETING_DIALOG);
break;
case PHARMACY_INTENT:
await dc.beginDialog(PHARMACY_DIALOG);
break;
case NONE_INTENT:
await context.sendActivities(ResponseRandomizer.getRandomResponse(RANDOM_PHRASE_PATH, POST_GREETING_MESSAGE_PHRASE_KEY));
break;
default:
await dc.context.sendActivity("I didn't understand what you just said to me.");
break;
}
break;
case DialogTurnStatus.waiting:
// The active dialog is waiting for a response from the user, so do nothing.
break;
case DialogTurnStatus.complete:
// All child dialogs have ended. so do nothing.
break;
default:
// Unrecognized status from child dialog. Cancel all dialogs.
await dc.cancelAllDialogs();
break;
}
}
} else if (context.activity.type === ActivityTypes.ConversationUpdate) {
if (context.activity.membersAdded.length !== 0) {
for (const idx in context.activity.membersAdded) {
if (context.activity.membersAdded[idx].id !== context.activity.recipient.id) {
const welcomeCard = CardFactory.adaptiveCard(WelcomeCard);
await context.sendActivity({ attachments: [welcomeCard] });
await context.sendActivities(ResponseRandomizer.getRandomResponse
(RANDOM_PHRASE_PATH, WELCOME_MESSAGE_PHRASE_KEY));
const useridCard = CardFactory.adaptiveCard(USERIDCard);
await context.sendActivity({ attachments: [useridCard] });
}
}
}
}
await this.conversationState.saveChanges(context);
await this.userState.saveChanges(context);
}
感谢所有帮助。可能永远不需要在其中存储任何有关我们的机器人当前设置方式的信息,但我只想确保这对我们而言不是错误。
答案 0 :(得分:0)
首先,就您自己的代码而言,对话框状态(其堆栈等)实际上只是一个黑匣子。所有您需要做的就是确保保存了为对话框状态创建属性的状态容器,根据上述内容,对话框状态即为您(即this.conversationState.saveChanges(context)
)。>
我需要查看您实际上是如何调用对话框的。至少在调用对话框方面,您可以使用onTurn
方法是什么样的来更新您的问题吗?
答案 1 :(得分:0)
如果您使用的是dialogStack
或DialogSet
,则肯定应该有一个WaterfallDialog
。这是关于对话框和conceptual information的SDK reference。 Sample 19的dialogStack
如下所示:
尽管您的初始化/构造函数代码使用了dialogState
和 dialogAccessor
,但在常规代码方面还是有点不合常规,我认为这没什么错。但是,这不应该成为问题。
据我所知,您的onTurn
代码也不错。
这使我相信以下两件事之一:
没有任何活动对话框时,您正在查看dialogStack
。 dialogStack
仅在向用户显示对话框时填充,然后在对话框末尾将其清除。听起来好像您的机器人没有问题,所以我想是这种情况。
哪个对话框给您问题(GreetingDialog或PharmacyOrderDialog)均未正确调用提示。
上面#2的可能修补程序:
您要将dialogDetails
添加到userState
中,然后将userState
传递到每个对话框中。您不是从dialogDetails
调用userState
的提示,对吗?如果是这样,那可能是一个问题。如果您正在执行 操作,则您的dialogStack
可能会出现在userState
中,而不是conversationState
中,这不是最佳选择。对话框/提示/瀑布对话框应该使用的唯一上下文是从conversationState
派生的上下文,就像在this.dialogState = conversationState.createProperty(DIALOG_STATE_PROPERTY);
中一样。因为您使用this.dialogs = new DialogSet(this.dialogState);
定义了对话框,所以add
到this.dialogs
的每个对话框都已经获得了正确的上下文和dialogState,这是应该的,您只需要在对话框中使用它即可。
也可能是您对话框中的某个地方,您在过早呼叫endDialog
或cancelAllDialogs
。
如果这不能解决您的问题,请发布其中一个对话框的代码,给您带来麻烦,我可以帮助您进一步解决问题。