本文继续围绕工业级业务对话平台和框架Rasa 的form全生命周期及Default Actions等进行解析。在实际业务对话场景中,为了完成具体的任务,需要使用form来收集用户信息,并相应地进行slots的设置。
一、Rasa Form全生命周期解析及Default Actions剖析
- Form全生命周期运行解析
在Rasa框架中使用form之前,需要确保Rule Policy被添加到你的policy配置里,这是因为需要使用policy来激活form。
如何定义一个form:
添加一个form到domain配置的forms部分,form的名称也是你在stories里或者rules里用于处理form执行的action的名称。你需要在required_slots里指定slots list。下面是一个form样例,可以看到slots的定义以及它们和entities之间的mapping关系:
你可以使用key “ignored_intents”来定义有哪些intents可以被form忽略。在ignored_intents里列出的intents会被添加到每个slot mapping的key “not_intent”里。下面的样例显示了一个form在进行slots填充时如何忽略掉intent “chitchat”:
一旦form action被首次调用,那么form就会被激活,然后提示用户输入下一个被要求的slot的值。对话机器人会查找response:utter_ask_<form_name>_<slot_name> 或者 utter_ask_<slot_name>,所以需要确保在domain文件里为每一个必需的slot定义这些responses。
激活一个form:
为了激活一个form,你需要添加一个story或者rule来描述什么时候对话机器人会运行这个form。如果是由一个特定的intent来触发一个form,可以这样使用rule:
active_loop这一步表示form应该在action运行之后被激活。
不激活一个form:
一个form的所有slots被填充后,这个form会自动进入不激活状态。你可以使用一个rule或者story来描述在form完成之后的行为,如果没有添加这些额外的rule或者story,那么对话机器人在form完成后会自动监听下一条用户输入。
下面的样例显示了在form完成之后运行actions:utter_submit和utter_slots_values:
关于运行form时的异常处理:
在实际对话中,用户并不总是按照对话机器人的要求提供form需要的信息,譬如用户在中间插入一些问题和闲聊内容等等,在form激活的情况下,如果用户输入没有填充所有要求的slots,那么form action的执行就会被拒绝,如果满足下面的条件就会触发ActionExecutionRejection:
-用户没有填充一个被请求的slot,并且你没有定义一个自定义action来验证slots或者抽取slots
-虽然定义了自定义action,但是action中的验证或抽取slots的方法没有返回任何events
为了拒绝form的执行,你也可以在验证或抽取方法里返回一个ActionExecutionRejection event。
为了处理上面提到的form拒绝执行的情况,你可以定义相关的rules或stories,如下面样例所示:
在用户决定终止他们的请求时,对话机器人应该停止向用户请求这些slots。对于这种场景,你可以使用default action “action_deactivate_loop”来终止form执行并且重置所请求的slots。下面是一个stories样例:
*注:Rasa强烈推荐使用交互式学习方式来构建这些rules和stories。如果你自己手写这些rules和stories,可能会错过重要的内容。
2. Form的高级用法
可以通过自定义action来实现form的完全定制。
关于验证form输入:
从用户输入中抽取slot的值之后,你可以验证slots。你可以实现一个自定义的action “validate_<form_name>”来验证任何抽取的slots,前提是把你的action添加到domain配置里:
当form执行时,Rasa会在每个用户turn之后运行你的action来验证最新填充的slots。可以通过继承FormValidationAction来简化验证slots的过程,你需要为每个抽取的slot定义方法validate_<slot_name>。下面的样例显示了如何验证slot “cuisine”:
当然也可以直接继承自Action来使用tracker.slots_to_validate来完全定制验证逻辑。
关于自定义slot mappings:
如果没有任何预定义的slot mappings满足你的业务要求,你可以使用自定义action “validate_<form_name>”来实现自己的抽取代码,然后Rasa会在form运行时触发你的action。
当继承FormValidationAction时,需要执行以下步骤来抽取自定义的slots:
-为每一个以自定义方式map的slot创建一个方法extract_<slot_name>
-在domain文件里,在form的required_slots部分,列出所有的slots,包括预定义部分和自定义部分的slots
另外你可以覆写方法required_slots来动态添加slots。
下面的样例显示了在一个form里,如何以自定义的方式抽取slot:
*注:FormValidationAction会自动设置requested_slot给required_slots中未被填充的第一个slot。
关于动态form行为:
默认情况下Rasa会基于你在domain配置里的form所列slots来请求下一个空的slot,如果你使用自定义slot mapping和FormValidationAction,那么会根据方法required_slots返回的slots来请求第一个空的slot,如果所有slots都被填充,那么这个form就会被不激活。
你可以根据需要动态更新form的required slots,譬如通过条件来控制slots的填充或者改变slots被请求的顺序等。
推荐使用FormValidationAction来覆写方法required_slots,从而定制form动态行为。下面样例显示了如何对一个slot根据条件判断进行动态设置:
关于”requested_slot” slot:
这个slot “requested_slot”会被自动添加到domain里作为text类型的slot。在对话时“requested_slot”的值会被忽略,如果你想改变这种行为,你需要把这个slot添加到你的domain文件里作为分类slot,并设置” influence_conversation”为True。如果你想根据当前被请求的slot来处理对话的unhappy paths,就可以这样做。下面样例显示了如何使用这个slot:
使用一个自定义action来请求下一个slot:
一旦form决定了用户应该填充的下一个slot,就会执行action utter_ask_<form_name>_<slot_name> 或者utter_ask_<slot_name>来要求用户提供必要的信息。如果使用常规对话不能满足要求,你可以使用一个自定义的action action_ask_<form_name>_<slot_name> 或者action_ask_<slot_name>来请求下一个slot。
3. Slot Validation Actions及Default Actions详解
关于Slot Validation Actions:
-action_validate_slot_mappings:你可以使用这个action来自定义在一个form上下文环境之外的slots的抽取和验证逻辑。这个action会在default action “action_extract_slots”之后被自动调用,所以名称不能被改变。在自定义slot mapping中不需要指定action的key,这是因为default action “action_extract_slots”会自动运行action “action_validate_slot_mappings”,前提是这个action被添加到domain的actions里(即在domain里注册)。如果使用Rasa SDK,那么这个action应该继承ValidationAction。
- validate_<form name>:如果在action名称中所指定的form被激活时,这个自定义action就会自动运行。如果使用Rasa SDK,那么这个action应该继承FormValidationAction。
-Regular Custom Action:你可以使用一个完全自定义的action在自定义抽取slots逻辑里返回slot events,前提是以上两种action都不能满足你的要求。
关于default actions:
Default actions是默认内置在对话管理器中的actions。大多数actions是基于一定的对话场景下被自动预测。你也可以自定义这些actions,即通过name方法返回与default action同样的name来实现自定义行为。然后把这个action添加到domain文件里。以下列举了一些default actions:
-action_listen:监听用户下一个输入
-action_restart:重设对话历史,包含所有slots
-action_session_start:启动一个新的对话
-action_default_fallback:取消最后一次对话机器人和用户的交互
-action_deactivate_loop:不激活active loop并重置请求的slot
-action_extract_slots:从最新的用户输入提取信息来设置或更新对话中的slots