最近借用了女朋友的公号,感觉如果只是用来发文章,太浪费微信给提供的这些功能了。想了想,先从最简单的开始,做一个聊天机器人吧。

使用Python实现聊天机器人的方案有多种:AIML、chatterBot以及图灵聊天机器人和微软小冰等。

考虑到以后可能会做一些定制化的需求,这里我选择了chatterBot(github 项目地址:https://github.com/gunthercox/ChatterBot)。

chatterbot是一款python接口的,基于一系列规则和机器学习算法完成的聊天机器人。具有结构清晰,可扩展性好,简单实用的特点。

chatterBot 的工作流程如图:

chatterBot 工作流程
  1. 输入模块(input adapter)从终端或者API等输入源获取数据
  2. 输入源会被指定的逻辑处理模块(logic Adapter)分别处理,逻辑处理模块会匹配训练集中已知的最接近输入数据句子A,然后根据句子A去找到相关度最高的结果B,如果有多个逻辑处理模块返回了不同的结果,会返回一个相关度最高的结果。
  3. 输出模块(output adapter)将匹配到的结果返回给终端或者API。

值得一说的是chatterBot 是一个模块化的项目,分为 input Adapter、logic Adapter、storage Adapter、output Adapter以及Trainer 模块。

logic Adapter是一个插件式设计,主进程在启动时会将用户定义的所有逻辑处理插件添加到logic context中,然后交MultiLogicAdapter 进行处理,MultiLogicAdapter 依次调用每个 logic Adapter,logic Adapter 被调用时先执行can_process 方式判断输入是否可以命中这个逻辑处理插件。比如”今天天气怎么样“这样的问题显然需要命中天气逻辑处理插件,这时时间逻辑处理插件的can_process 则会返回False。在命中后logic Adapter 负责计算出对应的回答(Statement对象)以及可信度(confidence),MultiLogicAdapter会取可信度最高的回答,并进入下一步。

下面我们来看下 chatterBot 如何使用

chatterBot 安装&使用

安装

chatterBot 是使用Python编写的,可以使用 pip 安装:

pip install chatterbot复制代码

chatterBot 的中文对话要求Python3 以上版本,建议在Python3.x 环境下开发

测试

打开iPython,输入测试一下

In [1]: from chatterbot import ChatBot  # import ChatBotIn [2]: momo = ChatBot('Momo', trainer='chatterbot.trainers.ChatterBotCorpusTrainer')
/Users/gs/.virtualenvs/py3/lib/python3.6/site-packages/chatterbot/storage/jsonfile.py:26: UnsuitableForProductionWarning: The JsonFileStorageAdapter is not recommended for production environments.self.UnsuitableForProductionWarning  # 这里storage adapter 默认使用的是 json 格式存储数据的,如果想在服务端部署,应该避免使用这种格式,因为实在是太慢了In [3]: momo.train("chatterbot.corpus.chinese")  # 指定训练集,这里我们使用中文# 下边是对话结果
In [4]: momo.get_response('你好')
Out[4]: <Statement text:你好>In [5]: momo.get_response('怎么了')
Out[5]: <Statement text:没什么.>In [6]: momo.get_response('你知道它的所有内容吗?')
Out[6]: <Statement text:优美胜于丑陋.>In [7]: momo.get_response('你是一个程序员吗?')
Out[7]: <Statement text:我是个程序员>In [8]: momo.get_response('你使用什么语言呢?')
Out[8]: <Statement text:我经常使用 Python, Java 和 C++ .>复制代码

这时你已经可以和机器人对话了,不过现在由于训练数据太少,机器人只能返回简单的对话。

这里是默认的中文对话训练数据 中文训练数据地址:https://github.com/gunthercox/chatterbot-corpus/tree/master/chatterbot_corpus/data/chinese。

那么我们怎么添加训练数据呢?

训练机器人

chatterBot 内置了training class,自带的方法有两种,一种是使用通过输入list 来训练,比如 ["你好", "我不好"],后者是前者的回答,另一种是通过导入Corpus 格式的文件来训练。也支持自定义的训练模块,不过最终都是转为上述两种类型。

chatterBot 通过调用 train() 函数训练,不过在这之前要先用 set_trainer() 来进行设置。例如:

In [12]: from chatterbot.trainers import ListTrainer  # 导入训练模块的 ListTrainer 类In [13]: momo.get_response('你叫什么?')  # 现在是答非所问,因为在这之前我们并没有训练过
Out[13]: <Statement text:我在烤蛋糕.>In [14]: momo.set_trainer(ListTrainer)  # 指定训练方式In [15]: momo.train(['你叫什么?', '我叫魔魔!'])  # 训练In [16]: momo.get_response('你叫什么?')  # 现在机器人已经可以回答了
Out[16]: <Statement text:我叫魔魔!>复制代码

训练好的数据默认存在 ./database.db,这里使用的是 jsondb。

对 chatterBot 的介绍先到这里,具体用法可以参考文档:ChatterBot Tutorial:http://chatterbot.readthedocs.io/en/stable/tutorial.html

接下来,介绍如何在项目中使用 chatterBot。

使用 Sanic 创建项目

Sanic 是一个和类Flask 的基于Python3.5+的web框架,它编写的代码速度特别快。

除了像Flask 以外,Sanic 还支持以异步请求的方式处理请求。这意味着你可以使用新的 async/await 语法,编写非阻塞的快速的代码。

对 Sanic 不了解的可以参考我之前的一篇文章: python web 框架 Sanci 快速入门,可以在公号输入 【sanic】获取文章地址。

这里之所以使用 Sanic 是因为他和Flask 非常像,之前我一直使用Flask,并且它也是专门为Python3.5 写的,使用到了协程。

首先建个项目,这里项目我已经建好了,项目结构如下:

.
├── LICENSE
├── README.md
├── manage.py   # 运行文件 启动项目 使用 python manage.py 命令
├── momo
│   ├── __init__.py
│   ├── app.py          # 创建app 模块
│   ├── helper.py
│   ├── settings.py     # 应用配置
│   └── views
│       ├── __init__.py
│       ├── hello.py    # 测试模块
│       └── mweixin.py  # 微信消息处理模块
├── requirements.txt
└── supervisord.conf复制代码

源码我已经上传到github,有兴趣的可以看一下,也可以直接拉下来测试。
项目代码地址

我们先重点看下 hello.py 文件 和 helper.py

# hello.py
# -*- coding: utf-8 -*-from sanic import Sanic, Blueprint
from sanic.views import HTTPMethodView
from sanic.response import textfrom momo.helper import get_momo_answer  # 导入获取机器人回答获取函数blueprint = Blueprint('index', url_prefix='/')class ChatBot(HTTPMethodView):# 聊天机器人 http 请求处理逻辑async def get(self, request):ask = request.args.get('ask')# 先获取url 参数值 如果没有值,返回 '你说啥'if ask:answer = get_momo_answer(ask)return text(answer)return text('你说啥?')blueprint.add_route(ChatBot.as_view(), '/momo')复制代码
# helper.py
from chatterbot import ChatBotmomo_chat = ChatBot('Momo',# 指定存储方式 使用mongodb 存储数据storage_adapter='chatterbot.storage.MongoDatabaseAdapter',# 指定 logic adpater 这里我们指定三个logic_adapters=["chatterbot.logic.BestMatch", "chatterbot.logic.MathematicalEvaluation",  # 数学模块"chatterbot.logic.TimeLogicAdapter",   # 时间模块],input_adapter='chatterbot.input.VariableInputTypeAdapter',output_adapter='chatterbot.output.OutputAdapter',database='chatterbot',read_only=True
)def get_momo_answer(content):# 获取机器人返回结果函数response = momo_chat.get_response(content)if isinstance(response, str):return responsereturn response.text复制代码

运行命令 python manage.py 启动项目。

在浏览器访问url: http://0.0.0.0:8000/momo?ask=你是程序员吗

运行结果

到这里,我们已经启动了一个web 项目,可以通过访问url 的方式和机器人对话,是时候接入微信公号了!

接入微信公众号

前提

  1. 拥有一个可以使用的微信公众号(订阅号服务号都可以,如果没有,可以使用微信提供的测试账号)
  2. 拥有一个外网可以访问的服务器(vps 或公有云都可以 aws 新用户免费使用一年,可以试试)
  3. 服务器配置了python3 环境,(建议使用 virtualenvwrapper 配置虚拟环境)

微信设置

登录微信公众号: mp.weixin.qq.com

打开:开发>基本配置

查看公号开发信息:

公号基本信息

开启服务器配置:

设置请求url,这里是你配置的url(需要外网可访问,只能是80或443端口)

开启服务器配置

填写token和EncodingAESKey,这里我选择的是兼容模式,既有明文方便调试,又有信息加密。

配置服务器

详细配置可以参考官方文档:接入指南

如果你的 服务器地址 已经配置完成,现在点击提交应该就成功了。如果没有成功我们接下来看怎么配置服务器地址。

代码示例

先看下 微信请求的视图代码:

# -*- coding: utf-8 -*-
from __future__ import unicode_literalsfrom six import StringIOimport re
import xmltodict
from chatterbot.trainers import ListTrainerfrom sanic import Blueprint
from sanic.views import HTTPMethodView
from sanic.response import text
from sanic.exceptions import ServerErrorfrom weixin import WeixinMpAPI
from weixin.lib.WXBizMsgCrypt import WXBizMsgCryptfrom momo.settings import Configblueprint = Blueprint('weixin', url_prefix='/weixin')class WXRequestView(HTTPMethodView):def _get_args(self, request):# 获取微信请求参数,加上token  拼接为完整的请求参数params = request.raw_argsif not params:raise ServerError("invalid params", status_code=400)args = {'mp_token': Config.WEIXINMP_TOKEN,'signature': params.get('signature'),'timestamp': params.get('timestamp'),'echostr': params.get('echostr'),'nonce': params.get('nonce'),}return argsdef get(self, request):# 微信验证服务器这一步是get  请求,参数可以使用 request.raw_args 获取args = self._get_args(request)weixin = WeixinMpAPI(**args) # 这里我使用了 第三方包 python-weixin 可以直接实例化一个WeixinMpAPI对象if weixin.validate_signature(): # 验证参数合法性# 如果参数争取,我们将微信发过来的echostr参数再返回给微信,否则返回 failreturn text(args.get('echostr') or 'fail')return text('fail')blueprint.add_route(WXRequestView.as_view(), '/request')复制代码

这里处理微信请求我使用的是 我用python 写的 微信SDK python-weixin,可以使用 pip 安装:

pip install python-weixin复制代码

这个包最新版本对Python3 加密解密有点问题,可以直接从github 安装:

pip install git+https://github.com/zongxiao/python-weixin.git@py3复制代码

然后更新 app.py 文件:

# -*- coding: utf-8 -*-
from sanic import Sanic
from momo.settings import Configdef create_app(register_bp=True, test=False):# 创建app    app = Sanic(__name__)if test:app.config['TESTING'] = True# 从object 导入配置app.config.from_object(Config)register_blueprints(app)return appdef register_blueprints(app):from momo.views.hello import blueprint as hello_bpfrom momo.views.mweixin import blueprint as wx_bpapp.register_blueprint(hello_bp)# 注册 wx_bp app.register_blueprint(wx_bp)复制代码

详细代码参考github: 微信聊天机器人 momo

接入聊天机器人

现在我们公号已经接入了自己的服务,是时候接入微信聊天机器人。

微信聊天机器人的工作流程如下:

微信聊天机器人工作流程

看我们消息逻辑处理代码:

# -*- coding: utf-8 -*-
from __future__ import unicode_literalsfrom six import StringIOimport re
import xmltodict
from chatterbot.trainers import ListTrainerfrom sanic import Blueprint
from sanic.views import HTTPMethodView
from sanic.response import text
from sanic.exceptions import ServerErrorfrom weixin import WeixinMpAPI
from weixin.reply import TextReply
from weixin.response import WXResponse as _WXResponse
from weixin.lib.WXBizMsgCrypt import WXBizMsgCryptfrom momo.settings import Config
from momo.helper import validate_xml, smart_str, get_momo_answer
from momo.media import media_fetchblueprint = Blueprint('weixin', url_prefix='/weixin')appid = smart_str(Config.WEIXINMP_APPID)
token = smart_str(Config.WEIXINMP_TOKEN)
encoding_aeskey = smart_str(Config.WEIXINMP_ENCODINGAESKEY)# 关注后自动返回的文案
AUTO_REPLY_CONTENT = """
Hi,朋友!
这是我妈四月的公号,我是魔魔,我可以陪你聊天呦!
我还能"记账",输入"记账"会有惊喜呦!
<a href="https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzAwNjI5MjAzNw==&scene=124#wechat_redirect">历史记录</a>
"""class ReplyContent(object):_source = 'value'def __init__(self, event, keyword, content=None, momo=True):self.momo = momoself.event = eventself.content = contentself.keyword = keywordif self.event == 'scan':pass    @propertydef value(self):if self.momo:answer = get_momo_answer(self.content)return answerreturn ''class WXResponse(_WXResponse):auto_reply_content = AUTO_REPLY_CONTENTdef _subscribe_event_handler(self):# 关注公号后的处理逻辑self.reply_params['content'] = self.auto_reply_contentself.reply = TextReply(**self.reply_params).render()def _unsubscribe_event_handler(self):# 取关后的处理逻辑,取关我估计会哭吧passdef _text_msg_handler(self):# 文字消息处理逻辑 聊天机器人的主要逻辑event_key = 'text'content = self.data.get('Content')reply_content = ReplyContent('text', event_key, content)self.reply_params['content'] = reply_content.valueself.reply = TextReply(**self.reply_params).render()class WXRequestView(HTTPMethodView):def _get_args(self, request):params = request.raw_argsif not params:raise ServerError("invalid params", status_code=400)args = {'mp_token': Config.WEIXINMP_TOKEN,'signature': params.get('signature'),'timestamp': params.get('timestamp'),'echostr': params.get('echostr'),'nonce': params.get('nonce'),}return argsdef get(self, request):args = self._get_args(request)weixin = WeixinMpAPI(**args)if weixin.validate_signature():return text(args.get('echostr') or 'fail')return text('fail')def _get_xml(self, data):post_str = smart_str(data)# 验证xml 格式是否正确validate_xml(StringIO(post_str))return post_strdef _decrypt_xml(self, params, crypt, xml_str):# 解密消息nonce = params.get('nonce')msg_sign = params.get('msg_signature')timestamp = params.get('timestamp')ret, decryp_xml = crypt.DecryptMsg(xml_str, msg_sign,timestamp, nonce)return decryp_xml, noncedef _encryp_xml(self, crypt, to_xml, nonce):# 加密消息to_xml = smart_str(to_xml)ret, encrypt_xml = crypt.EncryptMsg(to_xml, nonce)return encrypt_xmldef post(self, request):# 获取微信服务器发送的请求参数args = self._get_args(request)weixin = WeixinMpAPI(**args)if not weixin.validate_signature(): # 验证参数合法性raise AttributeError("Invalid weixin signature")xml_str = self._get_xml(request.body)  # 获取form datacrypt = WXBizMsgCrypt(token, encoding_aeskey, appid) decryp_xml, nonce = self._decrypt_xml(request.raw_args, crypt, xml_str) # 解密xml_dict = xmltodict.parse(decryp_xml)xml = WXResponse(xml_dict)() or 'success' # 使用WXResponse 根据消息获取机器人返回值encryp_xml = self._encryp_xml(crypt, xml, nonce) # 加密消息return text(encryp_xml or xml) # 回应微信请求blueprint.add_route(WXRequestView.as_view(), '/request')复制代码

可以看到,我处理微信请求返回结果比较简单,也是使用的 python-weixin 包封装的接口,
主要的处理逻辑是 WXResponse。

这里需要注意的是,如果服务器在5秒内没有响应微信服务器会重试。为了加快响应速度,不要在服务器 将 chatterBot 的 storage adapter 设置为使用 jsondb。

上边这些就是,微信聊天机器人的主要处理逻辑,我们运行服务,示例如下:

聊天示例图

可以看到这里聊天机器人也可以做简单的数学运算和报时,是因为我在上边指定处理逻辑的时候添加了数学模块和时间模块:

momo_chat = ChatBot('Momo',# 指定存储方式 使用mongodb 存储数据storage_adapter='chatterbot.storage.MongoDatabaseAdapter',# 指定 logic adpater 这里我们指定三个logic_adapters=["chatterbot.logic.BestMatch", "chatterbot.logic.MathematicalEvaluation",  # 数学模块"chatterbot.logic.TimeLogicAdapter",   # 时间模块],input_adapter='chatterbot.input.VariableInputTypeAdapter',output_adapter='chatterbot.output.OutputAdapter',database='chatterbot',read_only=True
)复制代码

到这里,微信机器人的搭建就完成了,详细代码已经长传到了 github: https://github.com/gusibi/momo/tree/chatterbot,感兴趣的可以参考一下。

参考链接

  • ChatterBot 项目地址:https://github.com/gunthercox/ChatterBot
  • ChatterBot Tutorial:http://chatterbot.readthedocs.io/en/stable/tutorial.html
  • 用Python快速实现一个聊天机器人:http://www.jianshu.com/p/d1333fde266f
  • 基于Python-ChatterBot搭建不同adapter的聊天机器人:https://ask.hellobi.com/blog/guodongwei1991/7626
  • 擁有自動學習的 Python 機器人 - ChatterBot:https://kantai235.github.io/2017/03/16/ChatterBotTeaching/
  • 使用 ChatterBot构建聊天机器人:https://www.biaodianfu.com/chatterbot.html
  • python-weixin sdk: https://github.com/gusibi/python-weixin

预告

这里,聊天机器人还是比较简单的只能回复简单的对话,下一篇将要结束如何在公号训练机器人以及一个更实用的功能,如何让公号变成一个博客写作助手。


最后,感谢女朋友支持。

欢迎关注(April_Louisa) 请我喝芬达
欢迎关注
请我喝芬达

微信公号 DIY:一小时搭建微信聊天机器人相关推荐

  1. 微信公众号上部署自己训练的聊天机器人(腾讯云服务器+TensorFlow2.1+Django3.1)

    文章目录 前言 1. 模型介绍 1.1 Encoder-Decoder框架 1.2 Attention机制 1.3 代码实现 2. 安装依赖库 3. 模型部署 4. 测试 前言   哈哈,重头戏终于来 ...

  2. 当“低代码”遇上“微信公众号”,当“系统搭建”遇上“社交流量”

    微信作为一个社交媒体平台,人均单日使用时间达到了85.8分钟,其推出的公众平台凭借着便捷灵活的操作方式,受到广大企业宣传的青睐和重视,成为企业对外传播品牌文化,市场营销的重要途径. 腾讯最新财报显示: ...

  3. 公众号文章排版神器,Markdown一键排版,微信公号文章里代码的美化排版

    自己经常在简书,掘金上面写一些技术文章,喜欢用Markdown编辑器.最近需要把自己的一些技术博客文章发表到微信公众号文章里. 刚开始偷懒,就直接把用markdown写的技术博客复制粘贴到公号里(大多 ...

  4. 微信公众号开发系列-玩转微信开发-目录汇总

    引言 最遗憾的不是把理想丢在路上,而是理想从未上路. 每一个将想法变成现实的人,都值得称赞和学习.致正在奔跑的您! 在现在这个无处不在的互联网背景下,各种应用已不再仅仅局限于网页或桌面应用了,IOS. ...

  5. 微信菜单 html页面添加的,微信公众号添加菜单栏外部链接(微信添加外部链接方法)...

    很多微信公号新手用户想通过自己的公众号来推广其他的连接地址,对于认证用户来说可以直接添加,但对于未认证的新手用户来说不知道该怎么做,那么现在就来告诉大家添加外部链接的方法吧. 方法如下: 1.首先打开 ...

  6. 微信公众号迁移丨如何迁移微信公众号 最详细公众号迁移流程和方法

    微信公众号迁移丨如何迁移微信公众号 最详细微信公众号迁移流程和方法 微信公众号如何迁移?微信公众号迁移公证书需要准备哪些资料? 怎么迁移微信公众号! 教你迁移微信公众号_迁移完成后,原账号就注销了,无 ...

  7. 【微信公众号开发】八、微信JS发起支付

    重要声明:本文章仅仅代表了作者个人对此观点的理解和表述.读者请查阅时持自己的意见进行讨论. 目录 本系列博文还包含了下面的博客: [微信公众号开发]一.运作及配置流程简介 [微信公众号开发]二.解析微 ...

  8. 微信公众号数据2019_如何制作微信公众号图文素材 微信公众号采集器好用吗

    现在有很多人都会通过微信公众号来发布文章.图片,这时候就需要使用一些编辑技巧了.下面拓途数据就和大家一同来看看如何制作微信公众号图文素材,微信公众号采集器好用吗? 微信公众号图文素材 如何制作微信公众 ...

  9. url 微信公众号开发 配置失效_微信公众号开发之授权登录

    一.UnionId和openId 微信登录最重要的两个返回信息,一个是UnionId,一个是OpenId.两者之间有着必然的联系. UnionID机制的作用说明:如果开发者拥有多个移动应用.网站应用和 ...

最新文章

  1. static关键字了解解析
  2. J2ME开发心得-数组的使用
  3. bzoj 3343: 教主的魔法
  4. 一本书让你懂得人生的价值
  5. 爬虫:Charles证书设置为系统信任证书(root)
  6. 在非容器(集群)环境下运行dapr
  7. C语言试题五十六之计算并输出给定整数n的所有因子(不包括1与自身)之和。规定n的值不大于1000。
  8. linux ftp 操作命令
  9. 7-54 查验身份证 (15 分)
  10. visual studio 代码提示插件_程序员请收好:10个非常有用的Visual Studio Code插件
  11. Linux基金会宣布行业进一步支持Akraino Edge Stack
  12. Xgboost和lightgbm的区别
  13. mysql集群系统_轻松构建Mysql高可用集群系统
  14. C语言经典100道编程练习题
  15. 获取图片的十六进制颜色码(keynote/ppt取色器)
  16. windows 双开微信
  17. fuzzy extractor 模糊提取器的代码解读和实现
  18. 瞳孔中的视觉刺激提取大脑中ERD/ERS
  19. PHP中的PEAR是什么?
  20. 2020-09-15,小米笔试,java

热门文章

  1. bldc不同载波频率_有刷CD电机好用还是无刷BLDC电机好用?该选那个?
  2. 查询课程名称为“数学“,且分数低于60的学生姓名和分数(不重点)
  3. java模拟电梯程序_Java编写的电梯模拟系统《结对作业》
  4. 微信公众号获取OpenId(未授权)(需要关注公众号)
  5. 解决UnicodeDecodeError: 'gbk' codec can't decode byte 0xaa in position 212: illegal multibyte sequence
  6. 甜点cc的2022走心总结
  7. 纪念中国人工智能学会成立40周年
  8. OpenCV:如何去除票据上的印章
  9. 【矩阵论笔记】线性变换在不同基偶下的矩阵之间的关系
  10. 如何在react-native中使用阿里iconfont矢量图标