1

构建自己的智能聊天机器人

 2 years ago
source link: http://wwj718.github.io/post/%E6%95%B0%E6%8D%AE/create-a-smart-chat-bot/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

构建自己的智能聊天机器人

2016-08-13
说明: 这篇文章读者较多,时常会收到邮件咨询问题, 大多是因为文章落后于源码库,我之后定期更新到最新源码库,大家之后发邮件,也麻烦注明使用的依赖库版本

# 2020.03.03
这篇文章是三年多以前写的,最近还收到一些邮件讨论这个

如果你在构建一个笔记严肃的聊天机器人项目,推荐使用rasa: https://github.com/RasaHQ/rasa

当然ChatterBot是一个很好的项目,让你理解chatbot的构成。

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 (我的当前版本是:chatterbot==0.5.4)

from chatterbot import ChatBot
from chatterbot.trainers import ChatterBotCorpusTrainer

chatbot = ChatBot("myBot")
chatbot.set_trainer(ChatterBotCorpusTrainer)

# 使用英文语料库训练它
chatbot.train("chatterbot.corpus.english")

# 开始对话 
chatbot.get_response("Hello, how are you today?")

采用中文语料库

我之前给这个项目添加了中文语料库,在新版本中可以直接使用

使用中文语料库来训练机器人(仅支持python3)

from chatterbot import ChatBot
from chatterbot.trainers import ChatterBotCorpusTrainer
deepThought = ChatBot("deepThought")
deepThought.set_trainer(ChatterBotCorpusTrainer)
# 使用中文语料库训练它
deepThought.train("chatterbot.corpus.chinese")  # 语料库

————更新于2016.08.30

我今天在pypi上看到,0.4.6版本(08.14号上传)已经把中文预料库包含在内了,直接pip3 install ChatterBot就行

————更新于2017.1.4

需要注意的是,python2中使用,不能直接用语料训练,需要手动训练

参见FAQ中的 手动训练(手动训练可以直接在python2中使用中文)

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

稀土掘金上的小伙伴@guoweikuang问道"采用中文语料库那个地方是怎么操作的",下边补充手动训练的办法。对原理有兴趣可以翻阅源码

from __future__ import unicode_literals
from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer
deepThought = ChatBot("Training demo")
deepThought.set_trainer(ListTrainer)
deepThought.train([
    "嗳,渡边君,真喜欢我?",
    "那还用说?",
    "那么,可依得我两件事?",
    "三件也依得",
])


# test
print(deepThought.get_response("真喜欢我?"))
print(deepThought.get_response("可依得我两件事?"))

———-更新于2016.10.26

通过设置好编码环境我们可以在python2使用中文训练机器人,这样就不需要在python2/3中来回切换了(我把它封装为服务不存在这个问题,且效率提高)

from __future__ import unicode_literals
import sys;reload(sys);sys.setdefaultencoding('utf8')
from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer
deepThought = ChatBot("Training demo")
deepThought.set_trainer(ListTrainer)
deepThought.train([
    "嗳,渡边君,真喜欢我?",
    "那还用说?",
    "那么,可依得我两件事?",
    "三件也依得",
])


# test
print(deepThought.get_response("真喜欢我?"))
print(deepThought.get_response("可依得我两件事?"))

chatbot = ChatBot("wwjtest", read_only=True) //否则bot会学习每个输入

创建自己的训练类

chatterbot/training

创建自己的adapters

参考默认使用的ClosestMatchAdapterVariableInputTypeAdapter即可

诸如我们可以写一个输入/输出 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_tokenizewordnetstopwords

这是我最近在做的

  • 使这个项目能更适合训练中文语料库
  • 用其他的文本相似算法写一个logic adapter
  • 加入中文的停用词等(取代nltk的停用词)
  • 使用snownlp和jieba替代既有依赖(nltk和textblob)
  • fork这个项目,采用它的架构,重写一个更适合中文的

有兴趣跟进的小伙伴,可以关注wwj718/deepThought

聊天语料库

聊天语料涉及隐私,网上几乎没有公开的中文语料,我们开脑洞:

  • siri对小冰(用wechat api使对话可编程)
  • 柏拉图《对话录》

ChatterBot本身支持python2/python3,如果要使用中文,目前只支持python3

Python2中文问题出在:

statement_list = self.context.storage.get_response_statements()

得到的statement_list是编码错误的句子列表(编解码问题)

解决思路可以参考我的这篇博客:编码相关的笔记

当前这个项目给出了一个漂亮的bot骨架,插件式的设计,十分利于插入强大的功能,这也是这个项目中我最喜欢的地方,就chat bot功能而言,功能比较简单、清晰


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK