聊天机器人是NLP(自然语言处理)上的一个重要研究和实际落地的方向
前段时间听了网上一个关于聊天机器人的公开课,对聊天机器人有了初步的认识,就此做一些总结
种类
左边的第一种属于闲聊机器人,一般采用端到端的方法去做
中间和右边的是任务导向型机器人,偏重于解决某一类问题。中间的是通过对话完成订票的任务,右边的则时完成学员对培训 课程的咨询,一般采用意图识别的方法去做
聊天机器人的评估方法
闲聊型chatbot: 聊了多久?对话轮次怎么样? 用户情感变化怎么样?
任务导向型chatbot: 多少人订单成功? 平均花了多久完成订单? 用户评价?
基于检索的方法
跟搜索引擎比较类似
知识库里面存储的是问题和答案的键值对,将知识库里面的数据键值对中的问题和指定的问题做一个相似度的计算得到相似度最高的那个数据,在将那个数据的答案返回
案例分析:
用户输入为 “我想了解老师的背景” 计算出和知识库里面的第五条的相似度最高为0.9 所以返回回答 “绝大部分都是全美前10学校的博士”
一个核心问题:怎么 计算两个短句子的相似度
用tf-idf或者word-embedding的形式将句子 转换成向量,再计算两个向量之间的余弦相似度
直接上代码
问题数据 question.dat
回答数据 answer.dat
def read_corpus(file): with open(file, mode='r', encoding='UTF-8') as fp: data = fp.readlines() return data questions = read_corpus('question.dat') answers = read_corpus('answer.dat') # print("questions\n{0}\n".format(questions)) # print("answers\n{0}\n".format(answers)) #一个原始的文本转换成向量 import jieba # 分词工具,最为常用的分词工具 import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer #Step1 : 对所有问题分词 question_seg = [" ".join (jieba.cut(q, cut_all=False)) for q in questions] from sklearn.metrics.pairwise import cosine_similarity #Step2 : 将字符串转换成向量 vertoeizer = TfidfVectorizer() X = vertoeizer.fit_transform(question_seg) #X是矩阵 # print("X\n{0}\n".format(X)) #稀疏矩阵 # print("X.toarray()\n{0}\n".format(X.toarray())) #非稀疏矩阵 def bit_product_sum(x, y): return sum([item[0] * item[1] for item in zip(x, y)]) def complete_vector_each(data, len_data, max): if len_data >= max: return data for i in range(max - len_data): data.append(0) return data def complete_vector(x,y): len_x = len(x) len_y = len(y) if len_x != len_y: max_len = max(len_x, len_y) x = complete_vector_each(x, len_x, max_len) y = complete_vector_each(y, len_y, max_len) return x, y def cosine_similarity_1(x, y, norm=False): """ 计算两个向量x和y的余弦相似度 """ # aa = [1,2,3,4] # bb= [10] # aa,bb = complete_vector(aa, bb) # print(aa) # print(bb) x,y = complete_vector(x,y) # method 2 cos = bit_product_sum(x, y) / (np.sqrt(bit_product_sum(x, x)) * np.sqrt(bit_product_sum(y, y))) return 0.5 * cos + 0.5 if norm else cos # 归一化到[0, 1]区间内 def get_max_idx(input_vec): cosine_similarity_values = [] for x in X: cosine_similarity_value = cosine_similarity_1(x.toarray()[0], input_vec.toarray()[0], norm=True) cosine_similarity_values.append(cosine_similarity_value) #return np.argmax(np.array(cosine_similarity_values)) return cosine_similarity_values.index(max(cosine_similarity_values)) def get_response(input): input_seq = " ".join(jieba.cut(input, cut_all=False)) input_vec = vertoeizer.transform([input_seq]) # result = cosine_similarity(input_vec,X)[0] # max_idx = np.argmax(result) max_idx = get_max_idx(input_vec) return answers[max_idx] print(get_response("导师的背景是什么啊?")) print(get_response("大部分是线上的课程吗?")) print(get_response("课程为什么收费高?"))sklearn.metrics.pairwise中的cosine_similarity计算余弦相似度的方法也可以自己实现,当两个向量的长度不一致的时候,可以采取补0的操作
运行一下 得到结果
基于模式匹配的方法
伪代码
核心就是定义一条条规则;不需要AI技术即可以实现; 最初的Alice聊天机器人系统是最经典的案例
正则是基于模式匹配任务型机器人的核心,它的优点是不需要依赖数据量,缺点是需要设计大量的规则,而且需要确保规则之间没有冲突,可扩展性差、重复工作很多,很难处理语句的多样化表达。
基于意图识别的方法
意图识别和实体识别是整个框架下的核心
对话管理系统是管理对话的流程(全局的状态机)。可以根据当前的状态和接下来的状态生成回复。
案例:订票系统
Chatbot: 先生你好,有什么需要帮忙的吗?
Customer: 我想查个机票
意图:查询机票
实体:{}
第一个意图发起为查询机票,聊天机器人准备客户的slotfilling填槽 【出发地 目的地 时间】
根据对话管理系统,机器人问出第二个问题
Chatbot: 出发地和目的地在哪里呢?
Customer: 从北京出发,到上海
意图:""
实体:{出发地:上海 目的地:北京}
顺利完成了出发地和目的地的填槽,开始问时间
Chatbot: 日期呢?打算什么时候出发?
Customer: 打算11月16日出发,最好晚上
意图:""
实体:{时间:11月16日 18:00-23:59 }
Chatbot: 找到了一个晚上东航的航班。9:10分出发,10:20到虹桥机场,可以吗?
Customer: 可以的,帮我订一下吧
后台判断跳槽完成,触发一个动作,从数据库里面读取关键信息之后填充到一个模板之后回复给客户
Chatbot: 好的,您打算用什么支付呢?
Customer:用微信吧
意图:支付
实体: {}
此时发起一个新的意图-支付,会有一个新的对话管理系统来实现下面的意图
Chatbot: 您可以扫一下二维码?
Customer:好了
Chatbot: 恭喜您支付成功,您的订单可以点击链接查看
Customer:好
下面来聊聊每个模块相应的处理方法
意图识别:
这是一个分类问题
1.基于模式匹配
msg.contains("查询") : 意图=查机票
当用户所问的问题中包含查询的字样式,后台把这个意图分类成查机票
2.分类方法
可以用一些分类方法 SVM,NN,RF。
工业界对大部分的意图识别的问题先采取基于模式匹配的方法,对于一些很难的问题可以采用分类方法进行分类
实体识别: 像时间,地点,产品这些都是属于实体
这个在nlp里面,对一句话中的每个单词进行标记(这个单词是属于地点的,还是不包含任何实体),这个属于时序的分类问题(sequential tagging problem)
我们可以采用经典的算法 CRF LSTM-CRF
对话的管理系统:
在学术中使用RF(reinfocement learning)
在工业中使用基于FSA(有限状态机)的方法
假如说我们现在已经知道用户的出发地,然后询问目的地,已经知道出发地和目的地,询问时间,当三者都知道的时候完成这个意图的对话管理等等
回复生成:
生成一些模板去回复,例如您定的航班{$fightNo}于{$departTime}从{$origin}出发,xxxxx
端到端的方法
Seq2Seq
LSTM-LSTM
Transfoermer
端到端的技术主要在闲聊机器人上应用