創新中心觀點
    數字中國·星火文集 | Rasa2 NLU 架構及源碼解析(三)
    2022-06-29

    Rasa2 NLU 架構及源碼解析(三)

    神州信息

    李丹 鄭飛 杜昕宸 韓彤 秦帥帥

    Rasa是當前智能機器人中最流行的的聊天機器人框架,是基于機器學習和自然語言處理技術開發的系統,用于構建上下文AI助手和聊天機器人。

    1.

    背景

    近年來,聊天機器人受到了學術界和工業界的廣泛關注。人工智能技術的快速發展突破了聊天機器人原有的技術瓶頸,并且實踐證明,聊天機器人的使用不僅能夠為企業減少一大筆人力成本,而且能夠明顯提高工作效率,國內外多家企業紛紛布局聊天機器人行業。微軟推出了基于情感計算的聊天機器人小冰,百度推出了用于交互式搜索的聊天機器人小度,進而推動了聊天機器人產品化的發展。聊天機器人系統可以看作是機器人產業與“互聯網+”的結合,符合國家的科研及產業化發展方向。

    隨著人工智能在銀行和金融科技的客戶服務方面取得了重大改進,客戶越來越習慣于獲得快速響應。金融機構必須全天候回答客戶問題和進行交易。金融機構業務擴展的加速使人工客服的成本大幅攀升的同時又無法持續滿足服務質量,人工智能機器人通過金融機構長期積累的業務經驗和數據培訓聊天機器人,可明顯改善客戶體驗。基于上述痛點和需求,各類聊天機器人框架應運而生。根據社區活躍度、技術的成熟完備度及被引用、點贊等指標,我們采用Rasa作為人機交互對話機器人基本框架。

    2.

    Rasa簡介

    Rasa Open Source有兩個主要模塊:

    ●Rasa NLU :用于理解用戶消息,包括意圖識別和實體識別。以pipeline的方式處理用戶對話,可在config.yml中配置。

    ●Rasa Core:主要負責對話管理。根據NLU輸出的信息、以及Tracker記錄的歷史信息,得到上下文的語境,從而預測用戶當前步最可能執行哪一個action。

    其中,Rasa NLU主要依賴自然語言處理技術,是可以獨立的、與整體框架解耦的模塊,可支持大量NLP前沿技術,以組件的形式,可以靈活與其他開源、自研框架搭配使用。

    3.

    Rasa NLU架構及源碼解析

    3.3 Custom Component案例

    3.3.1自定義組件方式

    ●拆分方式:將分詞、特征化、模型等部分進行解耦,以TextCNN意圖識別模型為例

    ●整體打包方式:將模型的各部分封裝一起,只對外暴露個別接口,以JointBert意圖和實體聯合識別模型為例

    3.3.2拆分方式

    3.3.2.1簡介

    TextCNN做意圖識別,以拆分的方式進行自定義組件,以字作為單位,不用分詞。只需拆分成:featurizer和 classifier兩部分。

    3.3.2.2組件介紹

    ●Featurizer:

    components.user_featurizer.UserFeaturizer

    主要功能:構建字典,獲取字到id的映射,得到句子的id 列表。

    主要參數:

    訓練流程:

    components的train函數 -> 構建字典:基于最小詞頻和詞典最大容量 -> 遍歷所有的訓練數據 -> 得到句子的id列表 -> 實例化特征類Features - > message設置

    預測流程:

    components的process函數 -> 獲取句子id列表 -> 實例化Features設置message

    ●Classifier:

    components.user_intent.UserIntentClassifier

    主要功能:利用TextCNN進行意圖分類

    主要參數:

    訓練流程:

    components的train函數 -> 過濾掉空的examples -> 獲取字典大小 -> 獲取label -> 構建label2id dict-> 構建模型網絡 -> model.train

    預測流程:

    components的process函數 -> 獲取句子id list -> 調用predict函數預測 -> _get_ranking 對結果進行排序 -> 保存到message

    注意:兩個組件之間的依賴關系,相關信息的傳遞,例如:詞典大小,無法在classifier中當作參數配置,只能根據featurizer中構建詞典的結果得到。這里通過在featurizer中構建字典之后保存到message中,在classifier中通過message獲取。

    3.3.2.3使用樣例

    注意:樣例僅配置了NLU部分,訓練時使用rasa train nlu,測試時使用rasa shell nlu。

    domain中的意圖:

    配置文件config:

    運行樣例:

    {

    "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意圖和詞槽聯合識別,以整體打包的方式進行自定義組件,包放在src/smartintslotpretrain,對外暴露三個函數即可,分別為:訓練train, 預測eval, 模型加載load_model。

    3.3.3.2組件介紹

    聯合識別組件:

    components.jointbert_intent_slot.JointBertIntentSlot

    主要功能:進行意圖和詞槽的聯合識別

    主要參數:

    訓練流程:

    JointBert作為外部包,提供三個接口,訓練train, 加載load_model,預測eval。

    component的train函數 -> 通過transfer_data進行數據格式轉換,將rasa的nlu數據轉化為JointBert所需要的數據格式(具體為:過濾空文本, auto_mark進行實體標注,注意實體標注可能存在group和role的區分,save format data 保存為特定格式的文件)-> 調用JointBert的train.train_model進行訓練。

    數據轉化樣例:

    nlu.yml中的數據:

    轉換之后的數據格式:

    auto_mark關鍵代碼:

    注:這里只標注了存在role的情況,如果存在group可按同樣的方式進行添加。

    預測流程:

    components的process函數 -> 文本和JointBert的模型傳入 eval.preditce_online中進行預測,得到 intent_dict, slot_dict -> format_entity 格式化成rasa需要的entity格式-> _sort_intent_ranking 對intent進行排序 -> message.set 進行保存結果。

    注:format_entity 為 auto_mark的逆過程,這兩部分需要對齊。

    以打包方式進行組件編寫的方式關鍵有三點:

    ●合理的提供模型的三個接口:訓練、模型加載、預測

    ●rasa數據到模型數據的轉換,不同模型訓練源碼需要的數據格式都不太相同。

    ●模型預測結果到rasa需要結果格式的轉換

    3.3.3.3使用樣例

    注意:樣例僅配置了NLU部分,訓練時使用rasa train nlu,測試時使用rasa shell nlu。

    domain中的intent和entity:

    配置文件config:

    運行樣例:

    {

    "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優缺點

    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命名實體識別解析

    https://www.bilibili.com/video/av16282127

    6.NLU自定義組件

    https://puluwen.github.io/2018/12/rasa-nlu/

    主站蜘蛛池模板: 石棉县| 静安区| 葵青区| 永修县| 安义县| 尼勒克县| 咸宁市| 株洲县| 越西县| 永泰县| 商河县| 东方市| 河池市| 肇庆市| 得荣县| 凤凰县| 华坪县| 商城县| 临湘市| 上林县| 蕲春县| 林甸县| 义乌市| 循化| 斗六市| 佛冈县| 集贤县| 麻江县| 安庆市| 简阳市| 富蕴县| 淄博市| 华阴市| 彩票| 静乐县| 武穴市| 鲁甸县| 龙胜| 靖边县| 普兰县| 景泰县|