1. 背景
應(yīng)項(xiàng)目需求,本qiang~這兩周全身心投入了進(jìn)去。
項(xiàng)目是關(guān)于一個(gè)博物館知識(shí)圖譜,上層做KBQA應(yīng)用。實(shí)現(xiàn)要求是將傳統(tǒng)KBQA中的部分模塊,如NLU、指代消解、實(shí)體對(duì)齊等任務(wù),完全由LLM實(shí)現(xiàn),本qiang~針對(duì)該任務(wù)還是灰常感興趣的,遂開(kāi)展了項(xiàng)目研發(fā)工作。
注意,此篇是純純的干貨篇,除了源碼沒(méi)有提供外,整體核心組件均展示了出來(lái)。也是這兩周工作的整體總結(jié),歡迎大家查閱以及加關(guān)注(不強(qiáng)求哈~)
2. 整體框架

整體思想還是遵循RAG策略,從圖譜召回候選背景知識(shí),讓LLM進(jìn)行潤(rùn)色回答。
具體的流程如下:
(1) 用戶提問(wèn):已發(fā)現(xiàn)的體重最大的肉食性恐龍是什么
(2) 對(duì)齊模塊。
對(duì)齊模塊的主要作用是針對(duì)問(wèn)題與知識(shí)圖譜中的實(shí)體、概念、關(guān)系、屬性進(jìn)行對(duì)齊。
其中候選概念、候選屬性、候選關(guān)系在圖譜中的數(shù)量是少量有限的,而實(shí)體的數(shù)量可多可少,因此候選概念、候選屬性、候選關(guān)系可以在查詢hugegraph后,直接拼到對(duì)齊prompt中(對(duì)齊的prompt預(yù)留了占位符),而實(shí)體則需要進(jìn)行預(yù)篩選,篩選的方式是通過(guò)問(wèn)題query與實(shí)體名進(jìn)行語(yǔ)義相似度比較,通過(guò)語(yǔ)義相似度引擎實(shí)現(xiàn),比如simbert, bge, gte等開(kāi)源模型,預(yù)篩選后的少量實(shí)體可以拼接到對(duì)齊prompt。
對(duì)齊的prompt增加要求和few-shot示例,可以解決常見(jiàn)對(duì)齊問(wèn)題,比如實(shí)體、概念、屬性、關(guān)系存在缺字、多字、相似字等情況。
(3) 對(duì)齊模塊經(jīng)過(guò)LLM進(jìn)行對(duì)齊,輸出對(duì)齊結(jié)果。
本示例的對(duì)齊結(jié)果為:(屬性-等于-體重)且(屬性值-等于-最大); (屬性-等于-食性)且(屬性值-等于-肉食性);(概念-等于-恐龍)。
(4) 對(duì)齊校準(zhǔn)模塊。
對(duì)齊校準(zhǔn)模塊主要針對(duì)LLM對(duì)齊結(jié)果進(jìn)行二次校對(duì),解決的問(wèn)題如下:
1) 一些LLM將概念與實(shí)體混淆的情況;
2) 與圖譜中的實(shí)體、概念、屬性、關(guān)系進(jìn)行對(duì)齊匹配;
3) 實(shí)體名和概念名重復(fù)時(shí),二者均進(jìn)行召回等
(5) 解析及溯源模塊
解析模塊:
針對(duì)校準(zhǔn)后的對(duì)齊結(jié)果,執(zhí)行解析模塊,解析模塊會(huì)基于對(duì)齊結(jié)果進(jìn)行判斷,該執(zhí)行如下哪種解析,候選的解析列表有:純實(shí)體解析、純概念解析、實(shí)體-屬性解析、概念-屬性解析、屬性-屬性值解析、屬性-屬性值-概念解析等。
(Ps: 候選解析列表是分析了大量數(shù)據(jù)之后,抽象出來(lái)的解析列表,常見(jiàn)的問(wèn)答基本就涵蓋在這些列表中)
每個(gè)解析模塊會(huì)有不同的解析邏輯,例如:
1) 純實(shí)體解析:會(huì)將查詢hugegraph得到的實(shí)體作為背景知識(shí)提供給LLM,如介紹下霸王龍
2) 純概念解析:會(huì)查詢概念下有哪些實(shí)體,且僅列出實(shí)體名稱作為背景知識(shí)提供給LLM,如恐龍都有哪些?
3) 實(shí)體-屬性解析:會(huì)查詢實(shí)體對(duì)應(yīng)的屬性或關(guān)系,并作為背景知識(shí),如霸王龍有多重多高?
4) 概念-屬性解析:會(huì)查詢概念下實(shí)體的屬性信息作為背景知識(shí),如恐龍目下動(dòng)物的體重分別是多少?
5) 屬性-屬性值解析:會(huì)查詢屬性對(duì)應(yīng)屬性值的信息,并作為背景知識(shí),如肉食性的動(dòng)物有?
溯源模塊:主要功能就是從圖譜中查詢的結(jié)果,需要返回圖譜對(duì)應(yīng)的實(shí)體id、概念id、屬性等
6) 問(wèn)答模塊
通過(guò)將解析后的背景知識(shí)以及用戶的問(wèn)題,經(jīng)過(guò)問(wèn)答prompt,然后調(diào)用LLM進(jìn)行潤(rùn)色回答。
PS:
對(duì)齊prompt調(diào)用大模型是非流式輸出,因?yàn)閷?duì)齊結(jié)果不需要實(shí)時(shí)同步給用戶;
問(wèn)答prompt調(diào)用大模型是流式輸出,因?yàn)閱?wèn)答結(jié)果需要實(shí)時(shí)同步給用戶
3. 優(yōu)缺點(diǎn)
(1) 優(yōu)點(diǎn)
1) 整體架構(gòu)簡(jiǎn)單,僅需要2個(gè)prompt,與LLM僅交互2次
2) 解析模塊基于多數(shù)據(jù)集進(jìn)行抽象,可覆蓋多數(shù)查詢場(chǎng)景
3) 針對(duì)未覆蓋的場(chǎng)景,解析模塊可支持快速擴(kuò)展適配
4) 遷移新圖譜時(shí),業(yè)務(wù)只需要更改prompt即可,對(duì)業(yè)務(wù)相對(duì)友好
(2) 缺點(diǎn)
1) 首字響應(yīng)時(shí)間主要耗時(shí)在對(duì)齊prompt與LLM的交互中,因?yàn)樾枰獙?duì)齊完整輸出結(jié)果
2) 概念、屬性、實(shí)體對(duì)齊集中在1個(gè)prompt中,所以prompt的長(zhǎng)度較長(zhǎng)
4. 多輪問(wèn)答實(shí)現(xiàn)
實(shí)現(xiàn)的思路如下:
1) 緩存歷史問(wèn)題以及緩存歷史對(duì)齊的實(shí)體或概念,如可以緩存最近10輪的用戶問(wèn)題以及對(duì)齊結(jié)果
2) 針對(duì)指代消解、語(yǔ)義對(duì)齊prompt調(diào)優(yōu),且多輪問(wèn)答的prompt也集成在對(duì)齊prompt中(因此,對(duì)齊prompt任務(wù)十分繁重)
具體示例如下(從對(duì)齊prompt截取了部分,第一次輸入?yún)⒖紴榭?:
歷史輸入信息:
```
輸入:鹽都龍喜歡吃什么
參考:
輸入:喜歡生活在什么地方
參考:鹽都龍
輸入:三角龍是植食還是肉食
參考:鹽都龍
輸入:有什么本事
參考:三角龍
輸入:普爾塔龍多重
參考:三角龍
```
現(xiàn)在請(qǐng)回答:
輸入: 吃什么
參考: 普爾塔龍
輸出:
具體的效果可以查閱下面章節(jié)中的效果示例。
5. 效果
圖譜三元組總量3000+,測(cè)試樣例共計(jì)385條,其中單輪問(wèn)答340條,多輪問(wèn)答45條。
???????? (1)單輪問(wèn)答效果,準(zhǔn)確率93%+
一階問(wèn)答:
問(wèn):華陽(yáng)龍的頭骨化石是在哪里發(fā)現(xiàn)的
答:華陽(yáng)龍的頭骨化石是在中國(guó)四川省發(fā)現(xiàn)的。
判斷問(wèn)答:
問(wèn):恐爪龍有4米長(zhǎng)嗎
答:恐爪龍的身長(zhǎng)是3.5米左右,沒(méi)有4米。
對(duì)比問(wèn)答:
問(wèn):三角龍和姜氏巴克龍誰(shuí)更重
答:三角龍更重。
條件問(wèn)答:
問(wèn):最大體型的長(zhǎng)羽毛恐龍是?
答:最大體型的長(zhǎng)羽毛恐龍是二連巨盜龍。
組合問(wèn)答:
問(wèn):?jiǎn)巫埳黹L(zhǎng)體重多少?
答:?jiǎn)巫埖纳黹L(zhǎng)是1~1.2米,體重約3.5千克。
???????? (2) 多輪問(wèn)答效果,準(zhǔn)確率93%+
1) 示例1:缺字情況
問(wèn):普爾塔多重
答:普爾塔龍的體重是75噸。
問(wèn):吃什么
答:普爾塔龍是植食性的
2) 示例2:錯(cuò)字情況
問(wèn):河堤列龍生活在什么地方
答:河堤獵龍生活在英國(guó)的懷特島和奇爾頓嶺。
問(wèn):它是什么時(shí)候的恐龍
答:河堤獵龍是早白堊世,巴雷姆期的恐龍。
3) 示例3:較困難的指代消解
問(wèn):三角龍是植食還是肉食
答:三角龍是植食性的。
問(wèn):有啥本事
答:三角龍的能力是快速奔跑。
問(wèn):和腫頭龍比,誰(shuí)更長(zhǎng)一些?
答:三角龍的身長(zhǎng)為8米,而腫頭龍的身長(zhǎng)為4~6米。因此,三角龍更長(zhǎng)一些。
問(wèn):那它的體重是多少?
答:三角龍的體重是6.1~12噸。
6. 答疑解惑
(1) 候選實(shí)體、候選概念、候選屬性如何動(dòng)態(tài)加載至prompt?
解:prompt預(yù)留占位符,代碼解析時(shí)進(jìn)行格式化
(2) 概念、屬性數(shù)量有限,可以全部寫(xiě)在prompt,但如果實(shí)體有1W個(gè)呢?
解:基于sim進(jìn)行候選實(shí)體召回策略
(3) 如何實(shí)現(xiàn)流式輸出?
解:基于tornado的websocket框架,結(jié)合異步框架asyncio以及python的yield、next等方法實(shí)現(xiàn)
(4) 非流式調(diào)用LLM出現(xiàn)網(wǎng)絡(luò)不穩(wěn)定導(dǎo)致超時(shí),如何解決?
解:增加重試機(jī)制
(5) 對(duì)齊結(jié)果如何進(jìn)一步保障?
解:增加對(duì)齊校準(zhǔn)模塊
(6) 如何減少頻繁調(diào)用hugegraph
解:預(yù)先加載圖譜至內(nèi)存,然后使用python的lru_cache緩存機(jī)制
(7) 如何提高屬性、概念、實(shí)體對(duì)齊的準(zhǔn)確率,比如多字、缺字、相近字等?
解:對(duì)齊prompt增加要求以及few-shot
(8) 如何解決實(shí)體文字完全不一致,但指的同一個(gè)實(shí)體的情況,比如霸王龍和雷克斯暴龍?
解:通過(guò)圖譜的別名維護(hù),且當(dāng)前別名與正式名地位相同
(9) 溯源是如何實(shí)現(xiàn)的?
解:在每個(gè)解析分支中,基于解析結(jié)果增加對(duì)應(yīng)圖譜的信息
(10) 如何實(shí)現(xiàn)最大、最小之類的查詢,如體重最大的植食性恐龍是哪個(gè)?
解:對(duì)齊結(jié)果:(屬性-等于-體重)且(屬性值-等于-最大)且(概念-等于-恐龍)
解析邏輯:篩選恐龍概念下實(shí)體 -> 食性為植食性的實(shí)體-> 其中體重最大的
(11) 如何實(shí)現(xiàn)關(guān)系的推理,比如魚(yú)石螈演進(jìn)關(guān)系的演進(jìn)關(guān)系是?
解:原始圖譜關(guān)系:魚(yú)石螈 -> 演進(jìn)關(guān)系 ->蜥螈 -> 演進(jìn)關(guān)系 -> 異齒龍
對(duì)齊結(jié)果:(實(shí)體-等于-魚(yú)石螈)且(屬性-等于-演進(jìn)關(guān)系);(屬性-等于-演進(jìn)關(guān)系)
答案:魚(yú)石螈的演進(jìn)關(guān)系是蜥螈,而蜥螈的演進(jìn)關(guān)系是異齒龍。
(12) 為什么說(shuō)解析模塊便于快速擴(kuò)展?
解:實(shí)體、概念、屬性查詢接口均封裝為獨(dú)立方法。
(13) 對(duì)比類、判斷類的問(wèn)題回答如何更加口語(yǔ)化?
解:?jiǎn)柎餻rompt調(diào)優(yōu)
(14) 如何快速定位問(wèn)題?
解:增加debug機(jī)制,即接口調(diào)用時(shí),debug機(jī)制會(huì)將每個(gè)階段的處理結(jié)果均記錄下來(lái),并返回。
(15) 目前支持多少輪問(wèn)答?
解:理論上支持N多輪,且N支持配置
(16) 如何提高指代消解的準(zhǔn)確率?
解:對(duì)齊prompt增加歷史的參考實(shí)體或概念
7. 遺留的問(wèn)題
(1) 基于屬性值查實(shí)體未實(shí)現(xiàn),分析部分badcase,屬于此類情況
(2) 路徑查詢未實(shí)現(xiàn),因?yàn)楫?dāng)前圖譜關(guān)系數(shù)量極少
8. 總結(jié)
一句話足矣~
本文主要是KBQA方案基于LLM實(shí)現(xiàn),主要模塊包括對(duì)齊、解析、潤(rùn)色、多輪問(wèn)答等內(nèi)容,而且基于業(yè)務(wù)測(cè)試集效果相對(duì)較好。
純純的干貨篇??!
原創(chuàng)聲明,禁止轉(zhuǎn)載!