You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
};

关键逻辑说明

  1. 对话优先:每次收到用户消息时,先尝试延续当前对话。如果用户正在填写联系方式的流程中,continueDialog会自动把回复传入对话的下一步,不会走到QnA查询环节。
  2. QnA兜底:只有当没有活跃对话时,才去调用QnA Maker处理用户的常规问题。
  3. 避免冲突:原代码中onMessage和onTurn都调用了dialog.run,会导致逻辑冲突,因此简化onMessage的处理。

这样修改后,当用户触发#Contact启动对话后,后续的回复会被对话组件正确接收,直到对话流程结束,才会回到QnA的常规处理逻辑。

内容的提问来源于stack exchange,提问作者Hessel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:04:07