如何留在机器人对话框中(Bot Framework,C#)

How to stay in a bots dialog (Bot Framework, C#)

我目前正计划在我的 C# 机器人中使用对话框。我已经设计了一个 完成对话框并将其实现到我当前的解决方案中,但是当我测试它时,我只能触发它的第一部分。

我的机器人配置如下:

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    string[] PostCodeDialogStartTrigger = new string[] { "trigger1", "trigger2", "trigger3" };
    if (PostCodeDialogStartTrigger.Contains(turnContext.Activity.Text) /* Maybe || ConversationState != null */)
    {
        await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
    }
    else
    {
        // First, we use the dispatch model to determine which cognitive service (LUIS or QnA) to use.
        var recognizerResult = await BotServices.Dispatch.RecognizeAsync(turnContext, cancellationToken);

        // Top intent tell us which cognitive service to use.
        var topIntent = recognizerResult.GetTopScoringIntent();

        // Next, we call the dispatcher with the top intent.
        await DispatchToTopIntentAsync(turnContext, topIntent.intent, recognizerResult, cancellationToken);
    }
}

我里面有一组字符串PostCodeDialogStartTrigger。我希望对话框在用户消息与触发器之一匹配时启动。否则我的常规流程应该开始,其中包括 LUIS 和用于一维对话的 QnA Maker。问题是我不能留在对话框中,因为下一条消息显然不会再次触发对话框。

有没有办法检查 ConversationState 或 UserState,如果有进展,对话会继续吗?

你想要的叫中断https://docs.microsoft.com/azure/bot-service/bot-builder-howto-handle-user-interrupt

核心机器人示例包括一种稍微复杂的处理中断的方法,方法是创建一个基础 CancelAndHelpDialog class,使任何对话都“可中断”,但有一种更简单的方法可以做到这一点。关键是默认每回合调用 ContinueDialogAsync ,只有在该回合发生中断时才不调用它。你可以认为每一轮都有三种情况:

  1. 发生中断
  2. 没有中断,但有一个活动对话
  3. 没有中断,也没有活动对话

逻辑可能如下所示:

string[] PostCodeDialogStartTrigger = new string[] { "trigger1", "trigger2", "trigger3" };

if (PostCodeDialogStartTrigger.Contains(turnContext.Activity.Text))
{
    // Case 1: Handle interruptions by starting a dialog
    await dialogContext.BeginDialogAsync(DIALOG_ID);
}
else
{
    // Case 2: Try to continue the dialog in case there is one
    var result = await dialogContext.ContinueDialogAsync();

    if (result.Status == DialogTurnStatus.Empty)
    {
        // Case 3: If there aren't any dialogs on the stack

        // First, we use the dispatch model to determine
        // which cognitive service (LUIS or QnA) to use.
        // . . .
    }
}

您可能会注意到我在这里没有使用 RunAsyncRunAsync 最适合你的机器人的“主对话框”,它意味着总是在堆栈上,如果你没有真正的主对话框,它就不会很好地工作。 RunAsync 的最初目的是将几个方法调用合并为一个,因为这是机器人调用 ContinueDialogAsync 的常见模式,然后检查结果,如果对话框堆栈,则启动主对话框是空的。您想做类似的事情,但不是在对话堆栈为空的情况下开始主对话,您只想调用调度。

如果你好奇,这里有一些其他的 Stack Overflow 帖子,你可以在其中阅读有关中断的内容:

  • What is the best practice to use LUIS for dialog interruption

我应该提一下,您正在尝试以一种过时的方式做事。您可能已经注意到 Dispatch 已被 Orchestrator, so you really should be using Orchestrator instead. Also, things like interruptions have been made easy by Composer 取代,并且建议大家现在无论如何都使用 Composer。