與圖數(shù)據(jù)庫(kù)協(xié)同:從語(yǔ)義檢索到關(guān)系推理的大模型知識(shí)問(wèn)答方案)
1. 從關(guān)鍵詞匹配到關(guān)系推理為什么單靠向量庫(kù)撐不起知識(shí)檢索做過(guò)大模型應(yīng)用的人大概都有過(guò)這種體驗(yàn)用戶問(wèn)某型號(hào)設(shè)備的散熱模塊和上一代相比在高溫環(huán)境下的性能衰減曲線有什么差異你把這句話丟進(jìn)向量數(shù)據(jù)庫(kù)返回的是一堆語(yǔ)義相似的文檔片段——可能是散熱模塊的規(guī)格說(shuō)明可能是高溫測(cè)試報(bào)告也可能是上一代產(chǎn)品的評(píng)測(cè)文章。這些片段單獨(dú)看都對(duì)但拼在一起就是答不出那個(gè)差異。問(wèn)題出在哪向量數(shù)據(jù)庫(kù)擅長(zhǎng)的是語(yǔ)義相似度檢索它把文本映射成高維空間里的點(diǎn)靠余弦距離找長(zhǎng)得像的內(nèi)容。但差異這個(gè)詞背后需要的是跨實(shí)體的關(guān)系比對(duì)設(shè)備A的散熱模塊、設(shè)備B的散熱模塊、高溫環(huán)境、性能衰減曲線這四個(gè)概念之間的連接關(guān)系向量相似度是表達(dá)不出來(lái)的。你問(wèn)的是關(guān)系它給你的是相似。這就是向量數(shù)據(jù)庫(kù)與圖數(shù)據(jù)庫(kù)協(xié)同的出發(fā)點(diǎn)。向量庫(kù)負(fù)責(zé)找到相關(guān)的東西圖數(shù)據(jù)庫(kù)負(fù)責(zé)理清這些東西之間的關(guān)系大模型負(fù)責(zé)把關(guān)系翻譯成人話。三者各司其職缺一不可。我最初做這個(gè)協(xié)同方案時(shí)踩的第一個(gè)坑就是試圖用純向量方案硬扛關(guān)系推理。結(jié)果就是檢索召回率看著挺高但答案的準(zhǔn)確率始終卡在60%上下——因?yàn)槟P湍玫降氖巧⒙涞钠嗡米约翰逻@些片段之間是什么關(guān)系猜錯(cuò)的概率自然高。后來(lái)引入圖數(shù)據(jù)庫(kù)做關(guān)系層同樣的模型、同樣的數(shù)據(jù)答案準(zhǔn)確率直接拉到85%以上。這個(gè)提升不是模型變強(qiáng)了而是喂給模型的信息從碎片變成了帶連接的結(jié)構(gòu)。這篇文章適合誰(shuí)看如果你正在做大模型的知識(shí)問(wèn)答、智能客服、企業(yè)知識(shí)庫(kù)或者任何需要理解關(guān)系的檢索場(chǎng)景那這套協(xié)同方案值得你花時(shí)間研究。如果你只是做簡(jiǎn)單的文檔問(wèn)答向量庫(kù)夠用但一旦涉及對(duì)比關(guān)聯(lián)推理多跳查詢圖數(shù)據(jù)庫(kù)的介入就是剛需。下面我會(huì)從架構(gòu)設(shè)計(jì)、數(shù)據(jù)建模、檢索鏈路、大模型融合、性能調(diào)優(yōu)幾個(gè)維度把整套方案的落地細(xì)節(jié)拆開講。每個(gè)環(huán)節(jié)我都會(huì)說(shuō)明為什么這么選以及我實(shí)際踩過(guò)哪些坑。2. 協(xié)同架構(gòu)的三種形態(tài)從各管各的到深度耦合向量庫(kù)和圖數(shù)據(jù)庫(kù)怎么協(xié)同不是只有一種答案。根據(jù)業(yè)務(wù)復(fù)雜度和實(shí)時(shí)性要求我實(shí)踐下來(lái)有三種形態(tài)復(fù)雜度從低到高適用場(chǎng)景也完全不同。2.1 旁路模式向量檢索為主圖查詢做補(bǔ)充這是最容易上手的形態(tài)。用戶query進(jìn)來(lái)先走向量庫(kù)做語(yǔ)義檢索拿到Top-K文檔片段同時(shí)用query里的實(shí)體詞去圖數(shù)據(jù)庫(kù)做一次關(guān)系查詢拿到相關(guān)的實(shí)體和關(guān)系路徑最后把兩部分結(jié)果一起塞給大模型做生成。這種模式的好處是改動(dòng)小。你原有的向量檢索鏈路不用動(dòng)只需要在旁邊加一個(gè)圖查詢的旁路。適合那些大部分問(wèn)題靠語(yǔ)義檢索能解決只有少數(shù)關(guān)系類問(wèn)題需要圖的場(chǎng)景。但它的局限也很明顯向量檢索和圖查詢是并行且獨(dú)立的兩者之間沒(méi)有信息交換。向量庫(kù)不知道圖里有哪些實(shí)體圖查詢也不知道向量檢索召回了什么。結(jié)果就是大模型拿到的上下文里可能向量片段講的是A設(shè)備圖路徑講的是B設(shè)備對(duì)不上。我早期做的一個(gè)設(shè)備運(yùn)維知識(shí)庫(kù)就用了這個(gè)模式效果只能說(shuō)能用。用戶問(wèn)某故障碼對(duì)應(yīng)的處理步驟向量檢索能召回故障碼說(shuō)明圖查詢能拿到故障碼關(guān)聯(lián)的部件但兩者經(jīng)常對(duì)不齊——因?yàn)橄蛄繖z索按語(yǔ)義相似度排圖查詢按實(shí)體匹配排排序邏輯不一致。2.2 串聯(lián)模式圖查詢先定位向量檢索再細(xì)化這個(gè)模式把順序倒過(guò)來(lái)先用圖數(shù)據(jù)庫(kù)做實(shí)體識(shí)別和關(guān)系定位確定用戶問(wèn)的是哪幾個(gè)實(shí)體、它們之間是什么關(guān)系然后帶著這些實(shí)體信息去向量庫(kù)做定向檢索。舉個(gè)例子用戶問(wèn)某型號(hào)泵體和上一代在密封結(jié)構(gòu)上的差異。串聯(lián)模式會(huì)先在圖里找到某型號(hào)泵體和上一代泵體兩個(gè)實(shí)體節(jié)點(diǎn)以及它們之間的替代關(guān)系邊然后帶著這兩個(gè)實(shí)體的ID去向量庫(kù)檢索只召回與這兩個(gè)實(shí)體相關(guān)的文檔片段。這樣召回的片段天然就是對(duì)齊的不會(huì)出現(xiàn)A設(shè)備配B文檔的情況。串聯(lián)模式的關(guān)鍵在于實(shí)體鏈接的準(zhǔn)確性。你得先把用戶query里的自然語(yǔ)言實(shí)體映射到圖數(shù)據(jù)庫(kù)里的節(jié)點(diǎn)ID。這一步做不好后面全白搭。我通常會(huì)用大模型做一次實(shí)體抽取再用圖數(shù)據(jù)庫(kù)的模糊匹配做候選召回最后用向量相似度做消歧。2.3 深度融合模式圖嵌入與向量空間對(duì)齊這是最復(fù)雜但也最強(qiáng)大的形態(tài)。核心思路是把圖數(shù)據(jù)庫(kù)里的節(jié)點(diǎn)和關(guān)系通過(guò)圖嵌入算法比如Node2Vec、TransE映射到和文本向量同一個(gè)空間里。這樣向量檢索的時(shí)候不僅能匹配文本語(yǔ)義還能匹配圖結(jié)構(gòu)語(yǔ)義。具體做法是對(duì)圖里的每個(gè)實(shí)體節(jié)點(diǎn)生成一個(gè)圖嵌入向量對(duì)每個(gè)文檔片段生成一個(gè)文本向量然后訓(xùn)練一個(gè)對(duì)齊層讓描述某實(shí)體的文本和該實(shí)體的圖嵌入在向量空間里靠近。檢索時(shí)用戶query的向量可以同時(shí)匹配文本向量和圖嵌入向量召回的結(jié)果既有語(yǔ)義相關(guān)的文檔也有結(jié)構(gòu)相關(guān)的實(shí)體。這個(gè)模式的門檻在于訓(xùn)練對(duì)齊層需要標(biāo)注數(shù)據(jù)而且圖嵌入的質(zhì)量高度依賴圖結(jié)構(gòu)的完整性。我目前只在兩個(gè)數(shù)據(jù)量較大、圖結(jié)構(gòu)較完善的場(chǎng)景里用了這個(gè)模式效果確實(shí)好但投入也大。中小規(guī)模的知識(shí)庫(kù)串聯(lián)模式性價(jià)比更高。三種模式的對(duì)比我整理成了一張表方便你根據(jù)自己場(chǎng)景選型模式改動(dòng)成本關(guān)系推理能力適用場(chǎng)景主要坑點(diǎn)旁路模式低弱語(yǔ)義檢索為主少量關(guān)系查詢向量與圖結(jié)果對(duì)不齊串聯(lián)模式中強(qiáng)實(shí)體關(guān)系明確的知識(shí)庫(kù)實(shí)體鏈接準(zhǔn)確率深度融合高最強(qiáng)大規(guī)模、圖結(jié)構(gòu)完善需要標(biāo)注數(shù)據(jù)訓(xùn)練對(duì)齊選型建議如果你剛開始做從串聯(lián)模式入手。旁路模式雖然簡(jiǎn)單但對(duì)齊問(wèn)題會(huì)讓你在后期花大量時(shí)間打補(bǔ)丁。深度融合等你的圖數(shù)據(jù)和標(biāo)注數(shù)據(jù)都到位了再考慮。3. 圖數(shù)據(jù)建模別把圖數(shù)據(jù)庫(kù)當(dāng)關(guān)系庫(kù)用圖數(shù)據(jù)庫(kù)的建模方式和關(guān)系型數(shù)據(jù)庫(kù)完全不同但很多人第一次用圖數(shù)據(jù)庫(kù)時(shí)會(huì)不自覺(jué)地用關(guān)系庫(kù)的思維去設(shè)計(jì)——建一堆節(jié)點(diǎn)表然后用邊去模擬外鍵。這樣做出來(lái)的圖查詢性能差而且完全發(fā)揮不出圖數(shù)據(jù)庫(kù)的優(yōu)勢(shì)。3.1 節(jié)點(diǎn)和邊的設(shè)計(jì)原則圖數(shù)據(jù)庫(kù)建模的核心原則是節(jié)點(diǎn)代表實(shí)體邊代表關(guān)系屬性掛在節(jié)點(diǎn)或邊上。聽起來(lái)簡(jiǎn)單但實(shí)操中有幾個(gè)關(guān)鍵決策點(diǎn)。第一個(gè)決策什么該做成節(jié)點(diǎn)什么該做成屬性。我的經(jīng)驗(yàn)是如果一個(gè)東西需要被單獨(dú)查詢或者被多條邊連接就做成節(jié)點(diǎn)如果它只是某個(gè)實(shí)體的描述性信息就做成屬性。比如設(shè)備型號(hào)應(yīng)該做成節(jié)點(diǎn)因?yàn)槎鄠€(gè)設(shè)備可能共享同一個(gè)型號(hào)但設(shè)備的生產(chǎn)日期就是屬性因?yàn)樗恍枰粏为?dú)查詢。第二個(gè)決策邊的方向怎么定。圖數(shù)據(jù)庫(kù)的邊是有方向的但很多關(guān)系是雙向的。我的做法是按語(yǔ)義方向建邊查詢時(shí)忽略方向。比如設(shè)備A使用部件B邊從A指向B查詢哪些設(shè)備使用了部件B時(shí)用反向遍歷。這樣既保持了語(yǔ)義清晰又不影響查詢靈活性。第三個(gè)決策要不要用超邊。有些關(guān)系涉及三個(gè)以上的實(shí)體比如設(shè)備A在時(shí)間T由人員P維修這是三元關(guān)系。圖數(shù)據(jù)庫(kù)原生不支持超邊通常的做法是建一個(gè)維修事件節(jié)點(diǎn)然后把它分別連到設(shè)備、時(shí)間、人員。這個(gè)中間節(jié)點(diǎn)看起來(lái)冗余但它讓查詢變得非常靈活——你可以從任何一個(gè)維度切入。3.2 實(shí)體消歧同一個(gè)東西別建兩個(gè)節(jié)點(diǎn)圖數(shù)據(jù)庫(kù)最怕的就是同一個(gè)實(shí)體被建成了多個(gè)節(jié)點(diǎn)。比如某型號(hào)泵體和某型號(hào)泵如果沒(méi)做消歧就會(huì)變成兩個(gè)節(jié)點(diǎn)它們之間的關(guān)系就斷了。這個(gè)問(wèn)題在數(shù)據(jù)來(lái)自多個(gè)源時(shí)特別嚴(yán)重。我的消歧方案分三步第一步用規(guī)則做初篩比如名稱完全相同的直接合并第二步用向量相似度做候選召回把名稱向量相似度高于閾值的節(jié)點(diǎn)對(duì)找出來(lái)第三步用大模型做最終判斷把兩個(gè)節(jié)點(diǎn)的屬性和關(guān)聯(lián)邊一起喂給模型讓它判斷是不是同一個(gè)實(shí)體。第三步聽起來(lái)重但實(shí)際跑下來(lái)大模型判斷的準(zhǔn)確率比純規(guī)則或純向量都高。因?yàn)槟P湍芸炊承吞?hào)泵體和某型號(hào)泵在上下文里指的是同一個(gè)東西而向量相似度可能因?yàn)槎嗔藗€(gè)體字就掉到閾值以下。注意消歧一定要在數(shù)據(jù)入庫(kù)前做不要等入庫(kù)后再合并。入庫(kù)后合并節(jié)點(diǎn)所有關(guān)聯(lián)邊都要重連代價(jià)極大。我踩過(guò)這個(gè)坑一個(gè)中型知識(shí)圖譜合并節(jié)點(diǎn)花了整整兩天。3.3 圖schema的演進(jìn)策略圖schema不是一次設(shè)計(jì)好就固定的。業(yè)務(wù)在變實(shí)體和關(guān)系也在變。我的做法是預(yù)留擴(kuò)展字段每個(gè)節(jié)點(diǎn)和邊都加一個(gè)type屬性用來(lái)標(biāo)記業(yè)務(wù)類型再加一個(gè)meta屬性存JSON格式的擴(kuò)展信息。這樣新增業(yè)務(wù)類型時(shí)不需要改schema只需要在type里加新值。另外圖schema的版本管理很重要。每次變更schema都要記錄變更內(nèi)容、變更原因、影響的查詢。我通常會(huì)在圖數(shù)據(jù)庫(kù)里建一個(gè)_schema_version節(jié)點(diǎn)記錄當(dāng)前版本和變更歷史。這樣出問(wèn)題時(shí)能快速定位是哪次變更導(dǎo)致的。4. 檢索鏈路設(shè)計(jì)從query到答案的完整流轉(zhuǎn)檢索鏈路是整個(gè)協(xié)同方案的核心。用戶的一個(gè)自然語(yǔ)言問(wèn)題要經(jīng)過(guò)實(shí)體識(shí)別、圖查詢、向量檢索、結(jié)果融合、大模型生成五個(gè)環(huán)節(jié)才能變成最終答案。每個(gè)環(huán)節(jié)都有講究。4.1 實(shí)體識(shí)別與鏈接把人話翻譯成圖語(yǔ)言用戶不會(huì)按圖數(shù)據(jù)庫(kù)的節(jié)點(diǎn)名稱來(lái)提問(wèn)。用戶說(shuō)那個(gè)新泵的密封圈圖數(shù)據(jù)庫(kù)里可能叫某型號(hào)泵體-密封組件。這中間的映射就是實(shí)體識(shí)別與鏈接要解決的問(wèn)題。我的做法是兩階段鏈接第一階段用大模型做實(shí)體抽取把query里的實(shí)體mention抽出來(lái)同時(shí)給出實(shí)體類型設(shè)備、部件、故障碼等第二階段用類型約束的向量檢索在對(duì)應(yīng)類型的節(jié)點(diǎn)里找最相似的候選再用大模型做最終確認(rèn)。這里有個(gè)細(xì)節(jié)大模型抽取實(shí)體時(shí)一定要讓它輸出實(shí)體類型。因?yàn)椴煌?