实现微信聊天机器人-中级篇

一、ChatterBot工作原理

Chatbot Engine的技术框架采用了开源项目ChatterBot (https://github.com/gunthercox/ChatterBot)。

ChatterBot是一个python库,利用它可以轻松的创建对话软件。

一个未经训练的ChatterBot实例开始不知道如何沟通,每次用户输入一个语句,ChatterBot就会保存这个语句以及它对应的问句。随着它接受更多的输入,它可以回应的语句数量会增加,每个输入和回应的对应关系准确性也会提高。程序通过搜索与输入语句最相似匹配的语句,来选择最相似的回应,然后基于人们对机器人回应语句的频次,返回最可能的回应。

下图展示了ChatterBot的工作流图:

总体上分为3个层次,输入层,逻辑处理层,输出层。各层都可以扩展自定义的模式。

· 输入层

从一些来源获得输入(如:终端控制台,API接口,语音识别输入等),然后将其转换成ChatterBot可以理解的格式。 目前支持VariableInputTypeAdapter,TerminalAdapter,HipChat等输入适配器。 可以定义自己的输入适配器,通过继承InputAdapter基类,重写process_input方法并返回指定对象Statement就可以实现。

逻辑处理层

逻辑处理层包含了一些逻辑适配器,ChatterBot通过这些逻辑选择一个给定输入语句的回应。 目前支持ClosestMatchAdapter,ClosestMeaningAdapter,ApproximateSentenceMatchAdapter,TimeLogicAdapter,MathematicalEvaluation等逻辑适配器。 ClosestMatchAdapter采用Levenshtein Distance来计算文本相似度。 ClosestMeaningAdapter基于由两个句子形成的字矩阵中每个单词的同义词集的接近程度。 TimeLogicAdapter用来回答关于当前时间的问句。 MathematicalEvaluation用来回答一些数学计算问题。 可以同时使用多个逻辑适配器来处理,机器人将返回最高计算置信度值的回应;如果多个适配器返回相同的置信度,那么选择适配器列表中第一个适配器。 同样,也可以定义自己的逻辑适配器,通过继承LogicAdapter基类,重写相关方法返回指定的值就可以实现。

输出层

返回输入语句的回应,支持多种输出源,如OutputFormatAdapter,TerminalAdapter,HipChat,Mailgun。 可以定义自己的输出适配器,通过继承OutputAdapter基类,重写process_response方法并返回指定对象Statement就可以实现。

以上3层分别对应了Chatterbot的3种适配器类型,输入适配器、逻辑适配器和输出适配器,另外,还有一种类型是存储适配器,存储适配器用来存储所有的对话及问答关系,以供逻辑适配器使用。

存储适配器也是可扩展的,目前支持JsonFileStorageAdapter,MongoDatabaseAdapter,TwitterAdapter,同样也可以自定义存储适配器。

实现微信聊天机器人-中级篇

二、ChatterBot使用

ChatterBot可以下载源码编译安装,也可以直接使用pip工具安装。

本例使用pip安装,如下

pip install chatterbot

下面通过一个简单例子说明如何使用:

from chatterbot import ChatBot

# 创建ChatBot实例

bot = ChatBot("Terminal",##bot名字

storage_adapter="chatterbot.adapters.storage.JsonFileStorageAdapter",##使用json文件存储数据

logic_adapters=[ ##逻辑适配器,可选多个

"chatterbot.adapters.logic.MathematicalEvaluation",

"chatterbot.adapters.logic.TimeLogicAdapter",

"chatterbot.adapters.logic.ClosestMatchAdapter"

],

input_adapter="chatterbot.adapters.input.TerminalAdapter",##终端输入适配器

output_adapter="chatterbot.adapters.output.TerminalAdapter",##终端输出适配器

database="../database.db"##文件存储路径

)


print("Type something to begin...")


# The following loop will execute each time the user enters input

while True:

try:

# We pass None to this method because the parameter

# is not used by the TerminalAdapter

##在终端输入语句,终端会显示回应

bot_input = bot.get_response(None)


# Press ctrl-c or ctrl-d on the keyboard to exit

except (KeyboardInterrupt, EOFError, SystemExit):

break


三、DeepQA介绍

DeepQA项目试图重现神经会话模型的结果(又名谷歌聊天机器人),它采用了RNN(seq2seq模型)判刑预测,使用Python和TensorFlow实现。

RNN是一种神经网络模型,目的使用来处理序列数据。在传统的神经网络模型中,是从输入层到隐含层再到输出层,层与层之间是全连接的,每层之间的节点是无连接的。但是这种普通的神经网络对于很多问题却无能无力。例如,你要预测句子的下一个单词是什么,一般需要用到前面的单词,因为一个句子中前后单词并不是独立的。RNN之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。

RNN已经在实践中证明对NLP是非常成功的,如词向量表达、语句合法性检查、词性标注等。在RNN中,目前使用最广泛最成功的模型便是LSTM(Long Short-Term Memory,长短时记忆模型)模型。

seq2seq模型是一个翻译模型,把一个sequence翻译成另一个sequence,它包含了两层LSTM,一个作为encoder,一个作为decoder。

这里不对DeepQA的实现具体分析,只说明其使用方法。

需要安装如下软件:

python 3

tensorflow (tested with v0.9.0)

numpy

nltk (natural language toolkit for tokenized the sentences) : pip install nltk

tqdm (for the nice progression bars) : pip install tqdm


训练模型:

python main.py


交互模式使用:

python main.py --test interactive


四、ChatterBot集成DeepQA

本例将DeepQA项目作为一个子包包含在ChatterBot项目中。

集成策略有2步:先将DeepQA封装一层调用接口,再编写自定义逻辑适配器。代码如下:

封装接口:chatbotmanager.py

import logging

import sys

import os

from .chatbot import Chatbot


logger = logging.getLogger(__name__)


BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


chatbotPath = "/".join(BASE_DIR.split('/'))


class ChatbotManager:

bot = None


@staticmethod

def initBot():

""" Instantiate the chatbot for later use

Should be called only once

"""

if not ChatbotManager.bot:

http://logger.info('Initializing bot...')

#ChatbotManager.bot = chatbot.Chatbot()

ChatbotManager.bot = Chatbot()

ChatbotManager.bot.main(['--modelTag', 'server', '--test', 'daemon', '--rootDir', chatbotPath])

else:

http://logger.info('Bot already initialized.')

@staticmethod

def callBot(sentence):

""" Use the previously instantiated bot to predict a response to the given sentence

Args:

sentence (str): the question to answer

Return:

str: the answer

"""

if ChatbotManager.bot:

return ChatbotManager.bot.daemonPredict(sentence)

else:

logger.error('Error: Bot not initialized!')


编写逻辑适配器:deep_adapter.py

from .logic_adapter import LogicAdapter

from chatterbot.conversation import Statement

from chatterbot.DeepQA.chatbot.chatbotmanager import ChatbotManager


class DeepLogicAdapter(LogicAdapter):

"""

The DeepLogicAdapter use the deep learning algorithm.

"""


def __init__(self, **kwargs):

super(DeepLogicAdapter, self).__init__(**kwargs)

ChatbotManager.initBot()


def process(self, statement):

question = statement.text

try:

answer = ChatbotManager.callBot(question)

except: # Catching all possible mistakes

answer = 'Error: Internal problem'


# Check eventual error

if not answer:

answer = 'Error: Try a shorter sentence'

confidence = 1

response = Statement(answer)

return confidence, response


五、总结

本文主要阐述了ChatterBot的原理和使用,并通过一个集成DeepQA项目的例子,讲解了如何在ChatterBot框架下扩展聊天逻辑。

聊天机器人的智能和准确率主要取决于逻辑适配器,我们的工作重点就是找到符合业务需求的各种逻辑算法和原理,然后扩展插件就可以了。