Rasa2 NLU 架構(gòu)及源碼解析(三)
神州信息
李丹 鄭飛 杜昕宸 韓彤 秦帥帥
Rasa是當(dāng)前智能機(jī)器人中最流行的的聊天機(jī)器人框架,是基于機(jī)器學(xué)習(xí)和自然語言處理技術(shù)開發(fā)的系統(tǒng),用于構(gòu)建上下文AI助手和聊天機(jī)器人。
1.
背景
近年來,聊天機(jī)器人受到了學(xué)術(shù)界和工業(yè)界的廣泛關(guān)注。人工智能技術(shù)的快速發(fā)展突破了聊天機(jī)器人原有的技術(shù)瓶頸,并且實(shí)踐證明,聊天機(jī)器人的使用不僅能夠?yàn)槠髽I(yè)減少一大筆人力成本,而且能夠明顯提高工作效率,國內(nèi)外多家企業(yè)紛紛布局聊天機(jī)器人行業(yè)。微軟推出了基于情感計(jì)算的聊天機(jī)器人小冰,百度推出了用于交互式搜索的聊天機(jī)器人小度,進(jìn)而推動了聊天機(jī)器人產(chǎn)品化的發(fā)展。聊天機(jī)器人系統(tǒng)可以看作是機(jī)器人產(chǎn)業(yè)與“互聯(lián)網(wǎng)+”的結(jié)合,符合國家的科研及產(chǎn)業(yè)化發(fā)展方向。
隨著人工智能在銀行和金融科技的客戶服務(wù)方面取得了重大改進(jìn),客戶越來越習(xí)慣于獲得快速響應(yīng)。金融機(jī)構(gòu)必須全天候回答客戶問題和進(jìn)行交易。金融機(jī)構(gòu)業(yè)務(wù)擴(kuò)展的加速使人工客服的成本大幅攀升的同時又無法持續(xù)滿足服務(wù)質(zhì)量,人工智能機(jī)器人通過金融機(jī)構(gòu)長期積累的業(yè)務(wù)經(jīng)驗(yàn)和數(shù)據(jù)培訓(xùn)聊天機(jī)器人,可明顯改善客戶體驗(yàn)。基于上述痛點(diǎn)和需求,各類聊天機(jī)器人框架應(yīng)運(yùn)而生。根據(jù)社區(qū)活躍度、技術(shù)的成熟完備度及被引用、點(diǎn)贊等指標(biāo),我們采用Rasa作為人機(jī)交互對話機(jī)器人基本框架。
2.
Rasa簡介
Rasa Open Source有兩個主要模塊:
●Rasa NLU :用于理解用戶消息,包括意圖識別和實(shí)體識別。以pipeline的方式處理用戶對話,可在config.yml中配置。
●Rasa Core:主要負(fù)責(zé)對話管理。根據(jù)NLU輸出的信息、以及Tracker記錄的歷史信息,得到上下文的語境,從而預(yù)測用戶當(dāng)前步最可能執(zhí)行哪一個action。
其中,Rasa NLU主要依賴自然語言處理技術(shù),是可以獨(dú)立的、與整體框架解耦的模塊,可支持大量NLP前沿技術(shù),以組件的形式,可以靈活與其他開源、自研框架搭配使用。
3.
Rasa NLU架構(gòu)及源碼解析
3.3 Custom Component案例
3.3.1自定義組件方式
●拆分方式:將分詞、特征化、模型等部分進(jìn)行解耦,以TextCNN意圖識別模型為例
●整體打包方式:將模型的各部分封裝一起,只對外暴露個別接口,以JointBert意圖和實(shí)體聯(lián)合識別模型為例
3.3.2拆分方式
3.3.2.1簡介
TextCNN做意圖識別,以拆分的方式進(jìn)行自定義組件,以字作為單位,不用分詞。只需拆分成:featurizer和 classifier兩部分。
3.3.2.2組件介紹
●Featurizer:
components.user_featurizer.UserFeaturizer
主要功能:構(gòu)建字典,獲取字到id的映射,得到句子的id 列表。
主要參數(shù):
訓(xùn)練流程:
components的train函數(shù) -> 構(gòu)建字典:基于最小詞頻和詞典最大容量 -> 遍歷所有的訓(xùn)練數(shù)據(jù) -> 得到句子的id列表 -> 實(shí)例化特征類Features - > message設(shè)置
預(yù)測流程:
components的process函數(shù) -> 獲取句子id列表 -> 實(shí)例化Features設(shè)置message
●Classifier:
components.user_intent.UserIntentClassifier
主要功能:利用TextCNN進(jìn)行意圖分類
主要參數(shù):
訓(xùn)練流程:
components的train函數(shù) -> 過濾掉空的examples -> 獲取字典大小 -> 獲取label -> 構(gòu)建label2id dict-> 構(gòu)建模型網(wǎng)絡(luò) -> model.train
預(yù)測流程:
components的process函數(shù) -> 獲取句子id list -> 調(diào)用predict函數(shù)預(yù)測 -> _get_ranking 對結(jié)果進(jìn)行排序 -> 保存到message
注意:兩個組件之間的依賴關(guān)系,相關(guān)信息的傳遞,例如:詞典大小,無法在classifier中當(dāng)作參數(shù)配置,只能根據(jù)featurizer中構(gòu)建詞典的結(jié)果得到。這里通過在featurizer中構(gòu)建字典之后保存到message中,在classifier中通過message獲取。
3.3.2.3使用樣例
注意:樣例僅配置了NLU部分,訓(xùn)練時使用rasa train nlu,測試時使用rasa shell nlu。
domain中的意圖:
配置文件config:
運(yùn)行樣例:
{
"text": "收不到余額變動提醒怎么辦",
"intent": {
"name": "personal_bank",
"confidence": 0.9055530429
},
"entities": [],
"intent_ranking": [
{
"intent": "personal_bank",
"confidence": 0.9055530429
},
{
"intent": "finance_investment",
"confidence": 0.0601818413
},
{
"intent": "personal_finance",
"confidence": 0.033517994
},
{
"intent": "corporate_bank",
"confidence": 0.0006058206
},
{
"intent": "other",
"confidence": 0.0001413494
}
]
}
3.3.3整體打包方式
3.3.3.1簡介
JointBert意圖和詞槽聯(lián)合識別,以整體打包的方式進(jìn)行自定義組件,包放在src/smartintslotpretrain,對外暴露三個函數(shù)即可,分別為:訓(xùn)練train, 預(yù)測eval, 模型加載load_model。
3.3.3.2組件介紹
聯(lián)合識別組件:
components.jointbert_intent_slot.JointBertIntentSlot
主要功能:進(jìn)行意圖和詞槽的聯(lián)合識別
主要參數(shù):
訓(xùn)練流程:
JointBert作為外部包,提供三個接口,訓(xùn)練train, 加載load_model,預(yù)測eval。
component的train函數(shù) -> 通過transfer_data進(jìn)行數(shù)據(jù)格式轉(zhuǎn)換,將rasa的nlu數(shù)據(jù)轉(zhuǎn)化為JointBert所需要的數(shù)據(jù)格式(具體為:過濾空文本, auto_mark進(jìn)行實(shí)體標(biāo)注,注意實(shí)體標(biāo)注可能存在group和role的區(qū)分,save format data 保存為特定格式的文件)-> 調(diào)用JointBert的train.train_model進(jìn)行訓(xùn)練。
數(shù)據(jù)轉(zhuǎn)化樣例:
nlu.yml中的數(shù)據(jù):
轉(zhuǎn)換之后的數(shù)據(jù)格式:
auto_mark關(guān)鍵代碼:
注:這里只標(biāo)注了存在role的情況,如果存在group可按同樣的方式進(jìn)行添加。
預(yù)測流程:
components的process函數(shù) -> 文本和JointBert的模型傳入 eval.preditce_online中進(jìn)行預(yù)測,得到 intent_dict, slot_dict -> format_entity 格式化成rasa需要的entity格式-> _sort_intent_ranking 對intent進(jìn)行排序 -> message.set 進(jìn)行保存結(jié)果。
注:format_entity 為 auto_mark的逆過程,這兩部分需要對齊。
以打包方式進(jìn)行組件編寫的方式關(guān)鍵有三點(diǎn):
●合理的提供模型的三個接口:訓(xùn)練、模型加載、預(yù)測
●rasa數(shù)據(jù)到模型數(shù)據(jù)的轉(zhuǎn)換,不同模型訓(xùn)練源碼需要的數(shù)據(jù)格式都不太相同。
●模型預(yù)測結(jié)果到rasa需要結(jié)果格式的轉(zhuǎn)換
3.3.3.3使用樣例
注意:樣例僅配置了NLU部分,訓(xùn)練時使用rasa train nlu,測試時使用rasa shell nlu。
domain中的intent和entity:
配置文件config:
運(yùn)行樣例:
{
"text": "今天黃金的價格是多少",
"intent": {
"name": "gold_price",
"confidence": 0.999890089
},
"entities": [
{
"entity": "date",
"value": "今天",
"start": 0,
"end": 2,
"extractor": "JointBertIntentSlot"
}
],
"intent_ranking": [
{
"intents": "gold_price",
"confidence": 0.999890089
},
{
"intents": "UNK",
"confidence": 3.54958e-05
},
{
"intents": "consume_check",
"confidence": 2.15434e-05
},
{
"intents": "currency_exchange",
"confidence": 2.13388e-05
},
{
"intents": "card_requirement",
"confidence": 1.93974e-05
},
{
"intents": "card_meterial",
"confidence": 1.20613e-05
}
]
{
"text": "10美元能兌換多少人民幣",
"intent": {
"name": "currency_exchange",
"confidence": 0.9999859333
},
"entities": [
{
"entity": "money",
"value": "10",
"start": 0,
"end": 2,
"extractor": "JointBertIntentSlot"
},
{
"entity": "currency_type",
"value": "美元",
"start": 2,
"end": 4,
"extractor": "JointBertIntentSlot",
"role": "from"
},
{
"entity": "currency_type",
"value": "人民幣",
"start": 9,
"end": 12,
"extractor": "JointBertIntentSlot",
"role": "to"
}
],
"intent_ranking": [
{
"intents": "currency_exchange",
"confidence": 0.9999859333
},
{
"intents": "UNK",
"confidence": 4.3686e-06
},
{
"intents": "gold_price",
"confidence": 3.5197e-06
},
{
"intents": "consume_check",
"confidence": 2.3771e-06
},
{
"intents": "card_meterial",
"confidence": 1.879e-06
},
{
"intents": "card_requirement",
"confidence": 1.8156e-06
}
]
}
{
"text": "6.1的黃金價格是多少",
"intent": {
"name": "gold_price",
"confidence": 0.9998868704
},
"entities": [
{
"entity": "date",
"value": "6.1",
"start": 0,
"end": 3,
"extractor": "JointBertIntentSlot"
}
],
"intent_ranking": [
{
"intents": "gold_price",
"confidence": 0.9998868704
},
{
"intents": "UNK",
"confidence": 3.81634e-05
},
{
"intents": "consume_check",
"confidence": 3.09156e-05
},
{
"intents": "currency_exchange",
"confidence": 2.11939e-05
},
{
"intents": "card_requirement",
"confidence": 1.48951e-05
},
{
"intents": "card_meterial",
"confidence": 7.9957e-06
}
]
}
3.3.4優(yōu)缺點(diǎn)
References
1. Rasa官方文檔
https://rasa.com/docs/rasa/2.x/components
2. diet介紹
https://www.yiyibooks.cn/nlp/diet/index.html
3. spaCy官方文檔
https://spacy.io/api/architectures#parser
4. Greedy transition-based parsing
https://explosion.ai/blog/parsing-english-in-python
5. spaCy v2.0命名實(shí)體識別解析
https://www.bilibili.com/video/av16282127
6.NLU自定義組件
https://puluwen.github.io/2018/12/rasa-nlu/