天气查询是聊天机器人里面常见和常用的功能之一,本文基于 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聊天机器人的测试账号,欢迎关注:
这是几个天气查询测试的例子,欢迎测试:
注:原创文章,转载请注明出处及保留链接“我爱自然语言处理”:http://www.52nlp.cn
本文链接地址:Rasa入坑指南二:基于 Rasa 构建天气查询机器人 http://www.52nlp.cn/?p=12311