对话系统Rasa - 对话设计 [翻译]

对话元素

对话元素是常见的会话元素。我们使用三个不同的抽象层次来讨论人工智能助手。这对产品团队很有帮助,这样就有了一种通用语言,设计师、开发人员和产品所有者可以使用它来讨论问题和新特性。

  • 最高等级:用户目标
  • 中间等级:对话元素
  • 最低等级:意图,实体,动作,插槽,和模板(intents, entities, actions, slots, and templates)

注意:

一些聊天机器人工具会使用intent描述用户目标。这是令人困惑的,因为只有一些消息才会告诉你用户的目标是什么。如果一个用户说“I want to open an account”(intent: open_account),那么很显然目标也是这个。但是,很多用户消息,如(“yes”, “what does that mean?", “I don't know”) 并没有明确的目标。在Rasa,每一个消息都有一个intent,而用户的目标描述的是一个人想要获得什么。

闲聊

闲聊指的是一来一回没有明确目标的谈话。包括问候,感谢,回应和话题外的闲聊。

问候

问候和再见是最简单的交流。每个对话系统都会遇到它们:

1
2
3
4
5
6
7
8
user> hello
bot> hi, how are you?

user> how are you?
bot> I am well, and you?

user> goodbye
bot> bye bye!

为了能够正确的针对问候和再见提供回复,需要针对它们分别定义回复语。如果你总是想要一样的回复,你可以使用MappingPolicy来触发这些回复。

在你的domain文件中,添加trigger元数据,到相应的intents上:

1
2
3
intents:
	- greet: {triggers: utter_greet}
	- goodbye: {triggers: utter_goodbye}

并且确认mapping policy出现在config.yml文件中。

1
2
3
policies:
	- name: "MappingPolicy"
	...

如果你想要实现更少限制的行为,可以使用常规的stories,而不用mapping policy。如下:

1
2
3
4
* greet
	- utter_greet
* goodbye
	- utter_ask_why_leaving

确认

用户通常会对助手的话做出反应,并期望得到确认。确认的表述可以简单到只竖起一个大拇指。助手需要向用户保证他们收到了消息。可以针对致谢实现特定的反馈。

1
2
3
4
5
6
user> woah that's expensive!
bot> we offer good value.
bot> would you like to continue getting a quote.

user> that's awesome!
bot> glad you think so :)

首先,需要NLU数据定义对应的响应和确认信息:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
## intent:acknowledge
- ok
- got it
- understood
- k

## intent:opinion+positive
- nice!
- excellent
- that's awesome

## intent:opinion+negative
- ugh
- that sucks
- woah! that's [expensive](price)

那么在创建故事的时候,如下:

1
2
3
4
5
6
7
8
## price reaction
* opinion+negative{"price": "expensive"}
  - utter_good_value
  - utter_ask_continue
  
## simple acknowledgement
* opinion+positive
  - utter_positive_feedback_reaction

题外话的闲聊

你的助手通常会接收到意料之外的输入。我们称为题外话的闲聊。(chitchat)。对用户的每个输入进行合理的顺畅的响应是不可能办到的,但是可以通过简单的确认,让用户知道我们已经接收到了消息。一个策略是从用户中收集训练数据,并定义意图和响应。参见 Explaining Possibilities,解释如何处理意料之外的输入。

1
2
3
4
5
6
7
8
user> will you marry me?
bot> no

user> aahhh
bot> I feel you

user> I can juggle 7 oranges
bot> wow!

辱骂

不幸的是,用户通常会辱骂你的助手。你需要承认他们的评价,并以一种反映助手个人形象的方式作出回应。如果用笑话进行回应,那么会鼓励用户继续辱骂的言语,因此要仔细考虑你的回应。你在这篇论文中( this paper)可以查看更多相关内容。

1
2
user> stupid bot
bot> that's not very nice

针对辱骂处理的最简单的方式是建立insult意图,并利用mapping policy进行响应。如下domain文件中:

1
2
intents:
  - insult: {triggers: utter_respond_insult}

在配置文件中:

1
2
3
policies:
  - name: "MappingPolicy"
  ...

完成任务

简单问题

简单问题,或FAQs,不管之前的对话内容是什么,应该接收到相同的答案。用户会问一些基本的问题,而你的助手应该可靠的回答这些问题。

1
2
3
4
5
user> what's your email address?
bot> it's contact@example.com

user> do you have a loyalty program?
bot> unfortunately we don't

与问候类似,可以使用mapping policy实现。

业务逻辑

注意:这里有详细的tutorial,介绍如何使用Rasa Forms,实现slot filling和业务逻辑。here

你的AI助手通常需要按照一些预定义的业务逻辑执行。为了指出如何帮助用户,通常你的助手会询问一些问题。获取得到的答案会影响到之后的会话。举个例子,一些产品只适用于特定区域或特定年龄段的用户。将相关逻辑实现到form内部,与学习的行为相分离是一种比较好的实现方式。一个独立的form可以覆盖所有的happy路径。(例如,用户需要提供所有需要的信息)。更多的内容可以参见:this tutorial.

1
2
3
4
5
6
7
8
9
user> I'd like to apply for a loan
bot> I'd love to help. Which state are you in?
user> Alaska
bot> Unfortunately, we only operate in the continental U.S.

user> I'd like to apply for a loan
bot> I'd love to help. Which state are you in?
user> California
bot> Thanks. Do you know what your credit score is?

关于如何利用forms实现业务逻辑,可以参见:Handling conditional slot logic

语境问题

不像针对FAQs的回答,针对语境问题的正确回复需要依赖于对话历史。这些问题指的是谈话中早些时候的一些问题,而这些问题本身就是模棱两可的。真正的用户经常会问“哪个更好?”“为什么?“。如果你的助手不理解这一点,并且只能回答诸如“哪一个储蓄账户的利率更高”这样的完整问题,这会让用户感到沮丧。“理解语境问题是二级和三级助理之间的一个关键区别( level 2 and level 3 assistants)。

1
2
3
4
5
6
7
bot> what's your email address?
user> why do you need to know that?
bot> I need your email so I can send you a confirmation

bot> are you currently a premium customer?
user> what do you mean?
bot> We have different memberships. Check your statement to see if you are a premium member.

不愉快的路径

当你的助手向用户询问想要的信息的时候,你通常会获取不是你想要的回复。举个例子,你的用户可能拒绝提供信息,他们也许纠正之前说的东西,或者用闲聊进行打断。你的助手能够处理这些边界问题是很重要的。除了你提问的你想要的信息,用户可以输入任何的话语,甚至简单的完全不管你的助手进行对话中断。这个从真实数据学习构建助手的关键原因。

针对不愉快的路径收集训练数据最好的方式是使用Interactive Learning.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
bot> what's your email address?
user> no.
bot> I will need your email address in order to create an account.
user> what's your email address?

bot> what's your email address?
user> work@example.com
bot> thanks, and your phone number?
user> no wait, please use personal@example.com
bot> ok, I'll use that email.
bot> thanks, and your phone number?

引导用户

隐式确认

隐式确认包括将理解的信息再次反馈给用户,让用户进行确认。这个也是让用户有个机会判断助手在理解上是不是有问题。

1
2
3
4
user> Can I get a large hawaiian and bbq pizza
bot> Sure, that's one large hawaiian and one regular bbq pizza
bot> Anything else?
user> No they should both be large

显式确认

显示确认意思是让用户明白你应该如何帮助他们。关于智能助手,要记住的一件重要事情是用户永远不会出错。当一个用户告诉你“I just moved”,即使你的助手不能够明确如何帮助他们,他们的表述也是很清楚的。如果你的助手没法明确的识别出用户的目标,可以直接要求澄清。

1
2
3
4
user> I just moved
bot> I'm not sure I understood you correctly. Do you mean ...
user> I want to cancel my contract
user> I want to update my personal details

你可以配置TwoStageFallbackPolicy,要求用户进行澄清,并将最可能的意图快速提供给用户。为了实现这点,需要配置policy,如下:

1
2
3
4
5
6
7
8
policies:
- name: TwoStageFallbackPolicy
  nlu_threshold: 0.3
  core_threshold: 0.3
  fallback_core_action_name: "action_default_fallback"
  fallback_nlu_action_name: "action_default_fallback"
  deny_suggestion_intent_name: "out_of_scope"
...

解释可能性

智能助手总是局限于帮助用户完成一组特定的任务,并且应该能够向用户解释他们能做什么。这包括对于超出范围的问题给出一致的响应。

1
2
3
4
5
6
user> What can you do?
bot> I can help you update your personal details, change your plan, and answer any questions you have about our products.

user> Can you get me a pizza?
bot> I'm afraid I can't help with that.
bot> I can help you update your personal details, change your plan, and answer any questions you have about our products.

何时对助手的适用性给出解释,需要在程序中进行设定,如:

1
2
3
4
5
6
7
8
## user asks whats possible
* ask_whatspossible
  - utter_explain_whatspossible

## user asks for something out of scope
* out_of_scope
  - utter_cannot_help
  - utter_explain_whatspossible

收集用户反馈

想要知道你的回复是不是解决了用户的问题,询问反馈是一种很好的方式。将这些反馈信息进行存储,有助于提高助手的可用性。

1
2
3
4
5
bot> Was that helpful?
user> no.
bot> Thanks. Why wasn't I able to help?
user> you didn't understand me correctly
user> you understood me, but your answers weren't very helpful.

可以利用表格收集用户反馈。为了实现这个,需要自定义表格行为,详细见:Forms

1
2
3
4
5
6
7
8
9
from rasa_sdk.action import FormAction

class FeedbackForm(FormAction):
    def name(self):
        return "feedback_form"
    
    @staticmethod
    def required_slots(tracker):
        return ["feedback", "negative_feedback_reason"]

在domain中的定义如下:

1
2
3
4
5
6
7
8
9
forms:
  - feedback_form
slots:
  feedback:
    type: bool
  feedback_reason:
    type: text
  requested_slot:
    type: text

还要确保将FormPolicy添加到configuration文件:

1
2
3
policies:
  - FormPolicy
  ...

交给人

当助手不能够帮助到用户,并且不能将对话交接给人工代理,用户会变得非常沮丧。总有一种方法可以让对话中断,并且有多重原因触发人工切换:

  • 用户要求与人对话
  • 助手陷入到理解用户的泥潭中
  • 助手理解用户想要什么,但是需要人工的参与
1
2
3
4
5
6
user> let me speak to a human
bot> let me put you in touch with someone

user> I want to cancel
bot> I'm afraid I can't help you with that.
bot> let me put you in touch with someone.

针对直接要求和人进行对话的实现可以使用mapping policy:

1
2
intents:
  - request_human: {"triggers": "action_human_handoff"}

原文链接