一般来说,机器人可以跟人对话,机器人说什么是最难的,顶多是人工编写几种规则和模版来回复即可。但是要让机器人理解人的意图,确实非常难的事情。因为语言具有多样性,多义词,一语双关,长短句等,尤其是中文的博大精深。因此机器人需要特别多的数据,也就是模拟人的问法,让机器人理解这些意图特征,理解人的问法,以及人是如何回复别人的问题,这部分内容在Rasa里面称为训练数据。
Rasa使用YAML格式作为一种统一和可扩展的方式来管理所有的训练数据,包括NLU数据、stories数据和rules规则。可以将训练数据拆分为任意数量的YAML文件,每个文件可以包含NLU数据、故事和规则的任意组合。训练数据解析器使用最上层的key确定训练数据类型。
开发者还在寻找 Markdown 数据格式?它在 Rasa 3.0 中被删除,但仍然可以找到markdown NLU data和markdown stories的文档。如果您仍然有 Markdown 格式的训练数据,那么推荐的方法是使用 Rasa 2.x 将您的数据从 Markdown 转换为 YAML。迁移指南 解释了如何执行此操作。
每个文件可以包含一个或多个带有key以及对应的训练数据。一个文件可以包含多个key,但每个key在单个文件中只能出现一次。可用的key包括:
开发者应该在所有 YAML 训练数据文件中指定版本key。如果开发者未在训练数据文件中指定版本key,Rasa 将假定开发者使用的是已安装的 Rasa 版本支持的最新训练数据格式。Rasa 版本高于开发者机器上安装的版本的训练数据文件将被跳过。目前,Rasa 3.x 的最新训练数据格式规范是 3.1。
这里拿一个样例来说明,nlu、stroies和rules数据都在一个文件中来展现:
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
要测试指定stories,需要将它们放入一个单独的文件中,并使用前缀test_:
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
NLU训练数据由按意图分类的示例用户对话组成。NLU训练数据还包括实体,可以从用户消息中提取结构化信息。您还可以向训练数据中添加额外的信息,如正则表达式和查找表,以帮助模型正确识别意图和实体。NLU训练数据在NLU键下定义。可以在此项下添加的内容包括:
例如带上标注的实体,但是标注信息是可选。
nlu: - intent: check_balance examples: | - What's my [credit](account) balance? - What's the balance on my [credit card account]{"entity":"account","value":"credit"}
nlu: - synonym: credit examples: | - credit card account - credit account
nlu: - regex: account_number examples: | - \d{10,12}
nlu: - lookup: banks examples: | - JPMC - Comerica - Bank of America
train examples按意图分组并列在 examples字段下。通常,开发者会在每一行列出一个示例,如下所示:
nlu: - intent: greet examples: | - hey - hi - whats up
但是,如果开发者有自定义 NLU 组件并且需要示例的元数据,也可以使用扩展格式:
nlu: - intent: greet examples: - text: | hi metadata: sentiment: neutral - text: | hey there!
metadata字段可以包含任意键值数据,这些数据与示例相关联并且可由 NLU 中的组件访问。在上面的示例中,情感元数据可以被管道中的自定义组件用于情感分析。
开发者还可以在意图级别指定此元数据:
nlu: - intent: greet metadata: sentiment: neutral examples: - text: | hi - text: | hey there!
在这案例里,metadata 字段所包含的内容会应用到每一个intent样例中。
如果开发者需要明确检索意图,你的NLU样例可能会跟下面一样:
nlu: - intent: chitchat/ask_name examples: | - What is your name? - May I know your name? - What do people call you? - Do you have a name for yourself? - intent: chitchat/ask_weather examples: | - What's the weather like today? - Does it look sunny outside today? - Oh, do you mind checking the weather for me please? - I like sunny days in Berlin.
所有检索意图都添加了一个后缀,用于标识Bot的特定响应字段。 在上面的例子中, ask_name 和 ask_weather 是后缀。 后缀与检索意图名称由 / 分隔符分隔。
Entities是可以从用户消息中提取到结构化的信息,在训练数据中使用实体名称进行标注。 除了实体名称之外,开发者还可以使用同义词、角色或组来标注实体。
在训练数据中,标注的实体样例如下所示:
nlu: - intent: check_balance examples: | - how much do I have on my [savings](account) account - how much money is in my [checking]{"entity": "account"} account - What's the balance on my [credit card account]{"entity":"account","value":"credit"}
标注实体的完整语法如下:
[]{"entity": " ", "role": " ", "group": " ", "value": " "}
role, group, and value关键词是在标注时是可选的。value 字段的内容可以参考 synonyms。如果你希望理解role 和 group 字段的内容,可以参考entity roles and groups.
同义词将提取的实体映射到提取的文本之外的值。开发者可以使用以下格式定义同义词:
nlu: - synonym: credit examples: | - credit card account - credit account
开发者还可以直接在训练数据中定义同义词,通过指定value字段来设置同义词:
nlu: - intent: check_balance examples: | - how much do I have on my [credit card account]{"entity": "account", "value": "credit"} - how much do I owe on my [credit account]{"entity": "account", "value": "credit"}
如果需要了解更多关于同义词的信息,可以去这里 NLU Training Data page.
开发者可以用正则表达式来提高意图分类和实体抽取的效果,正则表达式主要是用 RegexFeaturizer 和 RegexEntityExtractor 模块。
定义正则表达式的格式如下:
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)
account_number是正则表达式的名称。当用作特征RegexFeaturizer时,正则表达式的名称无关紧要。使用RegexEntityExtractor时,正则表达式的名称应与Bot要提取的实体名称对应上。
如果需要了解更多关于正则表达式的信息,可以去这里 NLU Training Data page.
查找表用于生成不区分大小写的正则表达式列表。它们可以与使用正则表达式的方式相同,与pipeline中的regexfeatureizer和RegexEntityExtractor组件结合使用。可以使用查找表来帮助提取具有已知可能值集的实体。保持开发者的查找表尽可能具体。例如,要提取国家名称,可以添加世界上所有国家的查找表。其实这个地方就是添加词库的功能。
nlu: - lookup: banks examples: | - JPMC - Comerica - Bank of America
stories和 rules都是用户和对话助手之间的对话流程表示,主要是用于训练对话管理模型。stories用于训练机器学习模型来识别对话中的模式并推广到看不见的对话路径。 rules描述了bot需要始终遵循相同路径的原则以及训练 RulePolicy规则策略。
stories通常由以下几个部分组成:
样例如下:
stories: - story: Greet the user metadata: author: Somebody key: value steps: # list of steps - intent: greet - action: utter_greet
每一个step可以是以下之一构成:
User Messages
所有用户消息都可以用 intent 字段和 entities 字段来指定,这个字段是可选的。
在编写故事时,开发者不必处理用户发送的消息的具体内容。相反,开发者可以利用 NLU pipline的输出,它使用意图和实体的组合来引用用户可以发送的具有相同含义的所有可能消息。
用户消息遵循的格式如下:
stories: - story: user message structure steps: - intent: intent_name # Required entities: # Optional - entity_name: entity_value - action: action_name
在样例“I want to check my credit balance”中,“credit”就是一个entities。训练数据中包含的实体也很重要,因为policy会根据意图和实体的组合来学习预测下一个动作(但是,开发者也可以使用use_entities属性更改此行为)。
Actions
Bot执行的所有动作都使用action字段来指定,后面跟动作名称。在编写故事时,一般会有两种类型的操作:
1.响应。由"utter_"开始,并且返回的是具体的消息。例如:
stories: - story: story with a response steps: - intent: greet - action: utter_greet
2.自定义动作。由“action_”开头,运行任意代码并发送任意数量的消息(或不发送)。例如:
stories: - story: story with a custom action steps: - intent: feedback - action: action_store_feedback
Forms
Forms是一种特定类型的自定义动作,它包含循环遍历一组必需的槽位以及向用户询问此信息的逻辑。开发者在Domain中来定义一个表单。Forms一旦定义,开发者应该作为规则指定表单的路径。开发者应该在故事中包括形式中断或其他“不确定的路径”,以便模型可以预测看不见的对话序列。表单作为动作中的一个步骤,通常采用以下格式:
stories: - story: story with a form steps: - intent: find_restaurant - action: restaurant_form # Activate the form - active_loop: restaurant_form # This form is currently active - active_loop: null # Form complete, no form is active - action: utter_restaurant_found
action步骤激活表单并开始遍历所需的槽位。 active_loop: restaurant_form 步骤表示当前有一个action表单。 与 slot_was_set 步骤非常相似,表单步骤不会将表单设置为活动状态,而是指示它应该已经被激活。 同样,active_loop: null 步骤表示在执行后续步骤之前不应激活任何表单。
表单可以被中断并保持活动状态; 在这种情况下,中断应该发生在 action: