目录
Rasa NLU负责意图提取和实体提取。例如,输入“明天上海的天气如何?”,Rasa NLU要提取出改句子的意图是查询天气,以及对应的实体值和类型名:明天—日期、上海—城市。
Rasa NLU使用有监督算法来完成功能,因此需要开发者提供适当数量的语料,包括意图信息和实体信息。
Rasa NLU在软件架构上设计的很灵活,允许开发者使用各种算法来完成功能,这些算法的具体实现被称为组件(component)。为了让组件灵活配置和维持正确的前后组件的依赖关系,Rasa NLU引入了有向无环图DAG的组件配置系统。
在示例项目文件列表中的 data/nlu.yml 正是Rasa NLU的数据文件,具体内容如下:
- version: "3.0"
-
- nlu:
-
- # 意图字段
- - intent: greet
- examples: |
- - hey!
- - hello!
- - hi!
- - hello there!
- - moin!
-
- # 同义词字段
- - synonym: 番茄
- examples: |
- - 番茄。
- - 西红柿
- - 洋柿子
- - 火柿子
-
- # 查找表字段
- - lookup: 城市
- examples: |
- - 北京
- - 上海
- - ...
- - 广州
- - 深圳
-
- # 正则表达式字段
- - regex: help
- examples: |
- - \bhelp\b
-
Rasa NLU的训练数据为YAML格式。从结构上说,Rasa N:U的训练数据都在键(key)为nlu的列表内。列表中每个元素都是一个字典,依靠字典中的键来区分功能。具有特殊含义的键有 intent、synonym、regex、lookup。除intent外,其他3个都是可选的。
具有intent键表明当前的对象是用来存储训练样例的。intent对应的值时意图名。需要注意的是意图名中不能包含“/”字符,因为Rasa已经将这个字符预留了。
具有synonym键表明当前的对象是用来存储同义词信息的。例如西红柿是番茄的同义词。在启动EntitySynonymMapper组件(后续章节介绍)的情况下,推理时,会将得到的实体值的同义词替换为标准词。即将“西红柿”、“洋柿子”全部替换为“番茄”。
具有lookup键表明当前的对象是用来存储查找表的。在实体识别和意图识别的时候,如果开发者能给这些组件一些额外的特征,那么将提高这些组件的准确度。

在上述实例中,会有查找表特征[0001111101111000]。在NER时,模型会重点考虑这些查找表的特征,因此,即使训练数据中未出现车站名,模型也能在查找表特征的帮助下,正确提取出车站名。
具有regex键表明当前的对象是用来存储正则表达式的。利用正则表达式匹配某种模式后,将这种模式是否出现作为特征传给NER组件或意图识别组件,以提高组件的性能。其优点是精度高,因此在特别规则的NER识别过程中,如身份证号码识别、电话号码识别等场景下,可以利用正则表达式特征提高识别准确率。

正则表达式同样也可以作为特征提供给NER模型做实体识别。
在Rasa中,查找表和正则表达式主要通过2种方式使用:
Rasa NLU是一个基于有向无环图的通用框架。有向无环图是由组件(component)相互连接构成的。一个NLU应用通常有实体识别、意图识别两个子任务。为了完成这些任务,一个典型的Rasa NLU配置通常包含如下各类组件。

1、语言模型组件:加载模型文件,为后续组件提供框架支持,如初始化spaCy和BERT;
2、分词组件:将文本分割成词,为后续的高级NLP任务提供基础数据;
3、特征提取组件:提取词语序列的文本特征,可以同时使用多个特征提取组件;
4、NER组件:根据前面提供的特征对文本进行命名实体识别;
5、意图分类组件:按照语义对文本进行意图的分类,也成意图识别组件;
6、结构化输出组件:将预测结果整理成结构化数据并输出。这一部分不是以组件的形式提供的,而是流水线内建的功能,开发者不可见。
语言模型组件加载预训练的词向量模型。目前有2个语言模型组件,如下表:
| 组件 | 备注 |
| spaCyNLP | 该组件所需的模型需要提前下载到本地,否则会出错 |
| MitieNLP | 需要预先训练好的模型 |
Rasa分词组件中支持中文语言的分词器如下表:
| 组件 | 依赖 | 备注 |
| JiebaTokenizer | Jieba | |
| MitieTokenizer | Mitie | 经过改造可以支持中文分词 |
| spaCyTokenizer | spaCy |
无论是实体识别还是意图分类,都需要上游的组件提供特征。Rasa的特征提取组件如下:
| 组件 | 依赖组件 | 备注 |
| MitieFeaturizer | MitieNLP | |
| spaCyFeaturizer | spaCyNLP | |
| ConveRFeaturizer | 分词组件 | 基于Poly AI的conveRT模型 |
| LanguageModelFeaturizer | 分词组件 | 基于HuggingFace的transformers库 |
| RegexFeaturizer | 分词组件 | 读取训练数据中的正则表达式配置 |
| CountVectorsFeaturizer | 分词组件 | 词袋模型 |
| LexicalSynacticFeaturizer | 分词组件 | 提供词法和语法特征,如是否句首、句尾、纯数字等 |
Rasa支持多种NER组件,多数不可同时使用,少数组件可以有条件的同时使用。
| 组件 | 备注 |
| CRFEntityExtractor | |
| spcaCyEntityExtractor | 只能使用spaCy内置的实体提取模型,不能再训练。内置实体种类为人名、地名、组织结构名等 |
| DucklingEntityExtractor | 只能使用预定义的实体,不能再训练。内置的实体种类为邮箱、距离、时间等 |
| MitieEntityExtractor | |
| EntitySynonymMapper | 用于同义词改写,将提取到的实体标准化 |
| DIETClassifier | |
| RegexEntityExtractor | 读取训练数据中的查找表及正则表达式,用于提取实体 |
意图分类组件如下表所示:
| 组件 | 依赖 | 备注 |
| MitieIntentClassifier | Mitie | |
| SklearnIntentClassifier | Scikit-learn | |
| KeywordIntentClassifier | ||
| DIETIntentClassifier | Tensorflow | |
| FallIntentClassifier | 如果其他组件预测的intent得分过低,则该组件将intent更改为NLU fallback |
Rasa提供DIETClassifier(基于Rasa自行研发的DIET技术)用户实体和意图的联合建模。
对于FQA等简单的QA问题,只需要使用NLU部分就可以轻松完成,因此Rasa提供了回复选择器(ResponseSelector)组件。
Rasa NLU基于有向无环图进行组件配置,此有向无环图在Rasa中称为流水线(pipeline)。
流水线定义了各个组件和组件之间的依赖关系,允许开发者对各个组件进行配置。Rasa NLU的配置文件使用的是YAML格式。下面是适合中文开发者的,推荐流水线配置:
- recipe: default.v1
-
- language: "zh"
-
- pipeline:
- -name: JiebaTokenizer # 分词组件,jiba分词可能会和实体边界产生冲突,后续介绍其他分词组件
- -name: LanguageModelFeaturizer
- model_name: "bert"
- model_weights: "bert-base-chinese"
- -name: "DIETClassifier"
大体上Rasa NLU的配置文件可以分为3个主要的键:recipe、language、pipeline。
recipe:表示当前配置文件所用的格式,当前Rasa只支持一种格式,那就是default.v1
language:用于指定Rasa NLU将要处理的语言
pipeline:配置文件的核心,由列表构成,每个元素都是一个字典(表现在YAML中类似于name: xxx),这些字典直接对应流水线组件
NLU的输出内容主要包括text、intent、entities 3个部分。分别表示请求文本、意图识别、实体识别。实例如下:
- {
- "text": "show me chinese restaurants", # 用户输入的文本
- "intent": "restaurant_search", # 意图字段
- "entities": [ # 实体字段
- {
- "start": 8, # 开始位置
- "end": 15, # 结束位置
- "value": "chinese", # 实体值
- "entity": "cuisine", # 实体类型
- "extractor": "CRFEntityExtractor",# 提取器信息
- "confidence": 0.854, # 置信度
- "processors": [],
- }
- ]
- }
Rasa是一种高度内聚的框架,可以使用Rasa自带的命令行工具进行模型训练和推理任务。
(1)训练模型
rasa train nlu
这条命令将会从 data/ 目录下查找训练数据,使用config.yml作为流水线配置并将训练后的模型保存在 models/ 目录中,模型的名字以nlu-为前缀
(2)命令行测试
rasa shell nlu
如果想自行制定模型,则可以使用如下命令:
rasa shell -m models/nlu-
.tar.gz
下面是rasa shell的使用界面:
- hello # 用户自己的输入
-
- # 返回结果
- {
- "text": "hello", # 原始文本
- "entities": [], # 实体字段
- "intent": { # 意图字段
- "name": "greet",# 意图类型
- "confidence": 0.996844410963013 # 置信度
- },
- "intent_ranking": [ # 各意图置信度
- {
- "name": "greet",
- "confidence": 0.9968444108963013
- },
- {
- "name": "mood_greet",
- "confidence": 5.1380e-05
- },
- ]
- }
(3)启动服务
Rasa NLU提供了 RESTful HTTP API的服务形式,使用如下命令开启。
rasa run -- enable-api
我们可以通过向 /model/parse 路径发送请求的方式使用预测服务,如使用curl作为客户端。
curl localhos:5005/model/parse -d '{"text":"hello"}'
在实际调试中,开发者可以考虑使用postman等工具发送请求,如下所示:

在学习完Rasa NLU模块后,检验学习效果最好的办法就是实战。本项目将构建一个简单的医疗领域机器人的NLU模块。它支持以下实体和意图识别:
具体代码可参考:Git