Bot混淆了并发用户的提示



我遇到一个问题,多个同时访问同一对话框的用户的提示值混淆了。有问题的对话框是"订单状态"对话框,其中会提示订单号。我看到的情况是,用户1查询订单A,用户2查询订单B(几乎同时(,然后两个用户都收到订单B的信息。

这是一个复杂的对话框,共享完整的代码没有帮助,但我认为以下几点可能相关:

  • 我在构造函数中使用this.queryData = {}来初始化一个对象,以保存我提示的所有订单查询参数,包括订单号。
    • 我以为这个对象可能被第二个用户覆盖了,但我也在这里设置用户和对话状态,就像我在每个对话框中所做的那样,所以我不确定是这样。我一直认为这个对话框的每个实例都是为每个用户唯一创建的
  • 我使用的是一个简单的文本提示:
return await step.prompt(TEXT_PROMPT, {
prompt: `Please provide your ${step.values.orderTypeText} number.`,
retryPrompt: `Please enter a valid ${step.values.orderTypeText} number.`,
});
  • 然后在下一步中将queryData对象指定为this.queryData.orderNumber = step.result.trim().split(" ").splice(-1)[0];

事实就是这样,除非有某种方式不是提示值,而是整个消息被发送给了错误的用户(但这似乎不太可能,而且在本例中它会同时发送给两个用户(。

我考虑过不使用this.queryData将信息存储在conversationState中,但我不想重做代码,除非我能确认这是我使用的实现的问题,特别是this.queryData而不是其他问题。

作为参考,以下是类定义,一直到构造函数的末尾:

class viewOrderDialog extends ComponentDialog {
constructor(dialogId, userDialogStateAccessor, userState, appInsightsClient, dialogState, conversationState) {
super(dialogId);
this.addDialog(new ChoicePrompt(CRITERIA_PROMPT));
this.addDialog(new TextPrompt(TEXT_PROMPT));
this.addDialog(new TextPrompt(LINE_PROMPT, this.validateLineNumber));
this.addDialog(new TextPrompt(EMAIL_PROMPT,this.validateEmail));
this.addDialog(new TextPrompt(ZIP_PROMPT,this.validateZip));
this.addDialog(new ConfirmPrompt(CONFIRM_PROMPT));
this.addDialog(new ChoicePrompt(CHOICE_PROMPT));
this.addDialog(new WaterfallDialog(WATERFALL_DIALOG, [
this.requestOrderNumber.bind(this),
this.selectOrderType.bind(this), // This is being bypassed by current Filtration store implementation
this.selectSearchCriteria.bind(this),
this.getQueryData.bind(this),
this.confirmBillingZip.bind(this),
this.confirmBillingEmail.bind(this),
this.displayLineStatus.bind(this),
this.getEmailAddress.bind(this),
this.setFollowUp.bind(this),
this.loopStep.bind(this)
]));
this.initialDialogId = WATERFALL_DIALOG;
this.queryData = {};
// State accessors
this.userDialogStateAccessor = userDialogStateAccessor;
this.userState = userState;
this.dialogState = dialogState;
this.conversationState = conversationState;
this.appInsightsClient = appInsightsClient;
this.addDialog(new PaginateDialog(PAGINATE_DIALOG, this.userDialogStateAccessor, userState, this.appInsightsClient));
// Luis Recognizer
this.luisRecognizer = new LuisRecognizer({
applicationId: process.env.LuisAppId,
endpointKey: process.env.LuisAPIKey,
endpoint: `https://${ process.env.LuisAPIHostName }`
}, {
includeAllIntents: true,
includeInstanceData: true,
spellCheck: true,
bingSpellCheckSubscriptionKey: process.env.bingAPIKey
}, true);
} // End constructor

我习惯于使用.net的Botframework,但我认为整体机制与节点不会有太大区别。

在BotBuilder的.net实现中,正如您所说,所有对话框实例都存储在应用程序启动时的一个实例中,以避免使用几乎相同的数据运行大量对话框实例。

为了避免对话框实例之间的信息混合,您有一些选项:

  • 使用状态管理来存储上下文数据,例如conversationData,用于会话范围内的域信息,并在所有对话框之间共享数据
  • 或者,您可以使用stepContext.options存储对话框域信息,当对话框停留在堆栈中时,它将在任何步骤中恢复(在进入最后一步之前,请调用endDialogreplaceDialog(

以下是有关如何存储数据的一些信息:
https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-howto-v4-storage?view=azure-僵尸服务-4.0&tabs=javascript

@Arie Rodrigues让我朝着正确的方向前进,但解决方案并不完全正确。事实上,Bot框架似乎确实使用了对话框的单个实例,它由对话/对话框状态控制。因此,构造函数中定义的this.queryData对象实际上被所有对话框共享。在适当的时机下,提示输入从一个用户的对话框交叉到另一个用户。

这可以通过任何非全局保存这些值的方法来解决。会话状态是一个很好的状态,但我不需要也不想在会话期间保存值,也不想每一步都检索和保存状态。相反,我使用了step.values来代替this.queryData。当对话框在某个步骤通过replaceDialog()循环时,我的代码实际上依赖于保持this.queryData的一些值,所以我必须确保在该方法的选项中传递这些值。这似乎解决了这个问题,因为我有4个测试人员在同一时间用不同的提示值点击相同的对话框,没有问题。

相关内容

最新更新