使用LUIS中断对话框的最佳实践是什么

时间:2019-07-16 14:59:13

标签: c# botframework

Core-Bot示例(https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/13.core-bot)显示了一种处理中断的方法,例如当用户在对话框中间键入“帮助”或“取消”时。它使用文字文本进行比较:

private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc, 
  CancellationToken cancellationToken)
{
  if (innerDc.Context.Activity.Type == ActivityTypes.Message)
  {
    var text = innerDc.Context.Activity.Text.ToLowerInvariant();

    switch (text)
    {
      case "help":
      case "?":
        await innerDc.Context.SendActivityAsync($"Show Help...",
          cancellationToken: cancellationToken);
        return new DialogTurnResult(DialogTurnStatus.Waiting);
      case "cancel":
      case "quit":
        await innerDc.Context.SendActivityAsync($"Cancelling", 
          cancellationToken: cancellationToken);
        return await innerDc.CancelAllDialogsAsync();
      }
    }
  }
}

我想使用LUIS来确定用户是否试图通过检查帮助意图来中断当前对话框。

问题是我不想对LUIS进行两次调用(即首先要检查它是否被打断,其次要在对话框继续时获取意图),并且我无法传递识别器结果通过OnContinueDialogAsync()方法转到对话框。

var result = await InterruptAsync(innerDc, cancellationToken);
if (result != null)
{
    return result;
}

return await base.OnContinueDialogAsync(innerDc, cancellationToken);

我认为可以只进行一次呼叫,然后使用状态访问器将识别结果存储在用户状态中,但这对我来说似乎是一种解决方法。

在中断和对话框中使用LUIS的推荐方法是什么?

1 个答案:

答案 0 :(得分:0)

这是我使用Redis Cache的方法。

我将创建一个“中断对话框”,我需要启用中断的任何对话框都可以继承该对话框。在此对话框中,我将调用LUIS识别器,而不是进行文本比较,这将返回意图。

protected override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default)
{
    var result = await InterruptAsync(innerDc, cancellationToken);
    if (result != null)
    {
        return result;
    }

    return await base.OnContinueDialogAsync(innerDc, cancellationToken);
}


private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc, CancellationToken cancellationToken)
{
    if (innerDc.Context.Activity.Type == ActivityTypes.Message)
    {
        var luisResult = await _recognizer.RecognizeAsync<MyLuisModel>(innerDc.Context, cancellationToken);
        switch (luisResult.TopIntent().intent)
        {
            case MyLuisModel.Intent.Cancel:
                return await CancelAllDialogsAsync(innerDc, cancellationToken);

            case MyLuisModel.Intent.SignOut:
                return await SignOutAsync(innerDc, cancellationToken);

        }
    }

    return null;
}

然后,在识别器类中,我可以为每种发音缓存LUIS Result。您必须确保每次重新发布LUIS模型时都清除高速缓存,或者具有较小的高速缓存到期时间。

public virtual async Task<T> RecognizeAsync<T>(ITurnContext turnContext, CancellationToken cancellationToken) where T : IRecognizerConvert, new()
{
    var utterance = turnContext.Activity?.AsMessageActivity()?.Text;
    if (string.IsNullOrWhiteSpace(utterance)) return default;
    var cacheKey = Regex.Replace(utterance, @"[^A-Za-z0-9]+", "_");
    var matches = Regex.Match(cacheKey, @"[A-Za-z0-9]+");
    if (!matches.Success) return default;
    cacheKey = "MyBot_" + cacheKey + "_" + nameof(T);

    var recognizerResult = await _cacheClient.Db15.GetAsync<T>(cacheKey);

    if (recognizerResult != null) return recognizerResult;

    recognizerResult = await _recognizer.RecognizeAsync<T>(turnContext, cancellationToken);
    await _cacheClient.Db15.AddAsync(cacheKey, recognizerResult, TimeSpan.FromDays(1));

    return recognizerResult;
}