🚀 原文地址:https://rasa.com/docs/rasa/fallback-handoff

本篇文章是关于如何处理机器人的各种故障的指南。即使你完美地设计了你的机器人,用户也会不可避免地说出意料之外的话。在这些情况下,机器人会回复失败,作为业务方,确保它正常运行非常重要。

1. 处理超出范围的消息

为避免用户感到沮丧,我们可以处理那些用户可能会询问,但是尚未实现用户目标的问题。

1.1 创建范围外的意图

我们需要在 NLU 训练数据中定义 out_of_scope 意图,并将任何已知的范围外请求添加为训练样本,例如:

  1. nlu:
  2. - intent: out_of_scope
  3. examples: |
  4. - I want to order food
  5. - What is 2 + 2?
  6. - Who's the US President?

与每个意图一样,我们应该从真实对话中获取大部分示例。

1.2 定义响应消息

我们需要在域文件中定义一个范围外的响应,使用话语 utter_out_of_scope 作为默认响应,示例如下:

  1. responses:
  2. utter_out_of_scope:
  3. - text: Sorry, I can't handle that request.

1.3 创建范围外的规则

最后,我们还需要给超出范围的请求编写规则:

  1. rules:
  2. - rule: out-of-scope
  3. steps:
  4. - intent: out_of_scope
  5. - action: utter_out_of_scope

1.4 处理特定范围外的消息

如果观察到用户询问你希望将来转换为用户目标的一些事情,我们可以将这些事情作为单独的意图来处理,为了让用户知道我们已经理解他们的信息,但目前还没有一个解决方案。例如,如果用户询问“我想在 Rasa 申请一份工作”,我们可以回复“我知道您在找工作,但恐怕我还不能掌握这项技能”。

out_of_scope 意图示例类似,我们需要使用训练示例创建新意图、定义响应消息,并创建规则。

2. 回退

尽管 Rasa 会泛化到未知的消息,但某些消息可能会收到分类低置信度。使用回退将有助于确保低置信度的消息得到妥善处理,让机器人可以选择默认消息进行响应或尝试消除用户输入中的歧义。

2.1 NLU回退

要处理 NLU 置信度低的传入消息,请使用 FallbackClassifier。使用此配置,当所有其他意图预测低于配置的置信度阈值时,将预测意图为 nlu_fallback。然后,当预测 nlu_fallback 意图时,我们可以编写一条规则告诉机器人应该做什么。

1)更新配置

要使用 FallbackClassifier,请将其添加到 NLU 管道中:

  1. pipeline:
  2. # other components
  3. - name: FallbackClassifier
  4. threshold: 0.7

2)定义响应消息

当用户消息被分类为低置信度时,通过添加响应来定义机器人应该发送的消息:

  1. responses:
  2. utter_please_rephrase:
  3. - text: I'm sorry, I didn't quite understand that. Could you rephrase?

3)创建NLU回退规则

以下规则是在用户在发送的消息被分类为置信度时,要求用户重新表述消息:

  1. rules:
  2. - rule: Ask the user to rephrase whenever they send a message with low NLU confidence
  3. steps:
  4. - intent: nlu_fallback
  5. - action: utter_please_rephrase

2.2 处理低动作置信度

由于用户可能会发送意料之外的消息,因此他们的行为可能会走上未知的对话路径。Rasa 使用经过优化后的机器学习策略来处理未知的对话路径,例如 TEDPolicy

在机器学习策略无法给出高置信度的下个预测动作的情况下,如果没有高于所配配置的置信度阈值的策略,我们可以配置规则策略以预测默认动作。

在低置信度动作情况下,我们可以配置动作来进行处理以及相应的置信度阈值,具体步骤如下:

1)更新配置

我们需要将 RulePolicy 添加到配置文件中的策略中。默认情况下,规则策略有以下相关设置:

  1. policies:
  2. - name: RulePolicy
  3. # Confidence threshold for the `core_fallback_action_name` to apply.
  4. # The action will apply if no other action was predicted with
  5. # a confidence >= core_fallback_threshold
  6. core_fallback_threshold: 0.4
  7. core_fallback_action_name: "action_default_fallback"
  8. enable_fallback_prediction: True

2)定义默认响应消息

在动作置信度低于阈值时,要定义机器人说什么,需要在域文件中定义响应 utter_default

  1. responses:
  2. utter_default:
  3. - text: Sorry I didn't get that. Can you rephrase?

当动作置信度低于阈值时,Rasa 将运行动作 action_default_fallback。这将发送 utter_default 响应,并恢复到导致回退的用户消息之前的对话状态,因此不会影响对未来动作的预测。

3)自定义默认动作

action_default_fallback 是 Rasa 中的一个默认动作,它向用户发送 utter_default 响应,我们可以创建自定义动作来作为回退。以下代码片段是自定义动作的实现,它与 action_default_fallback 执行相同的操作,但分派不同的模板 utter_fallback_template

  1. from typing import Any, Text, Dict, List
  2. from rasa_sdk import Action, Tracker
  3. from rasa_sdk.events import UserUtteranceReverted
  4. from rasa_sdk.executor import CollectingDispatcher
  5. class ActionDefaultFallback(Action):
  6. """Executes the fallback action and goes back to the previous state
  7. of the dialogue"""
  8. def name(self) -> Text:
  9. return ACTION_DEFAULT_FALLBACK_NAME
  10. async def run(
  11. self,
  12. dispatcher: CollectingDispatcher,
  13. tracker: Tracker,
  14. domain: Dict[Text, Any],
  15. ) -> List[Dict[Text, Any]]:
  16. dispatcher.utter_message(template="my_custom_fallback_template")
  17. # Revert user message which led to fallback.
  18. return [UserUtteranceReverted()]

2.3 两阶段回退

为了让机器人有机会弄清楚用户想要什么,我们希望通过提出澄清问题来尝试消除用户消息中的歧义。两阶段回退用于使用以下程序处理多个阶段的低 NLU 置信度:

  1. 用户消息被分类为低置信度
    • 要求用户确认意图
  2. 用户确认或否认了意图
    • 如果用户确认,对话将继续就像意图从一开始就被分类为高置信度
    • 如果用户否认,他们将被要求重新表述消息
  3. 用户重新表述他们的意图
    • 如果重新表述的消息被分类为高置信度,则对话会继续,就好像用户从一开始就有这样的意图
    • 如果重新表述的消息还是低置信度,那么用户将被要求确认该意图
  4. 用户去人或拒绝重新表述意图
    • 如果用户确认,则对话会继续,就好像用户从一开始就有这样的意图
    • 如果用户否认,将会触发最终回退动作,例如转接给人工。默认最终回退动作称之为 utter_default_fallback,此操作会导致机器人发出 utter_default 响应,并重置对话状态,就好像在两阶段回退期间发生的回合没有发生一样。

可以使用以下步骤启用两阶段回退:

1)更新配置

FallbackClassifier 添加到配置文件中的管道中,以及将 RulePolicy 添加到策略中:

  1. recipe: default.v1
  2. pipeline:
  3. # other components
  4. - name: FallbackClassifier
  5. threshold: 0.7
  6. policies:
  7. # other policies
  8. - RulePolicy

2)定义回退响应

当需要定义机器人如何要求用户重新表述他们的消息,请在域中定义 utter_ask_rephrase 响应:

  1. responses:
  2. utter_ask_rephrase:
  3. - text: I'm sorry, I didn't quite understand that. Could you rephrase?

Rasa 提供了默认实现来询问用户的意图,并要求用户进行重新表述。

3)定义两阶段规则

在训练数据中添加如下规则,此规则将确保 Rasa 在收到具有低分类置信度消息时激活两阶段回退:

  1. rules:
  2. - rule: Implementation of the Two-Stage-Fallback
  3. steps:
  4. - intent: nlu_fallback
  5. - action: action_two_stage_fallback
  6. - active_loop: action_two_stage_fallback

4)定义最终回退动作

当用户拒绝重新表述意图时,机器人如何进行响应,请在域中定义 utter_default 响应:

  1. responses:
  2. utter_default:
  3. - text: I'm sorry, I can't help you.

或者,我们可以通过在编写自定义动作 action_default_fallback 来完成更复杂的行为。例如,如果希望机器人呼叫并停止与用户进行交互:

  1. from typing import Any, Dict, List, Text
  2. from rasa_sdk import Action, Tracker
  3. from rasa_sdk.events import UserUtteranceReverted
  4. from rasa_sdk.executor import CollectingDispatcher
  5. class ActionDefaultFallback(Action):
  6. def name(self) -> Text:
  7. return "action_default_fallback"
  8. def run(
  9. self,
  10. dispatcher: CollectingDispatcher,
  11. tracker: Tracker,
  12. domain: Dict[Text, Any],
  13. ) -> List[Dict[Text, Any]]:
  14. # tell the user they are being passed to a customer service agent
  15. dispatcher.utter_message(text="I am passing you to a human...")
  16. # assume there's a function to call customer service
  17. # pass the tracker so that the agent has a record of the conversation between the user
  18. # and the bot for context
  19. call_customer_service(tracker)
  20. # pause the tracker so that the bot stops responding to user input
  21. return [ConversationPaused(), UserUtteranceReverted()]

:::warning 💡 自定义最终回退动作返回的事件
————————————————
应该将 UserUtteranceReverted() 作为自定义 action_default_fallback 返回的事件之一。不包括导致跟踪器在两阶段回退过程中发生所有事件的事件,这可能会干扰机器人策略管道的后续动作预测。最好是将来两阶段回退过程中发生的事件视为未发生,以便机器人可以应用规则或记忆的故事来正确地预测下一步动作。 :::

3. 人工交接

作为回退动作的一部分,一些情况下,我们希望机器人可以移交对话给人工进行处理。一个实现人工转接的直接方法是配置消息或语音通道,根据特定机器人或用户消息切换侦听的主机。

例如,作为两阶段回退的最终动作,机器人可以询问使用“你需要转接人工助理么?”,如果用户回答需要,机器人将发送带有特定负载的消息,例如 handoff_to_human 到通道。当此通道接收到消息,它将停止监听 Rasa Server,并会向人工通道发送一条消息,其中包含到那时为止的聊天对话记录。

从前端移交给人工的实现将取决于我们所使用的通道,可以在 Financial DemoHelpdesk-Assitant 中查看使用聊天室频道改编的实现示例。

4. 总结

为了让机器人优雅地处理故障,我们应该处理已知范围外的消息,并添加一个回退行为的表单。如果我们想添加人工对接,可以将其添加或作为回退设置的最后一步。以下是我们需要对每种方法进行更改的步骤:

对于范围外的意图:

  • 将每个范围外意图的训练示例添加到 NLU 数据中
  • 定义范围外的响应或动作
  • 为范围外的每个意图定义规则
  • 在配置文件 config.yml 中添加 RulePolicy

对于单阶段 NLU 回退:

  • 在配置文件 config.yml 管道添加 FallbackClassifier
  • 定义回退响应或动作
  • nlu_fallback 意图定义规则
  • 在配置文件 config.yml 中添加 RulePolicy

对于处理低核心置信度:

  • config.yml 文件中给核心回退配置 RulePolicy
  • 可选择性配置自定义回退动作
  • 定义 utter_default 响应

对于两阶段回退:

  • 在配置文件 config.yml 管道添加 FallbackClassifier
  • nlu_fallback 意图定义规则,用于触发 action_two_stage_fallback 动作
  • 在领域中定义范围外意图
  • 在配置文件 config.yml 中添加 RulePolicy

对于转接人工:

  • 配置前端切换主机
  • 编写自定义动作(可以是回退动作)来发送转交的负载
  • 添加触发转交的规则(如果不是回退的一部分)
  • 在配置文件 config.yml 中添加 RulePolicy