那些檢索增強生成 (Retrieval-Augmented Generation, RAG) 要踩的坑

 https://github.com/Deep-Learning-101 | https://huggingface.co/DeepLearning101

在踩了深度學習 (包含圖像識別、自然語言處理、語音處理等) 及現在最夯的大型語言模型 (Large Language Model, LLM) 一些會踩的坑後,應該都稍微有匯整到跟放到 HF Space 了?特別是現在很多人或公司跟單位都會先嘴自己有在做GenAI或者是大模型,怎麼判斷呢?先問問對方有幾張什麼類型的GPU吧 !!!

 那些大型語言模型要踩的坑 | 什麼是大語言模型,它是什麼?想要嗎? 
大型語言模型之 Cryptocurrency Exchange FAQ
多模態大型語言模型之單據核銷
大型語言模型之 High Entropy Alloys  FAQ

為啥這篇會想來分享一下跟在大量資料上訓練的 LLM,其最大差異就是能專注聚焦局部搜尋在我們私有資料上 的檢索增強生成 (Retrieval-Augmented Generation, RAG) ?畢竟再怎樣我不少論文勉強都算是做 Ontolgy 的啊,還因此在流浪到英國時特地去了趟 Ontology大本營,OWL.Manchester 啊 ! 不過,先簡單講一下本地端怎樣做RAG ?

想在自己本地端跑大模型,要先佈署安裝一下 Ollama,這裡有一些安裝及參數設定,目前我自己是用這幾個 (請視自己的GPU來決定,千萬不要想說用個幾張消費型的GPU,就想跟人家嘴砲說有做大模型或者是??);Ollama 安裝跟執行操作是真的不難,而且也能跑 embedding,不過 xinference 會更方便就是。
準備好相關模型跟佈署後,那就是要準備文檔的製作了,這裡就請不要無腦的塞入文檔讓它自動切割,特別是直接 pdf 或者 ppt,至少要像下面這樣,略為自己瞭解整理一下 !
基本上自動分段已經可以做到不錯,而且還可以做到有關鍵詞 (其實就是拉了關係出來)
一般來說,很常碰到是直接一堆 pdf 檔要做 embedding,這時候就會碰上無法順利辨識的問題,這邊附上一個不錯的套件,https://github.com/opendatalab/MinerU 
MinerU is a one-stop, open-source, high-quality data extraction tool, supports PDF/webpage/e-book extraction. (一款一站式、開源、高品質的資料擷取工具,支援PDF/網頁/電子書擷取。)
跑完後可以把 pdf 轉成 markdown,且內容只要再稍稍調整即可 !
另外也又找到一個也是數據處理的開源工具:https://github.com/adithya-s-k/omniparse
Ingest, parse, and optimize any data format ➡️ from documents to multimedia ➡️ for enhanced compatibility with GenAI frameworks
操作安裝也都很簡單,可以用 gradio ui 也可以直接用 curl
curl -X POST -F "file=@/path/to/document" http://localhost:8000/parse_document
所以,除了上述圖的 chunk 要先好好做的範例以外 (目前有很多蠻勵害的 jina 等的開源套件),再來則是 embedding 了
這邊我使用較多的就是  xinference  了,然後則是包含了 Rerank等的檢索用法,網路上很多開源的套件都有相關說明如下:
  • 向量檢索:透過生成查詢嵌入並查詢與其向量表示最相似的文字分段 
  • 全文檢索:索引文件中的所有詞彙,從而允許使用者查詢任意詞彙,並返回包含這些詞彙的文字片段
    • TopK:這是用來找到與使用者輸入的問題相似度最高的文字片段。
    • Score 閾值:這是設定文字片段的相似度閾值,也就是只召回超過設定分數的文字片段。
  • 混合檢索:同時全文檢索和向量檢索,並使用ReRANK重新排序,從兩類查詢結果中選擇匹配使用者問題的最佳結果,需配置 Rerank 模型 API。
    • ReRANK:計算候選文件清單與使用者問題的語意匹配度,根據語意匹配度重新進行排序,進而改善語意排序的結果。

看完前面說明,其RAG原理就是輸入私有的文檔後,每個文檔依照Token數量?字元數量?等一定規則,將每個文檔拆分為一個一個小片段(chunk);接著對這些chunk產生embeding,儲存到vector db 中,產生Index;待使用者搜尋時,會將語句轉換為embedding,跟 vector db 做向量相似度搜尋,搜尋到最相似的 embedding ,也就是查詢語句的向量比對 " 部分 " 知識庫的向量相似度再將對應上下文透過LLM做合成自然流暢的回答 (這裡很多人會糾結在以Q找Q再找A或者以Q找A,但這其實就回到 Rule-Based 啦);特別是最近很夯的所謂的 GraphRAG、Knowledge Graph (知識圖譜) 及 Ontology (知識本體) ?

https://github.com/microsoft/graphrag
From Local to Global: A Graph RAG Approach to Query-Focused Summarization

git clone https://github.com/microsoft/graphrag.git
#initialize:python -m graphrag.index --init --root .
#index:python -m graphrag.index --root .
#query:python -m graphrag.query --root . --method global "query"
#query:python -m graphrag.query --root . --method local "query"

下圖是 GraphRAG論文裡針對索引 (利用LLM來建立知識圖譜,找出對應的實體(節點)、關系(邊)等) 和查詢 (透過像是 Leiden來對整個圖譜做劃分以及摘要跟總結) 的處理過程;其中,LLM怎樣做圖譜可以在這裡找到 ! 當然,或許可以嘗試手工自己做KG (略麻煩也耗工),那你可能會找到一堆套件說可以輸入文件後自動幫你生成,但你還是得需要有個所謂的 NER,再把相關數據存入 Neo4j,再來則是透過Node2Vec、GraphSAGE等來做 embedding (這塊可能得看 GraphRAG是否能盡快解決 ?),接著是透過 FAISS、Milvus 等向量搜尋,那應該會做得比較流暢一點?最後說個招人討厭的實話,實在不怎建議為了一台車連輪子都自己造 ... 特別是在壓根連 GPU 都沒什麼資源的狀況下,一直呼叫外部API ... 這??LP比雞腿?
傳統RAG會做的chunk,在GraphRAG的論文裡也是沒漏掉,論文中就有提到1200個token會去得較好的效果,但是這會卡到所謂的 precison 跟 recall 的效果。另外,GraphRAG支援需要理解整個文本語料的問題,一種全局性的理解和摘要,而不是僅從文本的局部區域中檢索資訊,例如「資料集的主要主題是什麼?」的 "global search"" local search " 通常指的是文本的局部區域或文本塊,這些局部區域是RAG方法檢索的單元。

但截至本文的整理,根據官方的論文和一些 issue 跟範例:During our research we got the most quality out of gpt-4, gpt-4-turbo and gpt-4o, that's why out of the box we include support for these in both OpenAI and Azure environments. 看來官方是覺得比不上,所以就沒針對自己地端佈署運作有深入研究 !!! Regarding local hosting there's a very interesting conversation going on in this thread #339;初步評估結果是,以KG為基礎來做RAG,確實會因為具備所謂的 實體 (entity)、關係 (relation) 等,而優化了相關的結果,但是在 GraphRAG還未支援Local LLM 前,估計這成本會嚇到你的 XD (當然有人回覆 GPT4o便宜多了)。最後,論文還是有提供了效果的展示:

寫到這,可能會很想看看是不是只是嘴砲 ? 官網的文件其實寫得非常清楚
https://microsoft.github.io/graphrag/posts/get_started/ 
至於我到底做完了那些 ? 嗯 ! 我會一直更新補充的。