問答系統實踐(二)構建聊天機器人小天1.0

口水簡介

本文主要教你如何構建基於模糊檢索和深度學習的聊天機器人。之前在專欄的一篇文章已經介紹了FAQ客服機器人的基本構建流程,所以本文就不重複介紹了。詳細請參看:

其實無論客服機器人還是聊天機器人都離不開文本匹配,所以對於研究文本匹配的童鞋來說,能將自己所學的技術快速的應用到生活中去,算是一件最開心的事情了吧。本專欄介紹的聊天機器人均屬於單輪檢索式機器人,那多輪對話啥的,如果你看成由多個一輪構成,其實也可以,如果你有強大的語料庫,一個單輪檢索式機器人都有可能讓你覺得它能夠聯繫上下文;多輪對話難點在於如何利用你的session來進行下一輪對話,其實大部分都是機器人在引導你對話,而這後面都是強大的規則在支撐,機器人只是規則的表達方式而已,有時候你看到的“人工智能”其實就是無數個人工堆積的成果,有點跑題了。

本文介紹的聊天機器人可以幫助你熟悉構建機器人的一個簡單流程,技術比較簡單;同時爲了貫徹奧卡姆剃刀原則,本文用一份代碼同時完成了閒聊機器人和特定任務的FAQ客服機器人,讓你用最少的精力體會雙倍的快樂!下面請看具體介紹:

項目簡介

本項目由兩個部分組成,一是基於tf-idf檢索的召回模型,二是基於CNN的精排模型,本項目將兩者融合,構建 召回+排序 的客服聊天機器人。系統支持閒聊模式FAQ問答模式,採取的數據分別爲小黃雞閒聊數據集和垂直領域的FAQ問答數據集。該聊天機器人的版本爲小天1.0,速度提升的小天2.0版本會在後期陸續上傳。

目前該系統的優點在於:

一、 召回+排序 2個模塊互不干擾,便於自定義修改以及維護;

二、系統採取了排序規則優化,提升了檢索速度。

三、加入了簡單的倒排索引,優化了檢索流程。

根據目前的反饋,系統的難點在於構建一個精度高且耗時短的rerank模型,本項目所用的CNN模型需要你根據自己的語料去調參,CNN是最簡單也是比較有效的模型哦,後期有時間我會把其他相對來說比較nice的模型進行上傳。

項目結構和代碼

項目的基本結構如下:

stopwordList,userdict文件夾

word2vec文件夾中是中文詞向量:

Recall文件夾

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文件夾

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

本項目依靠route函數進行問答任務轉換,分爲 chat模式 和 faq 模式,這樣做的目的主要是系統可以根據不同的任務設置不同的情景對話,同時系統將2個語料集分開管理,避免了搜索時間的增加。目前的效果是如果你不輸入end終止對話,那麼你可以在對話中進行chat模式和faq模式的隨意轉化,隨心所欲!

調戲小天用戶指南

  • 初始化

  • 進入聊天模式

  • 輸入 faq ,進入任務問答模式

  • 再次輸入 chat,路由轉化爲聊天模式

  • 如果已經在 chat模式,再次輸入chat,那麼小天會給你提示

  • 輸入 end,結束對話

總結

本文使用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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章