Rasa NLU 组件的输入输出

本文将详细介绍 Rasa NLU 组件(component)的输入输出。


兼容性说明:

本文介绍的 Rasa NLU 知识都是基于 v0.13.2, 不同版本之间可能会有差异。但结构变动的不大,因此本文介绍的知识在后续版本,甚至 v1.x 依然有效。


组件的输入

训练阶段

训练模型

组件实例在训练阶段会通过 train 方法获得三个输入:

  • working_data: rasa_nlu.training_data.training_data.TrainingData 类型的对象,其是经过解析的训练数据
  • config: rasa_nlu.config.RasaNLUModelConfig 类型的对象,其是模型当前的配置信息
  • **context: 字典类型的对象,其是上游组件传递下来的上下文

一般性的,组件的处理流程就是读取所需的上下文和/或训练数据,然后训练组件,返回字典(如果有需要传递给下游组件的上下文的话),Trainer 会把上一个组件返回的字典 update 到现有的 context 中,然后把更新后的上下文传递个下一个组件作为上下文。

这里举几个例子:

  • 初始化组件一般会不读取上下文信息和训练数据,它会提供一个上下文信息(通常情况下初始化需要很久,并在后续多个组价中反复使用)给下游使用
  • 分词组件一般会读取训练数据,然后提供一个上下文信息(分词结果)给下游组件使用
  • 特征提取组件可能会读取分词组件提供的分词信息和训练数据,为下游的组件提供特征信息
  • NER 或者意图分类组件会读取上游组件提供的特征信息用于训练
保存模型

所有的组件都训练完成以后,那么就会进入保存模型的阶段。保存模型就是保存 pipeline 设置和各个组件的内部状态,以便在后续的模型载入阶段能顺利的还原成原来的模型状态。保存模型的过程就是逐一调用 pipeline 中每个组件对象的 persist 方法,具体传递给 persist 方法的参数有两个:

  • file_name: 训练系统已经为组件准备好的文件的路径。训练系统通过组件在 pipeline 中的顺序和名字等信息组合得到的文件名,可以保证这个名字在整个输出目录中是全局唯一的,组件可以放心使用,不用担心多个组件之间相互冲突的问题。
  • model_dir:模型输出的目录。由于组件可能会把状态保存到多个文件中,因此第一个参数提供的文件名就不够用了,这里系统提供了输出目录的路径。组件可以通过直接输出到输出目录,但需要组件负责保证输出文件不会相互冲突。

推理阶段

推理阶段一定程度上类似于组件的训练过程。不同的是,推理过程中没有训练数据需要传递,负责推理的 process 方法可以获得两个输入:

  • message: rasa_nlu.training_data.message.Message类型的对象,其表示的是用户的输入和组件之间传递的信息
  • **context: 普通的字典对象,用于表示的是整个 pipeline 组件提供的 context : 每个组件在被载入后,推理阶段之前,每个组件会被调用 provide_context 方法,该方法的返回值就是这个组件提供的 context, 所有的组件提供的 context 会在合并后,作为整个 pipeline 的 context

组件的输出

训练阶段

训练模型

训练阶段,模型在完成训练后(train 方法执行完成后),可以通过返回字典的方式将所提供的 context 信息提供给 trainer, trainer 会更新原来的 context,更新后的 context 将用于下一个组件的训练。

保存模型

所有模型都训练完成后,pipeline 会进入保存模型的循环,对 pipeline 中的每一个组件依次调用 persist 方法,组件的 presist 方法负责将该组件再次载入所需的一切数据都写入模型,如果是单个数据文件就可以考虑直接写入第一个参数所代表的系统已经为之定义好的路径中。如果有更多数据文件要输出,那么可以通过第二个参数所代表的模型输出目录,自行指定一个文件输出,文件路劲尽量避免和其他组件的输出冲突就行。

推理阶段

在模型推理时,pipeline 会先对所有组件依次调用 provide_context 方法,provide_context 如果返回的是字典(不是 None)那么这些字典会合并起来作为 context。推理时,pipeline 会对每一个组件调用 process 方法,其中有一个参数是 message:一个扩展的字典的对象, 组件通过直接操作字典或者调用 set 方法对 message 进行操作。其中区别是:直接操作字典的方式设置的属性并不会出现在最终的输出中(对外提供的API),而调用 set 方法设置的可能(根据设定)出现在最终的输出中。

组件的配置

每个组件在配置文件的 pipeline 字段被申明时,是可以直接指定相关配置参数的。比如简单的一个 pipeline 设置可能是这样的:

1
2
3
4
5
6
7
8
pipeline:
- name: "nlp_mitie"
model: "data/total_word_feature_extractor.dat"
- name: "tokenizer_mitie"
- name: "ner_mitie"
- name: "ner_synonyms"
- name: "intent_entity_featurizer_regex"
- name: "intent_classifier_mitie"

可以看到 pipeline 其实就是一个列表,每个列表元素都是一个组件的配置,但其本质是一个字典。每个字典必须要有的字段是 name ,它指定了所用组件的名字,用于查找指定的组件。剩余的字段(如果存在的话)都将作为组件的参数,在组件初始化时(调用类方法 create)作为参数(参数名:component_config,类型是字典)传递过去,从而实现组件的可配置化。