QnA Maker机器人添加对话遇阻:可行性与解决方法咨询
解决方案:在QnA Maker机器人中嵌入对话流程
问题1:需求完全可行,无需大量重构
当然可以在以QnA Maker为核心的机器人里启动自定义对话,而且不需要大改现有代码。核心问题是你当前的消息处理顺序搞反了——应该先处理活跃的对话,再去调用QnA服务,而不是反过来。
问题2:检测并优先处理活跃对话的方法
Bot Framework提供了内置方式判断和延续对话。你需要在处理QnA请求之前,先尝试继续当前的对话流程:如果对话正在进行中,continueDialog会自动处理用户的回复;如果对话已经结束或者没有活跃对话,再去调用QnA Maker查询答案。
对你现有代码的修改建议
你需要调整onTurn方法里的逻辑顺序,并且简化onMessage的处理(避免重复调用对话)。以下是修改后的关键代码:
async onTurn(turnContext) { // 处理用户加入事件(保留原逻辑) if (turnContext.activity.name === 'webchat/join') { await turnContext.sendActivity({ type: 'typing' }); await turnContext.sendActivity({ attachments: [CardFactory.adaptiveCard(IntroCard)] }); }; if (turnContext.activity.type === ActivityTypes.Message) { await turnContext.sendActivity({ type: 'typing' }); // 第一步:尝试继续活跃的对话(如果有的话) const dialogResult = await this.dialog.continueDialog(turnContext); // 如果对话没有在进行(或者已经完成),再调用QnA Maker if (dialogResult.status === DialogTurnStatus.empty || dialogResult.status === DialogTurnStatus.completed) { const qnaResults = await this.qnaMaker.getAnswers(turnContext); // 保存问题记录(保留原逻辑) if (turnContext.activity.name !== 'webchat/join') { let score = (qnaResults[0] != null) ? qnaResults[0].score : 'No answer found'; helper.storeQuestions(turnContext, score); }; // 处理QnA返回结果(保留原switch逻辑) if (qnaResults[0] && qnaResults[0].score > 0.5) { switch (qnaResults[0].answer) { case '#Weather': { var weatherForecast = await helper.getWeatherForecast(turnContext); await turnContext.sendActivity({ attachments: [CardFactory.adaptiveCard(weatherForecast)] }); break; } case '#DateTime': { await turnContext.sendActivity(moment().tz('Europe/Amsterdam').format('[Today is ]LL[ and the time is ] LT')); break; } case '#Help': { await turnContext.sendActivity({ attachments: [CardFactory.adaptiveCard(IntroCard)] }); break; } case '#Bots': { await turnContext.sendActivity({ attachments: helper.createBotsGallery(turnContext), attachmentLayout: AttachmentLayoutTypes.Carousel }); break; } case '#Contact': { // 启动收集联系方式的对话 await this.dialog.run(turnContext, this.dialogState); break; } default: { await turnContext.sendActivity(qnaResults[0].answer); break; } } } else { await turnContext.sendActivity('Some response'); } } // 如果对话正在进行,continueDialog已经处理了用户回复,无需额外操作 } } // 移除重复的对话调用逻辑 async onMessage(turnContext, next) { // 对话逻辑已在onTurn中处理,这里只需执行后续中间件 await next(); };
关键逻辑说明
- 对话优先:每次收到用户消息时,先尝试延续当前对话。如果用户正在填写联系方式的流程中,
continueDialog会自动把回复传入对话的下一步,不会走到QnA查询环节。 - QnA兜底:只有当没有活跃对话时,才去调用QnA Maker处理用户的常规问题。
- 避免冲突:原代码中
onMessage和onTurn都调用了dialog.run,会导致逻辑冲突,因此简化onMessage的处理。
这样修改后,当用户触发#Contact启动对话后,后续的回复会被对话组件正确接收,直到对话流程结束,才会回到QnA的常规处理逻辑。
内容的提问来源于stack exchange,提问作者Hessel
相关产品推荐
相关产品推荐

