The answer to life, universe and everything is 42 --deepThought
今年的F8 开发者大会,Facebook大谈他们看好聊天机器人的未来 。通过这些聊天机器人,用户可以在交谈中完成许多任务,在线购物,航班查询、组织会议等。如此一来,用户再不必下载一堆app,而只需打开一个简单的文本对话框,你就可以对着它说:神灯神灯,我的第三个愿望是我还要三个愿望
你是不定想到了:hi siri
说不定又是一次用户入口的重新洗牌,这样就不难解释科技界的大公司们蜂拥而至了
缘起
我一直对自然语言处理(NLP)兴致勃勃,这大半年对机器学习/深度学习兴致盎然,而聊天机器人恰好结合了两者。
对聊天机器人最早的兴趣可能追溯到大学。当时关注过一段时间风靡人人网的小黄鸡,后来发现它只是调用了一个闭源的云服务,转而折腾AIML。
最近下班后喜欢到星巴克看看课程(近期在跟udacity的这门课:Deep Learning),写写博客,今天也是如此,怕往后的时间会更多花在深度学习上(对RNN尤其感兴趣),这几天陆续对折腾过的聊天机器人做个笔记
聊天机器人 & 开源框架
目前聊天这块的云服务倒是不少,facebook也好微软也好,都有自己的框架。相比而言,开源的项目倒是没有很耀眼的,也许是起步不久的原因,大神们还在憋大招。
我们到github逛一圈,发现ChatterBot看起来挺酷, 项目活跃, 文档清晰,代码也算干净利落。
由于项目还小,源码读起来十分容易,作为构建自己的智能聊天机器人的脚手架是不错的
ChatterBot
ChatterBot是一个基于机器学习的聊天机器人引擎,构建在python上,可以从已有的对话中学习
, 该项目的设计允许它接入任何语言
原理
一个未经训练的ChatterBot机器人,并没有与用户交谈所需的知识。每当用户输入一句话,机器人将存下它,同时也存下答复的句子。 随着机器人接受的输入的增加,它能够回答的问题的数量和准确度都会相应提升.程序是如何响应用户输入的呢?首先从已知句子中匹配出与用户输入最相近的句子(如何衡量相近
, 大家可以想想),之后找到最有可能的回复,那么如何得出最有可能
的回复呢?由所有和机器交流过的人们,对这个输入问题(匹配过的)的各个回答的频率决定
安装和使用
安装
pip install chatterbot
基本使用
from chatterbot import ChatBot
from chatterbot.training.trainers import ChatterBotCorpusTrainer
chatbot = ChatBot("myBot")
chatbot.set_trainer(ChatterBotCorpusTrainer)
# 使用英文语料库训练它
chatbot.train("chatterbot.corpus.english")
# 开始对话
chatbot.get_response("Hello, how are you today?")
采用中文语料库
我已经给这个填充了中文语料库,作者把我的提交合并到master了,目前还没有打包发布到pypi,如果你想使用默认的中文预料来训练你需要这样做:
https://github.com/gunthercox/ChatterBot
pip3 install./ChatterBot # 需要使用python3,否则会有unicode问题,暂时没空做python2的兼容
使用中文语料库来训练机器人
from chatterbot import ChatBot
from chatterbot.training.trainers import ChatterBotCorpusTrainer
deepThought = ChatBot("deepThought")
deepThought.set_trainer(ChatterBotCorpusTrainer)
# 使用中文语料库训练它
deepThought.train("chatterbot.corpus.chinese") # 语料库
开始玩耍
print(deepThought.get_response("很高兴认识你"))
print(deepThought.get_response("嗨,最近如何?"))
print(deepThought.get_response("复杂优于晦涩")) #语出 The Zen of Python
print(deepThought.get_response("面对模棱两可,拒绝猜测的诱惑."))
# print(deepThought.get_response("生命、宇宙以及世间万物的终极答案是什么?"))
FAQ(非官方)
默认配置
默认情况下, ChatterBot 使用 JsonDatabaseAdapter
作为storage adapter,使用 ClosestMatchAdapter
作为 logic adapter, 使用 VariableInputTypeAdapter
作为 input adapter
只读模式
chatbot = ChatBot("wwjtest", read_only=True)
//否则bot会学习每个输入
创建自己的训练类
创建自己的adapters
参考默认使用的ClosestMatchAdapter、VariableInputTypeAdapter即可
诸如我们可以写一个输入/输出 adapters,对接到微信(我偏好werobot)
io的一个案例是chatterbot-voice(使用方法参考examples/example.py),这个adapters让我们可以使用语音与我们的机器人沟通,原理很简单,我此前折腾过BaiduYuyin,国内用户可以使用它
案例
参考examples ,案例中已经有很多种机器人了
训练好的模型如何分发
训练好的数据,默认存在./database.db
(参考jsondatabase.py),不是sqlite数据库,实际是jsondb,对json做了封装(参考jsondb/db.py)
算法相关
默认情况下,使用 ClosestMatchAdapter 作为 logic adapter ,用来找出与用户输入最接近的一句话
核心代码为:
from fuzzywuzzy import process
closest_match, confidence = process.extract(
input_statement.text,
text_of_all_statements,
limit=1
)[0]
这里我们用到了fuzzywuzzy,具体用法参考fuzzywuzzy#process
fuzzywuzzy用于计算句子直接的相似度,采用的字符串相似度算法为 Levenshtein Distance(编辑距离算法)
Levenshtein Distance
编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数,如果它们的距离越大,说明它们越是不同。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。(引用自维基百科)
从上述描述我们可以看出,这种算法适用于任何文字,而且我们使用process.extract
时,使用中文不会影响相似度度量的准确性。当然我们也可以看出这种算法的缺陷,它无法理解语义的相似性,甚至连同义词都完全无法处理。这是一个十分明显的短板,有必要重新实现一套度量文本相似的logic adapter
from fuzzywuzzy import fuzz
fuzz.ratio(u"你好", u"你好!") #80
fuzz.ratio(u"你好", u"你好") #100
其他算法
time_adapter.py中用到朴素贝叶斯:from textblob.classifiers import NaiveBayesClassifier
,这里也是目前唯一一处引用textblob的地方
接受的数据很简单,形如[("what time is it", 1), xxx, xxx,...]
nltk的使用
目前主要用了nltk的word_tokenize
、wordnet
和stopwords
todo
- 使这个项目能更适合训练中文语料库
- 用其他的文本相似算法写一个logic adapter
- 加入中文的停用词等(取代nltk的停用词)
- 使用snownlp和jieba替代既有依赖(nltk和textblob)
- fork这个项目,采用它的架构,重写一个更适合中文的
聊天语料库
聊天语料涉及隐私,网上几乎没有公开的中文语料,我们开脑洞:
- siri对小冰(用wechat api是对话可编程)
- 柏拉图《对话录》
- 论语
坑
ChatterBot本身支持python2/python3,如果要使用中文,目前只支持python2
Python2中文问题出在:
statement_list = self.context.storage.get_response_statements()
得到的statement_list
是编码错误的句子列表(编解码问题)
解决思路可以参考我的这篇博客:编码相关的笔记
结语
当前这个项目给出了一个漂亮的bot骨架,插件式的设计,十分利于插入强大的功能,这也是这个项目中我最喜欢的地方,就chat bot功能而言,功能比较简单、清晰