RAG 系統概略的運作流程
RAG 系統通過將人類輸入的自然語言查詢轉換成文字嵌入向量(Embedding),用於在語義上從向量資料庫中檢索出一組相關性最高的文件,然後將檢索到的文件傳遞給 LLM 去生成推論結果。這流程大致可分成以下兩個獨立的過程:索引(Indexing)和查詢(Querying)。
索引過程(Index Process)
在 RAG 系統中,檢索系統使用文件中文字語料轉換後的高維度向量來進行操作,文字嵌入以高維度向量的數字形式作為表現方式(維度試所使用的 embedding model 而定),在 Indexing 過程中,每份文件被分割成較小的塊(chunk),這些塊使用 embedding model 轉換成 embeddings,然後系統將原始 chunk 和 embeddings 成對的索引在向量資料庫(ex. Pinecone)中。
在這過程中軟體開發上面臨的設計決策包括如何有效率的分割文件、 每一個 chunk 應該多大以及 chunk 與 chunk 間需要重疊多少語料等等。如果 chunk 切得太小,每段 chunk 無法保留足夠的語意,反之如果每段 chunk 太長,則 chunk 中會包含過多的雜訊與含糊的語意。另外不同類型的文件需要不同的分塊和處理方式,例如影片內容需要先提取音訊然後透過 Whisper 之類的生成模型轉換成文字語料,另外在選擇使用哪一個 embedding model 去將語料向量化也很重要,因為改變使用的 embedding model 就需要重新索引所有 chunk 資料。
查詢過程(Query Process)
查詢的第一步是要將以自然語言表達的問題加上 context 轉換成 prompt text,然後透過 embedding model 將 prompt text 轉換成高維度文字向量的表現形式,然後透過該向量從向量資料庫中以語意相近程度(ex. 餘弦相似度)去定位出最相關的 Top-k 文件集,在理論上,這些被檢索出的文件由於語意上的相近,極有可能包含能夠解答輸入 LLM 問題的解答資訊。
而這個過程中要解決的問題其實相當的複雜,這些複雜度來自於 LLM 自身以及開發廠商(ex. OpenAI、Google 等等)在架構設計上的限制,如 token limit 以及 API rate-limit 等等,這些都會影響 RAG 檢索出相關文件後可代入 LLM 進行推論的語料數量的大小,實務上我們不可能代入無限制的 context 去輔助 LLM 的推論,正因為這樣的限制,每一個 chunk 的大小與 chunk 內容以及 chunk 上 meta data 的設計都會是影響 LLM 推論品質的因素。
RAG vs fine-tuning?
先天上,LLM 在處理最新知識或特定領域知識時具有一定的局限性,因為在各種主客觀條件下,開發者們不可能隨時隨地的對 LLM 重新進行預訓練跟指令式微調,因此 fine-tuning 跟 RAG 便成了某種『階段性』的解決方案。然而相較於 fine-tuning 這一項需要去變更到 LLM 類神經網路的權重與損失函數的技術,RAG 具有較短的開發時程需求,因為它不需要創建知識圖譜,且對數據的整理和清理要求較低。當然 RAG 系統在實務上也面臨著一大堆挑戰,包括如何確保搜尋到的資訊的品質、如何處理和整合來自不同來源的資訊,以及如何優化系統性能以處理大量查詢等等。
RAG 方法論在先天上系統性的限制
RAG, 全名為 Retrieval Augmented Generation(檢索增強生成),是一種結合了語意搜尋和 LLM(如 ChatGPT、Gemini)推論能力的方法論,其目的在於減少 LLM 產生的幻覺式回答、連結來源/參考至生成的回應,並降低對文件進行 meta data 進行標註的需求。透過這種方式,RAG 系統理論上能讓 LLM 生成更準確、更可靠的推論結果。
但因為搜尋系統既有的限制以及對於 LLM 本身推論能力強弱的依賴性,在實務中 RAG 具有許多限制,在研究報告「Seven Failure Points When Engineering a Retrieval Augmented Generation System」中,研究人員們透過系統性的實驗 RAG 在三個不同領域(研究、教育、生物醫學)歸納出 RAG 在實際操作中會遇到幾個關鍵的失敗點(共七項)並提出了以下兩個關鍵結論:
- RAG 系統的驗證只能在運行期間進行。
- RAG 系統的強健性是逐步迭代的過程而非一次性的設計可達成。
這意謂著在設計和部署 RAG 系統時,開發者需要採取迭代的方法,不斷收集反饋和進行調整,以提高系統的準確性和可靠性。
「Seven Failure Points When Engineering a Retrieval Augmented Generation System」的論文實驗方法
研究者們使用 BioASQ 資料集進行了一項實證實驗,以探索出 RAG 在實務應用上潛在的失敗點,該實驗涉及 15,000 份文件和 1,000 個對問答,他們對所有文件進行了索引,然後使用 GPT-4 作為進行答案推論的 foundation model 並將推論生成結果儲存了下來,最後所有問答對都通過 OpenAI 的 OpenAI Evals 進行了驗證,同時還搭配了人工查核的方式去檢視所有不一致以及所有被自動化 eval 系統標記為錯誤的項目,以及一些正確標籤的樣本,用以更細緻的進行模式的識別。
RAG 對其他相關研究的依賴
有趣的事情是,RAG 雖然是用來增強 LLM 推論成效的一個輔助方法,但 RAG 的效能良窳卻也在很大的程度上奠基在既有 LLM 的能力強弱之上,paper 中提到的一項最近的調查顯示,LLMs 被用於 RAG 流程中的多個環節之上,包括檢索器(Retriever)、數據生成(Data generation)、重寫器(Rewriter)和閱讀器(Reader)等等,但現階段在這些應用環節上卻也缺乏有效的評估指標,簡單的以列表的方式梳理如下:
- No metrics for query rewriting:RAG 系統中缺乏查詢重寫指標凸顯了在評估系統如何改寫用戶查詢以改善搜索結果方面存在的缺口,開發用於評估查詢重寫效果的指標,在檢索的過程中可以找出更相關的文件進而推升 LLM 推論生成的品質。
- Document re-ranking:有效的文件重排策略對於盡快向用戶呈現最相關的資訊至關重要,這件事要做得好不僅涉及如何有效的識別文件內容與查詢語句在語意上的相關性,還涉及如何優先檢索與排序最相關的文件,這些任務都需要開發更先進的演算法和機器學習模型來輔助。
- Effective content summarisation:從檢索到的文件中生成簡潔且訊息豐富的摘要是一項複雜的任務,這需要機器能夠理解文件文本內容的本質,這一挑戰不僅涉及要如何在龐大的語料中提取出重點,還涉及如何連貫、良好的 UX 去呈現它們,這些任務需要在 NLU 和摘要技術上的迭代改進來協助。
- Fact check:如何正確評估 LLM 在 RAG 的輔助下能夠生成真實的資訊是相當重要的一件事,鑒於世界知識的動態性質以及 LLM 的預訓練數據中可能存在的過時或不正確信息,這一挑戰可說是眾多潛在挑戰中最為棘手的一項,開發有效的方法來驗證和更新回答的事實內容也將是重要的後續研究方向。
論文中進行的案例研究
這項研究進行了三個案例研究,以探討實施 RAG 系統時遇到的挑戰,以下是每個案例研究的摘要,所有腳本、數據和 BioASQ 案例研究的每個失敗點的範例都可以在線上找到,其他兩個案例研究因保密問題而未被包括在內。
Cognitive Reviewer
這是一套支持研究人員分析科學文獻的 RAG 系統,研究人員指定一個研究問題或目標,然後上傳一系列相關研究論文。隨後,所有文件根據研究人員所述目標進行排序,以便手動審查。研究人員也可以直接對所有文件進行提問。這套系統目前被 Deakin University 的博士生用於支持他們的文獻回顧。Cognitive Reviewer 在 run-time 時進行索引,依賴於一個強大的 data pipeline 來處理上傳的文件,該系統還使用一個排序算法來對上傳的文件進行排序。
AI Tutor
這套 RAG 系統通過整合到 Deakin University 的學習管理系統中,索引了所有教育學習的內容,包括 PDF、Video(在分塊之前使用了 Whisper 進行影片轉錄與逐字稿的生成) 和文本文件,作為索引過程的一部分學生可以透過它提出有關課程的問題,答案從學習內容中獲得,學生能夠通過訪問答案來源列表來驗證答案。此套 RAG system 開發時程從 2023年 8月到 2023年 11月,於 2023年 10月 30日開始的一個單元進行了試點,該單元有 200名學生參加。研究者的目的是分享實作期間學到的經驗,並在試點結束時提出後續的發現。
實務上這個 RAG 系統包括一個 rewriter 來將查詢進行一般化(Generalise queries),他們設計了一套 Chat UI,其中使用者與 AI Tutor 之間的對話脈絡都會被作為每個問題的上下文。Rewriter 會將對話的上下文納入 LLM 推論回答的依據,並重寫查詢以解決模糊的請求,如「進一步解釋這個概念」。
Biomedical Question and Answer
前兩項案例研究聚焦於內容較小的文件,但為了探索更大規模的問題,研究人員們使用 BioASQ 資料集部署了一個用作生物醫藥學 Q&A 任務的 RAG 系統,該資料集內容包括問題、文件鏈接和答案。問題的答案會以 yes/no、文本摘要、事實或列表等等方式呈現給使用者。這個資料集由生物醫學專家搜集與準裡,包含特定領域的問題和答案成對資料。
研究人員下載了 4,017 份 BioASQ 資料集的開放文檔,共有 1,000 個問題,所有文件都經過了前文中所說的索引程序,並對 RAG 系統提出了問題,最後使用 OpenAI 的 OpenEvals 工具對生成的問題進行評估。從生成的問題中,研究者們人工檢查了 40 個問題以及被 #OpenEvals 標記為不準確的所有問題。他們發現自動評估系統對這個領域比起人類評估者來說更『悲觀(pessimistic)』。
上文中『悲觀』的意思是,OpenEvals 在評估測試問題和大型語言模型(LLM)生成的答案的正確性時,會使用更嚴格的標準。這意味著 OpenEvals 可能會對一些實際上可能被人類評估者認為是合理或準確的回答,給出較低的評價或認為它們不準確。這種更為悲觀或嚴格的評估標準,反映了自動化評估系統在判斷問題正確性時可能與人類評估者有所不同的視角。
造成這類評估上差異的可能的原因是 BioASQ 是一個特定領域的數據集,而人類評審者不見得是該領域的專家,這意味著在很多場景下,LLM 內含的世界知識可能比非專家更了解這個領域的細節。因此,這種「悲觀」的自動評估結果可能不完全反映問題的真實準確性。
論文中總結出的七大 RAG 可能失敗點
Missing Content
當 RAG 系統被問到一個無法從可用文件中找到答案的問題時,就會發生這種情況。理想情況下,RAG 系統應該能夠優雅地承認其限制。然而,挑戰在於區分真正無法回答的問題和那些相關但在可用內容中缺乏直接答案的問題。這凸顯了擁有一個全面、最新的文件檢索資料庫的重要性,以及開發機制讓 RAG 系統識別並優雅處理知識空白的重要性。
Missed the Top Ranked Documents
當包含答案的被檢索文件未能排名足夠高以被用於生成答案時就會發生這種情況,這需要更精細的排名算法,這些算法要能夠更好地理解文件與問題的相關性,可能包括從過去的互動中學習的反饋循環。
Not in Context – Consolidation strategy Limitations
在檢索到包含答案的文檔但未將其包含在生成答案的上下文中的情況下,這凸顯了現階段技術在選擇相關文件供 LLM 進行推論的限制,這表明 RAG 系統需要更先進的上下文管理和文件摘要技術去盡量在語料分塊檢索後保留原始文件的語意。
Not Extracted
這問題發生在當答案存在提供的上下文中但 LLM 未能成功提取出正確答案時,通常是因為上下文中有太多雜訊或矛盾信息,需要 LLM 在處理復雜或矛盾上下文時提高消除歧義和提取相關信息的能力,這可以通過在多樣化數據集上更好的訓練或整合推理能力來實現。
Wrong Format
當系統忽略了請求答案的格式(如表格或列表),它反映了在理解語言結構和用戶需求的結構方面的缺口,這表明需要更多關注訓練 LLM 識別和生成各種格式的回應,這需要對語言結構和用戶意圖的細緻理解。
Incorrect Specificity
對於用戶需求來說太泛或太具體的答案凸顯了系統輸出與用戶期望之間的不匹配,這個問題可以通過納入機制讓 RAG 系統澄清問題或請求更多細節,以及提高模型根據上下文脈絡或明確用戶指令調整回應具體性的能力來緩解。
Incomplete
不完整的答案雖然不是錯誤的,但未能提供所有尋求的信息,即使這些信息在上下文中可用並且可以提取,這指向了 RAG 系統需要開發更好的策略來全面提取和綜合信息的需求,可能通過答案的迭代細化或從多份文件中更有效地整合信息,例如問題「文件A、B和C 涵蓋了哪些關鍵點?」更好的做法是可能是分別提出這些問題而非嘗試一次性的從多份被檢索文件中找到答案。
Embedding model
TBD
OpenAI 新的 embedding model
Matryoshka Representation Learning(MRL)
OpenAI 最近出了一種新嵌入技術,讓開發者們可以在 model 的總向量維度內使用部分向量切塊(像是前 8、16、32、64、128 或 256 等維度,最高 2048 維向量)來儲存所想要呈現一個概念不同粗粒度的資訊,這技術叫做 Matryoshka Representation Learning(MRL) #套娃表示學習(?)
簡單的說,MRL 讓你可以利用整個向量空間前面的維度去代表概念的大方向與輪廓,然後迭代的用後面的維度去逐步添加欲描述概念的細節資訊。這個概念就像是以不同解析度來分類圖像,低解析度能提供大概的訊息,高解析度則補充細節,這也類似咱們人類對自然世界的感知,從粗糙到細膩。
這是透過改變損失函數來達成的。原本的損失函數是 L,用了 MRL 之後,我們把損失函數拆成好幾段,每段向量維度都算一次:Loss_Total = L(最多 8d) + L(最多 16d) + L(最多 32d) + … + L(最多 2048d) – 這樣模型就會去注意到向量每個部分的資訊。改過損失函數之後,這種可以截斷的向量就能免費拿到,不用額外計算成本。幾乎所有損失函數都通用,而且現有模型也可以微調,輸出 MRL 向量!真的是一項很猛的技術。
BTW!你其實可以用任何維度的切片,不只是 8、16、32 …因為資訊是按插值方式分布的;所以你可以自由選擇,拿你需要的維度大小就行。
t-SNE algorithm
全名為 t-Distributed Stochastic Neighbor Embedding,這是一種機器學習演算法,用於將高維度向量轉換成可以更加容易進行資料視覺化的 2D 或是 3D 向量的形式,t-SNE 會透過計算給定高維度向量空間中的每一個資料點與其他資料點間是屬於相鄰關係的機率,這機率計算通常是採用 #高斯分配(Gaussian distribution),兩點間計算出的機率愈高,就代表在空間維度上愈接近。
接下來就是如何將這些計算後的資料點映射到低維度的向量空間中(ex. 2D or 3D),這一個過程在一開始都是先隨機的將資料點放置在低維度空間中,因此不同的 t-SNE 算法通常會產生不一樣的低維度空間映射的結果。t-SNE 在低維度的向量空間中也會計算每一個資料點與其他資料點間相似程度的機率,只不過在低維度空間中計算機率的方法是採用 t-distribution,這也是 t-SNE 最前面這個 t 的來由。
在取得原始高維度向量空間中資料點間相鄰程度的高斯分配與低維度向量空間中資料點間相鄰程度的 t分配 之後,接著會使用 Kullback-Leibler(KL) 散度來衡量並優化兩個機率分配之間的差異。t-SNE 的目標是最小化這種 KL 散度,使低維度向量的表示盡可能地類似於高維度數據的相對距離。通過最小化 KL散度,t-SNE 能有效地在低維空間中排列數據點,以保留原始數據的局部結構。這個算法會逐步調整低維空間中點的位置,尋找最小化 KL散度的配置。這個過程確保在高維空間中靠近的點在低維表示中仍然靠近,從而維持原始數據的群聚和關聯模式的完整性。
資料點在高維度與低維度向量空間之間的映射是一個持續迭代的過程,通常是直到達成某一個設定的收斂水準或是某個固定迭代次數的門閥值,每一次迭代調整的資料點數量受到 Learning rate 這一個參數的影響,而這參數意味著在每一次的映射迭代中對資料點位置進行校正的數量。除了 Learning rate 之外,另一個重要的參數叫做 Perplexity(困惑度),這項參數影響 t-SNE 算法如何平衡資料集的局部與全局特性。困惑度大致決定了每個資料點應該有多少相鄰資料點,從而影響對局部細節和更廣泛資料集結構的關注。較高的 Perplexity 會納入更多相鄰的資料點,進而讓映射結果具有更全局的視角,而較低的 Perplexity 則更多地關注局部數據特點。
最後當 KL divergence 不會隨著映射優化的迭代次數增加而顯著的降低時,演算法就進入收斂的狀態,最終呈現出的結果是一個 2D 或 3D 的資料映射,其中相似的資料點被放置得更靠近,不相似的點則被放置得更遠,進而透過資料點在低維空間中的距離去觀察資料集中所有資料點間的群聚關係與分類特徵。
需要注意的是,由於演算法在優化迭代初始化時具備的隨機性,不同的 t-SNE 映射過程極有可能產生不同的映射結果。再來就是如果不同特徵的尺度不同,通常建議在應用t-SNE之前進行數據縮放或標準化,這一步驟非常重要,因為 t-SNE 對數據的尺度非常敏感。如果資料集中的特徵具有不同的尺度(例如,一個特徵的範圍在 0 到 1 之間,而另一個在 0 到 1000 之間),則可能扭曲 t-SNE 的結果,因為算法可能過度強調大尺度特徵。透過 Data Scaling 或 Normalize 確保每個特徵對距離計算的貢獻均等,從而獲得更準確、更有意義的低維資料點映射。常見的縮放方法包括 min-max normalization 和標準化(z-score normalization)。
Long-Context Retrieval Models with Monarch Mixer
A cool promise for long-context embedding models is the ability to ground retrieval in higher-level semantic context, which can alleviate the “embedding chunking” problem in RAG.
For instance, the M2-BERT-80M-32k-retrieval model can encode docs with dozens of pages in a single embedding.
There’s a bunch of ways that you can include long-context embeddings. One way is “hybrid” retrieval:
1️⃣ Retrieve chunks via standard similarity search
2️⃣ Look up the source document embedding (long-context) and compute overall document similarity
3️⃣ Weigh chunk similarity vs. document similarity with an alpha parameter.
Here’s a simple notebook showcasing this, though it’s very exploratory – we’re still in the early days of having embeddings fully capture the semantic meaning of arbitrary documents 🙂
There’s other approaches we tried too that were still a bit rough around the edges, at least over documentation. E.g. hierarchical retrieval.
- Chunk + Document Hybrid Retrieval with Long-Context Embeddings (Together.ai)
- Chunk + Document Hybrid Retrieval with Long-Context Embeddings (Together.ai) | Twitter
- Introducing the Together Embeddings endpoint — Higher accuracy, longer context, and lower cost
- Long-Context Retrieval Models with Monarch Mixer