本文继续围绕工业级业务对话平台和框架Rasa从源码的角度来解析如何定制DAG图中的NLU组件和policies组件。 下面从源码的角度介绍Rasa的Model Persistent机制,从持久化的角度来讲,就是把模型参数等相关的数据写入本地磁盘系统,或者第三方文件系统,或者分布式内存系统等,然后在调用模型做推理时可以从这些存储中读取数据。无论对于训练还是推理来说,这一环节都是至关重要的。
六、定制Graph Components
2. 关于Model Persistent机制
首先来看这个类ModelStorage,它的作用是为需要进行持久化操作的graph components提供存储服务的:
通过调用create方法创建ModelStorage:
调用方法from_model_archive来使用一个archive初始化ModelStorage:
调用方法metadata_from_archive从archive里获取模型的元数据信息:
调用方法create_model_package来创建用于加载和运行模型所需要的元数据信息:
然后再看这个类Resource,用来表示在DAG(有向无环图)图中一个已被持久化的graph component,注意这个类有两个属性”name”和” output_fingerprint”:
name:唯一标识resource,通常与graph node的名称一致
output_fingerprint:用于区别同样的resource被多次持久化之后产生的不同版本
这个类被注解为@dataclass,表明它是一个数据封装类,类似于一个Java Bean:
之所以需要Model Persistent这种机制,是因为在训练时一些graph components的数据(譬如模型的参数,对模型的一些描述信息等)需要通过持久化操作被存储起来,然后在推理时这些graph components可以从存储位置读取数据,一个典型的使用场景是存储模型的权重。另外通过这种缓存机制,在训练时如果修改了一个graph component,那么只需要对这个graph component和依赖它的其它graph components重新进行训练即可,而其余的components则维持原有训练后的状态不变。
以下是在Rasa cache目录里显示的一些数据存储文件样例:
Rasa在你定制的graph component的create和load方法的参数里提供了”model_storage”和”resource”这两个参数:
model_storage:提供访问所有graph components数据的入口
resource:用于在model storage里唯一标识你的定制组件数据的位置
- 数据写入Model Storage
为了在训练后持久化你定制的graph component,方法train需要访问参数”model_storage”和”resource”的值,所以需要在graph component初始化的时候把这些值传入__init__方法。然后train方法必须返回”resource”的值,这样Rasa才能缓存训练结果。
这里的with … as … 是Python的context manager的语法结构,超出了context的资源会被释放:
2. 从Model Storage读取数据
在推理时Rasa会调用load方法来实例化你的graph component,你可以使用这个context manager “self._model_storage.read_from(resource)”来取得对应组件数据存储位置的路径,通过这个路径来load被持久化的数据和实例化你的graph component。注意如果基于给定的resource没有找到被持久化的数据时,”_model_storage”会抛出一个ValueError的错误。
3. 关于resource写入缓存
调用以下方法来把resource写入缓存中:
然后调用read_from来从model storage中获取包含这个被持久化的resource的数据的目录,再把数据复制到接收这个resource的目录:
4. 关于从缓存加载resource
调用以下方法来从缓存中加载resource以便DAG图中的其它组件可以访问它,注意这里的参数model_storage,被缓存的resource会被添加到”ModelStorage”中,从而使这个resource能够被其它的graph 节点所访问,也就是针对DAG图中节点之间的依赖关系。
然后调用write_to获得能够对这个resource的数据进行持久化的目录,然后把resource的数据复制到resource被持久化的目录: