告別 RAG 還太早?聽聽 Anthropic 怎么說
你有沒有向你的RAG系統問過一個具體問題,卻得到一個令人沮喪的模糊答案?你并不孤單。以下是一個巧妙的改進方法如何改變游戲規則。
想象一下:你為公司的文檔建立了一個流暢的RAG(Retrieval Augmented Generation)系統。你問它:“2023年第二季度的收入增長是多少?”它自信地回答:“收入比上一季度增長了3%。”很好,但是……哪家公司?哪個季度?你的系統只是給了你一塊拼圖,卻沒有告訴你拼圖盒子在哪里。
如果你使用過RAG系統,你可能已經遇到過這個難題。好消息是?Anthropic最近推出了一種看似簡單的解決方案,稱為“contextual retrieval”,它顯示出顯著的效果——與現有技術結合時,檢索失敗率降低了高達49%。
讓我們深入探討這個方法的特別之處,以及為什么你可能想在下一個項目中實現它。
上下文問題:當好的chunk變得不好時
在了解解決方案之前,我們先來理解為什么標準的RAG系統在上下文方面會遇到困難。在一個典型的RAG流程中,你可能會這樣做:
1.將文檔分成chunk(通常每個幾百個token)
2.為每個chunk生成embeddings
3.將這些embeddings存儲在vector database中
4.當查詢到來時,找到語義上最相似的chunk5.將這些chunk輸入LLM以生成答案
這在許多用例中效果很好。詢問“machine learning最佳實踐”,你很可能會得到關于ML技術的相關chunk。但問題來了。
想象你的文檔包含多個公司的季度報告。當你將文檔分成chunk時,那個關鍵的“收入增長3%”被剝離了標識其為“Acme公司2023年第二季度表現”的上下文。你的embedding model看到“收入增長”并認為“這與財務相關!”但不知道是哪家公司或哪個時間段。
臨時解決方法:keyword search來救場?
許多開發者嘗試通過在semantic search之外添加keyword search(例如BM25)來修補這個問題。這在你尋找特定術語(如錯誤代碼)時很有幫助。搜索“Error TS-99”,keyword search會準確命中,而純semantic search可能會返回一般的故障排除指南。
但即使是這種雙重方法也有局限性。如果你的文檔多次提到“收入增長3%”但對應不同上下文,keyword search單獨無法知道你需要哪個實例。你仍然缺少關鍵的上下文信息。
引入Contextual Retrieval:教chunk記住它們來自哪里
這正是Anthropic方法的巧妙之處。他們沒有試圖修復檢索機制,而是增強了chunk本身。核心思想非常簡單:在存儲chunk之前,為其添加相關的上下文信息。
讓我們來看看收入的例子:
原始chunk:“收入比上一季度增長了3%”
帶上下文的chunk:“這個chunk來自Acme公司2023年第二季度表現的備案。收入比上一季度增長了3%”
現在,你的embedding model和keyword search都有了完整的圖景。當有人搜索“Acme 2023年第二季度收入”時,兩種搜索機制都能自信地識別出這是相關的chunk。
實現:讓LLM承擔重任
你可能會想:“好主意,但我不會手動為數千個chunk添加上下文。”這正是實現的趣味所在。Anthropic建議使用LLM(他們推薦高效的Claude Haiku模型)來自動生成這些上下文。
圖片
過程如下:
1.正常地將文檔分成chunk
2.對于每個chunk,將完整文檔和該特定chunk發送給LLM
3.使用一個提示,指示LLM生成一個簡潔的上下文語句
4.將此上下文添加到原始chunk之前
5.使用這些增強的chunk生成embeddings并更新BM25索引
這里的prompt engineering至關重要。你實際上是在要求LLM扮演偵探:“給定這個完整文檔和這個特定chunk,編寫一個簡短的上下文,幫助別人理解這個chunk在整體中的位置。”
數據:它真的有效嗎?
Anthropic的基準測試令人印象深刻。僅使用contextual embeddings,他們看到檢索失敗率降低了35%(從5.7%降至3.7%,基于top-20檢索)。當他們將contextual embeddings與contextual BM25結合時,改進幅度躍升至49%的失敗率減少。
圖片
更有趣的是,當他們在所有這些之上添加一個re-ranker時,平均檢索錯誤率從5.7%下降到僅1.9%。這是一個巨大的改進,僅通過一個預處理步驟和一些巧妙的prompt engineering實現。
權衡:沒有免費的午餐
在你急于實現之前,我們來談談成本。添加上下文意味著:
?更大的chunk:每個chunk增加50-100個token,這會稍微減少你能在LLM上下文窗口中適應的chunk數量
?處理成本:你需要在索引期間為每個chunk運行一次LLM調用
?存儲開銷:你的vector database和搜索索引會變得更大
圖片
Anthropic估計一次性處理成本約為每百萬token 1.02美元。這聽起來可能不多,但如果你處理數百萬文檔,成本會累積。好消息是,像prompt caching這樣的功能可以將成本降低高達90%,特別是在處理類似文檔時。
何時使用Contextual Retrieval(以及何時跳過)
以下是一個實用的決策樹:
使用contextual retrieval的場景:
?你的文檔包含多個實體、時間段或上下文
?你需要針對特定、定向查詢的高準確性
?你的knowledge base太大,無法使用長上下文LLM(超過200K token)
?檢索錯誤的成本很高(例如法律文件、財務報告)
考慮替代方案的場景:
?你的knowledge base較小(少于200K token或1MB,例如使用Gemini)
?你的文檔已經高度結構化,上下文清晰
?你處理的是一致的、chunk本身就自包含的內容
圖片
來自實踐的實施建議
根據Anthropic的實驗和他們分享的代碼,以下是一些實用建議:
?定制你的上下文提示:財務文檔的提示需要與技術文檔不同的上下文。試驗并迭代。
?明智選擇embedding model:在他們的測試中,Google的Gemini Text-004表現最佳,Voyage embeddings也顯示出很強的結果。
?不要吝嗇re-ranker:contextual retrieval加上re-ranking的組合顯示出最佳結果。考慮使用像Cohere的re-ranking API這樣的服務。
?檢索更多,然后過濾:Anthropic發現最初檢索20個chunk,然后使用re-ranker選擇最佳的chunk很成功。
?用你的實際數據測試:提供的基準測試基于特定數據集。你的結果可能因文檔類型和查詢模式而異。
圖片
大局觀:RAG并未消亡
隨著LLM擁有越來越大的上下文窗口,你可能想知道RAG是否正在過時。Anthropic的工作表明并非如此。即使有200K+ token的上下文窗口,RAG對于大型knowledge base仍然更具成本效益和可擴展性。Contextual retrieval讓RAG變得更好,而不是過時。
這樣想:長上下文LLM就像擁有對當前看到的一切的攝影記憶。RAG就像一個組織良好的圖書館,配備一個聰明的圖書管理員。Contextual retrieval只是為那個圖書管理員提供了一個更好的卡片目錄。
圖片
總結:小改變,大影響
Contextual retrieval不是一個革命性的新架構或復雜的神經網絡創新。它是一個巧妙的預處理步驟,承認一個簡單的事實:上下文很重要。通過確保每個chunk都帶有自己的上下文,我們不是在對抗embedding model或keyword search的局限性——我們是在與它們合作。
對于構建RAG系統的開發者來說,這種技術提供了一種相對簡單的方法來顯著提高檢索準確性。是的,有成本和權衡,但對于準確性至關重要的應用來說,投資可能是值得的。
下次你的RAG系統返回一個令人沮喪的模糊答案時,記住:它可能只是需要幫助記住它把鑰匙放哪兒了。Contextual retrieval確保每個chunk都帶有一張回家的地圖。