最佳对话流 Bot 框架架构设计建议

Design Advice on Architecture on Bot Framework for Best conversation flow

我正在构建一个聊天机器人,它使用 Microsoft Bot Framework v4 更具对话性。

我可以在架构中实现什么形式的结构来实现可以处理如下所述的复杂场景的机器人

用户:我想为我的租房者保险添加 Mac

{检测意图}

Bot:好的,你想要哪台笔记本电脑。

用户:2018 年的二手 Pro

{从用户话语中提取 "pro" 和“2018”}

Bot:好的,添加 MacBook Pro 2018 每月需要 5 美元。这对你有用吗?

网友:哦不好意思,其实是2017年的

{机器人检测意图并提取实体}

Bot:不用担心,添加您的 MacBook Pro 2017 仍然需要每月 5 美元,适合您吗?

用户:顺便问一下纽约的天气怎么样? {机器人检测中断}

机器人:纽约的天气是 28 摄氏度

Bot:你还想把你的Mac书添加到你的租借中吗?

用户:听起来不错

机器人:完美,你的Mac书没有投保。

机器人:顺便说一句,生日快乐!!

我知道 bot 框架可以与 LUIS 集成以从话语中检测用户意图,但是我如何将 Luis 放在聊天机器人项目中,以便它在对话流中处理所有用户话语。

因此在上述场景中,LUIS 可以帮助继续从用户话语中提取实体。

核心机器人 here 展示了如何处理 LUIS 和中断。

基本上,不是将 LUIS 添加为中间件,而是将其添加为 "helper" class:

LUIS 助手 class 将跟踪意图:


public static class LuisHelper
{
    public static async Task<BookingDetails> ExecuteLuisQuery(IConfiguration configuration, ILogger logger, ITurnContext turnContext, CancellationToken cancellationToken)
    {
        var bookingDetails = new BookingDetails();

        try
        {
            // Create the LUIS settings from configuration.
            var luisApplication = new LuisApplication(
                configuration["LuisAppId"],
                configuration["LuisAPIKey"],
                "https://" + configuration["LuisAPIHostName"]
            );

            var recognizer = new LuisRecognizer(luisApplication);

            // The actual call to LUIS
            var recognizerResult = await recognizer.RecognizeAsync(turnContext, cancellationToken);

            var (intent, score) = recognizerResult.GetTopScoringIntent();
            if (intent == "Book_flight")
            {
                // We need to get the result from the LUIS JSON which at every level returns an array.
                bookingDetails.Destination = recognizerResult.Entities["To"]?.FirstOrDefault()?["Airport"]?.FirstOrDefault()?.FirstOrDefault()?.ToString();
                bookingDetails.Origin = recognizerResult.Entities["From"]?.FirstOrDefault()?["Airport"]?.FirstOrDefault()?.FirstOrDefault()?.ToString();

                // This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.
                // TIMEX is a format that represents DateTime expressions that include some ambiguity. e.g. missing a Year.
                bookingDetails.TravelDate = recognizerResult.Entities["datetime"]?.FirstOrDefault()?["timex"]?.FirstOrDefault()?.ToString().Split('T')[0];
            }
        }
        catch (Exception e)
        {
            logger.LogWarning($"LUIS Exception: {e.Message} Check your LUIS configuration.");
        }

        return bookingDetails;
    }
}

在主对话框中,您将像这样调用 LUIS 助手:

private async Task<DialogTurnResult> ActStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Call LUIS and gather any potential booking details. (Note the TurnContext has the response to the prompt.)
    var bookingDetails = stepContext.Result != null
        ?
    await LuisHelper.ExecuteLuisQuery(Configuration, Logger, stepContext.Context, cancellationToken)
        :
    new BookingDetails();

    // In this sample we only have a single Intent we are concerned with. However, typically a scenario
    // will have multiple different Intents each corresponding to starting a different child Dialog.

    // Run the BookingDialog giving it whatever details we have from the LUIS call, it will fill out the remainder.
    return await stepContext.BeginDialogAsync(nameof(BookingDialog), bookingDetails, cancellationToken);
}

至于中断,处理这些问题的简单方法是将它们创建为组件对话框,然后在所有其他对话框上扩展该对话框:

我建议您看一下 Core Bot,因为它提供了您正在寻找的内容的基本轮廓。举个更复杂的例子,Bot Framework还有Virtual Assistant,here.