Rasa课程、Rasa培训、Rasa面试、Rasa实战系列之Rasa全新全局词槽映射的 3 大方法

Rasa课程、Rasa培训、Rasa面试、Rasa实战系列之Rasa全新全局词槽映射的 3 大方法

在 Rasa 3.0 中,Rasa启用了“全局词槽映射”,可以更好地控制聊天机器人中的对话信息。

词槽在对话过程中存储信息,例如用户名、帐号以及是否预订航班或火车。词槽映射是收集和准备此信息的过程,以便对话策略可以使用它来选择下一个操作或将其插入机器人的响应模板中。在 Rasa 3.0 中,我们启用了“全局词槽映射”,可以更好地控制信息。

在这篇博文中,我们将向您展示三种在 Rasa 助手中使用全局词槽映射来解决常见问题和解锁新功能的新方法。

根据外部信息决定你的机器人应该做什么

假设我们希望机器人根据一天中的时间表现出不同的行为。例如,如果用户要求与人聊天,而时间是在办公时间之外,机器人应该告诉办公时间并继续尝试解决用户的问题。但如果是在办公时间内,机器人应该将对话交给人工操作员。

这是一个高级决策的示例,因此我们希望使用影响策略的特征化词槽。因此,我们定义了一个office_open词槽,在办公室开放时使用插槽为True,否则为False。

slots:
  office_open:
    type: bool
    influence_conversation: true
    mappings:
    - type: custom
      action: action_set_office_open

slot 的值在 action_set_office_open中设置,我们需要在 action server 中定义

class ActionSetOfficeOpen(Action):


    def name(self) -> Text:
        return "action_set_office_open"


    def run(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any]
    ) -> List[Dict[Text, Any]]:
        office_open = random.choice([True, False]) # just for debugging
        return [
            SlotSet("office_open", office_open)
        ]

此代码现在将在每个用户消息之后运行,使得office_open保持最新,名称“action”可能会造成混淆,这不是策略预测的行动,它只是在 NLU 管道末端运行的一个代码。

有了office_open词槽,我们现在可以在两个简短的规则中定义机器人的行为***:

- rule: Deal with request_human at office hours
  steps:
  - intent: request_human
  - slot_was_set:
    - office_open: true
  - action: utter_handover_to_human  # Just an example for the demo


- rule: Deal with request_human outside office hours
  steps:
  - intent: request_human
  - slot_was_set:
    - office_open: false
  - action: utter_office_hours

在我们在 Rasa 中引入全局词槽映射之前,这是不可能的。您要么必须训练策略执行填充office_open位置的自定义操作,要么必须在一个自定义操作中处理决策,该自定义操作要么将工作时间传递给人类,要么打印办公时间。

规则的编写方式与故事相同,但它们通常仅代表对话的片段。每当机器人遇到对话与规则匹配的情况时,RulePolicy 就会执行规则定义的下一个操作。

使用一个dummy词槽同时填充多个词槽

词槽映射的常用 YAML 格式表明所有词槽都是独立填充的,并且每个词槽都有一个映射(自定义词槽填充操作)。但是,对于大多数应用程序,槽值是相互依赖的,最好声明一个执行所有映射的函数。

为此,您使用自定义映射定义一个虚拟词槽

slots:
  dummy:
    type: any
    influence_conversation: false
    mappings:
    - type: custom
      action: global_slot_mapping

并使用为此目的编写的自定义操作从global_slot_mapping函数中填充所有槽。
示例:以提取实体得分较低为条件设置策略
借助office_open词槽,我们让机器人对外部信息(一天中的时间)做出反应。但是由于词槽映射动作可以访问对话历史(tracker对象),我们还可以根据对话的属性设置词槽,包括通常不进入策略的信息,例如实体提取置信度分数。

假设我们向我们的机器人添加了一个表单,机器人在该表单中询问项目类型以及用户丢失物品时的最后一个已知位置。现在词槽和表单在域中定义为

slots:
  dummy:
    type: any
    mappings:
    - type: custom
      action: global_slot_mapping
  # Featurized slots for policies
  office_open:
    type: bool
    influence_conversation: true
    mappings:
    - type: custom
  low_entity_score:
    type: bool
    influence_conversation: true
    initial_value: false
    mappings:
    - type: custom
  # Unfeaturized slots for forms
  lost_item_type:
    type: text
    influence_conversation: false
    mappings:
    - type: custom
  last_known_item_location:
    type: text
    influence_conversation: false
    mappings:
    - type: custom
  # Unfeaturized slots for NLG
  unclear_entity_value:
    type: text
    influence_conversation: false
    mappings:
    - type: custom


forms:
  main_form:
    required_slots:
      - lost_item_type
      - last_known_item_location

您会看到只有dummy词槽具有词槽映射操作。此操作现在负责整个映射过程:

class GlobalSlotMapping(Action):


    def name(self) -> Text:
        return "global_slot_mapping"


    def run(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any]
    ) -> List[Dict[Text, Any]]:
        new_slot_values: Dict[Text, Any] = dict()


        # Office hours
        new_slot_values["office_open"] = random.choice([True, False])


        # Entity mapping and low entity score handling
        low_entity_score: bool = False
        for entity_type, value, score in get_entity_data(tracker.latest_message):
            print(f"{
      
      entity_type}: {
      
      value} ({
      
      score})")
            if score < 0.98:
                low_entity_score = True
                new_slot_values["unclear_entity_value"] = value
            else:
                if entity_type == "item":
                    new_slot_values["lost_item_type"] = value
                elif entity_type == "location":
                    new_slot_values["last_known_item_location"] = value
        new_slot_values["low_entity_score"] = low_entity_score


        return [
            SlotSet(name, value)
            for name, value in new_slot_values.items()
        ]

现在我们可以定义一个规则来处理低提取分数:

- rule: Handle low entity score in main form
  condition:
  - active_loop: main_form
  steps:
  - intent: inform
  - slot_was_set:
    - low_entity_score: true
  - action: utter_entity_unclear
  - action: main_form
  - active_loop: main_form

我们的机器人可以进行以下对话:

Your input ->  hi                                                                                                                                                                                      
Hello! How can I help you?
I am Lost & Found Bot and can help you find things.
Your input ->  i lost my umbrella                                                                                                                                                                      
Where did you last see your item?
Your input ->  on the tran                                                                                                                                                                             
I'm not sure what you mean by 'tran'.
Where did you last see your item?
Your input ->  i mean, on the train                                                                                                                                                                    
You are looking for 'umbrella', last seen at 'train'

注意实体提取器的置信度分数不一定可靠。很容易发生实体被错误地提取并且仍然具有非常高的分数的情况。重新训练您的模型也可能会极大地改变置信度分数。

使用词槽生成响应

我们刚刚看到了如何定义全局词槽映射以通过特征词槽影响策略的决策。或者,我们可以跳过信息流图中的策略,仅通过未特征化的词槽影响响应生成。

给定响应模板 ( utter_*),词槽可以通过两种方式影响机器人的响应:用于响应条件或用作变量。

示例:处理重复的问题

如果用户一次又一次地问同样的问题,你可能希望你的机器人给出更详细的答案。例如,如果用户不断询问机器人的能力,而机器人的回答是utter_abilities,您不希望机器人总是说完全相同的话。但您也不想在响应模板之间随机选择。使用全局词槽映射,您可以通过跟踪机器人utter_abilities执行的频率 、将此信息放入词槽num_utter_abilities中,并定义此响应模板以使其以该词槽为条件来做到这一点。

utter_abilities响应可能是:

responses:
  utter_abilities:
  - text: "I am Lost & Found Bot and can help you find things."
    condition:
      - type: slot
        name: num_utter_abilities
        value: 0
  - text: "I can help you find things that you've lost either on a train or some other place in town."
    condition:
      - type: slot
        name: num_utter_abilities
        value: 1
  - text: "Actually, I'm just a demo, so don't expect me to really find something."
    condition:
      - type: slot
        name: num_utter_abilities
        value: 2
  - text: "I can't do anything beyond what I already mentioned, sorry."

num_utter_abilities在词槽映射函数中使用以下代码使词槽保持最新:

class GlobalSlotMapping(Action):


    def name(self) -> Text:
        return "global_slot_mapping"


    def run(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any]
    ) -> List[Dict[Text, Any]]:
        new_slot_values: Dict[Text, Any] = dict()


        # ...


        # Count how often the bot executed `utter_abilities`
        num_utter_abilities = 0
        for event in tracker.applied_events():
            if event_is_action(event, "utter_abilities"):
                num_utter_abilities += 1
        new_slot_values["num_utter_abilities"] = num_utter_abilities


        return [
            SlotSet(name, value)
            for name, value in new_slot_values.items()
        ]

我们必须定义一些新的意图和适当的规则,以便您的机器人正确响应:

- rule: Respond to ask_what_can_do
  steps:
  - intent: ask_what_can_do
  - action: utter_abilities
  - intent: tell_me_more     # for this to work, set `restrict_rules: false` for the RulePolicy
  - action: utter_abilities
  - intent: tell_me_more
  - action: utter_abilities

我们的机器人可以进行以下对话:

Your input ->  hi                                                                                      
Hello! How can I help you?
I am Lost & Found Bot and can help you find things.
Your input ->  what can you do?                                                                        
I can help you find things that you've lost either on a train or some other place in town.
Your input ->  what else?                                                                              
Actually, I'm just a demo, so don't expect me to really find something.
Your input ->  tell me more                                                                            
I can't do anything beyond what I already mentioned, sorry.

这是一个非常简单的应用程序。但原则上,您可以使用词槽映射来根据您可以从对话历史记录(或外部来源)中提取的任何信息来调整您的响应模板。例如,您可以在 NLU 管道中添加一个轻量级分类器,并根据用户的写作风格调整您的响应。但是请记住,仅将您的机器人的响应设置为您确定了解用户的事情。

结论

如您所见,全局插词槽映射为 Rasa Open Source 引入了许多新功能,当您第一次了解它们时,这些新功能可能不会立即显现出来。它们是一项灵活而强大的新功能,我们期待看到它们可以为您解决各类问题。

Rasa课程资源发布

Gavin大咖简介

星空智能对话机器人创始人、AI通用双线思考法作者,现工作于硅谷顶级的AI实验室。专精于Conversational AI. 在美国曾先后工作于硅谷最顶级的机器学习和人工智能实验室

Gavin大咖微信:NLP_Matrix_Space

联系电话:+1 650-603-1290

联系邮箱:[email protected]

助教老师微信:Spark_AI_NLP
在这里插入图片描述
在这里插入图片描述

Rasa 3.x系列博客分享

猜你喜欢

转载自blog.csdn.net/duan_zhihua/article/details/124349826