创建由 Dialogflow 提供支持的 RBM 代理(高级版)

在此 Codelab 中,您将学习如何使用 Dialogflow 创建对话界面来为 RBM 代理提供支持。

您将在此 Codelab 中构建什么?

  • 为 RBM 代理的对话提供支持的 Dialogflow 代理
  • 一个虚构的自行车商店的对话界面,可让用户了解自行车店的相关信息并安排预约来修理或维修自行车

本文内容

  • 如何使用 Dialogflow 的三个主要构造(意图、实体和上下文)创建对话界面
  • 如何使用 Dialogflow 的 fulfillment 和内嵌编辑器(由 Cloud Functions for Firebase 提供支持)将对话界面连接到您自己的服务和 API
  • 如何从 Dialogflow 创建 RBM 响应类型,以便为用户打造丰富的 RBM 体验

所需条件

  • Google 帐号

创建和查询您的第一个代理

持续时间:10:00

创建您的第一个 Dialogflow 代理

如需创建 Dialogflow 代理,请执行以下操作:

  1. 打开新标签页并登录 Dialogflow
  2. 点击左侧导航栏中的创建代理

  3. 输入“CodelabRBMBikeShop”作为代理的名称,并将“English”作为默认语言,并将默认时区设置为您的时区。然后点击创建

Dialogflow 控制台

您现在应该会看到 Dialogflow 控制台。如果您正在使用较小的屏幕并且左侧导航栏已隐藏,请点击左上角的导航按钮。设置按钮会将您转到当前代理的设置。

页面中间显示了代理的意图列表。默认情况下,Dialogflow 代理从两个意图开始。如果代理理解不了用户所说的内容,则会匹配默认后备意图默认欢迎 intent 会问候用户。您可以更改这些 intent 以自定义体验。

右侧是 Dialogflow 模拟器。这样,您就可以通过说出或输入消息来试用代理。

查询代理

Dialogflow 代理的最佳描述方式是 NLU(自然语言理解)模块。它们可包含在您的应用、产品或服务中,以将自然用户请求转换为可操作的数据。

是时候试用代理了!在右侧模拟器中,点击显示立即试用 (Try it now) 的文本字段,输入“Hi”后按 Enter 键。

Dialogflow 会识别查询,与默认欢迎意图匹配,然后以一般问候语做出响应。这之所以可行,是因为 Dialogflow 会使用一些示例问候语自动训练默认欢迎 intent

创建 RBM 代理

登录 Business Communications Developer Console,然后点击创建代理

在“名称”字段中,输入“您的姓名自行车商店”(如“张三的自行车经纪人”),选择区域并点击“创建代理”。

将 RBM 代理连接到 Dialogflow

创建 RBM 代理后,点击该代理以查看其概览页面。点击左侧导航栏中的 Integrations(集成)链接。

默认情况下,RBM 代理使用 Google Cloud Pub/Sub 处理用户消息。如需将 RBM 代理连接到先前创建的 Dialogflow 代理,请点击 Dialogflow 集成。

在对话框中,点击连接现有模型。按照说明向 RBM 代理授予调用 Dialogflow 代理的权限,然后点击下一步

最后,您需要提供 Dialogflow 项目 ID。在与 Business Communications Developer Console 不同的浏览器标签页中,转到 Dialogflow 并打开您之前创建的 CodelabRBMBikeShop 代理。点击左侧导航栏中的项目名称旁边的齿轮图标。

点击此选项后,您会转到模型的设置。在 GOOGLE 项目下,找到并复制项目 ID

返回到打开了 Business Communications Developer Console 的标签页,将项目 ID 粘贴到对话框中,然后点击开始集成

此过程大约需要两分钟才能完成。完成后,您应该会看到突出显示了 Dialogflow 集成选项和可用的 View agent 链接。

现在,Codelab RBMBikeShop Dialogflow 代理会处理进出代理的所有消息。

邀请测试设备并发送消息

在深入了解 Dialogflow 之前,我们先设置您的测试设备。如果您还没有可以接收 RBM 消息的设备,请按照此指南准备好您的设备。

在 Business Communications Developer Console 中,点击左侧导航栏中的 Devices(设备)。在表单中输入采用 E.164 格式的设备的完整电话号码(例如 +12223334444),然后点击添加

在您的设备上,您会收到测试邀请。点按让我成为测试人员

在浏览器中,从“设备”列表中找到您的设备,并向设备发送一条测试消息。如果您在您的设备上收到来自 RBM 代理的消息,那么您就可以继续学习此 Codelab。

创建欢迎意图

通常,借助由 Dialogflow 提供支持的 RBM 代理,您需要发起 API 调用来指定用户的电话号码和开始对话的 Dialogflow intent(通常是您的代理的欢迎 intent)。对于此 Codelab,我们将跳过此步骤,并改为在上一步中通过 Business Communications Console 中的测试设备创建对话线程。但是,如果您想详细了解此 API 功能,请参阅此指南

首先,将 RBM 响应添加到默认欢迎 intent,以便 Dialogflow 可以将其与您的 RBM 代理一起使用。首先,导航到已打开 Dialogflow 的浏览器标签页。点击默认欢迎 intent,向下滚动到响应部分,点击响应类型列表中的 +,然后选择 RCS 商家消息 (RBM)

点击添加回复,然后选择简单回复。在简单响应 (Simple Response) 的文本字段中,输入“您好,欢迎来到 Hogarth 的自行车店”。您需要什么帮助?(请将 Hogarth 替换为您的名称),然后点击 Save(保存)。

发起对话

现在您已配置了欢迎 intent,请返回测试设备并发送“Hi”消息。此消息会触发默认欢迎 intent,您应该会看到类似下图的内容。

更新您的欢迎意图

现在,Dialogflow 已发送一条简单的消息,让我们来更新这条消息,使其变得更实用。我们不仅要问候用户,还要引导他们采取的行动。

我们正在创建的代理需要支持两个主要功能:查看营业时间和安排预约。我们将简单的响应欢迎消息替换为一个卡片,卡片中提供执行这些互动的建议回复。

默认欢迎 intent响应部分,选择 RCS 商家消息 (RBM) 标签页。点击垃圾桶图标以移除现有的简单回复。接下来,点击添加响应 (Add Responses) 并选择独立复合信息卡 (Standalone Rich Card)。

在独立复合信息卡表单中,输入以下内容:

  • 卡片标题:您好,欢迎来到 Hogarth 的自行车店。
  • 卡片说明:您需要什么帮助?请从下面的选项中进行选择:
  • 选择卡片方向:垂直
  • 图片/视频网址:https://storage.googleapis.com/df-rbm-codelab/bike-shop.jpg
  • Select Media Height(选择媒体高度):中等

点击添加建议,然后输入以下内容:

  • 建议内容:你们的营业时间是什么?
  • 建议回传:response_hours

如需添加其他建议,请点击 Add Suggestion(添加建议)并输入以下内容:

  • 建议文字:预约
  • 建议回传:response_appointment

点击保存

试试看!

模型显示“代理训练完成”后,返回您的设备,并向代理发送消息“Hi”。您现在应该会看到刚刚设计的独立复合卡

尝试点按您的营业时间是什么?。请注意,系统会触发默认后备 intent。这是因为您的 Dialogflow 代理不知道如何处理您为这条建议配置的回传数据“reply_hours”。

让我们一起解决这个问题。

创建“时间”意图

Dialogflow 使用意图来分类用户的意图。意图包含训练短语,它们是用户可能会向代理说出的内容示例。例如,有人想知道我们的自行车商店的营业时间,比如“您什么时候开始营业?”“您的营业时间是几点?”或“我可以晚点到多晚”。

所有这些查询都是唯一的,但它们的意图相同:获取有关自行车店何时营业的信息。

如需涵盖此查询,请创建一个“小时”意图:

  1. 在左侧导航栏中,点击意图旁边的 +
  2. 意图名称部分,输入“Hours”(小时)。
  3. 训练短语 (Training Phrases) 下,点击添加用户表达 (Add user expression),然后输入以下内容,每次输入后按 Enter 键:

    • When do you open?
    • What are your hours?
    • How late can I come in?
    • reply_hours

    最后一个训练短语用于映射您在上一部分中使用此意图配置的回传数据。

  4. Responses(响应)下方,点击 +,然后选择 RCS Business Messaging (RBM)

  5. 点击添加回复,然后选择简单回复

  6. 简单回复 (Simple Response) 的文本字段中,输入“We're open as 每个工作日上午 9 点至下午 5:30”。

  7. 点击保存

试试看!

现在,请尝试询问代理的营业时间。在设备的 RBM 代理对话中,输入“When are you open?&sot; when you send the message to your agent”。

您的代理现在可正确响应查询。请注意,虽然您的查询与训练短语略有不同(“您何时打开”与“您何时打开”);Dialogflow 仍然将查询与正确的意图相匹配。您也可以尝试点按复合信息卡中的您的营业时间是什么?

Dialogflow 使用训练短语作为机器学习模型的示例,以将用户查询与正确的意图匹配。机器学习模型会根据代理中的每个意图检查查询并为每个意图打分,然后匹配得分最高的意图。如果得分最高的 intent 得分非常低,系统会匹配后备 intent。

添加 fulfillment

虽然代理会正常运行,但其行为有点不自然。当用户询问“您是营业吗?”这样的内容时,代理会回答“我们每个工作日上午 9 点至下午 5:30 营业”。如果客服人员直接告诉我们商店是否营业,效果会更自然,也更有帮助。

为此,我们的代理需要检查商店目前是否正在营业,并在这两种情况下生成不同的响应。在 Dialogflow 中,应在 fulfillment 网络钩子中实现此类复杂逻辑。

fulfillment 网络钩子是一个由 Dialogflow 调用的 HTTP 服务器,其中包含有关当前对话状态的信息。执行方式会执行所有必需的操作,然后生成 Dialogflow 返回给用户的响应。

现在,我们将介绍部署 fulfillment 网络钩子的过程,以便让我们的代理做出更有帮助的响应。

设置:部署和启用 fulfillment

Dialogflow 具有内置的 Cloud Functions for Firebase 编辑器,允许您编写和部署用于处理执行方式的 JavaScript 代码。

在 Dialogflow 的左侧导航栏中,点击 Fulfillment 以打开 fulfillment 页面。点击内嵌编辑器旁边的切换开关以启用 Cloud Functions for Firebase 编辑器。

您会注意到,编辑器包含两个文件:“index.js”(包含 fulfillment 的主代码)和“package.json”(详细说明了必需的依赖项)。

现在,我们将导入一些示例代码来为您的执行方式提供支持。

将此文件的文本复制并粘贴到“index.js”中,替换其当前的所有内容:

https://storage.googleapis.com/df-rbm-codelab/index.js

现在,滚动到页面底部,然后点击部署。大约一分钟后,您的代码就会部署到 Cloud Functions for Firebase。

部署函数后,您可以在页面底部看到部署的日期和时间:

查看 fulfillment 代码。hoursHandler 函数会调用 currentlyOpen 以确定商店当前是否营业,并根据具体情况添加不同的 RBM 响应。

function hoursHandler(agent) {
    let responseText = 'We\'re currently closed, but we open every weekday at 9am!';
    if (currentlyOpen()) {
      responseText = 'We\'re open now!! We close at 5pm today.';
    }

    let payload = {
    "fulfillmentMessages": [
        {
          "platform": "GOOGLE_RBM",
          "rbmText": {
              "text": responseText
          }
        }
      ]
    };

    return response.status(200).json(payload);
}

intentMap.set('Hours', hoursHandler); 行会告知 fulfillment 库在“Hours”意图匹配时应运行 hoursHandler 函数。 不过,我们还需要告知 Dialogflow 为我们的“时间”意图启用 fulfillment。

在左侧导航栏中,点击 Intent 并打开“Hours”意图。打开底部的 Fulfillment 部分并选择为此意图启用网络钩子调用 (Enable webhook call for this intent),然后将其切换为开启。

保存此 intent 后,您可以试用一下。在右侧的模拟器中,输入“Are you open?"”。如果您点击 Diagnostic Info 并检查 API 响应,您应该会看到 fulfillment 响应。请注意,Cloud Functions for Firebase 服务器使用的时区为世界协调时间 (UTC),因此响应可能无法根据您当前的本地时间做出更正。

如果您的执行方式出现错误,Dialogflow 会使用 Intent 页面的 Responses 部分中定义的任何响应,让您的代理能够正常恢复。

接下来,我们将使用实体来提取用户查询的相关部分。这样,用户就可以在自行车商店预约服务,解决自行车维修或维修问题。

使用实体提取数据

持续时间:12:00

在本部分中,我们将介绍如何从用户查询中提取数据,以让用户预约我们的自行车店来维修或维修自行车。

向意图添加参数

参数是用户查询中 Dialogflow 提取的相关字词或短语,因此您的代理可以提供适当的响应。您将使用参数创建新的 intent,并学习如何在响应中加入其值。

  1. 点击左侧导航栏中的 Intent 旁边的 + 以创建新 intent。
  2. 对于意图名称,在页面顶部输入“预约”(Make Appointment)。
  3. 将以下内容添加为训练短语:
    • reply_appointment
    • I'd like to schedule an appointment for next Thursday
    • I'd like to get my bike fixedI have a mountain bike that needs servicing
    • My bike is broken
    • Can I schedule service for 4pm tomorrow?
    • Can you fix my road bike?
    • Can I set up an appointment for noon on Friday?

Dialogflow 会自动检测训练短语中的已知参数并为您创建这些参数。

Training Phrases 下,Dialogflow 会自动使用它收集的信息填充参数表:

  • 参数是可选的(非必需)
  • 命名为 datetime
  • 对应于系统实体类型 @sys.date@sys.time**
  • 值为 $date$time
  • 不是列表

使用参数数据

您可以在响应中使用参数的值。在这种情况下,您可以在响应中使用 $date$time,它们会被替换为在对代理的查询中指定的日期和时间。

响应 (Responses) 中,添加“RCS Business Messaging”标签页,将以下内容添加到简单响应 (Simple Response),然后点击保存

Great! I've set up your appointment for $date at $time.  See you then!

试试看!

现在,请在右侧面板的模拟器中使用“我可以预约明天下午 2 点吗”预约代理。

您可以在模拟器输出的底部看到 Dialogflow 从查询中正确提取了参数“tomorrow”和“2pm”,并将其正确解析为日期和时间。现在,在测试设备上尝试相同的操作,看看响应如何正确包含解析的日期和时间。

将参数设为必需

在我们的自行车店中,我们需要知道日期和时间的值,然后才能安排预约。默认情况下,所有 Dialogflow 参数都是可选的。为了将其设为必需参数,我们需要选中要设为必需的各个参数旁边的复选框。选中“预约”意图中每个参数旁边的复选框:

现在,每个参数都是必需的,我们需要为每个参数创建一个提示符。当用户最初表明自己的意图(在本例中,用于预约)时,提示要求用户为未提供的任何参数提供一个值。点击定义提示符,为参数创建提示,并为每个参数输入以下提示:

参数 提示
日期 你想过哪一天?
时间 您什么时候方便?

输入提示后,点击保存

试试看!

在设备上,点按预约建议或输入“我想修理自行车。”您会收到回复“What day do you want to come in?"”。指明日期(“明天”),您会收到回复,询问该日期对应时间。回复此邮件,你就会看到预约安排。

初始请求中包含一些信息(即“我想设置明天的预约”)的查询会填充正确的参数(日期),跳过日期提示(“您希望在哪一天送达”),然后转到时间提示(“您的时间是几点”)。

我们刚刚使用 Dialogflow 实体和参数创建了一个完全独特的对话,无需编写代码,并且只需极少的设置!接下来,我们将介绍如何使用执行方式来引导用户回答“预约什么日期”之类的问题。

设置:启用 fulfillment

在左侧导航栏中,点击 Intents 并打开“Make Appointment”意图。打开 Fulfillment,选择为此意图启用网络钩子调用 (Enable webhook call for this intent) 和启用网络钩子调用进行槽位填充 (Enable webhook call for slot fill),以使两者都开启,然后点击保存

两者均启用后,Dialogflow 会在此 intent 触发时,使用 fulfillment 生成所需参数的响应(如果需要),以及使用该 intent 的 RBM 响应。

实现执行方式

在 Dialogflow 的左侧导航栏中,点击 Fulfillment 以打开 fulfillment 页面。向下滚动到该行

intentMap.set('Hours', hoursHandler);

并将以下代码添加为下一行:

intentMap.set('Make Appointment', makeAppointment);

这会告知 fulfillment 库在“Make Appointment”意图匹配时应运行 makeAppointment 函数。

接下来,复制下面的代码并将其粘贴到 currentlyOpen 函数下。getSuggestedTimesgetSuggestedDates 这两个函数会创建有用的条状标签列表,以便于用户响应。

function getSuggestedTimes() {
  return [
        {
          "reply": {
            "text": "9 am",
            "postbackData": "9:00am"
            }
        },
        {
          "reply": {
            "text": "10 am",
            "postbackData": "10:00am"
          }
        },
        {
          "reply": {
            "text": "1 pm",
            "postbackData": "1:00pm"
          }
        },
        {
          "reply": {
            "text": "2 pm",
            "postbackData": "2:00pm"
          }
        }
      ];
}

function getSuggestedDates() {
  return [
        {
          "reply": {
            "text": "Tomorrow",
            "postbackData": "Tomorrow"
          }
        },
        {
          "reply": {
            "text": "A week from now",
            "postbackData": "A week from now"
          }
        },
        {
          "reply": {
            "text": "Two weeks from now",
            "postbackData": "Two weeks from now"
          }
        }
      ];
}

接下来,在 hoursHandler 下方复制并粘贴以下代码,然后点击 Deploy

function makeAppointment(agent) {
    // extract required parameters
    const appointmentDate = agent.parameters.date;
    const appointmentTime = agent.parameters.time;

    const gotAppointmentDate = appointmentDate.length > 0;
    const gotAppointmentTime = appointmentTime.length > 0;

    let responseText = '';
    let suggestions = [];

    if(gotAppointmentDate && gotAppointmentTime) {
      // We have all required parameters, return success message
      responseText = 'Great! I\'ve set up your appointment for ' +
          appointmentDate + ' at ' + appointmentTime + '.  See you then!';
    }
    else if(gotAppointmentDate) {
      responseText = 'What time works for you?';
      suggestions = getSuggestedTimes();
    }
    else if(gotAppointmentTime) {
      responseText = 'What day do you want to come in?';
      suggestions = getSuggestedDates();
    }
    else {
      responseText = 'What day do you want to come in?';
      suggestions = getSuggestedDates();
    }

    let payload = {
      "fulfillmentMessages": [
      {
        "platform": "GOOGLE_RBM",
        "rbmText": {
          "text": responseText,
          "rbmSuggestion": suggestions
        }
      }
    ]
    };

    return response.status(200).json(payload);
  }

请花几分钟时间检查代码。请注意,系统会检查必需参数是否有值,如果未设置,则通过适当的消息和一组建议提示用户。

试试看!

在设备上,点按预约建议或输入“我想修理自行车。”您收到回复“What day do you want to come in》,以及一些有用的建议:“明天”、“一周后”和“两周后”。指定日期(“明天”),您便会收到要求一段时间的回复。回复上述请求,您将看到已预约。

用上下文管理状态

持续时间:7:00

将上下文添加到对话状态

用户成功设置预约后,我们就可能需要收集他们的更多信息。假设我们的自行车店提供两种类型的预约:维修或调校。我们希望了解用户中的哪一个。

首先,让我们更新“预约”意图的响应,询问用户他们需要哪种预约类型。将 makeAppointment 执行函数中的成功响应替换为以下文本,然后点击部署

responseText = 'Great! I\'ve set up your appointment for ' +
    appointmentDate + ' at ' + appointmentTime + '.  Do you need a repair for just a tune-up?';

为了收集此问题的解答,我们需要创建另一个 intent。不过,请务必注意,只有在这个新问题得到解答后,才能匹配这个新的意图。为此,我们可以将其定义为后续意图。

后续意图是指只有在其“父”意图(在本例中为“预约”意图)匹配之后才能匹配的意图。点击左侧导航栏中的 Intent(如果菜单已隐藏,请点击左上角的菜单 ☰ 按钮)。然后,将鼠标悬停在“预约”意图上,并点击出现在意图名称右侧的添加后续意图

接下来,点击下拉菜单中的自定义

Dialogflow 会自动将后续意图命名为“预约 - 自定义”,箭头指示这些意图之间的关系。

后续意图只能在匹配父意图之后匹配。由于此意图只会在“预约”意图之后进行匹配,因此我们可以假设用户刚刚被问到“您是需要维修还是需要微调”。

为了获取此问题的答案,我们首先需要定义一些实体。

创建您的第一个实体

Dialogflow 允许您定义开发者实体,其功能类似于 Dialogflow 的系统实体。我们先创建实体类型。我们希望用户能够自行选择商店的预约类型,因此我们将实体类型命名为 AppointmentType。我们将在 AppointmentType 实体类型中为两种不同类型的预约添加两个实体:servicefix

如需创建实体类型,请执行以下操作:

  1. 在左侧导航栏中,点击实体旁边的 +
  2. 对于实体类型的名称,请输入“AppointmentType”。
  3. 点击文本字段并添加以下条目:
    • 服务
    • 修正
  4. 输入条目时,按 Tab 会将光标移到同义词字段。为每个条目添加以下同义词。请务必逐个添加每个字词,而不是复制并粘贴整个字符串:
条目 同义词
服务
  • 服务
  • 翻新
  • 维护
  • 调节
  • 调整
修复
  • 修复
  • 维修
  • 修改
  • 损坏
  • 爆胎
  • 固定
  1. 点击保存

每种实体类型都必须满足以下条件:

  • 定义类别的名称(“AppointmentType”)
  • 一个或多个条目(“service”和“fix”符号)
  • 一个或多个同义词(“维护”、“微调”等)

Dialogflow 可以处理复数和大写等简单事项,但请务必添加所有可能的同义词。添加得越多,代理就越能更好地确定实体。

添加新实体

现在,我们已经定义了用于预约的实体类型,接下来可以在“预约 - 自定义”意图的训练短语中使用该实体类型:

  1. 点击左侧导航栏中的 Intent,然后点击“Make Appointment”意图旁边的箭头,以显示其后续意图。点击“预约 - 自定义”意图。
  2. 将以下内容添加为训练短语:

    • 你能帮我修理自行车吗?
    • 我需要修理。

  3. 您应该会看到输入的训练短语中自动注释的预约实体类型。此操作会将 AppointmentType 参数添加到训练短语部分的下方。点击此复选框可将此参数标记为必需

  4. 点击定义提示符,然后输入“我们可以维修或维修自行车”。你想选哪个?

  5. 响应 (Responses) 中,将响应更改为“好的,我们安排 $AppointmentType.”,然后点击保存

试试看!

在设备上,点按预约建议或输入“我想修理自行车。”您收到回复“What day do you want to come in》,以及一些有用的建议:“明天”、“一周后”和“两周后”。指定日期(“明天”),您便会收到要求在该日期举行的答复。

选择一个时间,您将看到您创建的新响应,询问这是用于服务还是调整。

接下来,输入“我需要维修”。您应该会看到响应“好的,我们将安排修复”。这表明 Dialogflow 提取了正确的 AppointmentType 作为实体。

目前,对此意图的响应(“OK,我们将安排修复”)非常有用。最好能通过回复确认预约的日期和时间。为此,我们需要日期和时间,但日期和时间参数仅出现在“Make Appointment”意图中,而不出现在“Make Appointment - custom”意图中。

意图和上下文

如需使用从“预约”意图中收集的参数进行响应,您需要知道后续意图的工作原理。后续 intent 使用上下文跟踪是否已触发父 intent。如果检查“Make Appointment”意图,您会看到“MakeAppointment-Followup”列为输出上下文,以数字 2 开头:

匹配“Make Appointment”意图之后,Dialogflow 会将上下文“MakeAppointment-Followup”附加到对话两回。因此,当用户回答问题(“您是否需要维修或只需调校”)时,上下文“MakeAppointment 后续跟进”处于活跃状态。当 Dialogflow 匹配意图时,系统会优先考虑具有相同输入上下文的意图。

点击左侧导航栏中的 Intent,然后点击“MakeAppointment - custom”intent。

您可以看到 intent 与“Make Appointment”的输出上下文具有相同的输入上下文(“MakeAppointment-后续”。)因此,“MakeAppointment - 自定义”仅在与“Make Appointment”意图匹配之后才会匹配。

上下文和参数

上下文会存储参数值,这意味着您可以在“MakeAppointment - 自定义”等其他 intent 中访问“预约”intent 中定义的参数值。

将以下响应添加到“MakeAppointment - 自定义”intent 中,然后点击保存 (Save):好的,我们安排在 $MakeAppointment-Followup.time 中安排 $AppointmentType #MakeAppointment-Followup.date。我们下次再见。”

现在,您可以再次查询代理并获得正确的响应。首先输入“我可以预约明天上午 11 点服务自行车的预约吗”,然后以“我需要修理”回复问题。

在确认预约的响应中,您应该会看到从上下文检索了日期和时间参数值。

改进响应格式

持续时间:5:00

使用 fulfillment 设置日期和时间的格式

您可能已经注意到,成功消息中显示的日期和时间不是很方便用户使用。为了解决此问题,我们需要再次使用 fulfillment,以便我们可以使用 JavaScript 以方便用户阅读的方式设置日期和时间参数的格式。

导航到左侧导航栏中的“预约 - 自定义”意图,然后点击意图 (Intents),然后点击“MakeAppointment - custom”意图。滚动到页面底部,开启为此意图启用网络钩子调用 (Enable webhook call for this intent),然后点击保存

点击左侧导航栏中的 Fulfillment 链接以导航到 fulfillment。复制以下代码,并将其粘贴到 makeAppointment 函数下方。

function makeAppointmentFollowUp(agent) {
    let context = agent.getContext('makeappointment-followup');

    // extract required parameters
    const appointmentDate = new Date(context.parameters.date);
    const appointmentTime = new Date(context.parameters.time);
    const appointmentType = agent.parameters.AppointmentType;

    // format date and time to be human-readable
    const dateAsString = appointmentDate.toLocaleDateString('en-US',
        { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
    const timeAsString = appointmentTime.toLocaleString('en-US',
        { hour: 'numeric', minute: 'numeric', hour12: true });

    // compose response for user
    let responseText = 'Okay, we'll schedule a ' + appointmentType + ', ' + dateAsString +
        ', at ' + timeAsString + '.  We'll see you then.';

    let payload = {
      "fulfillmentMessages": [
      {
        "platform": "GOOGLE_RBM",
        "rbmText": {
          "text": responseText
        }
      }
    ]
    };

    return response.status(200).json(payload);
  }

在此函数下方,找到 intentMap.set('Make appointment', makeAppointment); 行并添加 intentMap.set('Make appointment - custom', makeAppointmentFollowUp);,以便系统在调用后续 intent 时调用您之前粘贴的函数。

查看 makeAppointmentFollowUp 代码,了解如何从传入上下文和此 intent 中提取参数。在生成 responseText 之前,代码现在会将日期和时间的格式设置为便于用户阅读。

试试看!

在设备上,点按预约建议或输入“我想修理自行车。”您收到回复“What day do you want to come in》,以及一些有用的建议:“明天”、“一周后”和“两周后”。指定日期(“明天”),您便会收到要求在该日期举行的答复。

选择一个时间,您将看到您创建的新响应,询问这是用于服务还是调整。

接下来,输入“我需要维修”。您应该会看到响应,以可读的格式确认预约类型、日期和时间。

大功告成!

持续时间:1:00

表现不错!

现在,您已经历了由 Dialogflow 提供支持的 RBM 代理的所有阶段。

针对这个激动人心的新平台开展开发工作!