用戶輸入
來源可以是web、微信、微博、等等一切類似平臺
用戶輸入類型應該以文字爲主
文字
語音
語音可以通過API識別爲文字。在不同平臺可能有不同的語音識別解決方案,例如在微信中可以考慮使用騰訊的服務。
或者使用其他第三方服務,下面列出的可能服務來自於Uberi
- CMU Sphinx
- Google Speech Recognition
- Wit.ai
- Microsoft Bing Voice Recognition
- api.ai
- Houndify API
- IBM Speech to Text
其他
其他可能用戶輸入包括但不限於,圖片,地點(座標),文件,視頻,URL(文本的一種)
文字處理
文字處理的基本流程是
- 中文分詞
- 實體識別
- 意圖判斷
中文分詞 Chinese Word segmentation
因爲要做實體識別,中文分詞可能是比較必要的部分
可以考慮的服務有jieba,stanford segmenter,pullword,或者其他免費、收費服務
實體識別 Named Entity Recognition
stanford ner對於中文只有三種類型實體的判斷,人物,地點,時間
爲了精確,考慮自己添加其他實體識別類型,例如:
- 電話號碼,手機,固話,400/800
- 價格,例如xx元
- 電子郵件
- 網址
- 年齡
- 數字
可以參考wit.ai和api.ai的實體類型
還有其他更模糊的實體,例如
- 要搜索的條目
- 要翻譯的英文單詞
意圖判斷 Intent Detection / Prediction
我想吐槽一下,這兩年雖然關於Dialogue和QA的論文不少,但是很多都太“學術化”的感覺。
如果用那些文章的方法搭建起來,別說用,我覺得可能想達到wit.ai或者api.ai的水平都不行。
這一部分可能是整個流程最難的部分,倒是也不是說真的最難,關鍵是沒有很好的現成的工具可以用~~
如果我們暫且把意圖分解爲兩部分:命令,非命令
一般來說,目的就是儘可能的提高命令的recall,而不是precision,這也是大部分機器人的做法。
簡單來說,就是用戶問“我想要看天氣”,我們返回天氣,如果用戶說“我討厭天氣預報”,我們可能還是會返回天氣。
即便這句話的語義完全不應該返回天氣,但是爲了高recall,而且因爲語義分析(相似度)完全沒有好辦法。
這個precision和recall的問題是一個難點,還有工程上考慮上下文是一個難點
一個樸素的想法是,像wit.ai那樣把一個場景(story)分開,如果在這個場景中,
所有場景的關鍵詞匹配閾值都改變(在某個場景中,則增加這個場景的匹配可能性)。
如果沒在場景中,則所有的匹配關鍵詞閾值還是原來那樣。
流程類似:
- 用戶輸入語句S
- S是否Exactly Match某條命令?
- S是否Prefectly Match某條命令
- S是否Regex Match某條命令
- 如果是,則確定是這條命令
- 在所有的命令庫中計算所有命令和S的距離(語義相似度)並排序
- 如果用戶的上下文在某個場景(story)中,則相關場景的得分提高
- 如果距離得分最高的命令大於某個閾值,則確定是這條命令
- 如果現在依然沒匹配到某條命令,則閒聊(chichat)
在不考慮命令的語義相似度是否準確的情況下,還有其他工程上的難點。
考慮是否構造一個類似於AIML的語言,能儘可能的提高效率。
這款語言應該定義好Exactly match,包括Regexp match,應該能定義好Story、Enity。
考慮XML或者JSON實現,當然你們都知道我不喜歡XML。
例如:
1、模糊匹配如“北京的天氣怎麼樣?”這種命令
如果系統判斷用戶在weather這個story中,那麼匹配“深圳呢?”這個命令的可能性也將大幅提高
[
{
"pattern": [
"{sys.location}{sys.date}天氣怎麼樣?",
"{sys.location}的溫度"
],
"mode": "normal",
"story": "weather",
"must_have": [
"sys.location"
],
"action": "get_weather({sys.location}, {sys.date || today})"
},
{
"pattern": [
"{sys.location}呢?"
],
"mode": "normal",
"story": "weather",,
"must_have": [
"sys.location"
],
"action": "get_weather({sys.location}, {today})"
},
{
"pattern": [
"{sys.date}呢?"
],
"mode": "normal",
"story": "weather",,
"must_have": [
"story.sys.location"
],
"action": "get_weather({story.sys.location}, {sys.date})"
}
]
運行如下:
- Q 北京今天天氣怎麼樣?
- A 匹配出sys.location是北京,sys.date是今天
- Q 深圳的溫度
- A 匹配出sys.location是深圳,sys.date沒有,默認是今天
- Q 廣州呢?
- A 匹配到了sys.location,當前的story是weather,返回溫度查詢
- Q 明天呢?
- A 匹配到了sys.date,查詢當前的story是weather,當前story下存在sys.location(廣州),返回溫度
2、命令式,不模糊的翻譯英文,任何以“翻譯:”,“翻譯 ”等開頭的就將被匹配
[
{
"pattern": [
"翻譯(\s+|,|:|:)([a-zA-Z0-9-\s]+)"
],
"mode": "regex",
"story": "translate_english",
action: "translate_english({$2})"
}
]
命令的語義相似度判斷:
編輯距離
Levenshtein Distance
基於wordnet
Synets Similarity
Jaccard Similarity
基於2vec
Mean of Word2Vec
Doc2Vec
其他
TreeLSTM
然而上面這些語義相似度判斷基本上都一個鳥樣,實際用起來其實和編輯距離沒太大區別,蠢死了~~