IBM Cloud Docs
改进带槽的对话节点

改进带槽的对话节点

在本教程中,您将增强一个具有插槽的简单节点,这些插槽收集进行餐厅预订所需的信息。

学习目标

在完成教程时,您将学习如何执行以下操作:

  • 测试带槽的节点
  • 添加用于处理公共用户交互的槽响应条件。
  • 预测和处理不相关的用户输入。
  • 处理意外的用户响应。

期限

完成本教程大约需要 2 到 3 个小时。

先决条件

开始之前,请先完成向对话添加带槽的节点。 必须先完成第一个槽教程,然后再开始此教程,因为您在第一个教程中创建的具有槽的节点上进行构建。

改进响应格式

保存日期和时间系统实体值时,这些值会转换成标准格式。 此标准化格式对于对值执行计算很有用,但您可能不希望向客户显示此重新格式化。 在此步骤中,您将重新格式化对话引用的日期 (2021-04-09) 和时间 (17:00:00) 值。

要重新格式化 $date 上下文变量值,请执行以下操作:

  1. 在对话中,打开 #reservation 节点。

  2. 单击 @sys-date 槽的 定制槽 图标 定制槽

  3. 从选项菜单 选项 菜单中,选择 打开 JSON 编辑器,然后编辑用于定义上下文变量的 JSON。 添加用于重新格式化日期的方法,以便将 2021-04-09 值转换为一周中的全天,后跟全月和全天。 按如下所示编辑 JSON:

    {
      "context": {
        "date": "<? @sys-date.reformatDateTime('EEEE, MMMM d') ?>"
      }
    }
    

    EEEE 指示您希望完整拼写星期几。 例如,如果使用 3 E (EEE),那么星期几将缩短为 Fri,而不是星期五。 MMMM 指示您希望完整拼写月份。 同样,如果仅使用 3 个 M (MMM),那么月份会简写为 Dec 而不是 December。

  4. 单击保存

  5. 要将时间值存储在 $time 上下文变量中的格式更改为使用小时,分钟并指示 AM 或 PM,请单击 @sys-time 槽的 定制槽 图标 定制槽

  6. 从选项菜单 选项 菜单中,选择 打开 JSON 编辑器,然后编辑用于定义上下文变量的 JSON,以使其如下所示:

    {
      "context": {
        "time": "<? @sys-time.reformatDateTime('h:mm a') ?>"
      }
    }
    
  7. 单击保存

  8. 再次测试节点。 打开“试用”窗格,然后单击清除以删除先前测试带槽的节点时指定的槽上下文变量值。 要查看所做更改的影响,请使用以下脚本:

    脚本详细信息
    说话者 话语
    我要订位
    助手 您要订哪天?
    星期五
    助手 您希望预留的时间是什么时间?
    5pm
    助手 几位就餐?
    6

    此时间,助手将使用 OK. I am making you a reservation for 6 on Friday, April 9 at 5:00 PM. 进行响应

您改进了对话在其响应中引用上下文变量值时使用的格式。 现在,该对话框使用 Friday, April 9 而不是更技术性的 2021-04-09。 同时,该对话使用5:00 PM,而不使用 17:00:00

一次询问所有信息

现在您已多次测试对话,您可能会注意到一次回答一个槽提示会很烦人。 为了避免用户一次只能提供一条信息的情况,您可以预先要求提供您需要的所有信息。 这样用户就有机会在单次输入中提供全部或部分信息。

具有槽的节点旨在查找并保存用户在处理当前节点时提供的任何槽值。 您可以通过告诉用户要指定哪些值来帮助用户利用设计。

在此步骤中,您将学习如何一次性提示所有内容。

  1. 打开 #reservation 节点。

  2. 单击 定制

  3. 插槽中,选中 提示所有内容 复选框以启用初始提示,然后单击 应用

    显示定制对话框,您在其中选择“提示所有内容”复选框。
    提示输入所有内容

  4. 返回到节点编辑视图,向下滚动到新添加的 如果未预先填充任何槽,请询问第一个 部分。 为节点添加以下初始提示: I can make a reservation for you. Just tell me the day and time of the reservation, and how many people will be dining.

  5. 单击 关闭 图标 关闭 以关闭节点编辑视图。

  6. 在“试用”窗格中测试此更改。 打开该窗格,然后单击清除以清空先前测试中的槽上下文变量值。

  7. 输入:I'd like to make a reservation

    对话现在响应为: I can make a reservation for you. Just tell me the day and time of the reservation, and how many people it is for.

  8. 输入 It's for Saturday. There will be 2 of us coming in at 8pm

    助手通过以下命令进行响应: OK. I am making you a reservation for 2 on Saturday at 8:00 PM.

    当用户在一个输入中提供所有内容时,显示“试用”窗格。
    所有内容的测试提示

如果用户在其初始输入中提供了一个槽值,那么不会显示要求提供所有信息的提示。 例如,用户的初始输入可能是 I want to make a reservation for this Friday night。 在这种情况下,将跳过初始提示,因为您不希望要求提供用户已提供的信息。 该对话将改为显示下一个空槽的提示。

正确处理零

在槽条件中使用 sys-number 系统实体时,服务不会正确处理零。 助手会将您为槽定义的上下文变量设置为 false,而不是将其设置为 0。 因此,槽不会认为它已满,而会反复提示用户输入数字,直到用户指定了非零的数字为止。

  1. 测试节点,以便更好地理解问题。 打开“试用”窗格,然后单击清除以删除先前测试带槽的节点时指定的槽上下文变量值。 请使用以下脚本:

    脚本详细信息
    说话者 话语
    我要订位
    助手 我可以为您订位。 就告诉我预约的日子和时间,还有多少人会用餐。
    我们想要在 5 月 23 日晚上 8 点就餐。 就餐人数是 0 位。
    助手 几位就餐?
    0
    助手 几位就餐?

    您将困在此循环中,直到指定除 0 以外的数字为止。

要确保 @sys-number 插槽正确处理零:

  1. 单击 定制槽 图标 定制槽

  2. 检查中,输入 @sys-number >= 0

  3. 现在,更改为数字存储的上下文变量。

    槽条件用于检查用户输入中的数字值,并将该数字存储在上下文变量中。 现在,您在 检查对象 字段中编辑了条件,找到了数字零的提及项。

    但是,您希望仅保存该数字,并将其存储在上下文变量中。 从选项菜单 选项 菜单中,选择 打开 JSON 编辑器,然后编辑用于定义上下文变量的 JSON。

    值如下所示:

    {
      "context": {
        "guests": "@sys-number >= 0"
      }
    }
    

    将其更改为类似于以下内容:

    {
      "context": {
        "guests": "@sys-number"
      }
    }
    
  4. 单击保存

    必须在 JSON 编辑器中编辑上下文变量值。 请勿编辑槽的检查字段中的值。 检查字段必须保持设置为 @sys-number >= 0。 { :important}

    在 JSON 编辑器中编辑值时,您实际上仅仅是在更改上下文变量中要保存的内容。 但是,您不希望更改输入中要检查的值。 这两个值将是不同的。

  5. 再次测试节点。 打开“试用”窗格,然后单击清除以删除先前测试带槽的节点时指定的槽上下文变量值。 要查看所做更改的影响,请使用以下脚本:

    脚本详细信息
    说话者 话语
    我想预约一下。
    助手 我可以为您订位。 就告诉我预约的日子和时间,还有多少人会用餐。
    我们想要在 5 月 23 日晚上 8 点就餐。 就餐人数是 0 位。

    此时间助手将使用 OK. I am making you a reservation for 0 on Thursday, May 23 at 8:00 PM. 进行响应

您格式化了数字槽,以便正确处理零。 但是,您可能不希望节点接受零作为有效的访客数。 在下一步中,您将了解如何验证用户指定的值。

验证用户输入

到目前为止,我们假定用户为槽提供了相应的值类型。 您可以通过向槽添加条件响应来考虑用户可能提供无效值的情况。 在此步骤中,您使用条件槽响应来执行以下任务:

  • 请检查请求的日期是否不是过去的日期。
  • 检查请求的预订时间是否在接待时段内。
  • 确认用户的输入。
  • 请检查提供的访客数是否大于零。
  • 指示您要将一个值替换为另一个值。

要验证日期,请完成以下步骤:

  1. 单击 @sys-date 槽的 定制槽 图标 定制槽

  2. 从选项菜单 选项 菜单中,选择 启用条件

  3. 已找到 部分中,单击 添加响应,然后单击 定制处理程序 图标 定制处理程序

  4. 添加以下条件和响应以检查用户指定的日期是否位于今天之前:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    @sys-date.before(now()) You cannot make a reservation for a day in the past. 清除槽并重新提示
  5. 添加将在用户提供有效日期时显示的第二个条件响应。 此类型的简单确认告知用户已理解响应。

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    true $date it is. 离开

要验证时间:

  1. 单击 @sys-date 槽的 定制槽 图标 定制槽

  2. 从选项菜单 选项 菜单中,选择 启用条件

  3. 已找到 部分中,单击 添加响应,然后单击 定制处理程序 图标 定制处理程序

  4. 添加以下条件和响应以检查用户指定的时间是否位于允许的时段内:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    @sys-time.after('21:00:00') Our last seating is at 9 PM. 清除槽并重新提示
    @sys-time.before('09:00:00') Our first seating is at 9 AM. 清除槽并重新提示
  5. 添加将在用户提供适用时段内有效时间时显示的第三个条件响应。 此类型的简单确认告知用户已理解响应。

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    true Ok, the reservation is for $time. 离开

您可以添加条件以验证访客数。

  • 检查指定的访客数是否大于零。
  • 预测并处理用户更改就餐人数的情况。

如果在处理具有槽的节点的任何时候,用户更改槽值,那么将更新相应的槽上下文变量值。 但是,告诉用户该值正在被替换,以向用户提供明确的反馈,并给用户一个纠正的机会是很有用的。

  1. 单击 @sys-number 槽的 定制槽 图标 定制槽

  2. 从选项菜单 选项 菜单中,选择 启用条件

  3. 已找到 部分中,单击 添加响应,然后单击 定制处理程序 图标 定制处理程序

  4. 添加以下条件和响应以验证访客数:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    @sys-number == 0 Please specify a number that is larger than 0. 清除槽并重新提示
    (event.previous_value != null) && (event.previous_value != event.current_value) Ok, updating the number of guests from <? event.previous_value ?&gt; to <? event.current_value ?>. 离开
    true Ok. The reservation is for $guests guests. 离开

添加确认槽

您可能希望设计对话以调用外部预留系统并为系统中的用户预订预留。 在应用程序完成此任务之前,您可能希望与用户确认对话是否正确理解预留的详细信息。 可以通过向节点添加确认槽来完成此操作。

  1. 确认槽期望用户提供“是”或“否”答案。 您必须培训对话,使其能够首先识别用户输入中的“是”或“否”意向。

  2. 单击意向选项卡以返回到“意向”页面。

  3. 添加以下意向和示例话语。

#yes

Yes
Sure
I'd like that
Please do
Yes please
Ok
That sounds good

显示 yes 意向
Yes 意向

#no

No
No thanks.
Please don't
Please do not!
That's not what I want at all
Absolutely not
No way

显示无意向
无意向

  1. 在对话中,打开 #reservation 节点。

  2. 然后检查 部分中,单击 添加槽 以添加第四个槽:

    槽详细信息
    检查对象 另存为 如果不存在,请询问
    (#yes || #no) && slot_in_focus $confirmation I'm going to reserve you a table for $guests on $date at $time. Should I go ahead?

    此条件检查任一回答。 根据用户是使用条件槽响应来回答“是”还是“否”,您可以指定接下来发生的情况。 slot_in_focus 属性强制使此条件的范围仅适用于当前槽。 此设置可防止可能与用户可能生成的 #yes#no 意向匹配的随机语句触发此槽。

    例如,用户可能正在回答访客槽的数量,并说出类似 Yes, there will be 5 of us. 的内容。 您不希望使用此响应中包含的Yes意外地填充确认槽。 通过将 slot_in_focus 属性添加到条件,仅当用户专门回答此槽的提示时,才会将来自用户的 yesno 回答应用于此槽。

  3. 单击 yes/no 槽的 定制槽 图标 定制槽

  4. 从选项菜单 选项 菜单中,选择 启用条件

  5. 已找到 部分中,单击 添加响应,然后单击 定制处理程序 图标 定制处理程序

  6. 添加以下条件和响应以检查 No 响应:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    #no Alright. Let's start over. I'll try to keep up this time. 清除槽并重新提示
  7. 找到 #no 意向时,需要重置先前保存的上下文变量,因此您可以再次要求提供信息。 从条件 选项 的选项菜单中,选择 打开上下文编辑器

  8. 使用以下值设置上下文:

    设置上下文
    Variable(变量)
    $date null
    $time null
    $guests null
  9. 单击保存

  10. 找不到 部分中,说明您期望用户提供“是”或“否”答案。

  11. 添加具有以下条件的响应:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    true Respond with Yes to indicate that you want the reservation to be made as-is, or No to indicate that you do not. 等待用户输入
  12. 单击保存

既然您具有针对槽值的确认响应,并且您一次性要求所有内容,那么您可能会注意到在显示确认槽响应之前会显示各个槽响应,这可能显示为重复。 编辑槽的“已找到”响应,以阻止这些响应在特定条件下显示。

  1. 单击 @sys-date 槽的 定制槽 图标 定制槽

  2. 已找到 部分中,替换 true 条件。 例如:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    !($time && $guests) $date it is 离开
  3. 单击 @sys-time 槽的 定制槽 图标 定制槽

  4. 已找到 部分中,替换 true 条件。 例如:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    !($date && $guests) Ok, the reservation is for $time. 离开
  5. 单击 @sys-number 槽的 定制槽 图标 定制槽

  6. 已找到 部分中,替换 true 条件。 例如:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    !($date && $time) Ok. The reservation is for $guests guests. 离开

如果日后添加更多槽,那么必须编辑这些条件以说明其他槽的关联上下文变量。 如果未包含确认槽,可以仅指定 !all_slots_filled,并且无论日后添加多少槽,它都始终保持有效。

重置槽上下文变量值

您可能会注意到,在每个测试之前,必须清除先前测试期间创建的上下文变量值。 您必须执行此操作,因为具有槽的节点仅提示用户它认为缺少的信息。 如果槽上下文变量全部填充为有效值,那么不会显示任何提示。 这也同样适用于运行时的对话。 您必须在对话中构建一种机制,通过该机制可将槽上下文变量重置为 null,以便这些槽可以由下一个用户重新填充。 为此,您将向带槽的节点添加父节点,用于将上下文变量设置为 null。

  1. 从对话框的树形视图中,单击带有槽的 #reservation 节点上的 Node 选项 图标 Node 选项图标 图标,然后选择 在上方添加节点

  2. 如果助手识别中,输入 #reservation 作为条件。 与带插槽的节点使用的条件相同,但稍后在此过程中更改带插槽的节点的条件。

  3. 助手响应中,单击选项菜单 选项,然后选择 打开上下文编辑器

  4. 使用以下值设置上下文:

    设置上下文
    Variable(变量)
    $date null
    $time null
    $guests null
    $confirmation null
  5. 单击以编辑另一个 #reservation 节点,即先前创建的节点以及您向其添加了插槽的节点。

  6. 将节点条件从 #reservation 更改为 ($date == null && $time == null)

  7. 单击具有槽的节点上的 Node 选项 图标 Node 选项图标 图标,然后选择 移动

    移动
    显示对话树。 用户正在单击具有槽的节点上的“移动”操作。

  8. 选择 #reservation 节点作为移至位置目标,然后从菜单中选择作为子节点

    显示对话树。 用户正在单击具有槽的节点上的“作为子节点”。
    移动为子节点

  9. 单击以编辑 #reservation 节点。 在 然后助手应该 部分中,从 等待回复 更改为 跳过用户输入

    显示重组为包含具有 #reservation 条件的根节点的对话框,以及设置为直接转至其子节点(即具有槽的节点
    跳过用户输入
    ) 的跳至操作的对话框

    用户输入与 #reservation 意向匹配时,会触发该节点。 这会将槽上下文变量都设置为 null,然后对话直接跳转至带槽的节点以进行处理。

为用户提供退出过程的方法

添加具有槽的节点很强大,因为它使用户能够跟踪提供您需要的信息,以便为他们提供有意义的响应或代表他们执行操作。 但是,用户可能正在提供预留详细信息,但决定不执行预留。 您必须为用户提供一种方法来正常退出该过程。 为此,可以添加一个槽处理程序,用于检测用户退出过程的想法,并退出节点而不保存收集的任何值。

  1. 意向中,使用以下示例话语添加 #exit 意向。

    I want to stop
    Exit!
    Cancel this process
    I changed my mind. I don't want to make a reservation.
    Stop the reservation
    Wait, cancel this.
    Never mind.
    

    显示退出意向
    #exit 意向

  2. 对话框中,单击以打开具有槽的节点,然后单击 管理处理程序

  3. 添加以下处理程序条件:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    #exit Ok, we'll stop there. No reservation will be made. 跳至响应

    跳至响应操作直接跳转至节点级别的响应,而不显示与其余任何未填充槽关联的提示。

  4. 单击 保存,然后再次单击 保存

现在,您需要编辑节点级别的响应,以便在用户希望退出流程而不是进行预留时识别该响应。

要为节点添加条件响应,请执行以下操作:

  1. 在具有插槽的节点中,单击 定制,将 多个条件响应 开关设置为 开启,然后单击 应用

    显示开启
    多个条件响应
    后的“多个响应”切换

  2. 助手响应中,单击 添加响应

  3. 添加具有以下条件的响应:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    has_skipped_slots I look forward to helping you with your next reservation. Have a good day. 缺省为节点设置

    has_skipped_slots 条件会检查槽节点的属性,以查看是否跳过了任何槽。 #exit 处理程序会跳过其余所有槽而直接转至节点响应。 因此,当存在 has_skipped_slots 属性时,您知道已触发 #exit 意向,并且对话框可以显示备用响应。

    如果配置多个槽以跳过其他槽,或者配置另一个节点级别事件处理程序以跳过槽,那么需要使用其他方法来检查是否触发了 #exit 意向。 请参阅 处理请求以退出进程 以获取替代方法。

  4. 您希望助手在显示标准的节点级别响应之前,先检查 has_skipped_slots 属性。 移动 has_skipped_slots 条件响应,以便在原始条件响应之前对其进行处理,否则将从不触发该响应。 要执行此操作,请将鼠标悬停在刚刚添加的响应上,使用 向上箭头 将其上移,然后单击 保存

    移动条件响应
    移动条件响应

  5. 在“试用”窗格中使用以下脚本来测试此更改。

    脚本详细信息
    说话者 话语
    我想预约一下。
    助手 我可以为您订位。 就告诉我预约的日子和时间,还有多少人会用餐。
    5 位
    助手 是的。 预订的就餐人数是 5 位。 您要订哪天?
    别管了
    助手 好,停止预订。 不会进行任何预订。 期待下一次帮您预订。 祝您生活愉快。

在用户经过几次尝试未能提供有效值时应用有效值

在某些情况下,用户可能未理解您询问的内容。 他们可能会反复用错误类型的值进行响应。 为了计划应对这种可能性,可以向槽添加计数器,并且在用户尝试提供有效值 3 次失败后,您可以代表用户将值应用于槽,然后离开。

对于 $time 信息,定义在用户未提供有效时间时显示的后续语句。 创建一个上下文变量,该变量可以跟踪用户提供的值与槽期望的值类型不匹配的次数。 您希望在处理具有槽的节点之前初始化上下文变量并将其设置为 0,因此将其添加到父 #reservation 节点。

  1. 对话框中,单击以编辑 #reservation 节点。

  2. 然后设置上下文中,单击 添加变量。 (如果 然后设置上下文 不可见,请单击 助手响应 中的选项菜单 选项,然后选择 打开上下文编辑器。)

  3. 使用以下值设置上下文:

    设置上下文
    Variable(变量)
    $counter 0
  4. 单击 关闭 图标 关闭 以关闭节点编辑视图。

  5. 从树形视图中,单击以编辑具有槽的节点。

  6. 单击 @sys-time 槽的 定制槽 图标 定制槽

  7. 单击选项菜单 选项,然后选择 启用条件。 出现 在以下情况下启用此槽: 部分,设置为 true

  8. 找不到 部分中,添加具有以下条件的响应:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    true Please specify the time that you want to eat. The restaurant seats people between 9AM and 9PM. 等待用户输入

现在,每次触发此响应时,都将 1 添加到 counter 变量。 仅当用户未提供有效的时间值时,才会触发此 找不到 响应。

  1. 助手响应中,单击选项菜单 选项,然后选择 打开上下文编辑器

  2. 使用以下值设置上下文:

    设置上下文
    Variable(变量)
    $counter "<? context['counter'] + 1 ?>"
  3. 单击保存

将第二个条件响应添加到 找不到 部分,该部分检查计数器是否大于 1,这指示用户先前提供了无效响应 3 次。 在这种情况下,对话会代表用户将时间值指定为常用晚餐预订时间 - 晚上 8 点。 当触发确认槽时,用户有机会更改时间值。

  1. 找不到 部分中,添加具有以下条件的响应:

    条件详细信息
    如果助手识别到 助手响应 那助理应该
    $counter > 1 You seem to be having trouble choosing a time. I will make the reservation at 8PM for you. 等待用户输入
  2. 必须将 $time 变量设置为 8 PM。 在 助手响应中,单击选项菜单 选项,然后选择 打开上下文编辑器

  3. 使用以下值设置上下文:

    设置上下文
    Variable(变量)
    $time "<? '20:00:00'.reformatDateTime('h:mm a') ?>"
  4. 单击保存

刚才添加的条件响应的条件比第一个条件响应使用的 true 条件更精确。 必须移动此响应,以使其出现在原始条件响应之前,否则将永远不会触发此响应。

  1. 将鼠标悬停在刚刚添加的响应上,使用 向上箭头 将其向上移动,然后单击 保存

  2. 使用以下脚本测试更改。

    脚本详细信息
    说话者 话语
    我想预约一下。
    助手 我可以为您订位。 就告诉我预约的日子和时间,还有多少人会用餐。
    明天
    助手 那就是 12 月 29 日周五。 您要订在几点?
    橙色
    助手 请指定要就餐的时间。 餐厅接待时间是上午 9 点至晚上 9 点。
    粉色
    助手 请指定要就餐的时间。 餐厅接待时间是上午 9 点至晚上 9 点。
    紫色
    助手 您似乎不知道该选择什么时间。 我将在 8 PM 为您进行预留。 几位就餐?

连接到外部服务

现在,您的对话可以收集并确认用户的预订详细信息,您可以调用外部服务在餐厅系统中或通过多餐厅在线预订服务来预订表。 有关更多详细信息,请参阅从对话节点发起程序化调用

在调用预订服务的逻辑中,请确保检查是否存在 has_skipped_slots,如果存在,请不要继续预订。

摘要

在本教程中,您测试了具有槽的节点,并进行了优化其与实际用户交互方式的更改。 有关此主题的更多信息,请参阅使用槽收集信息