将对话语言理解与 Bot Framework 集成

对话是用户查询与应用程序之间发生的交互。 对话管理是定义不同客户交互应发生的自动行为的过程。 对话语言理解可将意向分类并通过实体提取信息,而 Bot Framework SDK 允许为对话语言理解返回的响应配置应用的逻辑。

本教程介绍如何在 Bot Framework SDK 中为某个航班预订项目集成你自己的对话语言理解 (CLU) 项目,该航班预订项目包括三个意向:“预订航班”、“获取天气数据”和“无”。

先决条件

  • 在 Azure 门户中创建一个语言资源以获取密钥和终结点。 部署后,选择”转到资源”。
    • 你需要从你创建的资源获取密钥和终结点,以便将机器人连接到 API。 稍后需在本教程中将密钥和终结点粘贴到下方的代码内。
  • 下载 CoreBotWithCLU 示例
    • 克隆整个示例存储库以访问此解决方案。

在对话语言理解中导入项目

  1. 将 Core Bot with CLU 示例中的 FlightBooking.json 文件下载到 Cognitive Models 文件夹中。

  2. 登录到 Language Studio 并选择你的语言资源。

  3. 导航到“对话语言理解”并选择该服务。 随后你将转到项目页。 选择“创建新项目”按钮旁边的“导入”按钮。 导入包含名为 FlightBooking 的项目的 FlightBooking.json 文件。 这会自动导入包含所有意向、实体和语句的 CLU 项目。

    屏幕截图显示导入 Json 文件的位置。

  4. 加载项目后,选择左侧的“训练作业”。 按“启动训练作业”,提供模型名称 v1,然后按“训练”。 “标准训练”和评估设置等所有其他设置均可保持原样。

    C L U 中训练页的屏幕截图。

  5. 训练完成后,单击左侧的“部署模型”。 选择“添加部署”,创建名为 Testing 的新部署,并将模型 v1 分配给该部署。

    C L U 中部署模型屏幕中部署页面的屏幕截图。

更新设置文件

CLU 项目现已部署并已准备就绪,接下来请更新要连接到部署的设置。

在 Core Bot 示例中,使用适当的值更新 appsettings.json

  • CluProjectName 为 FlightBooking。
  • CluDeploymentName 为 Testing
  • CluAPIKey 可以是 Azure 门户上你的语言资源的“密钥和终结点”部分中的任一密钥。 也可以从 CLU 中的“项目设置”选项卡复制密钥。
  • CluAPIHostName 是 Azure 门户上你的语言资源的“密钥和终结点”部分中显示的终结点。 请注意,格式应该是 <Language_Resource_Name>.cognitiveservices.azure.cn(不包含 https://)。
{
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": "",
  "CluProjectName": "",
  "CluDeploymentName": "",
  "CluAPIKey": "",
  "CluAPIHostName": ""
}

识别集成点

在 Core Bot 示例中,可以签出 FlightBookingRecognizer.cs 文件。 将在此文件中对已部署的终结点发出 CLU API 调用,以检索意向和实体的 CLU 预测。

        public FlightBookingRecognizer(IConfiguration configuration)
        {
            var cluIsConfigured = !string.IsNullOrEmpty(configuration["CluProjectName"]) && !string.IsNullOrEmpty(configuration["CluDeploymentName"]) && !string.IsNullOrEmpty(configuration["CluAPIKey"]) && !string.IsNullOrEmpty(configuration["CluAPIHostName"]);
            if (cluIsConfigured)
            {
                var cluApplication = new CluApplication(
                    configuration["CluProjectName"],
                    configuration["CluDeploymentName"],
                    configuration["CluAPIKey"],
                    "https://" + configuration["CluAPIHostName"]);
                // Set the recognizer options depending on which endpoint version you want to use.
                var recognizerOptions = new CluOptions(cluApplication)
                {
                    Language = "en"
                };

                _recognizer = new CluRecognizer(recognizerOptions);
            }

在 Dialogs 文件夹下,找到使用以下内容做出 CLU 预测的 MainDialog。

            var cluResult = await _cluRecognizer.RecognizeAsync<FlightBooking>(stepContext.Context, cancellationToken);

MainDialog 后面是确定如何处理 CLU 结果的逻辑。

 switch (cluResult.TopIntent().intent)
            {
                case FlightBooking.Intent.BookFlight:
                    // Initialize BookingDetails with any entities we may have found in the response.
                    var bookingDetails = new BookingDetails()
                    {
                        Destination = cluResult.Entities.toCity,
                        Origin = cluResult.Entities.fromCity,
                        TravelDate = cluResult.Entities.flightDate,
                    };

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

                case FlightBooking.Intent.GetWeather:
                    // We haven't implemented the GetWeatherDialog so we just display a TODO message.
                    var getWeatherMessageText = "TODO: get weather flow here";
                    var getWeatherMessage = MessageFactory.Text(getWeatherMessageText, getWeatherMessageText, InputHints.IgnoringInput);
                    await stepContext.Context.SendActivityAsync(getWeatherMessage, cancellationToken);
                    break;

                default:
                    // Catch all for unhandled intents
                    var didntUnderstandMessageText = $"Sorry, I didn't get that. Please try asking in a different way (intent was {cluResult.TopIntent().intent})";
                    var didntUnderstandMessage = MessageFactory.Text(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
                    await stepContext.Context.SendActivityAsync(didntUnderstandMessage, cancellationToken);
                    break;
            }

在本地运行机器人

在计算机本地运行示例,或者从终端或 Visual Studio 运行机器人:

从终端运行机器人

从终端导航到 cognitive-service-language-samples/CoreBotWithCLU 文件夹。

然后运行以下命令

# run the bot
dotnet run

从 Visual Studio 运行机器人

  1. 启动 Visual Studio
  2. 在顶部导航菜单中,依次选择“文件”、“打开”、“项目/解决方案”
  3. 导航到 cognitive-service-language-samples/CoreBotWithCLU 文件夹
  4. 选择 CoreBotCLU.csproj 文件
  5. F5 运行项目

使用 Bot Framework Emulator 测试机器人

Bot Framework Emulator 是一个桌面应用程序,允许机器人开发者对 localhost 上的或者通过隧道远程运行的机器人进行测试和调试。

使用 Bot Framework Emulator 连接到机器人

  1. 启动 Bot Framework Emulator
  2. 依次选择“文件”、“打开机器人”
  3. 输入机器人 URL http://localhost:3978/api/messages,然后按“连接”并等待机器人加载完成
  4. 现在可以查询不同的示例(例如“Travel from Cairo to Paris”)并观察结果

如果 CLU 返回的首要意向解析为“Book flight”。 则机器人将提出更多问题,直到它存储了足够的信息来创建旅行预订。 此时机器人会将下述预订信息返回给用户。