目录
When to Write Stories vs. Rules#
Managing the Conversation Flow#
When to Use Slots to Influence Conversatiov
Using OR statements and Checkpoints#
Creating Logical Breaks in Stories#
Using Rules for Context Switching#
Using Stories for Context Switching#
Managing Conversation Data Files#
Command-line Interactive Learning#
Writing Conversation Data
对话数据包括故事和规则,它们构成Rasa助理对话管理模型的培训数据。编写良好的对话数据使你的助手能够可靠地遵循你规划的对话路径,并将其推广到意想不到的路径。
设计的故事#
在设计故事时,需要考虑两组对话互动:愉快的路径和不愉快的路径。愉快路径描述用户按照预期的对话流程进行操作,并在提示时始终提供必要的信息。然而,用户经常会在提问、闲聊或其他问题上偏离愉快的路径。我们称之为不快乐路径。
对于机器人来说,优雅地处理不愉快的路径非常重要,但是也不可能预测给定用户可能选择的路径。通常,当设计不愉快的路径时,开发人员会尝试考虑每一个可能的分叉路径。为状态机中的每一个可能的状态(其中许多状态永远无法达到)进行规划需要大量的额外工作,并显著增加训练时间。
相反地,我们建议在设计不愉快的路径时采用对话驱动的开发方法。对话驱动的开发促进尽早与测试用户共享您的机器人,并收集真实的对话数据,准确地告诉您用户是如何偏离愉快的路径的。从这些数据中,您可以创建故事来完成用户的请求,并开始考虑如何引导他们回到满意的路径。
When to Write Stories vs. Rules#
规则是对话管理器使用的一种训练数据,用于处理应该始终遵循相同路径的对话片段。
规则在实现时很有用:
单回合互动:有些信息不需要任何上下文来回答。规则是将意图映射到响应的一种简单方法,可以为这些消息指定固定的答案。
回退行为:与回退分类器结合使用,您可以编写规则,以响应具有特定回退行为的低可信度用户消息。
表单:激活和提交表单通常遵循一个固定的路径。您还可以编写规则来处理表单期间的意外输入。
因为规则不能概括为看不见的对话,所以您应该将它们保留为单回合的对话片段,并使用故事来训练多回合的对话。
一个规则的例子是,机器人返回一个固定的响应“utter_greet”给用户消息,意图是“greet”:
rules:
- rule: Greeting Rule
steps:
- intent: greet
- action: utter_greet
For multiple-turn interactions, you should define a story, for example:
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 Conversatiov
插槽充当机器人的内存。在定义插槽时,可以定义插槽是否应该影响对话。属性influence_conversation设置为false的插槽只能存储信息。属性influence_conversation设置为true的插槽可以根据对话流中存储的信息影响对话流。
需要在你的故事或规则中添加影响对话的插槽。这也适用于由自定义操作设置槽位的情况。例如,你可以使用一个自定义操作设置的布尔槽来根据它的值来控制对话流,使用下面的故事:
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
In cases where you don't want a slot to affect the conversation flow, you should set the slot's property influence_conversation
to false
. You do not need to include slot_was_set
events for slots in your stories which do not influence the conversation.
Implementing Branching Logic#
在编写故事时,有时下一个操作将依赖于自定义操作中返回的值。在这些情况下,在返回插槽和直接使用自定义操作代码来影响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
into a single story:
stories:
- story: check for rain
steps:
- intent: check_for_rain
- action: action_check_for_rain
with the custom action code:
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 []
In cases where the value is used to influence the action flow going forward, return a featurized slot to determine the stories. For example, if you want to collect information about new users, but not returning ones, your stories might look like this:
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语句作为创建新故事的替代选择。
例如,你可以合并这两个故事:
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
into a single story with an OR statement:
stories:
- story: newsletter signup with OR
steps:
- intent: signup_newsletter
- action: utter_ask_confirm_signup
- or:
- intent: affirm
- intent: thanks
- action: action_signup_newsletter
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#
在设计会话流程时,通常会创建一个从开始到结束的完整会话交互的长故事示例。在许多情况下,这将增加用于解释分支路径所需的训练故事的数量。相反,考虑将较长的故事分成处理子任务的较小对话块。
处理信用卡丢失的快乐故事可能是这样的:
处理丢失的信用卡涉及一系列的子任务,即检查欺骗性交易的消费历史,确认替换卡的邮寄地址,然后跟踪用户的任何额外请求。在这个对话弧中,有几个地方机器人会提示用户输入,从而创建需要解释的分支路径。
例如,当提示“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
By default, the form will continue to stay active and re-prompt for the necessary information, without having to create an additional training story.
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 Open Source。在编写故事和规则时,根据所表示的对话类型创建单独的文件通常是一个好主意。
例如,您可以创建一个文件聊天。yml处理闲聊,和一个常见问题。常见问题的yml文件。请参考我们的rasa-demo bot,了解复杂助手中故事文件管理的示例。8
Using Interactive Learning#
交互式学习通过与你的机器人交谈并提供反馈,使编写故事变得很容易。这是一种强大的方法来探索你的机器人可以做什么,以及最简单的方法来修复它所犯的任何错误。基于机器学习的对话的一个优点是,当你的机器人还不知道如何做某事时,你可以教它!
在Rasa Open Source中,您可以使用Rasa interactive在命令行中运行交互式学习。Rasa X为交互式学习提供了一个UI,您可以使用任何用户对话作为起点。参见与Rasa X文档中的机器人对话。
Command-line Interactive Learning#
CLI命令rasa interactive将在命令行中启动交互式学习。如果您的机器人有自定义操作,请确保也在单独的终端窗口中运行您的操作服务器。
在互动模式下,你将被要求在机器人继续之前确认每一个意图和行动预测。这里有一个例子:
? 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来批准一个预测,机器人将继续运行。如果你输入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_revert_fallback_events
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