搬山行者

无志愁压头,有志能搬山

业余程序员的学习笔记~


使用Rasa构建对话助理-概念

目录

概念(Concepts)

训练数据(Training Data)

训练数据格式(Training Data Format)

Rasa使用YAML作为统一和可扩展的方式来管理所有训练数据,包括NLU数据、故事和规则。

可以将训练数据拆分为任意数量的YAML文件,每个文件都可以包含NLU数据、故事和规则的任意组合。 训练数据解析器使用顶级键确定训练数据类型。

域使用与训练数据相同的YAML格式,也可以拆分为多个文件或合并为一个文件。 域包括响应和表单的定义。

高层结构

每个文件可以包含一个或多个带有相应训练数据的key。 一个文件可以包含多个key,但每个key在单个文件中只能出现一次。可用的key有:

  1. version
  2. nlu
  3. stories
  4. rules

应该在所有YAML训练数据文件中指定版本key。 如果没有在训练数据文件中指定版本key,Rasa将假定您使用的安装的Rasa版本支持的最新训练数据格式规范。将跳过Rasa版本高于安装的版本的训练数据文件。 目前,Rasa 3.x的最新训练数据格式规范为3.1。

示例

以下是一个简短的示例,它将所有训练数据保存在一个文件中:

version: "3.1"

nlu:
- intent: greet
  examples: |
    - Hey
    - Hi
    - hey there [Sara](name)

- intent: faq/language
  examples: |
    - What language do you speak?
    - Do you only handle english?

stories:
- story: greet and faq
  steps:
  - intent: greet
  - action: utter_greet
  - intent: faq
  - action: utter_faq

rules:
- rule: Greet user
  steps:
  - intent: greet
  - action: utter_greet

要指定测试故事,需要将它们放入单独的文件中:

# tests/test_stories.yml
stories:
- story: greet and ask language
- steps:
  - user: |
      hey
    intent: greet
  - action: utter_greet
  - user: |
      what language do you speak
    intent: faq/language
  - action: utter_faq

测试故事使用与故事训练数据相同的格式,应放置在前缀为test_的单独文件中。

如上述示例所示,用户键和示例键后面是 (管道)符号。在YAML中, 标识具有保留缩进的多行字符串。这有助于在训练示例中保留“,”等特殊符号。

NLU训练数据(NLU Training Data)

NLU(自然语言理解)的目标是从用户消息中提取结构化信息。 通常包括用户的意图及其消息包含的任何实体。 可以将正则表达式和查找表等额外信息添加到训练数据中,以帮助模型正确识别意图和实体。

训练示例(Training Examples)

NLU训练数据由按意图分类的示例用户话语组成。 为了更容易使用意图,给它们起一个与用户想要用这个意图完成的事情相关的名字,保持小写,避免空格和特殊字符。

/ 符号保留为分隔符,用于将检索意图与响应文本标识符分开。 确保不要以你的意图的名义使用它。

实体(Entities)

实体是用户消息中的结构化信息。为了使实体提取工作,需要指定训练数据来训练ML模型,或者需要定义正则表达式来使用基于字符模式的RegexEntityExtractor提取实体。

在决定需要提取哪些实体时,请考虑助手需要哪些信息来实现其用户目标。 用户可能会提供任何用户目标都不需要的其他信息;不需要将这些提取为实体。

同义词

同义词将提取的实体映射到以不区分大小写的方式提取的文字文本以外的值。 当用户对同一事物有多种引用方式时,可以使用同义词。

nlu:
- synonym: credit
  examples: |
    - credit card account
    - credit account

正则表达式

可以使用正则表达式结合管道中的RegexFeatureizer和RegexEntityExtractor组件来改进意图分类和实体提取。

nlu:
- regex: account_number
  examples: |
    - \d{10,12}

用于意图分类的正则表达式

通过在管道中包含RegexFeatureizer组件,可以使用正则表达式来改进意图分类。 使用正则表达式Featureizer时,正则表达式不会作为对意图进行分类的规则。 它只提供了一个特征,意图分类器将使用该特征来学习意图分类的模式。 目前,所有意图分类器都利用了可用的正则表达式特性。 尝试以尽可能少的单词匹配的方式创建正则表达式.

nlu:
- regex: help
  examples: |
    - \bhelp\b

实体提取的正则表达式

如果实体具有确定性结构,可以通过以下两种方式之一使用正则表达式:

  • 正则表达式作为特征

可以使用正则表达式为NLU管道中的RegexFeatureizer组件创建特征。

当正则表达式与RegexFeatureizer一起使用时,正则表达式的名称并不重要。 使用RegexFeatureizer时,正则表达式提供了一个功能,可以帮助模型学习符合正则表达式的意图/实体和输入之间的关联。

用于实体提取的正则表达式功能目前仅受CRFEntityExtractor和DIETClassifier组件的支持。 其他实体提取器,如MitieEntityExtractor或SpacyEntityExtractor,不会使用生成的功能,它们的存在也不会提高这些提取器的实体识别率。

  • 基于规则的实体提取正则表达式

可以使用NLU管道中的RegexEntityExtractor组件将正则表达式用于基于规则的实体提取。

使用RegexEntityExtractor时,正则表达式的名称应与要提取的实体的名称匹配。 例如,可以通过在训练数据中包含此正则表达式和至少两个带注释的示例来提取10-12位的帐号:

nlu:
- regex: account_number
  examples: |
    - \d{10,12}
- intent: inform
  examples: |
    - my account number is [1234567891](account_number)
    - This is my account number [1234567891](account_number)

查找表

查找表是用于生成不区分大小写的正则表达式模式的单词列表。它们的使用方式与正则表达式的使用方式相同,可以与管道中的RegexFeatureizer和RegexEntityExtractor组件结合使用。

nlu:
- lookup: banks
  examples: |
    - JPMC
    - Comerica
    - Bank of America

当使用带有RegexFeatureizer的查找表时,请为要匹配的意图或实体提供足够的示例,以便模型可以学习将生成的正则表达式用作特征。

当将查找表与RegexEntityExtractor一起使用时,请提供至少两个带注释的实体示例,以便NLU模型可以在训练时将其注册为实体。

实体角色和组

将单词注释为自定义实体允许在训练数据中定义某些概念。 例如,可以通过注释来识别城市

- I want to fly from [Berlin]{"entity": "city"} to [San Francisco]{"entity": "city"} .

为了区分不同的角色,除了实体标签外,还可以分配角色标签。

- I want to fly from [Berlin]{"entity": "city", "role": "departure"} to [San Francisco]{"entity": "city", "role": "destination"}.

还可以通过在实体标签旁边指定组标签来对不同的实体进行分组。 例如,组标签可用于定义不同的顺序。 在下面的示例中,组标签指定了哪些配料与哪些披萨搭配,以及每个披萨应该有多大的尺寸。

- Give me a [small]{"entity": "size", "group": "1"} pizza with [mushrooms]{"entity": "topping", "group": "1"} and
a [large]{"entity": "size", "group": "2"} [pepperoni]{"entity": "topping", "group": "2"}

提取器返回的实体对象将包括检测到的角色/组标签。

{
  "text": "Book a flight from Berlin to SF",
  "intent": "book_flight",
  "entities": [
    {
      "start": 19,
      "end": 25,
      "value": "Berlin",
      "entity": "city",
      "role": "departure",
      "extractor": "DIETClassifier",
    },
    {
      "start": 29,
      "end": 31,
      "value": "San Francisco",
      "entity": "city",
      "role": "destination",
      "extractor": "DIETClassifier",
    }
  ]
}

实体角色和组目前仅受DIETClassifier和CRFEntityExtractor的支持。

要从具有特定角色/组的实体中填充插槽,需要为插槽定义一个from_entity插槽映射,并指定所需的角色/组。例如

entities:
   - city:
       roles:
       - departure
       - destination

slots:
  departure:
    type: any
    mappings:
    - type: from_entity
      entity: city
      role: departure
  destination:
    type: any
    mappings:
    - type: from_entity
      entity: city
      role: destination

影响对话预测的实体角色和群体

如果想按角色或组影响对话预测,则需要修改故事,以包含所需的角色或组标签。 还需要在domain文件中列出实体的相应角色和组。

假设想根据用户的位置输出不同的句子。 例如,如果用户刚从伦敦抵达,可能想询问用户伦敦之旅的情况。 但是,如果用户正在前往马德里的途中,可能希望用户入住愉快。 可以通过以下两个故事来实现:

stories:
- story: The user just arrived from another city.
  steps:
    - intent: greet
    - action: utter_greet
    - intent: inform_location
      entities:
        - city: London
          role: from
    - action: utter_ask_about_trip

- story: The user is going to another city.
  steps:
    - intent: greet
    - action: utter_greet
    - intent: inform_location
      entities:
        - city: Madrid
          role: to
    - action: utter_wish_pleasant_stay

BILOU实体标记

DIETClassifier和CRFEntityExtractor具有选项BILOU_flag,它指的是机器学习模型在处理实体时可以使用的标记模式。 BILOU是“开始”、“内部”、“最后”、“外部”和“单位长度”的缩写。

- [Alex]{"entity": "person"} is going with [Marty A. Rick]{"entity": "person"} to [Los Angeles]{"entity": "location"}.
token BILOU_flag = true BILOU_flag = false
alex U-person person
is O O
going O O
with O O
marty B-person person
a I-person person
rick L-person person
to O O
los B-location location
angeles L-location location

故事

故事是一种训练数据,用于训练助手的对话管理模型。 故事可以用来训练能够泛化到不可见的对话路径的模型。

格式(Format)

故事是用户和人工智能助手之间对话的表示,转换为特定格式,用户输入表示为意图(必要时表示为实体),而助手的响应和动作表示为动作名称。

stories:
- story: collect restaurant booking info  # name of the story - just for debugging
  steps:
  - intent: greet                         # user message with no entities
  - action: utter_ask_howcanhelp
  - intent: inform                        # user message with entities
    entities:
    - location: "rome"
    - price: "cheap"
  - action: utter_on_it                  # action that the bot should execute
  - action: utter_ask_cuisine
  - intent: inform
    entities:
    - cuisine: "spanish"
  - action: utter_ask_num_people

用户消息(User Messages)

在撰写故事时,不必处理用户发送的消息的具体内容。 相反,可以利用NLU管道的输出,它允许仅使用意图和实体的组合来引用用户可以发送的所有可能的消息,以表示相同的意思。

在这里包含实体也很重要,因为策略会根据意图和实体的组合来学习预测下一个操作(但是,可以使用use_entities属性更改此行为)。

动作(Action)

机器人执行的所有操作,包括响应,都列在动作键下的故事中。

可以将domain中的响应作为一个动作,将其列在故事中。 同样,可以通过在domain中的操作列表中包含自定义操作的名称来指示故事应调用自定义操作。

事件(Events)

在训练过程中,Rasa不调用动作服务器。 这意味助手的对话管理模型不知道自定义操作将返回哪些事件。 因此,设置插槽或激活/停用表单等事件必须作为故事的一部分明确写出。

插槽事件(Slot Events)

插槽事件在故事中写在slot_was_set下。 如果此插槽设置在自定义操作中,请在自定义操作调用后立即添加slot_was_set事件。 如果您的自定义操作将插槽值重置为None,则相应的事件如下:

stories:
- story: set slot to none
  steps:
    # ... other story steps
    - action: my_custom_action
    - slot_was_set:
      - my_slot: null

表单事件(Form Events)

在处理故事中的形式时,需要记住三种事件。

表单动作事件(例如-action:restaurant_form)用于首次启动表单时的开头,以及在表单已处于活动状态时恢复表单动作时。

表单激活事件(例如-active_loop:restaurant_form)在第一个表单操作事件之后立即使用。

表单停用事件(例如-active_loop:null),用于停用表单。

检查点(Checkpoints#)

可以使用检查点来模块化和简化您的训练数据。 检查点可能很有用,但不要过度使用。 使用大量检查点会很快让你的示例故事变得难以理解,并会减缓训练速度。

stories:
- story: beginning of flow
  steps:
  - intent: greet
  - action: action_ask_user_question
  - checkpoint: check_asked_question

- story: handle user affirm
  steps:
  - checkpoint: check_asked_question
  - intent: affirm
  - action: action_handle_affirmation
  - checkpoint: check_flow_finished

- story: handle user deny
  steps:
  - checkpoint: check_asked_question
  - intent: deny
  - action: action_handle_denial
  - checkpoint: check_flow_finished

- story: finish flow
  steps:
  - checkpoint: check_flow_finished
  - intent: goodbye
  - action: utter_goodbye

与常规故事不同,检查点并不局限于从用户输入开始。 只要检查点插入到主故事中的正确位置,第一个事件就可以是自定义操作或响应。

或语句(Or Statements)

另一种写短篇故事或以相同方式处理多个意图或插槽事件的方法是使用or语句。 例如,如果要求用户确认某事,并且你想以同样的方式对待肯定和感谢的意图。 以下故事将在训练时转换为两个故事:

stories:
- story:
  steps:
  # ... previous steps
  - action: utter_ask_confirm
  - or:
    - intent: affirm
    - intent: thankyou
  - action: action_handle_affirmation

还可以将or语句与插槽事件一起使用。 以下意味着故事要求设置名称槽的当前值,并且是joe或bob:

stories:
- story:
  steps:
  - intent: greet
  - action: utter_greet
  - intent: tell_name
  - or:
    - slot_was_set:
        - name: joe
    - slot_was_set:
        - name: bob
  # ... next actions

#### 测试对话格式(Test Conversation Format)

测试对话格式是一种将NLU数据和故事组合到一个文件中进行评估的格式。 此格式仅用于测试,不能用于训练。

端到端训练(End-to-end Training)

通过端到端训练,不必处理NLU管道提取的消息的具体意图,也不必处理domain文件中单独的outter_响应。 相反,可以将用户消息和/或机器人响应的文本直接包含在故事中。

可以将端到端格式的训练数据与指定了意图和动作的标记训练数据混合在一起: 故事可以有一些由意图/动作定义的步骤,以及其他由用户或机器人话语直接定义的步骤。

我们称之为端到端训练,因为策略可以消费和预测实际文本。 对于端到端用户输入,忽略由NLU管道和提取实体分类的意图。

只有规则策略和TED策略允许端到端训练。

RulePolicy在预测过程中使用简单的字符串匹配。 也就是说,只有当规则中的用户文本字符串和预测期间的输入相同时,基于用户文本的规则才会匹配。

TEDPolicy通过额外的神经网络传递用户文本,以创建文本的隐藏表示。 为了获得强大的性能,需要提供足够的训练故事,以捕获任何端到端对话回合的各种用户文本。

端到端训练需要TEDPolicy中更多的参数。 因此,训练端到端模型可能需要大量的计算资源。

规则(Rules)

规则是一种训练数据,用于训练助手的对话管理模型。 规则描述了应始终遵循相同路径的简短对话

不要过度使用规则。 规则非常适合处理小的特定对话模式,但与故事不同,规则没有能力泛化到未被发现的对话路径。 结合规则和故事,使助手更强大,能够处理真实的用户行为。

编写规则

在开始编写规则之前,必须确保将规则策略添加到模型配置中:

policies:
- ... # Other policies
- name: RulePolicy

然后可以将规则添加到训练数据的规则部分。 要表明规则可以应用于对话中的任何点,请从启动对话的意图开始,然后添加助手应执行的响应操作。

rules:

- rule: Say `hello` whenever the user sends a message with intent `greet`
  steps:
  - intent: greet
  - action: utter_greet

此示例规则适用于会话开始时以及用户决定在正在进行的会话中发送带有意向问候的消息时。

在预测时,仅在训练数据中作为规则出现而不在故事中出现的对话回合将被TEDPolicy等仅使用机器学习的策略忽略。

rules:
- rule: Say `hello` whenever the user sends a message with intent `greet`
  steps:
  - intent: greet
  - action: utter_greet

stories:
- story: story to find a restaurant
  steps:
  - intent: find_restaurant
  - action: restaurant_form
  - action: utter_restaurant_found

例如,如果你如上所述定义了问候规则,但没有将其添加到任何故事中,那么在RulePolicy预测出“说出街道”后,TEDPolicy将做出预测,就像问候回合没有发生一样。

对话开始规则

要编写仅在对话开始时适用的规则,请在规则中添加一个conversation_start:true:

rules:

- rule: Say `hello` when the user starts a conversation with intent `greet`
  conversation_start: true
  steps:
  - intent: greet
  - action: utter_greet

如果用户在对话中稍后发送带有意图问候的消息,则规则将不匹配。

有条件的规则

条件描述了规则适用所必须满足的要求。 为此,请在condition键下添加有关先前对话的任何信息:

rules:

- rule: Only say `hello` if the user provided a name
  condition:
  - slot_was_set:
    - user_provided_name: true
  steps:
  - intent: greet
  - action: utter_greet

可以在条件下包含的可能信息包括slot_was_set事件和active_loop事件。

在规则之后跳过等待用户输入

默认情况下,完成最后一步后,规则将等待下一条用户消息:

rules:

- rule: Rule which will wait for user message when it was applied
  steps:
  - intent: greet
  - action: utter_greet
  # - action: action_listen
  # Every rule implicitly includes a prediction for `action_listen` as last step.
  # This means that Rasa will wait for the next user message.

如果需要将下一个动作预测交给另一个故事或规则,请在规则中添加wait_for_user_input:false:

rules:

- rule: Rule which will not wait for user message once it was applied
  steps:
  - intent: greet
  - action: utter_greet
  wait_for_user_input: false

中止规则

规则旨在处理聊天机器人的多个输出步骤。 一旦需要用户交互,它们就会终止。 这是通过启动表单自动发生的,因为它从第一个插槽的用户输入开始。 因此,启动后的所有步骤都将被忽略。

然而,终止也可以手动实现。这对于实现条件终止标准非常有用。

以下是一个示例:

rules:

- rule: Rule which will be conditionaly terminated
  steps:
  - intent: greet
  - action: action_check_termination
  - action: utter_greet
  wait_for_user_input: true
from rasa_sdk import Action
from rasa_sdk.events import FollowupAction

class ActionCheckTermination(Action):

    def name(self):
        return "action_check_termination"

    def run(self, dispatcher, tracker, domain):

        # your business logic here
        should_terminate = check_for_termination(<params>)

        if should_terminate:
            return [FollowupAction("action_listen")]

        return []

当终止完成时,即使在用户输入之后,也永远不会执行utter_greet,因为它会导致新的意图预测。

规则和表单

当表单处于活动状态时,机器人将根据表单的定义方式进行预测,忽略规则。 在以下情况下,规则再次适用:

该表单填写了所有必需的插槽 表单拒绝执行

Domain

Domain定义了助手操作的范围。 它指定了机器人应该知道的意图、实体、槽、响应、表单和操作。 它还定义了会话的配置。

version: "3.1"

intents:
  - affirm
  - deny
  - greet
  - thankyou
  - goodbye
  - search_concerts
  - search_venues
  - compare_reviews
  - bot_challenge
  - nlu_fallback
  - how_to_get_started

entities:
  - name

slots:
  concerts:
    type: list
    influence_conversation: false
    mappings:
    - type: custom
  venues:
    type: list
    influence_conversation: false
    mappings:
    - type: custom
  likes_music:
    type: bool
    influence_conversation: true
    mappings:
    - type: custom

responses:
  utter_greet:
    - text: "Hey there!"
  utter_goodbye:
    - text: "Goodbye :("
  utter_default:
    - text: "Sorry, I didn't get that, can you rephrase?"
  utter_youarewelcome:
    - text: "You're very welcome."
  utter_iamabot:
    - text: "I am a bot, powered by Rasa."
  utter_get_started:
    - text: "I can help you find concerts and venues. Do you like music?"
  utter_awesome:
    - text: "Awesome! You can ask me things like \"Find me some concerts\" or \"What's a good venue\""

actions:
  - action_search_concerts
  - action_search_venues
  - action_show_concert_reviews
  - action_show_venue_reviews
  - action_set_music_preference

session_config:
  session_expiration_time: 60  # value in minutes
  carry_over_slots_to_new_session: true

多个Domain文件

Domain可以定义为单个YAML文件,也可以拆分为目录中的多个文件。 当跨多个文件拆分时,Domain内容将被读取并自动合并在一起。

使用命令行界面,您可以通过运行以下命令来训练具有分割域文件的模型:

rasa train --domain path_to_domain_directory

意图(intents)

Doamin文件中的intents键列出了NLU数据和会话训练数据中使用的所有intent。

某些意图忽略实体

要忽略某些意图的所有实体,您可以将use_entities:[]参数添加到域文件中的意图中,如下所示:

intents:
  - greet:
      use_entities: []

要忽略某些实体或明确地只考虑某些实体,可以使用以下语法:

  intents:
- greet:
    use_entities:
      - name
      - first_name
- farewell:
    ignore_entities:
      - location
      - age
      - last_name

只能对任何单个意图use_entities或ignore_entities。

这些意图中被排除的实体将不会特征化,因此不会影响下一步的行动预测。 当有一个不关心被拾取实体的意图时,这很有用。

如果列出意图时没有use_entities或ignore_entities参数,则实体将正常显示。

也可以通过将实体本身的influence_conversation标志设置为false来忽略实体。

实体(Entities)

实体部分列出了NLU管道中任何实体提取器都可以提取的所有实体。

entities:
   - PERSON           # entity extracted by SpacyEntityExtractor
   - time             # entity extracted by DucklingEntityExtractor
   - membership_type  # custom entity extracted by DIETClassifier
   - priority         # custom entity extracted by DIETClassifier

使用多个Domain文件时,可以在任何Domain文件中指定实体,并且可以由任何Domain文件的任何意图使用或忽略实体。

如果使用的是“实体角色和组”功能,还需要在本节中列出实体的角色和组。

entities:
   - city:            # custom entity extracted by DIETClassifier
       roles:
       - from
       - to
   - topping:         # custom entity extracted by DIETClassifier
       groups:
       - 1
       - 2
   - size:            # custom entity extracted by DIETClassifier
       groups:
       - 1
       - 2

默认情况下,实体会影响动作预测。 为了防止提取的实体影响特定意图的对话,可以忽略某些意图的实体。 要忽略一个实体的所有意图,而不必在每个意图的ignore_entities标志下列出它,可以在实体下将标志influence_conversation设置为false:

entities:
- location:
    influence_conversation: false

插槽(Slots)

插槽是机器人的记忆。 它们充当键值存储,可用于存储用户提供的信息(例如他们的家乡)以及收集到的关于外部世界的信息(如数据库查询的结果)。

插槽在Domain的插槽部分定义,包括其名称、类型以及是否以及如何影响助手的行为。 以下示例定义了一个名为“slot_name”的插槽,键入文本和预定义的插槽映射from_entity。

slots:
  slot_name:
    type: text
    mappings:
    - type: from_entity
      entity: entity_name

插槽与对话行为(Slots and Conversation Behavior)

可以使用influence_conversation属性指定插槽是否影响对话。

如果想在不影响对话的情况下将信息存储在插槽中,请在定义插槽时设置influence_conversation:false。

以下示例定义了一个插槽年龄,它将存储有关用户年龄的信息,但不会影响对话的流程。这意味着助手每次预测下一个动作时都会忽略该时隙的值。

slots:
  age:
    type: text
    # this slot will not influence the predictions
    # of the dialogue policies
    influence_conversation: false

定义插槽时,如果省略influence_conversation或将其设置为true,则该插槽将影响下一个动作预测,除非它具有插槽类型Any。

插槽影响对话的方式将取决于其插槽类型。

以下示例定义了一个影响对话的插槽home_city。文本槽将影响助手的行为,具体取决于该槽是否有值。 文本槽的具体值(例如班加罗尔、纽约或香港)没有任何区别。

slots:
  # this slot will influence the conversation depending on
  # whether the slot is set or not
  home_city:
    type: text
    influence_conversation: true

例如,考虑两个输入“天气怎么样?”和“班加罗尔的天气怎么样 对话应该根据home_city插槽是否由NLU自动设置而产生分歧。 如果插槽已经设置,机器人可以预测action_forecast操作。 如果未设置插槽,则需要获取home_city信息,然后才能预测天气。

插槽类型(Slot Types)

文本槽(Text Slot)

  • 类型: text
  • 用途: 存储文本值。
  • 例子:
    slots:
     cuisine:
        type: text
        mappings:
        - type: from_entity
          entity: cuisine
    
  • 说明: 如果influence_conversation设置为true,则助手的行为将根据插槽是否设置而变化。不同的文本不会进一步影响对话。这意味着以下两个故事是相等的: ```yaml stories:
  • story: French cuisine steps:
    • intent: inform
    • slot_was_set:
      • cuisine: french
  • story: Vietnamese cuisine steps:
    • intent: inform
    • slot_was_set:
      • cuisine: vietnamese ```

布尔槽(Boolean Slot)

  • 类型: bool
  • 用途: 存储true或false值。
  • 例子:
    slots:
     is_authenticated:
        type: bool
        mappings:
        - type: custom
    
  • 说明: 如果influence_conversation设置为true,助手的行为将根据插槽是空的、设置为true还是设置为false而变化。 请注意,空的bool槽对对话的影响不同于将槽设置为false的情况。

分类插槽(Categorical Slot)

  • 类型: categorical

  • 用途: 存储可以取N个值之一的插槽。

  • 例子:

slots:
  risk_level:
    type: categorical
    values:
      - low
      - medium
      - high
    mappings:
    - type: custom
  • 说明:

如果influence_conversation设置为true,助手的行为将根据插槽的具体值而变化。 这意味着助手的行为会根据上述示例中的插槽的值是低、中还是高而有所不同。

默认值__other_会自动添加到用户定义的值中。 所有在插槽值中未明确定义的值都映射到__other_ __other_不应用作用户定义的值; 如果是这样,它仍将作为所有未发现的值映射到的默认值。

浮点插槽

  • 类型: float

  • 用途: 存储实数。

  • 例子: ```yaml slots: temperature: type: float min_value: -100.0 max_value: 100.0 mappings:
    • type: custom ```
  • 默认值: 最大值=1.0,最小值=0.0

  • 说明:

如果influence_conversation设置为true,助手的行为将根据插槽的值而变化。 如果该值介于min_value和max_value之间,则使用该数字的特定值。 低于min_value的所有值都将被视为min_value,高于max_value的值都将视为max_value。 因此,如果max_value设置为1,则插槽值2和3.5之间没有区别。

列表插槽

  • 类型: list
  • 用途: 存储值列表。
  • 例子: ```yaml slots: shopping_items: type: list mappings:
    • type: from_entity entity: shopping_item ```
  • 说明:

如果influence_conversation设置为true,则助手的行为将根据列表是否为空而变化。存储在插槽中的列表长度不影响对话。 只有列表长度是零还是非零才重要。

Any插槽

  • 类型: Any
  • 用途: 存储任意值(它们可以是任何类型,如字典或列表)。

  • 例子: ```yaml slots: shopping_items: type: any mappings:
    • type: custom ```
  • 说明:

在对话过程中,Any类型的插槽都会被忽略。 此插槽类型的属性influence_conversation不能设置为true。 如果想存储一个应该影响对话的自定义数据结构,使用自定义槽类型。

自定义插槽类型

也许餐厅预订系统最多只能处理6人的预订。 在这种情况下,希望插槽的值影响下一个选定的操作(而不仅仅是是否已指定)。 可以通过定义自定义插槽类来实现这一点。

下面的代码定义了一个名为NumberOfPeopleSlot的自定义插槽类。 特征化定义了如何将此插槽的值转换为向量,以便Rasa机器学习模型可以处理它。NumberOfPeopleSlot有三个可能的“值”,可以用长度为2的向量表示。

(0,0)	not yet set
(1,0)	between 1 and 6
(0,1)	more than 6
from rasa.shared.core.slots import Slot

class NumberOfPeopleSlot(Slot):

    def feature_dimensionality(self):
        return 2

    def as_feature(self):
        r = [0.0] * self.feature_dimensionality()
        if self.value:
            if self.value <= 6:
                r[0] = 1.0
            else:
                r[1] = 1.0
        return r

可以将自定义插槽类实现为独立的python模块,与自定义操作代码分开。 将自定义插槽的代码保存在一个名为“init.py”的空文件旁边的目录中,以便将其识别为python模块。 然后,可通过自定义插槽类的模块路径来引用它。

或者,假设已将上述代码保存在“addons/my_custom_slots.py”中,这是一个项目的目录:

└── rasa_bot
    ├── addons
    │   ├── __init__.py
    │   └── my_custom_slots.py
    ├── config.yml
    ├── credentials.yml
    ├── data
    ├── domain.yml
    ├── endpoints.yml
slots:
  people:
    type: addons.my_custom_slots.NumberOfPeopleSlot
    influence_conversation: true
    mappings:
    - type: custom

既然Rasa可以使用自定义插槽类,请添加根据people插槽的值而不同的训练故事。 可以为人们的值在1到6之间的情况写一个故事,为大于6的值写一个。 可以选择这些范围内的任何值来放入故事中,因为它们都是以相同的方式进行特征化的。

stories:
- story: collecting table info
  steps:
  # ... other story steps
  - intent: inform
    entities:
    - people: 3
  - slot_was_set:
    - people: 3
  - action: action_book_table

- story: too many people at the table
  steps:
  # ... other story steps
  - intent: inform
    entities:
    - people: 9
  - slot_was_set:
    - people: 9
  - action: action_explain_table_limit

插槽映射

Rasa附带了四个预定义的映射,用于根据最新的用户消息填充插槽。

除了预定义的映射外,还可以定义自定义插槽映射。 所有自定义插槽映射都应包含custom类型的映射。

槽映射被指定为Domain文件中键映射下的字典的YAML列表。 插槽映射按照它们在Domain中列出的顺序进行优先级排序。 找到的第一个应用的插槽映射将用于填充插槽。

默认行为是在每条用户消息后应用插槽映射,而不管对话上下文如何。 要使插槽映射仅在表单的上下文中应用,请参阅映射条件。 在表单上下文中应用from_entity槽映射还有一个默认限制; 有关详细信息,请参阅唯一的from_entity映射匹配映射匹配。

请注意,还可以为可选参数intent和not_intent定义意图列表。

from_entity

from_enity槽映射根据提取的实体填充槽。需要以下参数:

  • enity: 应填充插槽的实体

以下参数是可选的,可用于进一步指定映射何时应用:

  • intent:仅在预测到此意图时应用映射。
  • not_intent:在预测此意图时不应用映射
  • role:仅当提取的实体具有此角色时才应用映射
  • group:仅当提取的实体属于此组时才应用映射。
entities:
- entity_name
slots:
  slot_name:
    type: any
    mappings:
    - type: from_entity
      entity: entity_name
      role: role_name
      group: group name
      intent: intent_name
      not_intent: excluded_intent

唯一的from_entity映射匹配

在表单的上下文中应用from_entity槽映射存在限制。 当表单处于活动状态时,只有满足以下一个或多个条件,才会应用from_enity槽映射:

  1. 表单刚刚请求了具有from_entity映射的插槽
  2. 活动表单的required_slots中只有一个具有特定的from_enity映射,包括提取的实体的所有属性(即实体名称、角色、组)。 这被称为表单的唯一实体映射。 如果映射在required_slots列表中不唯一,则提取的实体将被忽略。

他的限制在于防止表单用相同的提取实体值填充多个所需的插槽。

例如,在下面的示例中,一个实体日期唯一地设置了插槽arrival_date,一个具有from角色的实体城市唯一地设置插槽departure_city,而一个具有角色的实体市唯一地设置槽arrival_city,因此即使没有请求这些插槽,它们也可以用来适应相应的插槽。 但是,没有角色的实体城市可以填充departure_city和arrival_city插槽,具体取决于请求的插槽,因此,如果在请求插槽arrival_date时提取了实体城市,则表单将忽略它。

slots:
  departure_city:
    type: text
    mappings:
    - type: from_entity
      entity: city
      role: from
    - type: from_entity
      entity: city
  arrival_city:
    type: text
    mappings:
    - type: from_entity
      entity: city
      role: to
    - type: from_entity
      entity: city
  arrival_date:
    type: any
    mappings:
    - type: from_entity
      entity: date
forms:
  your_form:
    required_slots:
    - departure_city
    - arrival_city
    - arrival_date

from_text

from_text映射将使用最后一个用户话语的文本来填充插槽名。 如果intent_name为None,则无论intent名称如何,该插槽都将被填充。 否则,只有当用户的意图是intent_name时,插槽才会被填满。

如果消息的意图是excluded_intent,则插槽映射将不适用。

slots:
  slot_name:
    type: text
    mappings:
    - type: from_text
      intent: intent_name
      not_intent: excluded_intent

from_intent

如果用户意图是intent_name,则from_intent映射将用值my_value填充插槽slot_name。 如果选择不指定参数intent,则无论消息的意图如何,只要intent未列在not_intent参数下,插槽映射都将应用。

以下参数是必需的: value:填充插槽插槽名的值 以下参数是可选的,可用于进一步指定映射何时应用: intent:仅在预测到此意图时应用映射。 not_intent:在预测此意图时不应用映射

slots:
  slot_name:
    type: any
    mappings:
    - type: from_intent
      value: my_value
      intent: intent_name
      not_intent: excluded_intent
from_trigger_intent

发件人_起重工_内容#

如果表单被带有intent_name的用户消息激活,则from_trigger_intent映射将用值my_value填充插槽slot_name。 如果消息的意图是excluded intent,则插槽映射将不适用。

slots:
  slot_name:
    type: any
    mappings:
    - type: from_trigger_intent
      value: my_value
      intent: intent_name
      not_intent: excluded_intent

映射条件

要仅在窗体的上下文中应用插槽映射,请在插槽映射的conditions键中指定窗体的名称。条件列出了active_loop键中映射适用的表单名称。

条件还可以包括requested_slot的名称。 如果未提及requested_slot,则无论表单请求哪个插槽,只要提取了相关信息,就会设置插槽。

slots:
  slot_name:
    type: text
    mappings:
    - type: from_text
      intent: intent_name
      conditions:
      - active_loop: your_form
        requested_slot: slot_name
      - active_loop: another_form

自定义插槽映射

当预定义的映射都不适合用例时,可以使用槽验证操作定义自定义槽映射。 必须将此插槽映射定义为自定义类型,例如:

slots:
  day_of_week:
    type: text
    mappings:
    - type: custom
      action: action_calculate_day_of_week

还可以使用custom槽映射列出在对话过程中将由任意自定义操作填充的槽,只列出类型而不列出特定操作。例如:

slots:
  handoff_completed:
    type: boolean
    mappings:
    - type: custom

此插槽不会在每个用户回合都更新,而只会在预测到返回SlotSet事件的自定义操作时更新一次。

初始插槽值

slots:
  num_fallbacks:
    type: float
    initial_value: 0
    mappings:
    - type: custom

响应(Responses)

响应是向用户发送消息而不运行任何自定义代码或返回事件的操作。 这些响应可以直接在响应键下的域文件中定义,并且可以包括丰富的内容,如按钮和附件.

表单

表单是一种特殊类型的操作,旨在帮助助手从用户那里收集信息。 在Domain文件的forms键下定义表单.

动作

动作是机器人实际可以做的事情。例如,动作可以:

  • 响应用户
  • 进行外部API调用,
  • 查询数据库
  • 几乎任何东西!

选择哪些操作应接收Domain

为此,必须首先在端点配置中为endpoints.yml中的action_endpoint启用选择性域.

# endpoints.yml
action_endpoint:
 url: "http://localhost:5055/webhook" # URL to your action server
 enable_selective_domain: true

启用自定义操作的选择性domain后,domain将仅发送给那些明确表示需要它的自定义操作。 从rasa-sdk FormValidationAction父类继承的自定义操作是此规则的例外,因为它们将始终将domain发送给它们。 若要指定某个操作是否需要domain,请将{send_domain:true}添加到domain.yml中操作列表中的自定义操作中

# domain.yml
actions:
  - action_hello_world: {send_domain: True} # will receive domain
  - action_calculate_mass_of_sun # will not receive domain
  - validate_my_form # will receive domain

会话配置(Session configuration)

会话交谈表示助手和用户之间的对话。会话可以通过三种方式开始:

  • 用户开始与助手对话
  • 用户在可配置的不活动期后发送他们的第一条消息
  • 使用 /session_start intent消息触发手动会话启动。

在session_config键下定义在domain中触发新会话的非活动期。

可用参数包括:

  • sessionexpiration_time定义了新会话开始后的不活动时间(分钟)。
  • carrie_over_slots_to_new_session决定是否应将现有的设置时隙转移到新会话。

默认会话配置如下:

session_config:
  session_expiration_time: 60  # value in minutes, 0 means infinitely long
  carry_over_slots_to_new_session: true  # set to false to forget slots between sessions

如果用户在60分钟不活动后发送了第一条消息,则会触发一个新的对话会话,并且任何现有的slot都会被转移到新会话中。 将session_session_time的值设置为0意味着会话不会结束。

会话启动会触发默认操作action_session_start。 其默认实现将所有现有插槽移动到新会话中。 请注意,所有对话都以action_session_start开头。例如,覆盖此操作可用于使用外部API调用的插槽初始化跟踪器,或使用机器人程序消息启动对话。 关于自定义会话启动操作的文档向您展示了如何做到这一点。

配置(Config)

domain文件中的config键维护store_entities_as_slots参数。 此参数仅在阅读故事并将其转换为跟踪器的情况下使用。 如果参数设置为True,如果故事中存在适用的实体,这将导致从实体隐式设置插槽。 当实体与from_enity插槽映射匹配时,store_entities_as_slots定义实体值是否应放置在该插槽中。 因此,此参数跳过在故事中手动添加显式的slot_was_set步骤。 默认情况下,此行为处于打开状态。

配置(Config)

模型配置(Model Configuration)

配置文件定义了模型将用于根据用户输入进行预测的组件和策略。

recipe键允许不同类型的配置和模型架构。 目前,支持“default.v1”和实验性“graph.v1”配方。

配置文件现在包含一个新的强制键assistant_id,它表示唯一的助手标识符。 assistant_id必须指定一个唯一的值,以区分部署中的多个助手。 assistant标识符将与模型id一起传播到每个事件的元数据中。

请注意,如果配置文件不包含此必需密钥或占位符默认值未被替换,则每次运行rasa时,都会生成一个随机的助手名称并将其添加到配置中。

语言和管道键指定了模型用于进行NLU预测的组件。 策略键定义了模型用于预测下一个操作的策略。

如果不知道要选择哪些组件或策略,可以使用建议配置功能,该功能将推荐合理的默认值。

建议配置

可以将pipeline和/或 policies键保留在配置文件之外。 当运行rasa时,建议配置功能将为缺失的密钥选择默认配置来训练模型。

确保在config.yml文件中使用2个字母的ISO语言代码指定语言键。

config.yml文件示例:

recipe: default.v1
assistant_id: example_bot
language: en

pipeline:
# will be selected by the Suggested Config feature

policies:
- name: MemoizationPolicy
- name: TEDPolicy
  max_history: 5
  epochs: 10

对于上面的示例,生成的文件可能看起来像这样:

recipe: default.v1
assistant_id: example_bot
language: en

pipeline:
# # No configuration for the NLU pipeline was provided. The following default pipeline was used to train your model.
# # If you'd like to customize it, uncomment and adjust the pipeline.
# # See https://rasa.com/docs/rasa/tuning-your-model for more information.
#   - name: WhitespaceTokenizer
#   - name: RegexFeaturizer
#   - name: LexicalSyntacticFeaturizer
#   - name: CountVectorsFeaturizer
#   - name: CountVectorsFeaturizer
#     analyzer: char_wb
#     min_ngram: 1
#     max_ngram: 4
#   - name: DIETClassifier
#     epochs: 100
#   - name: EntitySynonymMapper
#   - name: ResponseSelector
#     epochs: 100
#   - name: FallbackClassifier
#     threshold: 0.3
#     ambiguity_threshold: 0.1

policies:
- name: MemoizationPolicy
- name: TEDPolicy
  max_history: 5
  epochs: 10

如果愿意,可以取消对一个或两个键的建议配置的注释,并进行修改。 请注意,这将在再次训练时禁用此密钥的自动建议。 只要将配置注释掉,并且没有为密钥指定任何配置,每当训练新模型时,都会建议使用默认配置。

如果运行rasa train nlu,将仅自动选择管道的默认配置,如果运行rasa train core,将仅选择策略的默认配置。