揭祕「 B 站最火的 RAG 應用」是如何煉成的

近日,bilibili 知名科技 UP 主“Ele 實驗室”發佈了一個視頻,標題爲“當我開發出史料檢索 RAG 應用,正史怪又該如何應對?”

視頻連續三天被平臺打上“熱門”標籤,並迅速登上科技板塊全區排行榜前列。截至目前,視頻的觀看量近 70 萬,評論區討論異常激烈,很多技術愛好者、開發者都在評論區中提出了技術實現上的問題。作爲該視頻的技術支持方, Zilliz 最清楚其中的技術細節,今天我們就和大家聊聊這個「 B 站最火 RAG 視頻中的應用」——Mr History 是如何煉成的。

01. Mr History RAG 應用的背景介紹

經歷了大型語言模型(LLM)快速發展的 2023 年,業內越來越多地討論起了檢索增強生成(Retrieval-Augmented Generation,簡稱 RAG)技術,這個技術關鍵之處在於它結合了兩個重要的元素:檢索和生成。首先,它會通過搜索外部信息源(比如網頁或數據庫)來收集與問題相關的信息。然後,它會將這些信息巧妙地融入到它的回答中,生成一個更加準確、貼近實際情況的迴應。

這意味着無論你提出的問題是關於最新新聞、特定領域知識還是其他任何內容,RAG 都能提供更全面、有深度的答案。RAG 討論比較多的應用場景主要是在企業內部知識問答,但作爲一個技術,我們想在它與人文的交叉點做一些有趣的探索——使用 RAG 進行史料回答的探索,一是探索當前技術在具體的實踐中產生的應用場景, 二是想看一下 RAG 在應用時會遇到的具體挑戰。

二十四史是從黃帝記載到明代崇禎十七年(1644)的二十四部史書的合稱,如果能做一個關於二十四史的問答項目也是一個很有趣的事,畢竟喜歡歷史的朋友也往往對一些史實知道個粗略,想去了解一些更加詳細的細節。有一些朋友會說去找對應的人物傳就好了,但是在紀傳體中人物傳記並不是主人公的全貌,他的事蹟很有可能作爲配角分散在他人的傳記中。所以 RAG 的用處自然就是根據提問找到散佈在全書中的線索,推理出問題的答案。

先看了一下二十四史的數據,就發現了幾個很重要的特點:

  • 文言文非常喜歡省略主語,比如“高貴鄉公即尊位,賜爵關內侯。”這句話就會把主角鍾會給漏掉。

  • 文言文通常只稱呼名,比如“表念同爲皇族之情“,從這句話中就需要模型能推理出表是劉表,從而被召回。

  • 現代的 embedding 模型大部分都在對齊白話文與白話文,白話文與文言文缺乏對齊訓練。

經過以上的初步分析,我們決定先從白話文入手。目標和方法非常的明確,目前社區已經有了大量的 RAG 應用的教程,使用 LlamaIndex(完全可以是其他的 RAG 框架,比如 LangChain等),將文檔導入向量數據庫 Milvus(https://milvus.io/) 或者 Zilliz Cloud(https://zilliz.com.cn/cloud),接入 ChatGPT 的 API 作爲 query_engine,就完成了一個教科書式的關於史料的 RAG 應用,結果如下:

顯然,目前的 RAG 系統給出了一個出乎意料的答案。在完成了一個標準的 RAG 後,我們對最終呈現的結果並不滿意。當然,對 RAG 的質量評測通常是一個很複雜的系統工程,尤其是在缺乏數據標註的情況下,所以我們採用的是針對個例具體分析的方法來進行調優,根據“奧卡姆剃刀”法則,如果我們針對的個例的調優是簡潔優雅的情況下,那針對大部分其他案例都會帶來改善,我們先試着把這個問題給處理好。

02.提高 embedding 對於細節的捕捉能力

在 RAG 中,文本首先會根據 chunksize 來進行切分,每一個 chunk 計算出向量來方便檢索。典型的歷史問題通常都是涉及到(人物)(時間)(地點)的行爲,所以我們希望找回的語料內容能夠與問題在這些點的語義重合度較高。

我們使用的 embedding 模型是在開源社區中比較熱門的(BAAI/bge-base-zh-v1.5),它在大規模的中文數據集上經過訓練,能夠在效果和性能上取得一個不錯的平衡,需要分析的第一個原因可能是由於 chunksize 設置的過大,導致 embedding 對於細節刻畫得不是很好。所以我們採取了 LLamaIndex 中的 SentenceWindowNode, 按句來進行 embedding 的計算,但是最後返回給 LLM 來進行閱讀的文章確實包含了更多的上下文的一個窗口,這樣可以讓 LLM進行信息分析時能夠找到更多的線索。現在使用向量檢索確實發現對於細節的相關性有了很好的改善,但是也包含了一些關於關羽的其他內容甚至是和關羽的無關內容。

03.重排序進一步提高召回文本的相關性

即使我們通過 SentenceWindowNode 很好地提高了 embedding 對於細節的捕捉程度, 依然會出現不理想的排序。這可能與 embedding 模型是在大規模通用語料上訓練得到的有關。想要對此的改善通常是人工標註數據進行 embedding 模型的 finetune,但是我們希望使用更加通用的模型來進行處理。

我們使用 cross-encoder 方式設計的 rerank 模型(BAAI/bge-reranker-large)來進行文本相關性的計算,rerank 模型通過輸入(問題,文檔片段)直接生成分數,所以可以同時接收到二者的信息。用比喻來說,embedding 召回就是看簡歷留下大致印象,rerank 就是一對一的進行面試,所以通常的情況下都能進一步提高結果的相關程度。通過這個技術,我們找到了所有關羽殺死他人的文本,當然也包含了一些關羽被吳國殺死的信息。

04.大模型的選擇

在我們提供了儘可能高質量的史料信息後,就到了大模型最後的閱讀理解階段,我們一開始採用的是 gpt-35-turbo-1106,發現在這個問題上表現並不是很理想(可能是由於語料都是比較碎片化的段落),非常出現容易幻覺。在經過了一定的prompt工程後(例如:告訴它需要忠實地參考原文),但最終還是無法達到期待的效果。剛好 OpenAI 年底發佈了更便宜的 gpt4 版本 gpt4-turbo-1205, 無論是對於格式的要求,以及對於幻覺的克服,都有了顯著的提升,我們選擇了 gpt4-turbo 作爲最後的 reader。

05.爲段落加上引用

作爲一個史料的 RAG 應用,我們希望能夠在給出包含知識的原文同時能夠給出它在原文中的具體傳記名,由於語料中可以通過格式區分出來傳記名和正文,所以通過簡單的一些規則就可以提取出來每個段落對應的傳記名,並且通過將其作爲文本的 metadata。我們可以對 metadata 進行控制,只希望將傳記名告訴給 LLM 讓其來進行出處的標記,而不希望在 embedding 和 rerank 階段帶來影響,就可以控制它在只在 LLM 的 prompt 中呈現出來。

06.總結

現在,我們就可以產生出一個能夠初步符合預期的 RAG 系統了,這個 RAG 能夠捕捉到細粒度的相關性高的史料,並且可以準確地引用其對應出處。同時更強的 LLM 模型也可以從繁雜的史料片段中提取到對問題回答有幫助的知識。

我們在這個項目中首先分析了數據的特點,採取了更加適合現有模型的文本方案,接下來所採用的提升技術主要是儘可能地提高召回文本的與問題的相關性,並且通過讓 embedding 的文本與展示給 LLM 的文本不同的技巧來達到提高檢索精度,擁有足夠上下文,獲取引用信息的目的。我們儘可能地採取了通用的技巧,針對歷史 RAG 的場景,我們也可以去識別“人名”然後進行片段的過濾處理,或者額外分析一下發生的朝代,根據朝代信息來將召回片段進行過濾。

歸根結底就是當給出一個 query 後,怎麼儘可能地找到最相關的知識,不浪費 LLM 中的 prompt 空間。話說到這裏,必須要附上項目地址供感興趣的小夥伴參考呀,歡迎 Clone 體驗:https://github.com/wxywb/history_rag

此外,在社區的使用過程中,也有不懂編程的小夥伴在使用 history_rag遇 到了算力不足,以及部署數據庫的問題。目前,history_rag 除了需要本地部署數據庫和向量模型的 Milvus 模式外,還支持了 Zilliz Pipeline 的模式。

Zilliz Pipeline 是 Zilliz Cloud 推出的一項雲託管服務,可以將文本轉換爲向量插入到雲數據庫中。這樣搭配着其他在雲端部署的 LLM 可以使用戶不需要高性能的算力設備,以及擺脫複雜的數據庫管理。同時這個方案也可以與具體的 LLM 解耦,方便使用各種 LLM,社區也貢獻了通義千問的方案可以一鍵切換。

所以如果你對歷史非常感興趣,那麼你不需要會編程或計算機,直接來 GitHub 跟着文檔走一遍就好。

相關鏈接:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章