聊天機器人的三個基本部分 一個聊天機器人,有三個基本部分: 輸入輸出:用來接受、理解用戶問題,并生成、返回答案給用戶。 對話控制:用來構建雙向的關系。 i)用戶問題=>知識庫知識 ii)知識庫知識=>機器人答案 知識庫:用于回答用戶問題的知識的集合。
113750agw4ocaw0favck14.png (5.94 KB, 下載次數: 77)
下載附件
2018-1-17 20:57 上傳
NOTE:如上的三個部分是從功能角度的分析,并不是說一個Chatbot必須要有與之一一對應的模塊或分層。 聊天機器人的實現技術 從學術研究的角度講,聊天機器人所需技術涉及到自然語言處理、文本挖掘、知識圖譜等眾多領域。 在當前的研究中,大量機器學習、深度學習技術被引入。各種炫酷的算法模型跑在Google、微軟等IT寡頭的高質量數據上,得到了頗多激動人心的研究成果。 但具體到實踐當中,在沒有那么巨量的人工標注數據和大規模計算資源的情況下,于有限范圍(scope)內,開發一款真正有用的機器人,更多需要關注的往往不是高深的算法和強健的模型,而是工程細節和用戶體驗。 此處,我們只是簡單介紹幾種當前實踐中最常用,且相對簡單的方法: Solution-1: 用戶問題->標準問題->答案 知識庫中存儲的是一對對的“問題-答案”對(QA Pair)。這些Pair可以是人工構建的,源于專家系統或者舊有知識庫的,也可以是從互聯網上爬取下來的。 現在互聯網資源這么豐富,各種網頁上到處都是FAQ,Q&A,直接爬下來就可以導入知識庫。以很小的代價就能讓機器人上知天文下曉地理。 當用戶輸入問題后,將其和知識庫現有的標準問題進行一一比對,尋找與用戶問題最相近的標準問題,然后將該問題組對的答案返回給用戶。 其中,用戶問題->標準問題的匹配方法可以是關鍵詞匹配(包括正則表達式匹配);也可以是先將用戶問題和標準問題都轉化為向量,再計算兩者之間的距離(余弦距離、歐氏距離、交叉熵、Jaccard距離等),找到距離最近且距離值低于預設閾值的那個標準問題,作為查找結果。 但關鍵字匹配覆蓋面太小。距離計算的話,在實踐中比對出來的最近距離的兩句話,可能在語義上毫無關聯,甚至滿擰(比如一個比另一個多了一個否定詞)。另外,確認相似度的閾值也很難有一個通用的有效方法,很多時候都是開發者自己拍腦袋定的。 因此,這種方案,很難達到高質高效。 Solution-2. 用戶問題->答案 知識庫中存儲的不是問題-答案對,而僅存儲答案(文檔)。 當接收到用戶問題后,直接拿問題去和知識庫中的一篇篇文檔比對,找到在內容上關聯最緊密的那篇,作為答案返回給用戶。 這種方法維護知識庫的成本更小,但相對于Solution-1,準確度更低。 Solution-3. 用戶問題->語義理解->知識庫查詢->查詢結果生成答案 從用戶的問題當中識別出用戶的意圖,并抽取這個意圖針對的實體。 相應的,知識庫內存儲的知識,可以按照二維表的方式組織(類比關系數據庫中的table)。 Chatbot在提取了意圖和實體后,構造出對知識庫的查詢(Query),實施查詢,得出結果后生成回答,回復給用戶。 我們下面講的框架,就是基于本方案的。 極簡版聊天機器人架構 在此,給出一個極簡版Chatbot實現方案,幫助你在一天的時間內,開發一款問題解決型聊天機器人。 下圖是這款機器人的架構:
113811ked1ozl5elndsl2e.png (26.52 KB, 下載次數: 65)
下載附件
2018-1-17 20:57 上傳
最左側的語言理解(Language Understanding)模塊,和右上的回復生成器(ResponseGenerator)加起來對應的圖-1中的是I/O部分。 正中的對話管理器(Dialog Manager)和上下文存儲(Context Store)屬于圖-1里的中控部分。 最下方是知識庫。 語言理解 怎么能夠從用戶的提問當中發現意圖和實體呢? 最簡單的是基于規則的方法:用關鍵字/正則表達式匹配的方式,來發現自然語言中的意圖和實體。 GET_INPUT IF "有(.+)嗎" inUser_Input Intent = “商品推薦” ELIF "(郵費|郵資|運費|快遞費)+" inUser_Input Intent = “查詢郵費” ELIF "(保修|維修|修理|售后)+" inUser_Input Intent = “查詢售后” … … FOREACH(Color in Colors) IF (Color inUser_Input) Entity.Type = “ProductColor” Entity.Value = Color … … 這樣做的優點顯而易見:方便、直接。 缺點也很明顯:缺乏泛化能力。 一件事有很多種說法的時候,需要開發者將所有這些說法都手動添加到白名單里。 這樣不僅很難面面俱到,而且,還會碰到不能夠靠匹配關鍵詞解決的問題。比如,有人問“郵費能給免了嗎”,有人問“這個商品郵費多少錢?”,這根本是兩個意思,如果都有“郵費”匹配,給同一個答案,就答非所問了。 這個時候,就需要引入基于模型的方法:使用機器學習模型來進行意圖識別和實體抽取。 基于模型的語言理解包含兩個子任務: 意圖識別(intentionclassification):用來識別用戶所提問題的意圖,也就是用戶希望做一件什么事。 實體抽取(entityextraction):用于提取用戶對話中所提供的和意圖相關的參數(實體),例如時間、地點等。 具體某個Chatbot的意圖類型和實體類型,是其開發者自己定義的。例如小明的客服機器人可以如此定義: Case1:發到北京的貨包郵嗎?—— 意圖:查詢包郵;目的地實體:北京 Case2:00183號商品快遞到伊犁郵費多少?—— 意圖:查詢郵費;目的地實體:伊犁,商品Id實體:00183 Case3:02465號商品有保修嗎?——意圖:保修查詢;商品Id實體:02465 引用-2-1 或者,換個定義意圖和實體的方式,也沒有問題: Case2’:00183號商品快遞到伊犁郵費多少?—— 意圖:商品查詢;目的地實體:伊犁,商品Id實體:00183,商品屬性實體:郵費 Case3’:02465號商品有保修嗎?——意圖:商品查詢;商品Id實體:02465,商品屬性實體:保修 引用-2-2 一般來說,意圖識別是一個典型的分類模型(e.g. Logistic Regression,Decision Tree等),而實體抽取則是一個Sequence-to-Sequence判別模型(一般選用Conditional Random Field)。 語義理解模塊當然可以自己開發。不過,這需要長期積累的自然語言處理(NLP)的專業知識和經驗,高效的運算框架,以及標注工具的支持。 作為輕量級Bot的開發者,單獨開發一個語言理解模塊耗時耗力,效果還未必好。不如選用現成工具。在附錄中我們會介紹一款微軟對外發布的在線語言理解工具:LUIS。可以很方便的實現上述功能。 知識庫查詢和結果返回 知識庫用于存儲知識,本身可以是各種形式:數據庫,API,或者文本文件等。 用戶的問題經過語言理解,被提取成了意圖和若干實體。下面要做的是,針對不同的知識庫類型,將意圖和實體構造成對應的查詢。下表中幾種情況比較常用: 知識庫類型 查詢構造 回答生成 關系型數據庫 根據意圖和實體確定table name,where條件,和目標column等要素,構建SQL Query 將SQL Query結果填注到對應模板中,生成回答問題的自然語言 Web API 根據意圖和實體確定要調用的API類型和參數,構造Http Request 將Web API調用結果填注到對應模板中,生成回答問題的自然語言 結構化文本文件(json, xml等) 根據意圖和實體,確定對應文件路徑和對其中存儲數據結構的查詢 將獲取內容填注到對應模板中,生成回答問題的自然語言 非結構化文本文件 根據意圖和實體,確定對應文件路徑 直接返回文本內容 針對小明的問題,我們選擇SQL Server作為知識庫。知識存儲在table中。 用戶的問題經過語言理解,被提取成了意圖和若干實體。下面要做的就是:將解析出來的意圖和實體構造成一個SQL Query,用于在知識庫table中進行查詢。 例如,我們來看引用-2-2中的Case2’和Case3’。 知識庫里有一個Table,名字叫Product,其中每一個row對應一種產品,每個column對應一個屬性。 那么從Case2’中解析出來的意圖和實體(意圖:商品查詢;實體:[目的地:伊犁,商品Id:00183,商品屬性:郵費]),則可以被構造成一個SQL Query: SELECT ‘郵費’ FROM Product WHEREProduct_name = '00183' AND Destination = ‘伊犁’ 引用-3 Query在SQL Server中運行的結果(比如是26元),被放到一個預置的針對商品查詢的答案模板里,生成答案。 預置模板:“您查詢的${商品Id}號商品的${商品屬性}是${Query_Result}。” 生成答案:“您查詢的00183號商品的郵費是26元。” 引用-4 上下文存儲客戶和客服對話的時候,經常會問多個問題。而不同的問題之間,可能有一些信息是共享的。例如: 客戶:02366這款產品可以退換嗎?(問題1) 客服:7天之內無理由退換。 客戶:寄到南昌郵費多少啊?(問題2) 客服:10塊親。 客戶:武漢呢?(問題3) 引用-5 上例中,問題1詢問可否退換,并提到了一個產品的Id;問題2詢問到南昌的郵費,但是沒有提具體產品;問題3干脆只有一個地名。 但是作為人工客服很明白:問題2詢問的產品是問題1中出現的02366,而問題3則是詢問這款產品寄到武漢的郵費。 這些同一個對話中不同語句之間共享的信息,就是上下文(Context)。 想要機器人具備上下文的記憶、理解功能,而不是把用戶的每一個單獨語句當作本輪問題的全部信息來源,就需要有一個ContextStore來專門負責上下文信息的記錄、查詢、更新和刪除(CRUD)。參見圖-2中最右側下方的模塊。 每次用戶新輸入的信息都要先進行語言理解,再結合現有ContextStore中存儲的內容,或更新Context,或讀取之前的Context作為補充信息。 以引用-5為例,可以將意圖,和幾種實體類型對應的實體值(例如Id,目標屬性,目的地等)存儲在Context中。 當新的用戶語句輸入后,假設從中能夠提取出新的意圖或實體值,則用新值更新Context,否則,讀入現有的對應實體值,作為本次語言理解的補充。 在引用-5中,問題1中讀取到了商品查詢的意圖,商品Id,和“退換“這一商品屬性,將它們存入Context。 問題2中讀取到了”郵費“這一商品屬性,和之前存儲的不同,則更新Context的商品屬性值,并新存入“目的地”這一實體。 問題3則更新了目的地,并讀取其他的包括意圖、商品Id和商品屬性的值,與目的地一起用來構造查詢。 Context的場景針對性非常強,很多時候需要針對不同的意圖,記錄不同類型的實體值。在不同意圖之間切換的時候,也有可能會保留部分原有實體。這些都要針對具體情況case by case分析。 具體ContextStore中存儲什么樣的內容,CRUD策略是什么,都是開發者需要自己決定。 機器人的反問 某些情況下,Chatbot可能需要反問用戶若干問題,或者和用戶確認之前的某個回答,在這種情況下,就需要有內部流程控制。 例如:在商品查詢的目標屬性為郵費時,目的地缺失,這時候就需要主動要求用戶輸入對應的值。 不同場景的需求不同,這樣的控制流程很難統一規劃,因此需要在具體實踐中根據具體需求,完成細節。 或者,也可以主動提出幾個備選問題,請用戶選擇他們想問的。 開發一款機器人的基本流程 按照我們剛才說的: 1. 創建語言理解模塊。 定義意圖、實體類型;收集數據,選取特征;進行標注、訓練驗證和測 2. 創建一個知識庫。 創建SQL Server Database及若干表格,用來存儲問答知識。 3. 編寫中控程序,負責負責: i)接受用戶問題并調用語言理解模塊進行解析; ii)根據語言理解結果構知識庫查詢; iii)執行知識庫查詢; iv)根據數據庫查詢結果構造答案; v)創建并維護Context。 在完成了上述工作后,一個可以理解人類語言的聊天機器人就可以上線為顧客服務了。 在實踐當中,還有一些問題需要注意: Tip-1:語言理解部分可以考慮同時采用model-based模型和rule-based模型。 Model-based模型雖然可擴展性強,但也會有精準度不高,不容易即時修改等問題(雖然可以在線訓練和發布,但作為model-based分類器和判別工具,如須改變某句話的分類,或許并不能靠添加單一的訓練數據來完成)。 在這種情況下,考慮和rule-based的意圖、實體識別相結合。可以通過添加一系列正則表達式來匹配意圖,抽取實體。 Tip-2:某些情況下,Chatbot可能需要反問用戶若干問題,或者和用戶確認之前的某個回答,在這種情況下,就需要有內部流程控制。 例如:在商品查詢的目標屬性為郵費時,目的地缺失,這時候就需要主動要求用戶輸入對應的值。 不同場景的需求不同,這樣的控制流程很難統一規劃,因此需要在具體實踐中根據具體需求,完成細節。 Tip-3:有些時候,在無法明確用戶意圖時,也可以主動提出幾個備選問題,請用戶選擇他們想問的。 總之,在實踐中由于具體的場景和需求,會遇到各種各樣的問題。到時候,就兵來將擋,水來土掩吧! 附錄:微軟語言理解智能服務 LUIS 為了幫助普通開發者解決自然語言理解這一開發瓶頸,微軟推出了自己的語言理解智能服務 - LUIS。
113935hpcwz5k7kdpsl4r4.jpeg (23.77 KB, 下載次數: 64)
下載附件
2018-1-17 20:57 上傳
LUIS (LanguageUnderstanding Intelligent Service) 的使命是讓非NLP專業的開發者,能夠輕松地創建和維護高質量的自然語言理解模型,并無縫對接到相關應用中去。 使用LUIS,一個Bot需要創建一個(或多個)LUIS App,然后標注所期望的輸入(用戶的自然語言提問)和輸出(意圖和實體),再經過在線訓練來獲得自己的語言理解模型。 整個開發過程中,開發者只需要清晰地定義自己需要讓機器理解的用戶意圖和實體即可,并不需要了解背后算法的細節。 LUIS的開發流程包括三大步驟:
113955n27zgl8tt2ml2l0n.jpeg (14.6 KB, 下載次數: 50)
下載附件
2018-1-17 20:57 上傳
數據輸入和標注 LUIS開發者可以在界面上輕松地進行在線數據標注。 首先,在對應的用戶意圖中輸入自然語言語句,例如:在“商品查詢”意圖中輸入一句“00183號商品快遞到伊犁郵費多少?” ;然后,通過鼠標選取實體并指定類型,例如:選擇“郵費”標注為“商品屬性”。 標注結果在頁面上顯示如下:
114016vqwl6dd3aldqqlld.jpeg (11.3 KB, 下載次數: 59)
下載附件
2018-1-17 20:57 上傳
LUIS平臺會自動從用戶輸入并標注的數據中提取文本特征。這些特征,包括LUIS預設的常用文本特征(從大數據語料中提取),也包括用戶自定的新特征。 LUIS允許用戶通過兩種方式來定義新特征: 短語列表特征(Phrase List Features) 需用戶自己定義若干短語列表,這些被定義在同一列表中的短語,都會被當作同一個實體類型中的實體處理。
114041knzmr33f6drw99wq.jpeg (18.79 KB, 下載次數: 56)
下載附件
2018-1-17 20:57 上傳
在定義過程中,LUIS還會通過其語義詞典(semantic dictionary)挖掘技術,根據用戶輸入的短語,自動從海量的網絡數據中發現相似的短語,并推薦給用戶。從而有效地提升了效率。 模式特征(Pattern Features) 也稱為正則表達式特征。主要用于定義若干正則表達式。 LUIS根據這些表達式從用戶輸入數據中抽取符合其模式的實體。 模型的訓練 LUIS的模型訓練過程極其簡單,開發者只需點擊一下 “Train” 按鈕,后臺就會基于輸入數據進行自動訓練。 訓練的時間與標注數據量相關,標注數據越多,訓練所需的時間越長。同時,訓練時間還與LUIS App所支持的意圖和實體個數相關,意圖和實體越多,訓練時間也越長。 模型的測試、發布和服務 訓練完模型,開發者可以對其進行性能測試。方法有兩種: 交互式測試:開發者可以在頁面上直接輸入自然語言語句,然后目測模型輸出結果。 批量測試:開發者需要上傳一份測試數據,LUIS完成全部測試后給出精準率和召回率等統計數據,并針對每一項意圖和實體的繪制出Confusion Matrix。 測試過的模型,只需點擊“Publish”按鈕,就可以發布到微軟的Azure云平臺上,成為一個立即可用的API Service。 開發者可以通過Http的Get方法,調用模型,對新的語句進行意圖識別和實體抽取。 迭代更新 上述三個步驟是可以不斷重復迭代的。 模型訓練完發布上線后,可以繼續輸入、標注新的數據,重新訓練,再次發布。如此循環往復,逐步改進質量。 使用提示 1. 當前的LUIS是一個純粹model-based的語言理解工具。 雖然可擴展性強,但也會有精準度不高,不容易即時修改等問題(雖然可以在線訓練和發布,但作為model-based分類器和判別工具,如須改變某句話的分類,或許并不能靠添加單一的訓練數據來完成)。 在這種情況下,可以考慮LUIS和rule-based的意圖、實體識別相結合。可以通過添加一系列正則表達式來匹配意圖,抽取實體。 2. 每一個LUIS App都有一個內置的意圖,叫做None,非常有用。一般用它來收集那些用戶經常會問,但是Chat Bot并不打算回答的問題。 若不在None中指定它們,這些問題很可能會被錯誤的預測為其他用戶自定義的意圖,造成Chat Bot的over trigger(e.g.用戶問:你是女孩嗎?Bot回答:江浙滬包郵),從而嚴重影響用戶體驗。
|