天气查询是聊天机器人里面常见和常用的功能之一,本文基于 Rasa 构建一个中文的天气查询机器人。幸运的是,这件事已经有同学操作过了:使用 Rasa 构建天气查询机器人,不仅有文章,还有训练数据和相关代码,以及Web UI查询界面,相当完备。而问题在于, Rasa的版本跳跃貌似比较大,我接触Rasa比较晚,第一篇文章《Rasa入坑指南一:初识Rasa》使用的Rasa版本是 1.2.3,貌似目前看到的很多实战文章都是0.x的 Rasa 相关版本,在一些操作方面好像有不小的区别,包括之前罗列的一些参考文章,以及这篇天气查询机器人实战教程。

学习一个项目最好是首先跑通它,从该项目的Github主页入手:https://github.com/howl-anderson/WeatherBot,一个使用 Rasa 技术栈 (Rasa NLU, Rasa Core, Rasa Core SDK)构建的简单的中文天气情况问询机器人(chatbot), 附带有基于 Web 的用户界面(UI) http://weather_bot.xiaoquankong.ai/ ,不过目前这个demo页面可以访问,但是chatbot demo无法使用,具体原因不详。该项目采用了组件相互隔离来构建整个系统:

整个系统分成 4 个 APP:

组件 仓库地址 说明
User Interface WeatherBot_UI 负责提供用户 UI ,方便用户使用,Rasa Core 支持和多种即时通讯软件(IM)的整合,Rasa Core 提供了一种称之为 Channel 的特性来方便接入 API。
Diaglog Manager WeatherBot_Core 负责管理整个对话的流程,它会主动调用 NLU 来解析用户的意图和提取相关的实体,在需要执行业务动作的时候会调用 Action Server 执行具体的业务动作。
NLU WeatherBot_NLU 负责理解用户的意图和提取相关的实体。
Action Server WeatherBot_Action 负责执行自定义 Action (通常都是具体的业务动作,在本项目中是请求远程服务器以查询天气情况)

这个查询机器人可以根据用户提供的城市(北京、上海等)和日期(明天、后天等),查询出相应的天气预报,作者也给出了受限功能说明,很细致:

  • 受限于天气数据提供方的能力,这个机器人只能查询 中国大陆地区市级城市 三天以内 (今天,明天,后天) 的气象数据,不能查询过去(昨天,前天)等历史数据。
  • 受限于开发时间,这个机器人 不提供 诸如 这个星期五、下个星期一 这种需要计算才能得到日期给定方式。也 不能提供 诸如 绝对日期:三月一号、六一儿童节日 这种日期的查询能力。
  • 因为使用的是免费的天气查询接口,所以 会有配额限制,可能会因为 超出调用次数 ,而在一个小时内不能用。同时网络查询接口可能存在不稳定因素,导致 没有结果返回或者出现异常尝试多次重新发送请求可解决问题

首先看一下 WeatherBot NLU, 按 github 上面的步骤执行即可,其中 Rasa NLU 训练时用到了MITIE,需要一份中文训练好的数据:total_word_feature_extractor.dat ,这份数据我没有用作者提供的,而是CrownPKU 这篇文章中《用Rasa NLU构建自己的中文NLU系统》中提供的用中文wikipedia和百度百科语料生成的一个total_word_feature_extractor_chi.dat,文章中有百度网盘链接,可以自行下载使用。

其他部分基本上按照该项目github的说明文档操作即可,其中也涉及到了新知天气免费api的申请,各部分跑起来之后,我在本地局域网下测试了这个Demo:

对于当前版本的Rasa(1.x),貌似这种组织方式不灵,我重新组合了一个版本,放到Github上了:WeatherBot_Rasa

使用的方法比较简单:

git clone https://github.com/panyang/WeatherBot_Rasa
cd WeatherBot_Rasa/
virtualenv -p python3 venv
source venv/bin/activate
pip install -r raw_requirements.txt 

如果一切无误,会显示安装成功如下这些Python模块:

Successfully installed ConfigArgParse-0.15.1 Jinja2-2.10.3 MarkupSafe-1.1.1 Pillow-6.2.0 PyJWT-1.7.1 PyYAML-5.1.2 SQLAlchemy-1.3.10 Werkzeug-0.16.0 absl-py-0.8.1 aiofiles-0.4.0 aiohttp-3.6.2 apscheduler-3.6.1 astor-0.8.0 async-generator-1.10 async-timeout-3.0.1 attrs-19.3.0 boto3-1.9.253 botocore-1.12.253 bz2file-0.98 cachetools-3.1.1 certifi-2019.9.11 cffi-1.13.0 chardet-3.0.4 click-7.0 cloudpickle-1.2.2 colorclass-2.2.0 coloredlogs-10.0 colorhash-1.0.2 cryptography-2.8 cycler-0.10.0 decorator-4.4.0 dill-0.3.1.1 dnspython-1.16.0 docopt-0.6.2 docutils-0.15.2 dopamine-rl-2.0.5 fbmessenger-6.0.0 flask-1.1.1 flask-cors-3.0.8 future-0.18.1 gast-0.2.2 gevent-1.4.0 gin-config-0.2.1 google-api-python-client-1.7.11 google-auth-1.6.3 google-auth-httplib2-0.0.3 google-pasta-0.1.7 googleapis-common-protos-1.6.0 greenlet-0.4.15 grpcio-1.24.1 gunicorn-19.9.0 gym-0.15.3 h11-0.8.1 h2-3.1.1 h5py-2.10.0 hpack-3.0.0 httpcore-0.3.0 httplib2-0.14.0 httptools-0.0.13 humanfriendly-4.18 hyperframe-5.2.0 idna-2.8 idna-ssl-1.1.0 itsdangerous-1.1.0 jieba-0.39 jmespath-0.9.4 jsonpickle-1.2 jsonschema-2.6.0 kafka-python-1.4.7 keras-applications-1.0.8 keras-preprocessing-1.1.0 kfac-0.2.0 kiwisolver-1.1.0 markdown-3.1.1 matplotlib-3.1.1 mattermostwrapper-2.1 mesh-tensorflow-0.1.4 mitie-0.7.0 mpmath-1.1.0 multidict-4.5.2 networkx-2.4 numpy-1.17.3 oauth2client-4.1.3 opencv-python-4.1.1.26 packaging-19.2 pika-1.0.1 promise-2.2.1 prompt-toolkit-2.0.10 protobuf-3.10.0 psutil-5.6.3 pyasn1-0.4.7 pyasn1-modules-0.2.7 pycparser-2.19 pydot-1.4.1 pyglet-1.3.2 pykwalify-1.7.0 pymongo-3.9.0 pyparsing-2.4.2 pypng-0.0.20 python-crfsuite-0.9.6 python-dateutil-2.8.0 python-engineio-3.9.3 python-socketio-4.3.1 python-telegram-bot-11.1.0 pytz-2019.3 questionary-1.3.0 rasa-1.4.0 rasa-sdk-1.4.0 redis-3.3.11 requests-2.22.0 requests-async-0.5.0 requests-toolbelt-0.9.1 rfc3986-1.3.2 rocketchat-API-0.6.35 rsa-4.0 ruamel.yaml-0.15.100 s3transfer-0.2.1 sanic-19.9.0 sanic-cors-0.9.9.post1 sanic-jwt-1.3.2 sanic-plugins-framework-0.8.2 scikit-learn-0.20.4 scipy-1.3.1 six-1.12.0 sklearn-crfsuite-0.3.6 slackclient-1.3.2 sympy-1.4 tabulate-0.8.5 tensor2tensor-1.14.1 tensorboard-1.14.0 tensorflow-1.14.0 tensorflow-datasets-1.2.0 tensorflow-estimator-1.14.0 tensorflow-gan-1.0.0.dev0 tensorflow-metadata-0.15.0 tensorflow-probability-0.7.0 termcolor-1.1.0 terminaltables-3.1.0 tqdm-4.36.1 twilio-6.32.0 typing-extensions-3.7.4 tzlocal-2.0.0 ujson-1.35 uritemplate-3.0.0 urllib3-1.25.6 uvloop-0.13.0 wcwidth-0.1.7 webexteamssdk-1.2 websocket-client-0.54.0 websockets-8.0.2 wrapt-1.11.1 yarl-1.3.0

训练前请在data目录下放一份:
total_word_feature_extractor.dat

然后运行命令:

rasa train

训练完毕后提示在models目录下生成一个带时间戳的模型:

Your Rasa model is trained and saved at '/home/textminer/rasa/github/WeatherBot_Rasa/models/20191021-075519.tar.gz'.

这个时候可以通过 shell 先测试一下 rasa nlu 模型:

rasa shell nlu

可以直接在shell里测试一下这个NLU模型:

NLU model loaded. Type a message and press enter to parse it.
Next message:
南京天气
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 0.531 seconds.
Prefix dict has been built succesfully.
{
  "intent": {
    "name": "weather_address",
    "confidence": 0.6241327029086164
  },
  "entities": [
    {
      "entity": "address",
      "value": "南京",
      "start": 0,
      "end": 2,
      "confidence": null,
      "extractor": "MitieEntityExtractor"
    }
  ],
  "intent_ranking": [
    {
      "name": "weather_address",
      "confidence": 0.6241327029086164
    },
    {
      "name": "weather_address_date-time",
      "confidence": 0.335181045100534
    },
    {
      "name": "weather",
      "confidence": 0.018341411952395713
    },
    {
      "name": "goodbye",
      "confidence": 0.011158568993978163
    },
    {
      "name": "weather_date-time",
      "confidence": 0.005973027654893278
    },
    {
      "name": "greet",
      "confidence": 0.005213243389582762
    }
  ],
  "text": "南京天气"
}
Next message:
南京后天天气
{
  "intent": {
    "name": "weather_address_date-time",
    "confidence": 0.8035961060556133
  },
  "entities": [
    {
      "entity": "address",
      "value": "南京",
      "start": 0,
      "end": 2,
      "confidence": null,
      "extractor": "MitieEntityExtractor"
    },
    {
      "entity": "date-time",
      "value": "后天",
      "start": 2,
      "end": 4,
      "confidence": null,
      "extractor": "MitieEntityExtractor"
    }
  ],
  "intent_ranking": [
    {
      "name": "weather_address_date-time",
      "confidence": 0.8035961060556133
    },
    {
      "name": "weather_address",
      "confidence": 0.15077106814519672
    },
    {
      "name": "weather_date-time",
      "confidence": 0.027055046492687005
    },
    {
      "name": "weather",
      "confidence": 0.00967189410739954
    },
    {
      "name": "goodbye",
      "confidence": 0.005244734275551237
    },
    {
      "name": "greet",
      "confidence": 0.003661150923551948
    }
  ],
  "text": "南京后天天气"
}
Next message:
你好
{
  "intent": {
    "name": "greet",
    "confidence": 0.7938494377878306
  },
  "entities": [],
  "intent_ranking": [
    {
      "name": "greet",
      "confidence": 0.7938494377878306
    },
    {
      "name": "goodbye",
      "confidence": 0.13593726937916922
    },
    {
      "name": "weather_date-time",
      "confidence": 0.022534878642556908
    },
    {
      "name": "weather",
      "confidence": 0.020089607170533996
    },
    {
      "name": "weather_address_date-time",
      "confidence": 0.014591517459516744
    },
    {
      "name": "weather_address",
      "confidence": 0.01299728956039253
    }
  ],
  "text": "你好"
}

不过要跑通全流程,需要先将 WeatherBot_Action 跑起来,可以按该 github 项目的说明申请心知天气的api,将这个 action 项目跑起来。然后可以通过 "rasa shell" 命令测试全流程了:

Bot loaded. Type a message and press enter (use '/stop' to exit): 
Your input ->  你好                                                             
Building prefix dict from the default dictionary ...
Loading model from cache /tmp/jieba.cache
Loading model cost 0.553 seconds.
Prefix dict has been built succesfully.
你好,请说出需要提供天气预测服务的地点和时间
Your input ->  南京                                                             
什么时候?
Your input ->  后天                                                             
正在查询中,请稍后 ...

            南京 后天 (2019-10-23) 的天气情况为:白天:多云;夜晚:多云;气温:23-15 °C
        
Your input ->  明天                                                             
正在查询中,请稍后 ...

            南京 明天 (2019-10-22) 的天气情况为:白天:多云;夜晚:多云;气温:23-15 °C
        
Your input ->  今天                                                             
正在查询中,请稍后 ...

            南京 今天 (2019-10-21) 的天气情况为:白天:晴;夜晚:多云;气温:25-15 °C

最后可以启动 Rasa 的 API 接口:

rasa run -m models --enable-api

我通过rest api的方式把这个rasa 天气查询接口对接到"Python时代与机器学习"公众号了,这个公众号之后将主要作为Rasa聊天机器人的测试账号,欢迎关注:

这是几个天气查询测试的例子,欢迎测试:

注:原创文章,转载请注明出处及保留链接“我爱自然语言处理”:https://www.52nlp.cn

本文链接地址:Rasa入坑指南二:基于 Rasa 构建天气查询机器人 https://www.52nlp.cn/?p=12311

作者 52nlp

《Rasa 入坑指南二:基于 Rasa 构建天气查询机器人》有12条评论
  1. rasa run -m models --enable-api部署之后,怎么访问? 看了官方的http api 还是不清楚怎么访问。没有看到一个api中既包含nlu和core功能。。。。求指教下。比如"北京今天天气怎么样"。需要现有调用哪些api才能够实现这个完整的对话???多谢!

    [回复]

    52nlp 回复:

    这个api只暴露了最外层的一个接口,触发之后内部模块之间也有相互的调用

    [回复]

    Jason 回复:

    能否更详细些。比如您部署到微信公众号上,这期间先后调用了哪些API,内部的处理逻辑是怎么样的?求指教下。

    [回复]

    52nlp 回复:

    这个你直接部署测试一下就清楚了。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注