天天看点

问答系统实践(二)构建聊天机器人小天1.0

口水简介

本文主要教你如何构建基于模糊检索和深度学习的聊天机器人。之前在专栏的一篇文章已经介绍了FAQ客服机器人的基本构建流程,所以本文就不重复介绍了。详细请参看:

其实无论客服机器人还是聊天机器人都离不开文本匹配,所以对于研究文本匹配的童鞋来说,能将自己所学的技术快速的应用到生活中去,算是一件最开心的事情了吧。本专栏介绍的聊天机器人均属于单轮检索式机器人,那多轮对话啥的,如果你看成由多个一轮构成,其实也可以,如果你有强大的语料库,一个单轮检索式机器人都有可能让你觉得它能够联系上下文;多轮对话难点在于如何利用你的session来进行下一轮对话,其实大部分都是机器人在引导你对话,而这后面都是强大的规则在支撑,机器人只是规则的表达方式而已,有时候你看到的“人工智能”其实就是无数个人工堆积的成果,有点跑题了。

本文介绍的聊天机器人可以帮助你熟悉构建机器人的一个简单流程,技术比较简单;同时为了贯彻奥卡姆剃刀原则,本文用一份代码同时完成了闲聊机器人和特定任务的FAQ客服机器人,让你用最少的精力体会双倍的快乐!下面请看具体介绍:

项目简介

本项目由两个部分组成,一是基于tf-idf检索的召回模型,二是基于CNN的精排模型,本项目将两者融合,构建 召回+排序 的客服聊天机器人。系统支持闲聊模式和FAQ问答模式,采取的数据分别为小黄鸡闲聊数据集和垂直领域的FAQ问答数据集。该聊天机器人的版本为小天1.0,速度提升的小天2.0版本会在后期陆续上传。

目前该系统的优点在于:

一、 召回+排序 2个模块互不干扰,便于自定义修改以及维护;

二、系统采取了排序规则优化,提升了检索速度。

三、加入了简单的倒排索引,优化了检索流程。

根据目前的反馈,系统的难点在于构建一个精度高且耗时短的rerank模型,本项目所用的CNN模型需要你根据自己的语料去调参,CNN是最简单也是比较有效的模型哦,后期有时间我会把其他相对来说比较nice的模型进行上传。

项目结构和代码

项目的基本结构如下:

stopwordList,userdict文件夹:

问答系统实践(二)构建聊天机器人小天1.0

word2vec文件夹中是中文词向量:

问答系统实践(二)构建聊天机器人小天1.0

Recall文件夹:

问答系统实践(二)构建聊天机器人小天1.0
问答系统实践(二)构建聊天机器人小天1.0

recall_model.py

是模糊匹配模型的问答主函数,不需要训练,需保证输入正确语料,根据不同的任务调用不同的语料集,支持单独测试

# 可以利用以下代码单独进行测试
if __name__ == '__main__':
    # 设置外部词
    seg = Seg()
    seg.load_userdict('./userdict/userdict.txt')
    # 读取数据
    List_kw, questionList, answerList = read_corpus1()
    # 初始化模型
    ss = SentenceSimilarity(seg)
    ss.set_sentences(questionList)
    ss.TfidfModel()         # tfidf模型
    # ss.LsiModel()         # lsi模型
    # ss.LdaModel()         # lda模型

    while True:
        question = input("请输入问题(q退出): ")
        if question == 'q':
            break
        time1 = time.time()
        question_k = ss.similarity_k(question, 5)
        print("亲,我们给您找到的答案是: {}".format(answerList[question_k[0][0]]))
        for idx, score in zip(*question_k):
            print("same questions: {},                score: {}".format(questionList[idx], score))
        time2 = time.time()
        cost = time2 - time1
        print('Time cost: {} s'.format(cost))
           

Rerank文件夹:

问答系统实践(二)构建聊天机器人小天1.0

rerank使用说明:

第一步:qacnn.py

先训练深度学习模型,得到checkpoint等文件,支持训练和测试,这一步确保得到一个高效的rerank模型

def main():

    embedding = load_embedding(embeding, embeding_size, vocab_file)
    preprocess_data1 = preprocess(train_file)
    preprocess_data2 = preprocess(test_file)

    train_data = read_train(preprocess_data1, stopword_file, vocab_file)
    test_data = read_train(preprocess_data2, stopword_file, vocab_file)
    train_corpus = load_train_data(train_data, max_q_length, max_a_length)
    test_corpus = load_train_data(test_data, max_q_length, max_a_length)

    config = NNConfig(embedding)
    config.ques_length = max_q_length
    config.ans_length = max_a_length
    # config.embeddings = embedding
    train(deepcopy(train_corpus), test_corpus, config)


if __name__ == '__main__':
    save_path = "./model/checkpoint"
    best_path = "./model/bestval"
    train_file = '../data/corpus1/raw/train.txt'
    test_file = '../data/corpus1/raw/test.txt'
    stopword_file = '../stopwordList/stopword.txt'
    embeding = '../word2vec/70000-small.txt'
    vocab_file = '../data/corpus1/project-data/word_vocab.txt'
    max_q_length = 15
    max_a_length = 15
    embeding_size = 200
    main()
           

第二步:rerank_model.py

不支持单独使用,是系统的调用文件,你可以修改里面的相关信息来满足你的需求

# 得到深度模型计算的相似度分数
def test(corpus, config):
    process_data = read_test(corpus, stopword_file, vocab_file)
    test_corpus = load_test_data(process_data, max_q_length, max_a_length)
    # tf.reset_default_graph() 可以防止模型重载时报错
    tf.reset_default_graph()
    with tf.Session() as sess:
        model = SiameseQACNN(config)
        saver = tf.train.Saver()
        saver.restore(sess, tf.train.latest_checkpoint(best_path))

        iterator = Iterator(test_corpus)
        res = []
        for batch_x in iterator.next(config.batch_size, shuffle=False):
            batch_q, batch_a, batch_qmask, batch_amask = zip(*batch_x)
            batch_q = np.asarray(batch_q)
            batch_a = np.asarray(batch_a)
            predictions = sess.run([model.res], feed_dict={model._ques: batch_q,
                                                model._ans: batch_a,
                                                model.dropout_keep_prob: 1.0})
            res.append([i for i in predictions])
        return res
           

最后介绍的,就是系统的一个中控文件qa-control.py

问答系统实践(二)构建聊天机器人小天1.0

本项目依靠route函数进行问答任务转换,分为 chat模式 和 faq 模式,这样做的目的主要是系统可以根据不同的任务设置不同的情景对话,同时系统将2个语料集分开管理,避免了搜索时间的增加。目前的效果是如果你不输入end终止对话,那么你可以在对话中进行chat模式和faq模式的随意转化,随心所欲!

调戏小天用户指南

  • 初始化
问答系统实践(二)构建聊天机器人小天1.0
  • 进入聊天模式
问答系统实践(二)构建聊天机器人小天1.0
问答系统实践(二)构建聊天机器人小天1.0
问答系统实践(二)构建聊天机器人小天1.0
  • 输入 faq ,进入任务问答模式
问答系统实践(二)构建聊天机器人小天1.0
  • 再次输入 chat,路由转化为聊天模式
问答系统实践(二)构建聊天机器人小天1.0
  • 如果已经在 chat模式,再次输入chat,那么小天会给你提示
问答系统实践(二)构建聊天机器人小天1.0
  • 输入 end,结束对话
问答系统实践(二)构建聊天机器人小天1.0

总结

本文使用tf-idf+cnn构建了聊天机器人小天,此外你可以尝试其他思路来构建和优化你的聊天机器人,比如说:

其他方案:使用word2vec等词向量进行相似度计算构建聊天机器人

可以优化的地方有:

  1. 结巴分词得出每个词的词性,根据词性来对word2vec的每个词进行权重加权,比如,你可以设置名词的权重为1.2,代词之类的权重为0.4等
  2. 巧妙将woed2vec和tf-idf结合起来,利用tf-idf得到每个词的权重,同上做权重加权
  3. 速度优化上,为了避免每次计算都加载问句库词向量寻址,可以将标准问句的句向量存好,需要架子啊的时候再加载进来。
  4. 如果用深度学习模型,可以保存为PB文件,方面server端的部署

本项目github地址:

聊天机器人小天1.0

QAmodel-for-Retrievalchatbot

继续阅读