開發一個智能問答機器人

近期開發了一套基於天然語言處理的問答機器人,以前沒有作過python,主要作asp.net,寫這篇目的是給想要開發這類智能客服系統的朋友提供一個思路,項目已經上線,但在開發和設計過程當中仍然有不少問題沒有獲得解決,也指望和你們一同討論學習。html

最終的上線效果: python

開發過程大概3階段,第一階段 完成基礎一問一答功能;第二階段 加入意圖識別,能夠進一步區分用戶問題,特定意圖好比工資查詢,將會調用第三方接口;第三階段 上下文處理,引導用戶進行多輪問答;git

插一句微軟認知服務是雲端的較好解決方案,  BOT Framework平臺集成了多種對接方式,無需本身開發。LUIS的配置和發佈也很是方便,特別的若是使用場景真的很是簡單(一問一答),能夠僅用QnAMaker。github

but... 基於業務數據暴露和其餘安全性考慮,有時須要將服務部署在本地(內網),我主要想說的就是本地開發搭建的問答服務。web

1 基礎問答實現

1.1選型算法

可以作基礎問答的開源項目很是多chatterbot,rasa_core等等。我選用的是chatterbot(0.7.6)json

1.2開發api

在搭建完開發環境後chatterbot能夠直接使用,默認算法是編輯距離,因此理論上支持任何語言,包括中文。數組

我主要修改了chatterbot算法模塊,適配器模塊和輸入輸出模塊,最終輸出格式以下安全

{
    "text": "三方協議一式三方,三方蓋完章後,學校,公司,學生本人各留一份。",
    "in_response_to": [{
        "text": "三方協議如何存檔?",
        "created_at": "2017-11-24T15:11:06.500966",
        "occurrence": 4
    }],
    "created_at": "2017-11-24T15:11:06.500",
    "extra_data": {
        "userid": "1000058"
    },
    "question": "三方協議如何存檔?",
    "oriquestion": "三方協議",
    "channel": "2",
    "suggestions": [
        ["三方協議如何存檔?", 0.62],
        ["三方協議能夠他人帶簽署領取嗎?", 0.42],
        ["實習生三方協議上面部門怎麼填寫?", 0.4]
    ]
}

text答案,in_response_to上下文,extra_data附加信息(能夠放用戶身份標識等),question匹配到的問題,oriquestion用戶輸入問題,channel詞庫編號(支持多詞庫每一個詞庫可能有不一樣的處理),感興趣問題列表(匹配度稍低的問題)

chatterbot的adapter原本設計是能夠放多個,每一個適配器完成本身的功能(解耦),但實際使用時(5000條問答),多適配器是很是緩慢的,因爲每一個適配器都會循環處理或比對問題,因此建議只放一個adapter實現全部功能

'logic_adapters':['mybot.MyLogicAdapter']

算法

位於comparisons.py中默認的編輯距離算法或傑拉德類似係數算法,都是基於簡單的文本比對,沒法處理同義詞近義詞。這裏咱們引入的word2vec算法

訓練數據來自中文維基百科,加入了特定業務文檔數據(僅73M,維基百科1.11G...)

使用jieba分詞,gensim word2vec訓練模型,特徵向量400維,大概須要14小時(參考個人吃雞電腦I7 7700 GTX1080)。

# 裝載以前訓練好的模型

custom_model = Word2Vec.load('data/custom.model')

用戶輸入先經過jieba分詞,獲得詞和詞頻的數組,例如:查詢個人薪資
查詢 2
我 5
的 1
薪資 3
# 查詢key在模型中向量
vec =custom_model['查詢'] 

# 加權(模型中向量*jieba分詞中權重)
sentvec = sentvec + vec * 2

把句子中詞向量相加獲得整個句子的向量。

再利用夾角餘弦,與業務詞庫中的問題比較,獲得最類似的問題匹配。

此方法,能夠處理諸如,皇后->女人 這類的近義問題。從圖上能夠看到女人與皇后餘弦夾角小於皇后與木頭餘弦夾角,結論爲女人與皇后更類似。

 

因此最終的算法:編輯距離+word2vec。

2 意圖識別

意圖識別屬於天然語言理解範圍,主流機器學習算法支持向量機、決策樹等分類方法。咱們使用意圖識別主要用來分離出用戶的查詢意圖,再調用對應的第三方接口將數據返回給用戶,例如 北京今每天氣?識別爲天氣意圖,實體爲北京。

2.1選型

咱們這裏選用開源項目rasa_nlu(11.0.3),這是一個集意圖識別,實體提取功能於一體的項目。能夠生成以下的數據

{
  "intent": {
    "name": "weather",
    "confidence": 0.44477984330690684
  },
  "entities": [
    {
      "entity": "city",
      "value": "大連",
      "start": 0,
      "end": 2,
      "extractor": "ner_mitie"
    },
    {
      "entity": "date",
      "value": "後天",
      "start": 2,
      "end": 4,
      "extractor": "ner_mitie"
    }
  ],
  "intent_ranking": [
    {
      "name": "weather",
      "confidence": 0.44477984330690684
    },
    {
      "name": "bookhotel",
      "confidence": 0.37330751883981904
    },
    {
      "name": "map",
      "confidence": 0.18191263785327412
    }
  ],
  "text": "大連後每天氣怎麼樣"
}

2.2開發

在實際使用中,有時可能僅須要提取實體,因此我額外作了一個流程,僅提取實體。

{
  "entities": [
    {
      "entity": "city",
      "value": "大連",
      "start": 0,
      "end": 2,
      "extractor": "ner_mitie"
    }
  ],
  "text": "大連天氣怎麼樣"
}

2.3命名實體提取替換

項目最終使用"pipeline": ["tokenizer_jieba","ner_synonyms","intent_entity_featurizer_regex","intent_featurizer_mitie","intent_classifier_sklearn","ner_corenlp"]

以前使用MITIE做爲命名實體提取,但MITIE須要本身訓練,實際使用時訓練語句過少,正確率偏低,改用corenlp,默認支持中文 我截取目標默承認以識別的實體類型
# DATE: type:日期  eg:明天
# LOCATION: type:地點 eg:齊齊哈爾
# MISC: type:其餘 eg:怎麼樣
# MONEY: type:金額
# ORGANIZATION: type:組織
# PERCENT: type:百分比
# PERSON: type:人 eg:特朗普
# TIME: type:時間 eg:下午
# O: type:動詞或其餘 eg:查詢
# COUNTRY: type:國家 eg:中國
# STATE_OR_PROVINCE: type:城市/省會 eg:北京
# CITY: type:城市 eg:西安

 

 

2.0補充

系統缺陷修復,使用rasa_nlu意圖分類,基於sklearn-svmcv算法,可是分類後,各意圖結果相加始終等於1,我以前的設想(後面有詳細說明):設定一個閾值好比0.7,判斷最高匹配度的意圖是否大於閾值,若是大於則認爲明確意圖。但這基於問題是意圖的前提,

我訓練意圖用了三個分類weather,bookhotel,map,但我沒法將問答的5000個問題訓練爲other意圖,因爲5000個問答中涉及多領域,很是多的特徵向量會對意圖分類形成很大影響,使分類不許確。

目前的解決方案爲在乎圖識別前,加入一個二分類器,也基於sklearn的分類器,用於區分問題仍是意圖,訓練使用18000條生產環境用戶問題和6000*3加權的意圖問題(等量的訓練數據)訓練並比較準確率。

用戶問題 標識(1意圖0普通問題)
今每天氣如何 1
我想預訂北京的酒店 1
機器人的內部處理流程是怎樣的 0
公司發展歷程 0

 

 

 

 

 

生成pkl文件。將pkl文件放入指定位置,替換最準確算法。

當前最高爲隨機森林算法

******************* NB ********************

accuracy: 90.06%

******************* KNN ******************** 

accuracy: 87.50%

******************* LR ********************

accuracy: 90.91%

******************* RF ********************

accuracy: 96.31%

******************* DT ********************

accuracy: 95.17%

******************* SVM ********************

accuracy: 25.28%

******************* SVMCV ********************

accuracy: 93.75%

******************* GBDT ********************

accuracy: 87.78%

 

3 上下文

看了不少大神基於深度學習算法的帖子還有論文,感受實在力不從心... 這裏使用模板配置的方式,引導用戶完成上下文。

JSON數據格式

{
"rule": [{
"intent": "weather",
"entities": [
{"name":"city","type":"city","required":"true","prompts":["請問查詢哪裏的天氣","想查詢哪一個城市的天氣"]},
{"name":"date","type":"date","required":"false","prompts":[]}
]
},
{
"intent": "bookhotel",
"entities": [
{"name":"city","type":"city","required":"true","prompts":["請問預訂哪裏","想預訂哪一個城市"]},
{"name":"checkindata","type":"date","required":"true","prompts":["請問什麼時候入住","預訂酒店的時間"]},
{"name":"checkoutdata","type":"date","required":"false","prompts":[]}
]
},
{
"intent": "bookticket",
"entities": [
{"name":"fromcity","type":"city","required":"true","prompts":["請提供出發城市","從哪起飛"]},
{"name":"tocity","type":"city","required":"true","prompts":["請提供到達城市","到哪落地"]},
{"name":"date","type":"date","required":"true","prompts":["請問預訂機票的時間","想預訂哪天的機票"]}
]
}
]
}

這就是上下文的控制流程,主要代碼邏輯控制,沒有使用機器學習算法。

  

特別的,這裏閾值很是的重要,閾值範圍0~1,越小越容易被理解爲意圖,當爲1時,等同於關鍵字匹配。

舉個栗子,若是閾值設定很是小,用戶的普通提問都會被理解爲意圖,不會進入chatterbot問答中,若是很是大,則難以進入意圖識別,訓練data 查詢工資,若是用戶輸入「查詢個人工資」可能也不會進入意圖查詢

閾值我使用梯度降低算法,擬合成二維曲線,找到最高點,0.74

 

後記

項目開發過程大概4個月(第一週,學習python基礎語法,主要了解函數,變量賦值邏輯,web api實現,以後開始學習深度學習算法,主要從帖子、論文和視頻,MIT、臺大、Stanford的教學視頻都很是好,能夠在B站上看,選型時幾乎試用了全部開源的QA項目,通常QA項目都須要訓練,準備語料因此耗費了大量時間),獨立開發,實際編碼時間一個月,最後用asp.net mvc封裝了這些接口,作了問答頁面和簡單的後臺語料管理系統(我也想用python...來不及)

咱們業務問答5000多條,一共有3個實習生,配合我標註語料,編寫測試集和驗證集(真正的工做量在這)

最終正確率:68.4%(微軟驗證集正確率:81.7%)

 

chatterbot 項目主框架

https://github.com/gunthercox/ChatterBot

sklearn 意圖問題分類

https://github.com/automl/auto-sklearn

rasa_nlu 意圖識別模塊

https://github.com/RasaHQ/rasa_nlu

gensim word2vec算法實現

https://github.com/RaRe-Technologies/gensim

word2vec,中文處理

https://github.com/zake7749/word2vec-tutorial

類似度比較-向量餘弦夾角

https://github.com/kris2692/Vector-semantics

 

主要問題:

1.正確率過低:若是單用word2vec算法,正確率只有36.2%,單用編輯距離算法正確率59.8%,不知道爲什麼我寫word2vec算法正確率如此低,一直沒有找到緣由。

2.數據分散,用多種語言編寫:整個項目一共三部分:chatterbot,rasa_nlu,mvc web,在修改意圖時很是麻煩,在管理系統修改意圖後,生成json文件,須要手工拷貝到rasa_nlu項目中,再使用cmd命令train,start server。

 

補充

開發一個智能問答機器人(優化篇)

相關文章
相關標籤/搜索