前言

    Rasa NLU 是一个开源的、可本地部署并配套有语料标注工具的自然语言理解框架。其本身是只支持英文和德文,中文因为其特殊性需要加入特定的 tokenizer 作为整个流水线的一部分,Rasa_NLU_Chi 作为 Rasa_NLU 的一个 fork 版本,加入了 jieba 作为中文的 tokenizer,实现了中文支持 [GitHub:Rasa NLU Chi]。

    自然语言理解(Natural Language Understanding)系统是 chatbot 的基石,尽管使用正则或者模板匹配的方式也能在很多场景下实现一个简单的问答系统,但却缺乏泛化和学习的能力,而基于机器学习的 NLU 系统则可以举一反三不断学习改进模型从而获得越来越好的性能表现。

    目前已有的 NLU 工具,大多是以服务的方式,通过调用远程 http 的 restful API 来对目标语句进行解析。包括 Google 的 API.ai、Microsoft 的 Luis.ai、Facebook 的 Wit.ai 等。这些 NLU 系统一边为用户提供NLU的服务,一边也通过用户自己上传的大量标注和非标注数据不断训练和改进自己的模型。对于数据敏感的用户来说,开源的 NLU 工具如 Rasa.ai 就为我们提供了另一种选择。而且这样的开源工具可以本地部署,针对实际需求训练和调整模型,甚至对一些特定领域的需求效果要比那些通用的在线 NLU 服务还要好。

 

Rasa Stack

    Rasa Stack 包括 Rasa NLU 和 Rasa Core,前者负责进行语义理解(意图识别和槽值提取),而后者负责会话管理,控制跟踪会话并决定下一步要做什么,两者都使用了机器学习的方法可以从真实的会话数据进行学习;另外他们之间还相互独立,可以单独使用。

    下图是一个简单的基于 Rasa 的 workflow 示意

 

Pipeline

    Rasa基本上提供了一个在各种NLP和ML库之上的高层次的API来负责”意图”的分类和“实体”的提取。这些NLP和ML库则被称为后端,是他们使得Rasa变得智能化。Rasa nlu 支持不同的 Pipeline,其后端实现可支持 spaCy、MITIE、MITIE + sklearn 以及 tensorflow,其中 spaCy 是官方推荐的,另外值得注意的是从 0.12 版本后,MITIE 就被列入 Deprecated 了。

  • MITIE: 一个包罗万象的库; 换言之,它有一个内置的用于”实体”提取的NLP库以及一个用于”意图”分类的ML库。
  • spaCy + sklearn: spaCy是一个只进行”实体”提取的NLP库。而sklearn是与spaCy一起使用的,用于为其添加ML功能来进行”意图”分类操作。
  • MITIE + sklearn: 该组合使用了两个各自领域里最好的库。该组合既拥有了MITIE中良好的”实体”识别能力又拥有sklearn中的快速和优秀的”意图”分类。

    目前对于中文有两条管道:

      a、使用 MITIE+Jieba:

        这种方式训练比较慢,效果也不是很好,最后出现的intent也没有分数排序。

// sample_configs/config_jieba_mitie.yml

language: "zh"

pipeline:
- name: "nlp_mitie"
  model: "data/total_word_feature_extractor_zh.dat"
- name: "tokenizer_jieba"
- name: "ner_mitie"
- name: "ner_synonyms"
- name: "intent_entity_featurizer_regex"
- name: "intent_classifier_mitie"

      b、(推荐)使用 MITIE + Jieba + sklearn

// sample_configs/config_jieba_mitie_sklearn.yml

language: "zh"

pipeline:
- name: "nlp_mitie"
  model: "data/total_word_feature_extractor_zh.dat"  // 加载 mitie 模型
- name: "tokenizer_jieba"  // 使用 jieba 进行分词
- name: "ner_mitie"  // mitie 的命名实体识别
- name: "ner_synonyms"
- name: "intent_entity_featurizer_regex"
- name: "intent_featurizer_mitie"  // 特征提取
- name: "intent_classifier_sklearn" // sklearn 的意图分类模型

      b+、(可选)使用Jieba用户自定义词典或更改Jieba默认词典:

        需要用户把jieba自定义词典放到rasa_nlu_chi/jieba_userdict/下面。系统在训练和预测时都会自动寻找并导入jieba分词

// sample_configs/config_jieba_mitie_sklearn_plus_dict_path.yml

language: "zh"

pipeline:
- name: "nlp_mitie"
  model: "data/total_word_feature_extractor_zh.dat"
- name: "tokenizer_jieba"
  default_dict: "./default_dict.big"
  user_dicts: "./jieba_userdict"
# you can put in file path or directory path as the "user_dicts" value
#  user_dicts: "./jieba_userdict/jieba_userdict.txt"
- name: "ner_mitie"
- name: "ner_synonyms"
- name: "intent_entity_featurizer_regex"
- name: "intent_featurizer_mitie"
- name: "intent_classifier_sklearn"

 

使用Rasa NLU

  • 下载安装

    1. 为防止版本冲突问题,创建Python虚拟环境

      链接:https://jingyan.baidu.com/article/b7001fe15d584c4e7282ddb2.html

      1.1 创建一个文件夹(如pythonEnv),控制台进入该文件夹,运行

python -m venv .

      1.2 完成后会在该文件夹下生成一些文件,控制台进入Scripts文件夹,运行activate即可

    2. 安装jieba、scikit-learn、mitie(版本可以自己选择

pip install jieba==0.41
pip install scikit-learn==0.19.2

      安装 MITIE 前需要先安装 Visual Studio环境、cmake、boost(缺一不可)链接:win10下安装MITIE

      #BUG# 安装Boost可能会遇到的错误:‘cl’ 不是内部或外部命令,也不是可运行的程序或批处理文件。可以搜索一下电脑里有没有cl.exe,有的话就配置环境路径 [链接];没有的话,可能是vs安装的时候,默认不安装c++,所以需要重新运行vs安装文件,点击修改,点击编程语言,选择c++,装完之后配置环境变量Path,cl命令就能正常运行了 [来源]

      安装 MITIE 可以通过GitHub下载 https://github.com/mit-nlp/MITIE.git ,解压后进入文件夹运行 python setup.py install 或者选择直接在线安装:

pip install git+https://github.com/mit-nlp/MITIE.git

    3. 下载 Rasa_nlu_chi 解压并安装

GitHub:https://github.com/crownpku/rasa_nlu_chi.git

python setup.py install

      注意:安装过程中如有些包因网络没安装上报错,可以进入下面目录再安装(实在不行手动安装),等依赖安装完后再次运行上面的命令

      注意:发现numpy、matplotlib、gevent死活安装不上,控制台一片红….后来发现是requirements中给的版本太低了,不支持python3.7

gevent==1.2.2  → 1.4.0
matplotlib==2.1.0 → 3.2.2
numpy==1.14.0 → 1.19.0

      安装成功

 

  • 前提准备

    一、MITIE模型

      由于在 pipeline 中使用了 MITIE,所以需要一个训练好的 MITIE 模型。MITIE 模型是非监督训练得到的,类似于 word2vec 中的 word embedding,需要大量的中文语料,由于训练这个模型对内存要求较高,并且耗时很长,这里直接使用了网友分享的中文 wikipedia 和百度百科语料生成的模型文件,通过下面的百度网盘可以直接下载 total_word_feature_extractor_chi.dat

链接:https://pan.baidu.com/s/1kNENvlHLYWZIddmtWJ7Pdg 密码:p4vx

      实际应用中,如果做某个特定领域的 NLU 并收集了很多该领域的语料,可以自己去训练 MITIE 模型,具体训练方法可以参考MITIE – Github。

    二、 Rasa_nlu 语料

      得到 MITIE 词向量模型以后便可以借助其训练 Rasa NLU 模型,这里需要使用标注好的数据来训练 rasa_nlu,Rasa 也很贴心的提供了数据标注平台 #rasa-nlu-trainer# 供用户标注数据。Rasa框架提供了两种NLU模型训练样本数据格式,即MarkdownJSON,我们可以将NLU训练数据保存到单独的文件或者多个文件的目录。这里我们使用项目里提供的标注好的数据(demo-rasa_zh.json)直接进行训练。

// 取自demo-rasa_zh_medical.json
[
	{
	    "text": "我生病了,不知道去哪里看病",
	    "intent": "medical_department",
	    "entities": []
    },
    {
	    "text": "头上烫烫的,感觉发烧了,该去看哪个诊所哪个科室好呢",
	    "intent": "medical_department",
	    "entities": [
	      {
	        "start": 8,
	        "end": 10,
	        "value": "发烧",
	        "entity": "disease"
	      }
	    ]
    }

]

 

  • 训练 rasa_nlu 模型并测试

     1. 将下载好的total_word_feature_extractor_zh.dat 模型放在项目data文件夹下:

      注:放在这里是因为 sample_configs/config_jieba_mitie_sklearn.yml 中设置了模型的位置,也可以自己修改

     2. Rasa_nlu 语料示例已经存在项目中(data/examples/rasa/demo-rasa_zh.json)

    3. 训练模型(控制台此时处于 rasa_nlu_chi 项目路径下)

python -m rasa_nlu.train -c sample_configs/config_jieba_mitie_sklearn.yml --data data/examples/rasa/demo-rasa_zh.json --path models

      会生成一个类似model_20170714-195758的文件。如果没有配置project_name,模型会存储在默认的 /models/default 文件夹下;如果在配置文件中指定项目名称,会存储在 /models/your_project_name 的文件夹里(注:有博主建议不要设置project_name,因为会导致各种问题 [来源]

    4. 启动rasa_nlu的后台服务

python -m rasa_nlu.server -c sample_configs/config_jieba_mitie_sklearn.yml --path models

      # Warning # 这步可能会有一个警告 YAMLLoadWarning: calling yaml.load() without Loader=… is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details. 虽然不影响什么,但看着难受就要解决掉![链接]

Rasa_NLU_Chi-master\rasa_nlu\utils\__init__.py

     5. 新开启一个控制台,使用 curl 调用服务验证(注意根据自己的模型名称修改model字段

curl -XPOST localhost:5000/parse -d '{"q":"我感觉headache该吃什么药?", "project": "", "model": "model_20201209-151953"}' | python -mjson.tool

      # BUG # 没有得到响应数据,在后台服务终端看到输出错误:builtins.UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xce in position 4: invalid continuation byte. 看起来是编码问题,但能力有限,没找到解决方法,且听说curl命令会遇到不少坑,所以改用Postman请求服务 [Postman下载及使用入门]

    6. 改用Postman调用服务验证

 

      # BUG # 使用Postman请求并得到响应,但显示 “error”: “bad input shape (1, 5)”.  解决方案是scikit-learn版本太新了…要降级一下。

      # BUG # 降级了 scikit-learn 后又报了一个错:“error”: “No module named ‘sklearn.preprocessing._label'”. 网上找到的原因:在Scikit-Learn版本中,从0.21.X升级到0.22.X重命名了模块(通常在模块名称前添加下划线字符)。例如, sklearn.preprocessing.label.LabelEncoder 变为 sklearn.preprocessing._label.LabelEncoder [来源]. 升级了不行降级了也不行?然后反反复复试验了几遍,结果就是在这两个BUG之间不断反复。后来一想,会不会是因为之前rasa-nlu是在scikit-learn==0.22.1下安装的,换成低版本的话,rasa-nlu也要重装。一试,终于对了!

 

其他

    讨论:有关spaCy + sklearn与mitie+sklearn的问题

 

参考

    ⭐使用 Rasa NLU 构建一个中文 ChatBot

    ⭐用Rasa NLU构建自己的中文NLU系统 ( MITIE模型训练、Rasa UI界面

    ⭐Python使用Rasa_NLU/Rasa_NLU_Chi将中文自然语言转化为结构化数据 (安装遇到的问题汇总

    使用Botkit和Rasa NLU构建智能聊天机器人(NLP与NLU的认识、NLU常用术语

    RASA_NLU 入门(两个坑:配置mitie 和 curl命令

    搭建一个中文rasa-nlu踩过的坑( curl命令遇到的各种错误

    一个基于Rasa Stack 带有WebUI的中文知识问答机器人

本文地址:https://blog.csdn.net/sinat_36226553/article/details/110846622