November 15, 2019

基于 Rasa 开发对话机器人 - 2

基于 Rasa 开发对话机器人 - 2

From 《Building Chatbots with Python》, C4,Building Chatbots the Hard Way...

从头开始训练、创建一个对话机器人

  • 首先有三个名词解释:

    • 意图
      • 就是判断用户说的一段话主要是想订餐?查询天气?找工作还是要租房子... 等等
    • 实体
      • 一般是指NER(命名实体识别),就是识别出待处理文本中三大类(实体类、时间类和数字类)、七小类(人名、机构名、地名、时间、日期、货币和百分比)命名实体
    • 回复
      • 根据用户意图和对话实体,生成回复的信息
  • 以创建一个占星机器人为例

    • 基于 Rasa NLU,我们来创建这个对话机器人,首先要确定一下这个 robot 应该做什么以及会做什么
      1. 首先对话机器人应该识别出来用户打招呼的内容,并回应
      2. 对话机器人需要分清楚用户是否在咨询占星相关的内容
      3. 如果用户没有主动说明自己的星座,那么对话机器人应该主动向用户发问,请用户提供他的星座。
      4. 如果用户并不清楚自己的星座,对话机器人应该询问用户的生日,然后告诉用户他所属的星座。
      5. 用户可以订阅或者取消每日星座信息
      6. 对话机器人应该可以从已有的对话信息中学习到如何生成新的对话的能力
      7. 如果用户有明显的拼写错误的话,对话机器人应该能识别出来(这点上中文可能要困难一些)
    • 定义好对话机器人的功能之后,接下来就从意图和实体识别方面看下,对话机器人需要识别哪些意图,和实体:
      1. 打招呼,用户通过打招呼的方式发起一个对话
      2. 发起占星请求,用户主动询问占星相关的内容
      3. 用户告知所属星座
      4. 用户告知生日
      5. 用户发起订阅或者取消订阅请求
    • 准备工作基本就这些,事实上你可以根据自己的兴趣设计、增减几个意图,这个定好了之后接下来我们就可以愉快的开始设计一场人类和机器人之间的对话了
  • 接下来我们来简单设计一下人类和机器人之间的聊天剧本,比如这样:

    --2019-11-15--10.10.07
    上面只是一个直白的例子,用来让设计者对整个剧本有点感觉,可以随时根据需要增减剧本的内容。另外,我们应该可以通过训练对话模型,让对话机器人自动生成可以接受的对话内容,而不是堆叠一堆的 if...else..,你懂得...

为聊天机器人准备语料

  • Rasa NLU 支持多种语料类型,包括 txt 文本、json、markdown 中的一种或几种,下面我们以 json 为例讨论。

  • 以 json 格式整理训练模型用的语料

    1. Rasa NLU 默认的 json 语料格式如下,首先是一个 dict,然后里面有一个名为 rasa_nlu_data 的 key,它的 value 是一个有三个 key 的 dict,这 3 个 key 是 3 个 list,分别叫 common_examples/regex_features/entity_synonyms', 还是上个图吧...:
      {
          "rasa_nlu_data": {
              "common_examples": [],
              "regex_features": [],
              "entity_synonyms": []
          }
      }
      
    2. 看名字就知道了,common_examples 里面会拿来放大部分的语料信息
    3. regex_features 名字上写的清楚,正则表达式的方式来帮助识别意图和实体,算是个工具
    4. entity_synonyms 则列出了定义好的实体同义词
  • 接下来我们写一个实际的文件说明:

    1. mkdir horoscope_bot

    2. cd horoscope_bot

    3. jupyter notebook

    4. 在 jupyter notebook 里面创建一个叫 data 的文件夹(如果不知道 jupyter notebook 请自行google)

    5. data 文件夹下创建一个 text 类型的文件,名字改成 data.json

    6. data.json 长成这样:

      {
          "rasa_nlu_data": {
              "common_examples": [
                  {
                      "text": "Hello", 
                      "intent": "greeting", 
                      "entities": []
                  },
                  {
                      "text": "I want to know my Horoscope",
                      "intent":"get_horoscope",
                      "entities": []
                  }, 
                  {
                      "text": "Can you please tell me my horoscope?", 
                      "intent": "get_horoscope",
                      "entities": []
                  }, 
                  {
                      "text": "Please subscribe me",
                      "intent": "subscription" 
                  }
              ],
              "regex_features": [], 
              "entity_synonyms": []
          } 
      }
      
    7. 比较简陋的一个例子,但说明问题够了,先保存到 jypter notebook,后面我们会用到的

  • 聪明的你可能已经发现了,在创建、训练一个对话机器人的过程中,coding 的工作其实并不多,只要搞清楚结构,写几行正确的代码就可以了,脏活反而是如何清洗、处理原有数据形成 Rasa 需要的语料,Corpus,Rasa 官方「曾经」提供了一个专门用来标注语料的工具叫 rasa-nlu-trainer,但他们现在忙着推自己的 Rasa-X 商业化,这个项目也就给 deprecated 了...

    • 除此之外,说到语料标注,其实 Rasa 的一个联创,其实应该也是 spaCy 的联创,Ines Montani (https://twitter.com/inesmontani),还做了一个叫 Prodigy 的工具,收费(个人 390刀,公司490刀,每年...),但体验很好,是一个python 的包,装完后启动一个本地的web server,用浏览器访问,长成下面这样,不缺银子可以去买一个:
      --2019-11-15--4.05.36