Transformer课程 业务对话机器人Rasa 3.x 写入会话数据(Writing Conversation Data)

对话数据包括构成Rasa助理对话管理模型训练数据的故事和规则。写得好的对话数据使您的助理能够可靠地遵循您安排的对话路径,并概括到意外的路径。

Rasa 官网

https://rasa/blog/

Designing Stories

在设计故事时,需要考虑两组对话互动:快乐路径和不快乐路径。“快乐路径”描述了用户何时按照您的预期遵循对话流程,并在提示时始终提供必要的信息。然而,用户经常会因为问题、闲聊或其他问题而偏离快乐的道路。我们称之为不幸之路。

对你的机器人来说,优雅地处理不愉快的路径是很重要的,但也无法预测给定用户可能会选择哪条路径。通常,在设计不愉快的路径时,开发人员会尝试解释每一条可能的分歧路径。为状态机中的每个可能状态(其中许多状态永远无法达到)进行规划需要大量额外的工作,并显著增加了训练时间。

相反,我们建议在设计不愉快的路径时采用对话驱动的开发方法。对话驱动开发促进尽早与测试用户共享您的机器人,并收集实际的对话数据,准确地告诉您用户如何偏离快乐路径。根据这些数据,您可以创建故事来完成用户的请求,并开始思考如何引导他们回到快乐的道路。

When to Write Stories vs. Rules

何时写故事与规则

规则是对话管理器用于处理应始终遵循相同路径的对话片段的一种训练数据。
在实施以下各项时,规则可能很有用:

  • 单回合互动:一些消息不需要任何上下文来回答。规则是将意图映射到响应的一种简单方法,可以指定这些消息的固定答案。
  • 回退行为:与 FallbackClassifier回退分类器相结合,您可以编写规则,以响应具有特定回退行为的低可信度用户消息。
  • 表单:激活和提交表单通常都遵循固定路径。您还可以编写规则来处理表单期间的意外输入。

因为规则不会泛化到看不见的对话,所以您应该为单回合对话片段保留规则,并使用故事来训练多回合对话。

bot对于意图“greet”向用户消息返回固定响应“utter_greet” 的规则示例如下:

rules:
- rule: Greeting Rule
  steps:
  - intent: greet
  - action: utter_greet

对于多回合互动,您应该定义一个故事,例如:

stories:
 - story: Greeting and ask user how they're doing
   steps:
   - intent: greet
   - action: utter_greet
   - action: utter_ask_how_doing
   - intent: doing_great
   - action: utter_happy

Managing the Conversation Flow

管理会话流,以下是管理故事中对话流的一些技巧:

When to Use Slots to Influence Conversations

何时使用插槽影响对话:插槽充当机器人的内存。定义插槽时,可以定义插槽是否应影响对话。属性“influence_conversation”设置为false的插槽只能存储信息。属性influence_conversation设置为true的插槽可以根据存储在其中的信息影响对话流。

可以根据插槽映射slot mappings在每个用户消息之后设置插槽。它们也可以通过响应用户消息而运行的自定义操作进行设置。所有影响谈话的插槽都需要添加到您的故事或规则中。例如,您可以使用自定义操作设置的布尔槽,根据对话流的值,使用以下故事控制对话流:

stories:
- story: Welcome message, premium user
  steps:
   - intent: greet
   - action: action_check_profile
   - slot_was_set:
     - premium_account: true
   - action: utter_welcome_premium

- story: Welcome message, basic user
  steps:
   - intent: greet
   - action: action_check_profile
   - slot_was_set:
     - premium_account: false
   - action: utter_welcome_basic
   - action: utter_ask_upgrade

如果不希望某个插槽影响会话流,则应将该插槽的属性influence_conversation设置为false。您不需要在您的故事中包含不影响对话的slot_was_set事件。

Implementing Branching Logic

编写故事时,有时下一个操作将取决于某个自定义操作中返回的值。在这些情况下,在返回插槽和直接使用自定义操作代码来影响bot下一步的操作之间,找到正确的平衡是很重要的。

在仅使用一个值来确定BOT的响应的情况下,考虑将决策逻辑嵌入自定义操作中,而不是在故事中使用特征化插槽。这有助于降低总体复杂性,并使您的故事更易于管理。

例如,您可以转换以下故事:

stories:
- story: It's raining now
  steps:
  - intent: check_for_rain
  - action: action_check_for_rain
  - slot_was_set:
    - raining: true
  - action: utter_is_raining
  - action: utter_bring_umbrella

- story: It isn't raining now
  steps:
  - intent: check_for_rain
  - action: action_check_for_rain
  - slot_was_set:
    - raining: false
  - action: utter_not_raining
  - action: utter_no_umbrella_needed

变成一个故事:

stories:
- story: check for rain
  steps:
  - intent: check_for_rain
  - action: action_check_for_rain

使用自定义动作代码:

def run(self, dispatcher, tracker, domain):
    is_raining = check_rain()
    if is_raining:
        dispatcher.utter_message(template="utter_is_raining")
        dispatcher.utter_message(template="utter_bring_umbrella")
    else:
        dispatcher.utter_message(template="utter_not_raining")
        dispatcher.utter_message(template="utter_no_umbrella_needed")
    return []

如果该值用于影响后续的动作流,则返回一个特征化的槽以确定故事。例如,如果您想收集新用户的信息,但不想返回新用户,您的故事可能如下所示:

stories:
- story: greet new user
  steps:
  - intent: greet
  - action: check_user_status
  - slot_was_set:
    - new_user: true
  - action: utter_greet
  - action: new_user_form
  - active_loop: new_user_form
  - active_loop: null

- story: greet returning user
  steps:
  - intent: greet
  - action: check_user_status
  - slot_was_set:
    - new_user: false
  - action: utter_greet
  - action: utter_how_can_help

Using OR statements and Checkpoints

OR语句和检查点对于减少您必须编写的故事数量非常有用。但是,应谨慎使用。过度使用OR语句或检查点会降低训练速度,创建过多的检查点会使您的故事难以理解。

OR statements

在bot以相同方式处理不同意图或插槽事件的故事中,您可以使用OR语句作为创建新故事的替代方案。

例如,您可以合并这两个故事:

stories:
- story: newsletter signup
  steps:
  - intent: signup_newsletter
  - action: utter_ask_confirm_signup
  - intent: affirm
  - action: action_signup_newsletter

- story: newsletter signup, confirm via thanks
  steps:
  - intent: signup_newsletter
  - action: utter_ask_confirm_signup
  - intent: thanks
  - action: action_signup_newsletter

用OR语句将其转换为一个故事:

stories:
- story: newsletter signup with OR
  steps:
  - intent: signup_newsletter
  - action: utter_ask_confirm_signup
  - or:
    - intent: affirm
    - intent: thanks
  - action: action_signup_newsletter

在训练时,这个故事将被分成两个原始的故事。
考虑重组数据:如果您注意到您在故事中经常使用OR语句,请考虑重组您的意图,以减少它们的粒度,并更广泛地捕获用户消息。

Checkpoints

检查点对于将故事模块化为经常重复的独立块非常有用。例如,如果您希望您的机器人在每个对话流结束时询问用户反馈,可以使用检查点来避免在每个故事结束时包含反馈交互:

stories:
- story: beginning of conversation
  steps:
  - intent: greet
  - action: utter_greet
  - intent: goodbye
  - action: utter_goodbye
  - checkpoint: ask_feedback

- story: user provides feedback
  steps:
  - checkpoint: ask_feedback
  - action: utter_ask_feedback
  - intent: inform
  - action: utter_thank_you
  - action: utter_anything_else

- story: user doesn't have feedback
  steps:
  - checkpoint: ask_feedback
  - action: utter_ask_feedback
  - intent: deny
  - action: utter_no_problem
  - action: utter_anything_else

不要过度使用,检查点旨在使人们更容易在许多不同的故事中重复使用对话的某些部分。我们强烈反对在现有检查点内使用检查点,因为这会显著增加训练时间,并使您的故事难以理解。

Creating Logical Breaks in Stories

在故事中创造逻辑中断

在设计会话流时,通常很容易创建长话短说的示例,以捕获从头到尾的完整会话交互。在许多情况下,这将增加说明分支路径所需的训练故事的数量。相反,请考虑将较长的故事分隔成处理子任务的较小对话块。

处理丢失的信用卡的快乐之路故事可能如下所示:

stories:
- story: Customer loses a credit card, reviews transactions, and gets a new card
  steps:
  - intent: card_lost
  - action: check_transactions
  - slot_was_set:
    - reviewed_transactions: ["starbucks"]
  - action: utter_ask_fraudulent_transactions
  - intent: inform
  - action: action_update_transactions
  - intent: affirm
  - action: utter_confirm_transaction_dispute
  - action: utter_replace_card
  - action: mailing_address_form
  - active_loop: mailing_address
  - active_loop: null
  - action: utter_sent_replacement
  - action: utter_anything_else
  - intent: affirm
  - action: utter_help

处理丢失的信用卡涉及一系列子任务,即检查欺诈交易的支出历史记录,确认替换卡的邮寄地址,然后跟进用户的任何其他请求。在这个对话中,有几个地方bot会提示用户输入,创建需要说明的分支路径。

例如,当提示“完全询问欺诈交易utter_ask_fraudulent_transactions”时,如果不适用,用户可能会以“拒绝”意图回应。当被问及机器人是否还有其他可以帮助他们的事情时,用户也可能选择以“拒绝”的意图回应。

我们可以将这一长故事分成几个小故事,如下所示:

stories:
- story: Customer loses a credit card
  steps:
  - intent: card_lost
  - action: utter_card_locked
  - action: spending_history_form
  - active_loop: spending_history_form
  - active_loop: null
  - slot_was_set:
    - reviewed_transactions: ["starbucks"]
  - action: utter_ask_fraudulent_transactions

- story: Customer reviews transactions and gets a new card
  steps:
  - action: utter_ask_fraudulent_transactions
  - intent: inform
  - action: action_update_transactions
  - slot_was_set:
    - reviewed_transactions: ["target", "starbucks"]
  - intent: affirm
  - action: utter_confirm_transaction_dispute
  - action: utter_replace_card
  - action: mailing_address_form
  - active_loop: mailing_address
  - active_loop: null
  - action: utter_sent_replacement
  - action: utter_anything_else

- story: Customer has something else they need help with
  steps:
  - action: utter_anything_else
  - intent: affirm
  - action: utter_help

Handling Context Switching

处理上下文切换

通常,用户不会回答你向他们询问的信息,而是用无关的问题偏离快乐的道路。使用CDD了解用户的不愉快路径,您可以创建处理上下文切换的故事。

Using Rules for Context Switching

在某些情况下,例如单回合会话,您可以使用规则而不是通过故事来处理上下文切换。
考虑一下这个对话场景:

在这个例子中,用户在支付他们的信用卡账单时,要求查询他们的账户余额,然后被引导回信用卡支付形式。因为无论上下文如何,请求帐户余额都会得到相同的响应,所以您可以创建一个规则,该规则将在现有流程中自动触发:

rules:
- rule: Check my account balance
  steps:
  - intent: check_account_balance
  - action: action_get_account_balance

默认情况下,表单将继续保持活动状态,并重新提示输入必要的信息,而无需创建额外的训练故事。

Using Stories for Context Switching

当用户的交互需要多次对话时,您需要编写额外的故事来处理上下文切换。如果您有两个不同的会话流,并且希望用户能够在这两个流之间切换,那么您需要创建故事,指定切换将如何发生以及如何维护上下文。

例如,如果要在用户请求时切换上下文,然后在该请求完成后返回到原始流:

您需要创建一个描述此上下文切换交互的故事:

stories:
- story: Context switch from credit card payment to money transfer
  steps:
  - intent: pay_credit_card
  - action: credit_card_payment_form
  - active_loop: credit_card_payment_form
  - intent: transfer_money                         # - user requests a money transfer
  - active_loop: null                              # - deactivate the credit card form
  - action: transfer_money_form                    # - switch to the money transfer form
  - active_loop: transfer_money_form
  - active_loop: null
  - action: utter_continue_credit_card_payment     # - once the money transfer is completed,
                                                   #   ask the user to return to the
                                                   #   credit card payment form

Managing Conversation Data Files

管理会话数据文件

您可以将训练数据作为单个文件或包含多个文件的目录提供给Rasa开源。在编写故事和规则时,通常最好根据所代表的对话类型创建单独的文件。

例如,您可以创建聊天文件chitchat.yml用于处理聊天和常见问题,faqs.yml用于问答的常见问题。有关复杂助手中的故事文件管理示例,请参阅我们的rasa演示机器人。

Using Interactive Learning

交互式学习通过与机器人对话并提供反馈,使编写故事变得简单。这是一个探索你的机器人能做什么的强大方法,也是修复它所犯错误的最简单方法。基于机器学习的对话的一个优点是,当你的机器人还不知道如何做某事时,你可以直接教它!

在Rasa开源中,您可以使用Rasa interactive在命令行中运行交互式学习。RASAX为交互式学习提供了一个UI,您可以使用任何用户对话作为起点。请参见Rasa X文档中的“与机器人对话”。

Command-line Interactive Learning

CLI命令rasa interactive将在命令行上启动交互式学习。如果您的机器人有自定义操作,请确保在单独的终端窗口中运行操作服务器。

在交互模式下,您将被要求在bot继续之前确认每个意图和动作预测。下面是一个例子:

? Next user input:  hello

? Is the NLU classification for 'hello' with intent 'hello' correct?  Yes

------
Chat History

 #    Bot                        You
────────────────────────────────────────────
 1    action_listen
────────────────────────────────────────────
 2                                    hello
                         intent: hello 1.00
------

? The bot wants to run 'utter_greet', correct?  (Y/n)

您将能够在对话的每个步骤中看到对话历史记录和插槽值。

如果键入y以批准预测,则bot将继续。如果键入n,您将有机会在继续之前更正预测:

? What is the next action of the bot?  (Use arrow keys)
 » <create new action>
   1.00 utter_greet
   0.00 ...
   0.00 action_back
   0.00 action_deactivate_loop
   0.00 action_default_ask_affirmation
   0.00 action_default_ask_rephrase
   0.00 action_default_fallback
   0.00 action_listen
   0.00 action_restart
   0.00 action_session_start
   0.00 action_two_stage_fallback
   0.00 utter_cheer_up
   0.00 utter_did_that_help
   0.00 utter_goodbye
   0.00 utter_happy
   0.00 utter_iamabot

在任何时候,您都可以使用Ctrl-C访问菜单,允许您创建更多的故事,并从迄今为止创建的故事中导出数据。

? Do you want to stop?  (Use arrow keys)
 » Continue
   Undo Last
   Fork
   Start Fresh
   Export & Quit

rasa 官网链接

https://rasa/docs/rasa/generating-nlu-data

Rasa系列博客:

  • 业务对话机器人Rasa 3.x Internals及Rasa框架定制实战
  • 业务对话机器人Rasa核心算法DIET及TED论文详解
  • 业务对话机器人Rasa 3.x部署安装初体验
  • 业务对话机器人Rasa 3.x Playground
  • 业务对话机器人Rasa 3.x Command Line Interface
  • 业务对话机器人Rasa 3.x 命令 rasa shell 及rasa run
  • 业务对话机器人Rasa 3.x 命令rasa run actions、rasa test、rasa data split 、rasa data convert nlu
  • 业务对话机器人Rasa 3.x 命令rasa data migrate、rasa data validate、rasa export、rasa evaluate markers、rasa x
  • 业务对话机器人Rasa 3.x 会话驱动开发(Conversation-Driven Development)
  • 业务对话机器人Rasa 3.x 生成自然语言理解NLU数据

更多推荐

Transformer课程 业务对话机器人Rasa 3.x 写入会话数据(Writing Conversation Data)