在下一步可以处理输入之前,Qna和LUIS中断对话框

问题描述 投票:2回答:1

我将QnaMaker和LUIS集成到我的机器人中。我希望用户能够在对话之间提问。我已经发现问题是,在处理用户的输入之前,机器人总是首先查看luis和qna。

例如,如果我有“立即开始”和“立即停止”的选择提示,Luis或qna将中断并处理输入,再次重新启动对话框,导致无限循环,并且永远不会到达下一步。

我认为这对我来说是糟糕的设计。有没有办法让下一步先处理结果?如果它不能识别结果,那么luis和qna应该处理输入。

    private async Task<bool> IsTurnInterruptedDispatchToQnAMakerAsync(ITurnContext turnContext, string topDispatch, string appName, CancellationToken cancellationToken = default(CancellationToken))
    {
        var dc = await _dialogs.CreateContextAsync(turnContext);
        const string qnaDispatchKey = "q_xxxxxxxx";

        if (topDispatch.Equals(qnaDispatchKey))
        {
            var results = await _services.QnAServices[appName].GetAnswersAsync(turnContext);
            if (results.Any())
            {
                await turnContext.SendActivityAsync(results.First().Answer, cancellationToken: cancellationToken);
            }

            if (dc.ActiveDialog != null)
            {
                await dc.RepromptDialogAsync();
            }

            return true;
        }

        return false;
    }

        return false;
    }

OnTurnAsync()

            var interruptedQnaMaker = await IsTurnInterruptedDispatchToQnAMakerAsync(turnContext, topDispatch, QnaConfiguration, cancellationToken);
            if (interruptedQnaMaker)
            {
                await _basicAccessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
                await _basicAccessors.UserState.SaveChangesAsync(turnContext, false, cancellationToken);
                return;
            }
c# botframework luis qnamaker
1个回答
1
投票

你有两个问题,我会回答它们。我不知道是否有“最好”的方法来做到这一点 - 这实际上取决于你的代码。您可能还需要对以下两件事进行组合。

Using LUIS and QnA in a Choice Prompt

我的示例演示了如何使用LUIS执行此操作,但您可以非常轻松地替换QnAMaker。

将你的BotServices传递给你的对话框(在MyBot.cs的构造函数中):

Dialogs.Add(new MyDialog(services));

注意:根据您执行此操作的位置,您可以传入LuisRecognizer而不是所有服务。

BotServices的构造函数中使用MyDialog

public class MyDialog : ComponentDialog
{
    private readonly BotServices _services;
    public MyDialog(BotServices services) : base(nameof(QuickDialog))
    {
        [...]
        _services = services;
    }

在ChoicePrompt中创建验证器:

AddDialog(new ChoicePrompt(nameof(ChoicePrompt), luisValidation));

创建验证器,允许您调整用户的输入并将其设置为其他内容(如LUIS意图):

private async Task<bool> LuisValidationAsync(PromptValidatorContext<FoundChoice> promptContext, CancellationToken cancellationToken)
{
    // ...Succeeded will only be true for a ChoicePrompt if user input matches a Choice
    if (!promptContext.Recognized.Succeeded)
    {
        // User input doesn't match a choice, so get the LUIS result
        var luisResults = await _services.LuisServices["nameOfLuisServiceInBotFile"].RecognizeAsync(promptContext.Context, cancellationToken);
        var topScoringIntent = luisResults?.GetTopScoringIntent();
        var topIntent = topScoringIntent.Value.intent;
        // Save the results and pass them onto the next waterfall step
        promptContext.Recognized.Succeeded = true;
        promptContext.Recognized.Value = new FoundChoice()
        {
            Index = 0,
            Score = 1,
            Value = topIntent
        };
        // We converted to a valid LUIS result, so return true
        return true;
    }
    // ...Succeeded was true, so return true
    return true;
}

Process the Result

您可以使用结果执行某些操作,而不是仅仅更改用户的输入。例如,在下一步中,您可以:

switch ((stepContext.Result as FoundChoice).Value)
{
    case "Reply":
        await stepContext.Context.SendActivityAsync("Reply");
        break;
    case "Cancel":
        return await stepContext.EndDialogAsync("Cancel Me");                    
}
return await stepContext.NextAsync();

如果用户调用“取消”意图,这将冒泡到MyBot.csdialogResult.Result将等于“取消我”。

Skipping LUIS/QnA Recognition

您可以通过两种方式跳过LUIS识别:

1. Bypass LUIS and QnA Calls

如果您不想检查中断,请设置您想要跳过它的条件。你可以使用类似的东西:

var interruptedQnaMaker = false;
if (!<yourCondition>)
{
    var interruptedQnaMaker = await IsTurnInterruptedDispatchToQnAMakerAsync(turnContext, topDispatch, QnaConfiguration, cancellationToken);
}

我在a Node bot做了一些相似的事情,在那里我完全跳过了某些对话框的luisRecognizer。对你来说,它可能或多或少看起来像这样:

var dc = await _dialogs.CreateContextAsync(turnContext);
if (dc.ActiveDialog != null && dc.ActiveDialog.id == "SkipLuisDialog")
{
    var interruptedQnaMaker = await IsTurnInterruptedDispatchToQnAMakerAsync(turnContext, topDispatch, QnaConfiguration, cancellationToken);
}

2. Adjust your LUIS app

看起来你已经设置好了,这样当LUIS返回一个匹配topDispatch的intent(qnaDispatchKey)时,就是当你触发一个中断时。如果“立即开始”和“立即停止”返回qnaDispatchKey作为意图,您可以调整您的LUIS应用程序以防止。强文本

© www.soinside.com 2019 - 2024. All rights reserved.