Botframework 如何在聊天机器人中有效地使用QnA和Luis

Botframework 如何在聊天机器人中有效地使用QnA和Luis,botframework,chatbot,azure-language-understanding,qnamaker,Botframework,Chatbot,Azure Language Understanding,Qnamaker,我正在用C#构建聊天机器人,使用: .NetCore 2.1; sdk4.0 我开始使用QnA Maker和LUIS integrated构建聊天机器人 我对如何有效地同时使用QnA和LUIS感到困惑。例如,让我们假设这个机器人现在将作为一个FAQ机器人。我有50个常见问题,我希望机器人回答。在我的头脑中,我会用这50个问题和交替的短语在QnA中创建一个知识库 一个调度文件将创建一个应用程序和一个单一的意图,将话语映射到QnA Maker的知识库,我完成了吗 我想知道为什么我要像在教程中那样给L

我正在用C#构建聊天机器人,使用:

.NetCore 2.1; sdk4.0

我开始使用QnA Maker和LUIS integrated构建聊天机器人

我对如何有效地同时使用QnA和LUIS感到困惑。例如,让我们假设这个机器人现在将作为一个FAQ机器人。我有50个常见问题,我希望机器人回答。在我的头脑中,我会用这50个问题和交替的短语在QnA中创建一个知识库

一个调度文件将创建一个应用程序和一个单一的意图,将话语映射到QnA Maker的知识库,我完成了吗

我想知道为什么我要像在教程中那样给LUIS添加意图只有LUIS才有家庭自动化和天气的两个意图……除非我将这些意图映射到QnA Maker KB中的问题……它们是否执行任何功能?我感到困惑的是,为什么微软认为有必要区分回复是来自QnA制造商还是符合LUIS的意图。根据我的理解,在路易斯有一个意图,而没有来自QnA的回复是无用的


其次,我想让客户机能够维护他们的知识库和意图……如果您添加了新的意图或问题,是否每次都必须刷新分派文件

问题的一部分在于,如果您只使用一个QnA KB,而不是多个,那么您遵循的指南是错误的。您希望遵循的是以下内容:

如果您添加了额外的KB,或者添加了LUIS模型,那么您将需要添加dispatch。否则,通过添加它,您只会让您自己变得更复杂

为了回答您的问题:您参考的教程中介绍的NLP with Dispatch示例仅显示了如何实现Dispatch。dispatch.cs对话框中有一个部分显示了一个基本的“以下是返回意图时发生的情况”:

 private async Task DispatchToTopIntentAsync(ITurnContext<IMessageActivity> turnContext, string intent, RecognizerResult recognizerResult, CancellationToken cancellationToken)
{
    switch (intent)
    {
    case "l_HomeAutomation":
            await ProcessHomeAutomationAsync(turnContext, recognizerResult.Properties["luisResult"] as LuisResult, cancellationToken);
            break;
        case "l_Weather":
            await ProcessWeatherAsync(turnContext, recognizerResult.Properties["luisResult"] as LuisResult, cancellationToken);
            break;
        case "q_sample-qna":
            await ProcessSampleQnAAsync(turnContext, cancellationToken);
            break;
        default:
            _logger.LogInformation($"Dispatch unrecognized intent: {intent}.");
            await turnContext.SendActivityAsync(MessageFactory.Text($"Dispatch unrecognized intent: {intent}."), cancellationToken);
            break;
    }
}
private async Task DispatchToTopIntentAsync(iTurContext turnContext、字符串意图、识别器结果识别器结果、取消令牌取消令牌)
{
开关(意图)
{
案例“l_家庭自动化”:
等待ProcessHomeAutomationAsync(turnContext,recognizerResult.Properties[“luisResult”]作为luisResult,cancellationToken);
打破
案例“l_天气”:
等待ProcessWeatherAsync(turnContext,recognizerResult.Properties[“luisResult”]作为luisResult,cancellationToken);
打破
案例“q_样本-qna”:
wait ProcessSampleQnAAsync(turnContext,cancellationToken);
打破
违约:
_logger.LogInformation($“分派未识别的意图:{intent}.”);
Wait turnContext.SendActivityAsync(MessageFactory.Text($“分派未识别的意图:{intent}”)、cancellationToken;
打破
}
}
如果您确实决定使用dispatch模型来构建NLP,那么在这些情况下,您需要开始对话。例如:

protected override async Task RouteAsync(DialogContext dc, CancellationToken cancellationToken = default(CancellationToken))
{
    // Get cognitive models for locale
    var locale = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
    var cognitiveModels = _services.CognitiveModelSets[locale];

    // Check dispatch result
    var dispatchResult = await cognitiveModels.DispatchService.RecognizeAsync<DispatchLuis>(dc.Context, CancellationToken.None);
    var intent = dispatchResult.TopIntent().intent;

    // Identify if the dispatch intent matches any Action within a Skill if so, we pass to the appropriate SkillDialog to hand-off
    var identifiedSkill = SkillRouter.IsSkill(_settings.Skills, intent.ToString());

    if (identifiedSkill != null)
    {
        // We have identiifed a skill so initialize the skill connection with the target skill
        var result = await dc.BeginDialogAsync(identifiedSkill.Id);

        if (result.Status == DialogTurnStatus.Complete)
        {
            await CompleteAsync(dc);
        }
    }
    else if (intent == DispatchLuis.Intent.l_general)
    {
        // If dispatch result is general luis model
        cognitiveModels.LuisServices.TryGetValue("general", out var luisService);

        if (luisService == null)
        {
            throw new Exception("The general LUIS Model could not be found in your Bot Services configuration.");
        }
        else
        {
            var result = await luisService.RecognizeAsync<GeneralLuis>(dc.Context, CancellationToken.None);

            var generalIntent = result?.TopIntent().intent;

            // switch on general intents
            switch (generalIntent)
            {
                case GeneralLuis.Intent.Escalate:
                {
                    // start escalate dialog
                    await dc.BeginDialogAsync(nameof(EscalateDialog));
                    break;
                }

                case GeneralLuis.Intent.None:
                default:
                {
                    // No intent was identified, send confused message
                    await _responder.ReplyWith(dc.Context, MainResponses.ResponseIds.Confused);
                    break;
                }
            }
        }
    }
    else if (intent == DispatchLuis.Intent.q_faq)
    {
        cognitiveModels.QnAServices.TryGetValue("faq", out var qnaService);

        if (qnaService == null)
        {
            throw new Exception("The specified QnA Maker Service could not be found in your Bot Services configuration.");
        }
        else
        {
            var answers = await qnaService.GetAnswersAsync(dc.Context, null, null);

            if (answers != null && answers.Count() > 0)
            {
                await dc.Context.SendActivityAsync(answers[0].Answer, speak: answers[0].Answer);
            }
            else
            {
                await _responder.ReplyWith(dc.Context, MainResponses.ResponseIds.Confused);
            }
        }
    }
    else if (intent == DispatchLuis.Intent.q_chitchat)
    {
        cognitiveModels.QnAServices.TryGetValue("chitchat", out var qnaService);

        if (qnaService == null)
        {
            throw new Exception("The specified QnA Maker Service could not be found in your Bot Services configuration.");
        }
        else
        {
            var answers = await qnaService.GetAnswersAsync(dc.Context, null, null);

            if (answers != null && answers.Count() > 0)
            {
                await dc.Context.SendActivityAsync(answers[0].Answer, speak: answers[0].Answer);
            }
            else
            {
                await _responder.ReplyWith(dc.Context, MainResponses.ResponseIds.Confused);
            }
        }
    }
    else
    {
        // If dispatch intent does not map to configured models, send "confused" response.
        // Alternatively as a form of backup you can try QnAMaker for anything not understood by dispatch.
        await _responder.ReplyWith(dc.Context, MainResponses.ResponseIds.Confused);
    }
}
受保护的覆盖异步任务RouteAsync(DialogContext dc,CancellationToken CancellationToken=default(CancellationToken))
{
//获取区域设置的认知模型
var locale=CultureInfo.CurrentUICulture.TwoLetterIsLanguageName;
var cognitiveModels=_services.CognitiveModelSets[locale];
//检查调度结果
var dispatchResult=await cognitiveModels.DispatchService.RecognizeAsync(dc.Context,CancellationToken.None);
var intent=dispatchResult.TopIntent().intent;
//确定分派意图是否与技能中的任何动作匹配如果匹配,我们将转到相应的SkillDialog进行移交
var identifiedSkill=SkillRouter.IsSkill(_settings.Skills,intent.ToString());
if(identifiedSkill!=null)
{
//我们已经识别了一个技能,因此初始化与目标技能的技能连接
var result=wait dc.BeginDialogAsync(identifiedSkill.Id);
if(result.Status==DialogTurnStatus.Complete)
{
等待完成同步(dc);
}
}
else if(intent==DispatchLuis.intent.l_-general)
{
//如果调度结果是通用luis模型
认知模型.LuisServices.TryGetValue(“一般”,out-var-luisService);
if(luisService==null)
{
抛出新异常(“在您的Bot服务配置中找不到通用LUIS模型”);
}
其他的
{
var result=await luisService.RecognizeAsync(dc.Context,CancellationToken.None);
var generalitent=result?.TopIntent().intent;
//打开总的意图
交换机(总机)
{
案例generaluis.Intent.Escalate:
{
//启动升级对话框
等待BeginDialogAsync dc(姓名(升级对话));
打破
}
案例generaluis.Intent.None:
违约:
{
//未确定意图,请发送混淆的消息
wait_responder.replywhith(dc.Context,MainResponses.ResponseIds.middle);
打破
}
}
}
}
else if(intent==DispatchLuis.intent.q_常见问题)
{
认知模型.QnAServices.TryGetValue(“faq”,out-var-qnaService);
if(qnaService==null)
{
抛出新异常(“在您的Bot服务配置中找不到指定的QnA Maker服务。”);
}
其他的
{
var answers=await qnaService.GetAnswersAsync(dc.Context,null,null);
if(answers!=null&&answers.Count()>0)
{
等待dc.Context.SendActivityAsync(答案[0]。回答,说:答案[0]。回答);
}
其他的
{
wait_responder.replywhith(dc.Context,MainResponses.ResponseIds.middle);
}
}
}
否则,如果(在