在 Rasa Open Source 2.0 中,有三种主要的对话策略。在这篇博客中,重点介绍它们是如何协同工作的,并在此过程中解释 RulePolicy 背后的动机。 为了研究 Policies 之间的交互作用,我们将剖析 moodbot, 它是在命令行上运行rasa init
时创建的助手。
请注意,此博客文章是基于 Rasa 2.0.6 编写的
一、三种对话策略
使用 Rasa 构建的聊天助手会使用 Policy 来确定在对话的每个步骤中应采取的动作。 默认的config.yml
文件有三种不同的策略:
RulePolicy 处理与预定义规则模式匹配的对话, 它根据
rules.yml
文件中的规则进行预测。MemoizationPolicy 检查当前对话是否与训练数据中的任意story相匹配。 如果匹配,它将根据匹配的story预测下一个动作。
这些Policy按层次结构运行,每个Policy都会做出预测,但是如果两个Policy给出相同的置信度,则最终动作是具有最高优先级的动作。
如果我们采用标准设置,三者的优先级是:
RulePolicy
——> MemoizationPolicy
——>TEDPolicy
下面通过一个基本示例,来解释这些policies是如何被触发的
二、 Moodbot
通过rasa init
启动新的Rasa项目时,会生成一个聊天机器人:moodbot,我们通过研究这个机器人来深入了解这些 policies。
它在data / stories.yml
文件中包含一些story。 这些 story 会被MemoizationPolicy记住,同时也会被 TED policy 用作训练数据。
在data / rules.yml
文件中定义了一些规则:
还有一个包含已配置的策略的
config.yml
文件。 为了方便探索不同的 policy,暂时关闭了 fallback predictions。 相关配置如下所示:下图是通过rasa shell与moodbot交谈时可能遇到的情况:
要查看 policy 机制在后台执行的动作,可以在本地运行“ rasa shell --debug”。 这个命令显示所有调试相关的信息,其中包括来自已激活 policies 的信息。 完整的日志显示的内容远远超过于此,为了便于理解,此处展示的是包含了重点的摘要。
请注意,在将控制权交还给用户之前,会触发一个“ action_listen”。 这是一个在 shell 中不直接体现的动作,但是它仍然是非常重要的动作。 在将控制权交还给用户之前,助手可能需要依次执行多个动作。 这就是为什么“listening” 是 Rasa 中需要由策略触发的显式动作的原因。
对话的不同部分由不同的策略机制处理。 对于“ utter_iamabot”和“ utter_goodbye”,我们有可以直接应用的规则。 没有适用于utter_greet动作的预定义规则,而是由MemoizationPolicy触发。
因为对话遵循与
stories.yml
中的故事相同的模式,所以 MemoizationPolicy 会处理“ utter_greet”动作。
看一个长一点的对话:
通过检查前面给出的故事和规则可以理解这些响应如何生成的,由于对话遵循的是一个示例故事,因此我们主要依赖于MemoizationPolicy,但是最终的
goodbye
由 RulePolicy 处理,因为我们对此有一个规则。
三、触发 TED
在前面两个示例中,TED 没有被触发。 现在尝试说出一些非常意外的事情,例如在机器人询问我们的状况如何时回答“否”,以强制执行此动作:
TED 之所以被utter_greet
动作触发,是因为在对话中,没有与上述对话情形匹配的规则,也没有任何适用于 MemoizationPolicy 的故事。 这意味着此时将需要 TED 尝试预测下一个最佳动作。
故事虽然也被用作 TED 的训练数据,但是在moodbot 中只有三个故事,没有一个看起来像这次对话。 因此,当 TED 在这里进行预测时,它的置信度非常低。
我们可以调整config.yml
文件中的参数来处理这些情况:
如果没有一个策略能够做出可靠的预测,则可以将“ RulePolicy”配置为退回到特定动作。 默认情况下,此设置为“打开”状态,可以指定置信度阈值以及需要触发的动作。 假设在domain.yml
文件中定义了utter_rephrase
,则聊天助手在重新训练后将遵循不同的路径:
四、了解区别
在前面展示了策略机制如何“协同工作”。 读者可能会产生疑问:“为什么”是以这种方式设计的。 为了解释这么设计的原因,考虑一个更高级的对话,在业务中可能希望聊天助手能够处理下面这样的对话:
作为一项实验,创建一个仅包含故事的聊天助手。这意味着只能使用MemoizationPolicy和TEDPolicy。如果训练数据中包含许多示例故事,那么使用这种方法当然可以走得很远。 但是训练数据不可能涵盖所有的对话情形。
举个例子; 想一想以上对话中,用户可能会问“你是机器人吗?”的所有地方:
聊天助手始终能够正确回答此问题,对我们而言至关重要,但是,为了确保从MemoizationPolicy得到正确的响应,我们可能需要创建很多故事,很明显,这是不切实际的。
相反,可以训练TEDPolicy以预测此处的正确动作,但是TED旨在解决复杂对话,这里的都是单轮对话,所以使用像TED这样的东西有点大材小用了。 要查看TED处理复杂对话任务的示例,请参见此处的示例。
这里可以改善训练数据,以使TED能够进行正确的推断,但是如果引入另一个概念,可能会更加实用,一个比故事具有更高层次的概念。 这将使我们能够定义在特定的单轮互动中需要的动作。 “无论何时,如果我们看到challenge_bot
的意图,那么只有一个适当的回应。”
这里我们需要引入的概念就是“rules”。 Rules使对话中处理特定情况变得容易,使我们可以更直接地控制对话。
总结就是,Rules是用来处理story无法覆盖到的对话情形,对于这种情形统一使用一个固定的回复,把这种情形的意图定义为challenge_bot
。
五、 规则不能解决所有问题
有人可能会问“我们是否可以对所有内容都使用规则?” 答案是不”。如果要使用规则进行所有动作,则需要精确定义用户可能进行的每种交互。 这将使机器人很快变得难以维护,因为需要跟踪所有不同的对话情形。
根据设计,Rasa仅允许编写简短对话的规则。 这是为了防止我们创建不可维护的状态机。 规则的目的是提供另一种自定义聊天助手如何处理对话的方式,但不是故事的替代品。
三种使用规则的常见情形:
- 控制fallback behaviour:可以将规则与FallbackClassifier结合使用,以自定义当NLU模型对其预测不确定时所发生的情况。 还可以将其与自定义 fallback classifiers结合使用。
- 单轮互动:如果想保证单轮互动中的特定结果,那么规则是一种非常方便的工具。 可能会遇到这样的情况,即使没有完美的故事,也很容易预先定义正确的动作。 算法白板的一集在此处详细介绍了这种现象。
- Forms:用户在Forms中提供的信息需要谨慎处理。 可以使用规则和自定义动作来自定义Forms的初始化,提交,停用或检查方式。 查看文档以获取更多信息。
六、总结
在这篇文章中,我们回顾了Rasa内部不同的策略机制如何相互影响以及它们在设计会话助手时如何发挥作用。 RulePolicy,MemoizationPolicy和TEDPolicy相互补充。 每种策略都可以针对用例进行自定义,但是没有一种适用于所有情况的策略。
之所以引入RulePolicy,是因为它使得在对话助手中实施特定任务变得更加容易。 在故事之前考虑规则,因此可以让我们明确地引导对话朝着正确的方向发展。