IBM Cloud Docs
通过上下文使对话个性化

通过上下文使对话个性化

要个性化对话,助手可以从客户收集信息,然后在对话中稍后进行参考。

跨多轮对话保留信息

对话是无状态的,这意味着从与用户的一个交互到下一个交互,对话不会保留相关信息。 将对话添加到助手并进行部署时,助手将保存来自一个消息调用的上下文,然后在当前会话中的下一个请求上重新提交该上下文。 当用户与助手交互以及指定的会话不活动时间范围时,当前会话将持续。 允许的最长会话不活动时间范围为 5 分钟到 7 天,具体取决于您的套餐类型。 如果未将对话添加到助手,那么作为定制应用程序开发者,您应负责维护应用程序需要的任何持续信息。

应用程序可以将信息传递到对话,对话可以更新此信息,然后将其传递回应用程序,或者传递到后续节点。 对话使用上下文变量来执行此操作。

上下文变量

上下文变量是在节点中定义的变量。 可以为其指定缺省值。 然后,其他节点,应用程序逻辑或用户输入可以设置或更改上下文变量的值。

可以通过引用对话节点条件中的上下文变量来根据上下文变量值检查条件,以确定是否执行节点。 您还可以从对话节点响应条件引用上下文变量,以根据外部服务或用户提供的值显示不同的响应。

了解更多信息:

从应用程序传递上下文

通过设置上下文变量并将上下文变量传递到对话,可将信息从应用程序传递到对话。

例如,应用程序可以设置 $time_of_day 上下文变量,并将其传递到对话,该对话可以使用信息来定制其向用户显示的问候语。

显示“欢迎”节点,该节点使用响应条件来检查从应用程序传递到对话的 $time_of_day 上下文变量的值。
时间上下文

在此示例中,对话知道应用程序将此变量设置为以下某个值:morningafternoonevening。 它可以检查每个值,并根据提供的值,返回相应的问候语。 如果该变量未传递或具有与某个期望值不匹配的值,那么会向用户显示更通用的问候语。

在节点之间传递上下文

对话还可以添加上下文变量,以将信息从一个节点传递到另一个节点,或更新上下文变量的值。 当对话要求并从用户获取信息时,它可以跟踪信息并在稍后的对话中进行引用。

例如,在一个节点中,您可能要求用户提供名字,然后在后面的节点中用名字来称呼他们。

显示一个简介节点,该节点询问用户的名称,并将其存储为上下文变量。 下一个节点使用 $username 上下文变量按名称引用用户。
将上下文从一个节点传递到另一个节点

在此示例中,系统实体 @name 用于从输入中抽取用户的名称 (如果用户提供了名称)。 在 JSON 编辑器中,将定义用户名上下文变量并将其设置为 @name 值。 在随后的节点中,$username 上下文变量包含在响应中,这样就可以用名字来称呼用户。

定义上下文变量

在节点的编辑视图中,通过将变量名称添加到变量字段,并向字段添加该变量的缺省值,可定义上下文变量。

  1. 单击以打开要向其添加上下文变量的对话节点。

  2. 转至 助手响应 部分,然后单击菜单图标 溢出菜单图标

  3. 单击打开上下文编辑器

  4. 将变量名称和值对添加到变量字段。

    • name 可以包含任何大写和小写字母字符,数字字符 (0-9) 和下划线。

    • value 可以是任何受支持的 JSON 类型,如简单字符串变量、数字、JSON 数组或 JSON 对象。

下表显示了有关如何为不同类型的值定义名称和值对的一些示例:

定义名称/值对
Variable(变量) 值类型
dessert "cake" 字符串
age 18 编号
toppings_array ["onions","olives"] JSON 数组
full_name {"first":"John","last":"Doe"} JSON 对象

然后,要引用这些上下文变量,请使用语法 $name,其中 name 是您定义的上下文变量的名称。

例如,可将以下表达式指定为对话响应:

The customer, $age-year-old <? $full_name.first ?>, wants a pizza with <? $toppings_array.join(' and ') ?>, and then $dessert.

生成的输出如下所示:

The customer, 18-year-old John, wants a pizza with onions and olives, and then cake.

还可以使用 JSON 编辑器来定义上下文变量。 如果要将复杂表达式添加为变量值,那么您可能希望使用 JSON 编辑器。 有关更多详细信息,请参阅 JSON 编辑器中的上下文变量

常见上下文变量任务

要存储由用户作为输入提供的整个字符串,请使用 input.text

捕获用户输入
Variable(变量)
repeat <?input.text?>

例如,用户输入可能为 I want to order a device. 如果节点响应为 You said: $repeat,那么响应将显示为 You said: I want to order a device.

要在上下文变量中存储实体的值,请使用以下语法:

捕获实体提及项
Variable(变量)
place @place

例如,用户输入可能是 I want to go to Paris. 如果 @place 实体识别 Paris,那么助手会将 Paris 保存在 $place 上下文变量中。

要存储从用户输入中抽取的字符串的值,可以包含使用 extract 方法将正则表达式应用于用户输入的 SpEL 表达式。 以下表达式从用户输入中抽取数字,并将其保存到 $number 上下文变量。

使用 String 方法
Variable(变量)
数字 <?input.text.extract('[\d]+',0)?>

要存储模式实体的值,请将 .literal 附加到实体名称。 使用此语法可确保与指定模式匹配的用户输入文本的准确范围存储在变量中。

捕获模式实体值
Variable(变量)
email <? @email.literal ?>

例如,用户输入为 Contact me at joe@example.com. Your entity is named @email 识别 name@domain.com 电子邮件格式。 通过配置上下文变量来存储 @email.literal,可指示要存储与模式匹配的输入部分。 如果省略值表达式中的 .literal 属性,那么会返回为模式指定的实体值名称,而不是与模式匹配的用户输入分段。

删除上下文变量

要删除上下文变量,请将该变量设置为 null。

使上下文变量为 null
Variable(变量)
order_form null

更新上下文变量值

要更新上下文变量的值,请使用与先前上下文变量相同的名称来定义上下文变量,但这次为其指定不同的值。

多个节点设置同一上下文变量的值时,该上下文变量的值可能会在与用户的交谈过程中更改。 应用的值取决于用户在对话过程中触发的节点。 为最后一个节点中的上下文变量指定的值将覆盖先前处理的节点为该变量设置的任何值。

有关在上下文变量值为 JSON 对象或 JSON 数组数据类型时如何更新该值的信息,请参阅更新 JSON 格式的上下文变量值

如何处理上下文变量

定义上下文变量的位置很重要。 助手处理了在对话节点中定义了上下文变量的部分后,才会创建该上下文变量,并将其设置为您所指定的值。 在大多数情况下,可将上下文变量定义为节点响应的一部分。 执行此操作时,将在助手返回节点响应时创建上下文变量并为其提供指定的值。

对于具有条件响应的节点,将在满足特定响应的条件并处理该响应时创建并设置上下文变量。 例如,如果为条件响应 #1 定义上下文变量,并且助手处理响应 #2,那么不会设置为条件响应 #1 定义的变量。

有关添加您希望助手在用户与带槽的节点交互时设置的上下文变量的信息,请参阅 向带槽的节点添加上下文变量

操作顺序

定义要一起处理的多个变量时,定义这些变量的顺序不会确定助手对其进行求值的顺序。 助手会按随机顺序对变量求值。 不要在第一个上下文变量中设置值,并期望在第二个变量中使用该值,因为第一个上下文变量可能不会在第二个上下文变量之前执行。 例如,不要使用两个上下文变量来实现用于检查用户输入是否包含单词 Yes 的逻辑。

使用两个上下文变量来检查用户输入中的值
Variable(变量)
user_input <? input.text ?>
contains_yes <? $user_input.contains('Yes') ?>

请改为使用略复杂一些的表达式,以避免在对列表中的第二个变量 (contains_yes) 求值之前,必须依赖于对第一个变量 (user_input) 求值。

使用单个上下文变量
Variable(变量)
contains_yes <? input.text.contains('Yes') ?>

向带槽的节点添加上下文变量

有关槽的更多信息,请参阅使用槽收集信息

要添加在满足槽的响应条件后处理的上下文变量,请执行以下操作:

  1. 在编辑视图中打开带槽的节点。
  2. 单击 定制槽 图标 定制槽
  3. 单击 选项 图标 选项,然后选择 启用条件
  4. 单击要与上下文变量关联的响应旁边的 定制处理程序 图标 编辑槽
  5. 单击“助手”响应部分中的 选项 图标 选项,然后单击 打开上下文编辑器
  6. 将变量名称和值对添加到变量字段。

要添加在满足槽条件后设置或更新的上下文变量,请完成以下步骤:

  1. 在编辑视图中打开带槽的节点。
  2. 单击 定制槽 图标 定制槽
  3. 单击 选项 图标 选项,然后选择 启用条件
  4. 添加 JSON 格式的变量名称和值对。
{
"time_of_day": "morning"
}

无法使用上下文编辑器来定义在对话节点求值的此阶段期间设置的上下文变量。 您必须改为使用 JSON 编辑器。 有关使用 JSON 编辑器的更多信息,请参阅 JSON 编辑器中的上下文变量

JSON 编辑器中的上下文变量

您还可以在 JSON 编辑器中定义上下文变量。 如果您正在定义复杂上下文变量,并且希望在添加或更改该变量时能够看到完整的 SpEL 表达式,请使用 JSON 编辑器。

名称和值对必须满足以下要求:

  • name 可以包含任何大写和小写字母字符,数字字符 (0-9) 和下划线。

    可以在名称中包含其他字符,例如句点和连字符。 但是,如果执行此操作,那么每次引用变量时都必须指定速记语法 $(variable-name)。 有关更多详细信息,请参阅用于访问对象的表达式

  • value 可以是任何受支持的 JSON 类型,如简单字符串变量、数字、JSON 数组或 JSON 对象。

以下 JSON 样本定义 $dessert 字符串、$toppings_array 数组、$age 数字和 $full_name 对象上下文变量的值:

{
  "context": {
    "dessert": "cake",
    "toppings_array": [
      "onions",
      "olives"
    ],
    "age": 18,
    "full_name": {
      "first": "Jane",
      "last": "Doe"
    }
  },
  "output":{}
}

要定义 JSON 格式的上下文变量,请完成以下步骤:

  1. 单击以打开要向其添加上下文变量的对话节点。

    为此节点定义的任何现有上下文变量值都会显示在一组相应的变量字段中。 如果不希望这些字段显示在节点的编辑视图中,您必须关闭上下文编辑器。 您可以通过用于打开 JSON 编辑器的相同菜单来关闭上下文编辑器;以下步骤描述如何访问该菜单。

  2. 单击助手响应的 选项 图标 选项,然后单击 打开 JSON 编辑器

    如果为节点启用了 多个条件响应 设置,那么必须首先单击要与上下文变量关联的响应的 定制响应 定制响应 图标。

  3. 添加 "context":{} 块(如果不存在)。

    {
      "context":{},
      "output":{}
    }
    
  4. 在 context 块中,为要定义的每个上下文变量添加 "name""value" 对。

    {
      "context":{
        "name": "value"
    },
      "output": {}
    }
    

    在此示例中,将名为 new_variable 的变量添加到已包含变量的上下文块。

    {
      "context":{
        "existing_variable": "value",
        "new_variable":"value"
      }
    }
    

    要引用上下文变量,请使用语法 $name,其中 name 是您定义的上下文变量的名称。 例如,$new_variable

了解更多信息:

删除 JSON 格式的上下文变量

要删除上下文变量,请将该变量设置为 null。

{
  "context": {
    "order_form": null
  }
}

如果要删除上下文变量的所有跟踪,可以使用 JSONObject.remove(string) 方法将其从 context 对象中删除。 但是,您必须使用变量来执行除去操作。 在消息输出中定义新变量,以便不会将其保存到当前调用之外。

{
  "output": {
    "text" : {},
    "deleted_variable" : "<? context.remove('order_form') ?>"
  }
}

或者,可以删除应用程序逻辑中的上下文变量。

更新 JSON 格式的上下文变量值

通常,如果节点为已经设置的上下文变量设置值,那么新值会覆盖先前的值。

更新复杂 JSON 对象

这将覆盖除 JSON 对象以外的所有 JSON 类型的先前值。 如果上下文变量是复杂类型(如 JSON 对象),那么会使用 JSON 合并过程来更新变量。 合并操作将添加任何新定义的属性,并覆盖对象的任何现有属性。

在此示例中,名称上下文变量定义为复杂对象。

{
  "context": {
    "complex_object": {
      "user_firstname" : "Paul",
      "user_lastname" : "Pan",
      "has_card" : false
    }
  }
}

对话节点使用以下值来更新该上下文变量 JSON 对象:

{
  "complex_object": {
    "user_firstname": "Peter",
    "has_card": true
  }
}

结果为以下上下文:

{
  "complex_object": {
    "user_firstname": "Peter",
    "user_lastname": "Pan",
    "has_card": true
  }
}

更新数组

如果对话上下文数据包含值的数组,那么可以通过附加值、除去值或替换所有值来更新该数组。

选择以下某个选项以更新数组。 在每种情况下,我们都会看到操作之前的数组,操作以及应用操作之后的数组。

  • 附加:要将值添加到数组末尾,请使用 append 方法。

    对于以下对话运行时上下文:

    {
      "context": {
        "toppings_array": ["onion", "olives"]
      }
    }
    

    进行以下更新:

    {
      "context": {
        "toppings_array": "<? $toppings_array.append('ketchup', 'tomatoes') ?>"
      }
    }
    

    结果:

    {
      "context": {
        "toppings_array": ["onion", "olives", "ketchup", "tomatoes"]
      }
    }
    
  • 除去:要除去元素,请使用 remove 方法并在数组中指定其值或位置。

    • 按值除去:按元素的值从数组中除去元素。

      对于以下对话运行时上下文:

      {
        "context": {
          "toppings_array": ["onion", "olives"]
        }
      }
      

      进行以下更新:

      {
        "context": {
          "toppings_array": "<? $toppings_array.removeValue('onion') ?>"
        }
      }
      

      结果:

      {
        "context": {
          "toppings_array": ["olives"]
        }
      }
      
    • 按位置除去:按元素的索引位置从数组中除去元素:

      对于以下对话运行时上下文:

      {
        "context": {
          "toppings_array": ["onion", "olives"]
        }
      }
      

      进行以下更新:

      {
        "context": {
          "toppings_array": "<? $toppings_array.remove(0) ?>"
        }
      }
      

      结果:

      {
        "context": {
          "toppings_array": ["olives"]
        }
      }
      
  • 覆盖: 要覆盖数组中的值,请将数组设置为新值:

    对于以下对话运行时上下文:

    {
      "context": {
        "toppings_array": ["onion", "olives"]
      }
    }
    

    进行以下更新:

    {
      "context": {
        "toppings_array": ["ketchup", "tomatoes"]
      }
    }
    

    结果:

    {
      "context": {
        "toppings_array": ["ketchup", "tomatoes"]
      }
    }
    

设置一个上下文变量等于另一个上下文变量

将一个上下文变量设置为等于另一个上下文变量时,即相当于定义了从一个上下文变量指向另一个上下文变量的指针。 稍后,如果其中一个变量的值发生更改,那么另一个变量的值也会发生更改。

例如,如果按如下所示指定上下文变量,那么当 $var1$var2 的值稍后发生更改时,其他值也会发生更改。

设置一个上下文变量等于另一个上下文变量
Variable(变量)
var2 var1

不要将一个变量设置为等于另一个变量以捕获时间点值。 对于数组,如果要捕获存储在上下文变量中的数组值并在稍后使用该值,请改为根据该变量的当前值创建新变量。

例如,要在特定点创建数组值的副本,请添加使用现有数组的值填充的数组。 为此,可以使用以下语法:

{
"context": {
   "var2": "<? output.var2?:new JsonArray().append($var1) ?>"
 }
 }