设计故事

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

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

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

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

1 stories:
2 - story: Greeting and ask user how they're doing
3 steps:
4 - intent: greet
5 - action: utter_greet
6 - action: utter_ask_how_doing
7 - intent: doing_great
8 - action: utter_happy

管理对话流程

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

何时使用插槽来影响对话

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

需要将影响对话的插槽添加到您的故事或规则中。这也适用于插槽是由自定义操作设置的情况。例如,您可以使用由自定义操作设置的布尔槽来根据其值使用以下故事控制对话流:

 1 stories:
2 - story: Welcome message, premium user
3 steps:
4 - intent: greet
5 - action: action_check_profile
6 - slot_was_set:
7 - premium_account: true
8 - action: utter_welcome_premium
9
10 - story: Welcome message, basic user
11 steps:
12 - intent: greet
13 - action: action_check_profile
14 - slot_was_set:
15 - premium_account: false
16 - action: utter_welcome_basic
17 - action: utter_ask_upgrade

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

实现分支逻辑

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

如果某个值仅用于确定机器人的响应,请考虑将决策逻辑嵌入自定义操作中,而不是在您的故事中使用特征化槽。这有助于降低整体复杂性并使您的故事更易于管理。

例如,您可以转换这些故事:

 1 stories:
2 - story: It's raining now
3 steps:
4 - intent: check_for_rain
5 - action: action_check_for_rain
6 - slot_was_set:
7 - raining: true
8 - action: utter_is_raining
9 - action: utter_bring_umbrella
10
11 - story: It isn't raining now
12 steps:
13 - intent: check_for_rain
14 - action: action_check_for_rain
15 - slot_was_set:
16 - raining: false
17 - action: utter_not_raining
18 - action: utter_no_umbrella_needed

合成一个故事是:

1 stories:
2 - story: check for rain
3 steps:
4 - intent: check_for_rain
5 - action: action_check_for_rain

在actions文件里定义:

1 def run(self, dispatcher, tracker, domain):
2 is_raining = check_rain()
3 if is_raining:
4 dispatcher.utter_message(template="utter_is_raining")
5 dispatcher.utter_message(template="utter_bring_umbrella")
6 else:
7 dispatcher.utter_message(template="utter_not_raining")
8 dispatcher.utter_message(template="utter_no_umbrella_needed")
9 return []

如果该值用于影响前进的动作流,请返回一个特征化槽来确定故事。例如,如果您想收集有关新用户的信息,但不收集回访用户的信息,您的故事可能如下所示:

 1 stories:
2 - story: greet new user
3 steps:
4 - intent: greet
5 - action: check_user_status
6 - slot_was_set:
7 - new_user: true
8 - action: utter_greet
9 - action: new_user_form
10 - active_loop: new_user_form
11 - active_loop: null
12
13 - story: greet returning user
14 steps:
15 - intent: greet
16 - action: check_user_status
17 - slot_was_set:
18 - new_user: false
19 - action: utter_greet
20 - action: utter_how_can_help

使用 OR 语句和检查点

OR 语句检查点 可用于减少您必须编写的故事数量。但是,应谨慎使用它们。过度使用 OR 语句或检查点会减慢训练速度,创建过多的检查点会使您的故事难以理解。

OR 语句

在机器人以相同方式处理不同意图的故事中,您可以使用 OR 语句作为创建新故事的替代方法。

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

 1 stories:
2 - story: newsletter signup
3 steps:
4 - intent: signup_newsletter
5 - action: utter_ask_confirm_signup
6 - intent: affirm
7 - action: action_signup_newsletter
8
9 - story: newsletter signup, confirm via thanks
10 steps:
11 - intent: signup_newsletter
12 - action: utter_ask_confirm_signup
13 - intent: thanks
14 - action: action_signup_newsletter

用 OR 语句合并成一个故事:

1 stories:
2 - story: newsletter signup with OR
3 steps:
4 - intent: signup_newsletter
5 - action: utter_ask_confirm_signup
6 - or:
7 - intent: affirm
8 - intent: thanks
9 - action: action_signup_newsletter

检查点

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

 1 stories:
2 - story: beginning of conversation
3 steps:
4 - intent: greet
5 - action: utter_greet
6 - intent: goodbye
7 - action: utter_goodbye
8 - checkpoint: ask_feedback
9
10 - story: user provides feedback
11 steps:
12 - checkpoint: ask_feedback
13 - action: utter_ask_feedback
14 - intent: inform
15 - action: utter_thank_you
16 - action: utter_anything_else
17
18 - story: user doesn't have feedback
19 steps:
20 - checkpoint: ask_feedback
21 - action: utter_ask_feedback
22 - intent: deny
23 - action: utter_no_problem
24 - action: utter_anything_else

检查点旨在使在许多不同的故事中重用某些对话部分变得更容易。强烈建议不要在现有检查点内使用检查点,因为这会显着增加训练时间并使故事难以理解。

在故事中创造逻辑中断

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

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

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

处理丢失的信用卡涉及一系列子任务,即检查欺诈交易的消费历史,确认更换卡的邮寄地址,然后跟进用户的任何额外请求。在此对话弧中,机器人会在多个位置提示用户输入,从而创建需要考虑的分支路径。

例如,当提示“utter_ask_fraudulent_transactions”时,如果没有任何适用,用户可能会以“拒绝”意图进行响应。当被问及机器人是否可以帮助他们做任何其他事情时,用户还可以选择以“拒绝”意图进行响应。

我们可以将这个长故事分成几个小故事:

 1 stories:
2 - story: Customer loses a credit card
3 steps:
4 - intent: card_lost
5 - action: utter_card_locked
6 - action: spending_history_form
7 - active_loop: spending_history_form
8 - active_loop: null
9 - slot_was_set:
10 - reviewed_transactions: ["starbucks"]
11 - action: utter_ask_fraudulent_transactions
12
13 - story: Customer reviews transactions and gets a new card
14 steps:
15 - action: utter_ask_fraudulent_transactions
16 - intent: inform
17 - action: action_update_transactions
18 - slot_was_set:
19 - reviewed_transactions: ["target", "starbucks"]
20 - intent: affirm
21 - action: utter_confirm_transaction_dispute
22 - action: utter_replace_card
23 - action: mailing_address_form
24 - active_loop: mailing_address
25 - active_loop: null
26 - action: utter_sent_replacement
27 - action: utter_anything_else
28
29 - story: Customer has something else they need help with
30 steps:
31 - action: utter_anything_else
32 - intent: affirm
33 - action: utter_help

rasa 如何写一个故事的更多相关文章

  1. 一个故事带你理解if __name__ == '__main__'

    如果你刚刚接触python,相信会在看别人的程序的时候会遇到if __name__ == '__main__'酱紫的语法,如果当时没看懂现在也一知半解的话,看下去,本文可以帮你解决这个问题. 大家都知 ...

  2. IP概念盛行的背后:资本在狂欢,电影想哭泣 IP,英文“Intellectual Property”的缩写,直译为“知识产权”。它的存在方式很多元,可以是一个故事,也可以是某一个形象,运营成功的IP可以在漫画、小说、电影、玩具、手游等不同的媒介形式中转换。

    IP概念盛行的背后:资本在狂欢,电影想哭泣 IP容易拉投资.谈合作,甚至还能简化宣发途径,越来越多的人涌入了电影这个产业,争抢IP成为他们进入行业的最快捷的方法.IP盛行暴露出的另一个问题是国产电影原 ...

  3. 写一个体验良好的git commit

    一直在使用git也看过格式各样commit log , review 代码时最刺激的是看到这类 "." 应付差事,还有 "fix bug","fix& ...

  4. (转)一个故事讲完https

    (转)一个故事讲完https 2 1  序言 今天来聊一聊https 安全传输的原理. 在开始之前,我们来虚构两个人物, 一个是位于中国的张大胖(怎么又是你?!), 还有一个是位于米国的Bill (怎 ...

  5. 一个故事讲懂vue父子组件传值

    作者:李佳明同学链接:https://www.jianshu.com/p/2272b6ca0f0c 一个故事讲懂vue父子组件传值 讲故事前先讲代码 父组件向子组件传值 父组件数据传递给子组件可以通过 ...

  6. 2019-5-24-WPF-源代码-从零开始写一个-UI-框架

    title author date CreateTime categories WPF 源代码 从零开始写一个 UI 框架 lindexi 2019-05-24 15:54:36 +0800 2018 ...

  7. 也谈如何写一个Webserver(-)

    关于如何写一个Webserver,很多大咖都发表过类似的文章.趁着这个五一假期,我也来凑个份子. 我写Webserver的原因,还得从如何将http协议传送的消息解析说起.当时,我只是想了解一下htt ...

  8. 一个故事看懂HTTPS

    我是一个浏览器,每到夜深人静的时候,主人就打开我开始学习. 为了不让别人看到浏览记录,主人选择了"无痕模式". 但网络中总是有很多坏人,他们通过抓包截获我和服务器的通信,主人干了什 ...

  9. 怎样写一个webpack loader

    div{display:table-cell;vertical-align:middle}#crayon-theme-info .content *{float:left}#crayon-theme- ...

随机推荐

  1. P4774-屠龙勇士-扩展中国剩余定理

    屠龙勇士 很久很久以前,巨龙突然出现,带来了灾难带走公主又消失不见.王国十分危险,世间谁最勇敢,一位英雄出现-- 学习于该大佬博客 那么你就是这位英雄,不过不同的是,你面对的是一群巨龙,虽然巨龙都不会 ...

  2. 第二十二篇 -- 事件与信号(自定义label信号的双击功能)

    在第六篇中已经学习过了自定义信号的相关内容了,那一篇中讲的是自定义类中的自定义信号,类和信号都是自己定义的.那么今天想要学习的是事件处理和信号的关系.如同Label标签,它本身有很多的信号,但是它没有 ...

  3. react踩坑笔记

    1.create-react-app中配置webpack // 方法一:将项目的配置文件抽取到项目中,即运行: npm run eject // 方法二:使用react-app-rewired 2.c ...

  4. JAVASE:01数据类型及其拓展

    JAVASE:01数据类型及其拓展 八大基本数据类型 与c不同的地方:long类型后加L:float类型后加F: public class Demo02 { public static void ma ...

  5. 洛谷P3052题解

    题面 看起来非常简单,但是细节多的一批的状压DP入门题. 我设 \(f_i\) 为 \(i\) 状态时最小分组数, \(g_i\) 为 \(i\) 状态时最后一组剩余空间. 对于每一个 \(i\) , ...

  6. 靶机DC-2 rbash绕过+git提权

    这个靶机和DC-1一样,一共5个flag.全部拿到通关. root@kali:/home/kali# nmap -sP 192.168.1.* 先扫一下靶机的IP地址,拿到靶机的地址为192.168. ...

  7. Git-06-远程仓库

    本地仓库推送到远程仓库 1 创建ssh key 用户主目录下运行如下命令,然后一路回车 ssh-keygen -t rsa -C "1029612787@qq.com" 2 找到公 ...

  8. MySQL5.6忘记root密码

    第一步 修改 /etc/my.conf 文件 添加 skip-grant-tables 到 [mysqld] 下面就可以 这个参数的意思是设置为无需密码验证的登录 登录之后,可以添加用户,可以修改密码 ...

  9. DVWA(三):SQL injection 全等级SQL注入

    (本文不定期更新) 一.所需环境: 1.DVWA 2.web环境 phpstudy/wamp 3.burp suite 二.SQL注入产生的原因: 程序员在编写代码的时候,没有对用户输入数据的合法性进 ...

  10. 嵌入式ARM汇编详解

    文章目录 零.预备知识 1.ARM与X86 2.ARM中指令的执行 3.ARM的九种寻址方式 立即数寻址 寄存器寻址 寄存器间接寻址 寄存器偏移寻址 寄存器基址变址寻址 批量寄存器寻址 相对寻址 堆栈 ...