最近借用了女朋友的公号,感觉如果只是用来发文章,太浪费微信给提供的这些功能了。想了想,先从最简单的开始,做一个聊天机器人吧。
最近借用了女朋友的公号,感觉如果只是用来发文章,太浪费微信给提供的这些功能了。想了想,先从最简单的开始,做一个聊天机器人吧。
使用Python实现聊天机器人的方案有多种:AIML、chatterBot以及图灵聊天机器人和微软小冰等。
考虑到以后可能会做一些定制化的需求,这里我选择了 chatterBot(github 项目地址:https://github.com/gunthercox/ChatterBot)。
chatterbot是一款python接口的,基于一系列规则和机器学习算法完成的聊天机器人。具有结构清晰,可扩展性好,简单实用的特点。
chatterBot 的工作流程如图:
输入模块(input adapter)从终端或者API等输入源获取数据
输入源会被指定的逻辑处理模块(logic Adapter)分别处理,逻辑处理模块会匹配训练集中已知的最接近输入数据句子A,然后根据句子A去找到相关度最高的结果B,如果有多个逻辑处理模块返回了不同的结果,会返回一个相关度最高的结果。
输出模块(output adapter)将匹配到的结果返回给终端或者API。
值得一说的是chatterBot 是一个模块化的项目,分为 input Adapter、logic Adapter、storage Adapter、output Adapter以及Trainer 模块。
logic Adapter是一个插件式设计,主进程在启动时会将用户定义的所有逻辑处理插件添加到logic context中,然后交MultiLogicAdapter 进行处理,MultiLogicAdapter 依次调用每个 logic Adapter,logic Adapter 被调用时先执行canprocess 方式判断输入是否可以命中这个逻辑处理插件。比如”今天天气怎么样“这样的问题显然需要命中天气逻辑处理插件,这时时间逻辑处理插件的canprocess 则会返回False。在命中后logic Adapter 负责计算出对应的回答(Statement对象)以及可信度(confidence),MultiLogicAdapter会取可信度最高的回答,并进入下一步。
展开全文
下面我们来看下 chatterBot 如何使用
chatterBot 安装&使用 安装
chatterBot 是使用Python编写的,可以使用 pip 安装:
pip install chatterbot
chatterBot 的中文对话要求Python3 以上版本,建议在Python3.x 环境下开发
chatterBot 的中文对话要求Python3 以上版本,建议在Python3.x 环境下开发
打开iPython,输入测试一下
In[1]:from chatterbot import ChatBot# import ChatBot
In[2]:momo =ChatBot('Momo',trainer='chatterbot.trainers.ChatterBotCorpusTrainer')
/Users/gs/.virtualenvs/py3/lib/python3.6/site-packages/chatterbot/storage/jsonfile.py:26:UnsuitableForProductionWarning:TheJsonFileStorageAdapteris not recommended forproduction environments.
self.UnsuitableForProductionWarning# 这里storage adapter 默认使用的是 json 格式存储数据的,如果想在服务端部署,应该避免使用这种格式,因为实在是太慢了
In[3]:momo.train("chatterbot.corpus.chinese")# 指定训练集,这里我们使用中文
# 下边是对话结果
In[4]:momo.get_response('你好')
Out[4]:<Statementtext:你好>
In[5]:momo.get_response('怎么了')
Out[5]:<Statementtext:没什么.>
In[6]:momo.get_response('你知道它的所有内容吗?')
Out[6]:<Statementtext:优美胜于丑陋.>
In[7]:momo.get_response('你是一个程序员吗?')
Out[7]:<Statementtext:我是个程序员>
In[8]:momo.get_response('你使用什么语言呢?')
Out[8]:<Statementtext:我经常使用Python,Java和C++.>
这时你已经可以和机器人对话了,不过现在由于训练数据太少,机器人只能返回简单的对话。
这里是默认的中文对话训练数据 中文训练数据地址:
https://github.com/gunthercox/chatterbot-corpus/tree/master/chatterbot_corpus/data/chinese。
这里是默认的中文对话训练数据 中文训练数据地址:
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]:<Statementtext:我在烤蛋糕.>
In[14]:momo.set_trainer(ListTrainer)# 指定训练方式
In[15]:momo.train(['你叫什么?','我叫魔魔!'])# 训练
In[16]:momo.get_response('你叫什么?')# 现在机器人已经可以回答了
Out[16]:<Statementtext:我叫魔魔!>
训练好的数据默认存在 ./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 不了解的可以参考我之前的一篇文章: ,可以在公号输入 【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,有兴趣的可以看一下,也可以直接拉下来测试。项目代码地址:https://github.com/gusibi/momo/tree/chatterbot
我们先重点看下 hello.py文件 和 helper.py。
# hello.py
# -*- coding: utf-8 -*-
fromsanic importSanic,Blueprint
fromsanic.views importHTTPMethodView
fromsanic.response importtext
frommomo.helper importget_momo_answer # 导入获取机器人回答获取函数
blueprint =Blueprint('index',url_prefix='/')
classChatBot(HTTPMethodView):
# 聊天机器人 http 请求处理逻辑
async defget(self,request):
ask =request.args.get('ask')
# 先获取url 参数值 如果没有值,返回 '你说啥'
ifask:
answer =get_momo_answer(ask)
returntext(answer)
returntext('你说啥?')
blueprint.add_route(ChatBot.as_view(),'/momo')
# helper.py
fromchatterbot importChatBot
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
)
defget_momo_answer(content):
# 获取机器人返回结果函数
response =momo_chat.get_response(content)
ifisinstance(response,str):
returnresponse
returnresponse.text
运行命令 python manage.py启动项目。
在浏览器访问url: http://0.0.0.0:8000/momo?ask=你是程序员吗
到这里,我们已经启动了一个web 项目,可以通过访问url 的方式和机器人对话,是时候接入微信公号了!
接入微信公众号 前提
拥有一个可以使用的微信公众号(订阅号服务号都可以,如果没有,可以使用微信提供的测试账号)
拥有一个外网可以访问的服务器(vps 或公有云都可以 aws 新用户免费使用一年,可以试试)
服务器配置了python3 环境,(建议使用 virtualenvwrapper 配置虚拟环境)
登录微信公众号(https://mp.weixin.qq.com)
打开:开发>基本配置
查看公号开发信息:
开启服务器配置:
设置请求url,这里是你配置的url(需要外网可访问,只能是80或443端口)
填写token和EncodingAESKey,这里我选择的是兼容模式,既有明文方便调试,又有信息加密。
详细配置可以参考官方文档:接入指南(https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432)
如果你的 服务器地址已经配置完成,现在点击提交应该就成功了。如果没有成功我们接下来看怎么配置服务器地址。
代码示例
先看下 微信请求的视图代码:
# -*- coding: utf-8 -*-
from__future__ importunicode_literals
fromsix importStringIO
importre
importxmltodict
fromchatterbot.trainers importListTrainer
fromsanic importBlueprint
fromsanic.views importHTTPMethodView
fromsanic.response importtext
fromsanic.exceptions importServerError
fromweixin importWeixinMpAPI
fromweixin.lib.WXBizMsgCryptimportWXBizMsgCrypt
frommomo.settings importConfig
blueprint =Blueprint('weixin',url_prefix='/weixin')
classWXRequestView(HTTPMethodView):
def_get_args(self,request):
# 获取微信请求参数,加上token 拼接为完整的请求参数
params =request.raw_args
ifnotparams:
raiseServerError("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'),
}
returnargs
defget(self,request):
# 微信验证服务器这一步是get 请求,参数可以使用 request.raw_args 获取
args =self._get_args(request)
weixin =WeixinMpAPI(**args)# 这里我使用了 第三方包 python-weixin 可以直接实例化一个WeixinMpAPI对象
ifweixin.validate_signature():# 验证参数合法性
# 如果参数争取,我们将微信发过来的echostr参数再返回给微信,否则返回 fail
returntext(args.get('echostr')or'fail')
returntext('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 -*-
fromsanic importSanic
frommomo.settings importConfig
defcreate_app(register_bp=True,test=False):
# 创建app
app =Sanic(__name__)
iftest:
app.config['TESTING']=True
# 从object 导入配置
app.config.from_object(Config)
register_blueprints(app)
returnapp
defregister_blueprints(app):
frommomo.views.hello importblueprint ashello_bp
frommomo.views.mweixin importblueprint aswx_bp
app.register_blueprint(hello_bp)
# 注册 wx_bp
app.register_blueprint(wx_bp)
详细代码参考github: 微信聊天机器人 momo(https://github.com/gusibi/momo/tree/chatterbot)
接入聊天机器人
现在我们公号已经接入了自己的服务,是时候接入微信聊天机器人。
微信聊天机器人的工作流程如下:
看我们消息逻辑处理代码:
# -*- coding: utf-8 -*-
from__future__ importunicode_literals
fromsix importStringIO
importre
importxmltodict
fromchatterbot.trainers importListTrainer
fromsanic importBlueprint
fromsanic.views importHTTPMethodView
fromsanic.response importtext
fromsanic.exceptions importServerError
fromweixin importWeixinMpAPI
fromweixin.reply importTextReply
fromweixin.response importWXResponseas_WXResponse
fromweixin.lib.WXBizMsgCryptimportWXBizMsgCrypt
frommomo.settings importConfig
frommomo.helper importvalidate_xml,smart_str,get_momo_answer
frommomo.media importmedia_fetch
blueprint =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>
"""
classReplyContent(object):
_source ='value'
def__init__(self,event,keyword,content=None,momo=True):
self.momo =momo
self.event =event
self.content =content
self.keyword =keyword
ifself.event =='scan':
pass
@property
defvalue(self):
ifself.momo:
answer =get_momo_answer(self.content)
returnanswer
return''
classWXResponse(_WXResponse):
auto_reply_content =AUTO_REPLY_CONTENT
def_subscribe_event_handler(self):
# 关注公号后的处理逻辑
self.reply_params['content']=self.auto_reply_content
self.reply =TextReply(**self.reply_params).render()
def_unsubscribe_event_handler(self):
# 取关后的处理逻辑,取关我估计会哭吧
pass
def_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.value
self.reply =TextReply(**self.reply_params).render()
classWXRequestView(HTTPMethodView):
def_get_args(self,request):
params =request.raw_args
ifnotparams:
raiseServerError("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'),
}
returnargs
defget(self,request):
args =self._get_args(request)
weixin =WeixinMpAPI(**args)
ifweixin.validate_signature():
returntext(args.get('echostr')or'fail')
returntext('fail')
def_get_xml(self,data):
post_str =smart_str(data)
# 验证xml 格式是否正确
validate_xml(StringIO(post_str))
returnpost_str
def_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)
returndecryp_xml,nonce
def_encryp_xml(self,crypt,to_xml,nonce):
# 加密消息
to_xml =smart_str(to_xml)
ret,encrypt_xml =crypt.EncryptMsg(to_xml,nonce)
returnencrypt_xml
defpost(self,request):
# 获取微信服务器发送的请求参数
args =self._get_args(request)
weixin =WeixinMpAPI(**args)
ifnotweixin.validate_signature():# 验证参数合法性
raiseAttributeError("Invalid weixin signature")
xml_str =self._get_xml(request.body)# 获取form data
crypt =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)# 加密消息
returntext(encryp_xml orxml)# 回应微信请求
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
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)
请我喝芬达
欢迎关注(April_Louisa)
tips
2017 华为开发者大赛交流群」了解更多参赛信息,和小伙伴们一起组队参赛。
tips
2017 华为开发者大赛交流群」了解更多参赛信息,和小伙伴们一起组队参赛。