測試不同的RAG技術(shù)以找到最佳方案
檢索增強(qiáng)生成(RAG)技術(shù)通過結(jié)合大型語言模型(LLMs)與外部數(shù)據(jù)檢索能力,能夠提供準(zhǔn)確且富含上下文的答案。無論是構(gòu)建客戶支持聊天機(jī)器人還是研究助手,RAG都能通過從數(shù)據(jù)庫中提取相關(guān)信息來增強(qiáng)AI的性能。然而,不同的RAG技術(shù)在性能上存在差異,選擇最佳技術(shù)需要進(jìn)行測試。本文將全面探討各類RAG技術(shù),包括基礎(chǔ)方法和高級手段,并對它們進(jìn)行評估,以幫助您根據(jù)需求選擇最合適的技術(shù)。
什么是RAG及其測試的重要性
想象一下,向AI提問:“如何解決智能手機(jī)上的登錄問題?”標(biāo)準(zhǔn)的大型語言模型可能會給出通用或過時的回答。而RAG技術(shù)通過檢索相關(guān)數(shù)據(jù)(例如來自產(chǎn)品手冊)并將其輸入到大型語言模型中,從而生成精確的答案,以此改善了這一情況。這使得RAG非常適用于需要最新或特定信息的應(yīng)用場景,如技術(shù)支持或醫(yī)療咨詢。
測試RAG技術(shù)至關(guān)重要,因為每種方法在文檔索引、檢索或生成的方式上各有不同,會對準(zhǔn)確性、速度和成本產(chǎn)生影響。通過比較這些技術(shù),我們可以為特定的使用場景找到最佳設(shè)置。
RAG系統(tǒng)的核心組件
RAG流程主要包含三個階段:
- 索引:將文檔分割成塊,將其轉(zhuǎn)換為數(shù)值向量(嵌入),并存儲在向量數(shù)據(jù)庫中。
- 檢索:在數(shù)據(jù)庫中搜索與查詢相關(guān)的塊。
- 生成:使用大型語言模型將檢索到的數(shù)據(jù)與查詢結(jié)合起來生成答案。
RAG技術(shù)列表
以下是我們將要比較的主要RAG技術(shù):
- 樸素RAG(基準(zhǔn))
- 分塊策略(固定大小、基于句子、語義)
- 重排序
- 查詢轉(zhuǎn)換(查詢重寫、多查詢、HyDE)
- 圖RAG(GraphRAG)
- RAG融合(RAG-Fusion)
- 上下文壓縮
- 自查詢檢索
- 多文檔代理
- 動態(tài)檢索
- 遞歸檢索
- 父文檔檢索
1. 樸素RAG(基準(zhǔn))
這是最簡單的方法:將文檔分割成固定大小的塊,對其進(jìn)行嵌入處理(例如使用BERT),存儲在向量數(shù)據(jù)庫(例如FAISS)中,并根據(jù)查詢相似度檢索前k個塊。
示例:對于查詢“如何解決智能手機(jī)上的登錄問題?”,樸素RAG將手冊分割成500字的塊,并檢索前5個塊。
代碼片段(使用LlamaIndex):
from llama_index import VectorStoreIndex, SimpleDirectoryReader
from llama_index.llms import OpenAI
documents = SimpleDirectoryReader("manuals/").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("How do I fix a login issue on my smartphone?")
print(response)輸出:“要解決登錄問題,請嘗試通過‘忘記密碼’鏈接重置密碼或清除設(shè)置中的應(yīng)用緩存?!?/p>
優(yōu)點:簡單、快速。
缺點:可能會遺漏上下文或檢索到不相關(guān)的塊。
2. 分塊策略
分塊會影響檢索質(zhì)量。分塊方式包括:
- 固定大?。喊丛~數(shù)分割(例如500詞)。
- 基于句子:按句子分割以保證語義連貫性。
- 語義:使用AI將相關(guān)句子分組。
示例:基于句子的分塊將登錄查詢的故障排除部分完整保留。
代碼片段(語義分塊):
from llama_index import SemanticSplitter
splitter = SemanticSplitter(chunk_size=512)
chunks = splitter.split_documents(documents)
index = VectorStoreIndex.from_documents(chunks)
response = index.as_query_engine().query("How do I fix a login issue?")
print(response)輸出:“通過設(shè)置>應(yīng)用清除緩存。如果問題仍然存在,請重置密碼?!?/p>
優(yōu)點:更好地保留上下文。
缺點:語義分塊計算密集。
3. 重排序
重排序使用交叉編碼器或大型語言模型對檢索到的塊進(jìn)行重新排序,以對查詢-塊相關(guān)性進(jìn)行評分。
示例:重排序會優(yōu)先考慮有關(guān)登錄故障排除的塊,而不是通用設(shè)置的塊。
代碼片段(使用Cohere):
from cohere import Client
cohere_client = Client("YOUR_COHERE_API_KEY")
chunks = index.retrieve("How do I fix a login issue?")
reranked = cohere_client.rerank(query="How do I fix a login issue?", documents=[chunk.text for chunk in chunks])
top_chunks = [chunks[i] for i in reranked.results[:5]]輸出:“清除緩存;使用‘忘記密碼’鏈接?!?/p>
優(yōu)點:提高相關(guān)性。
缺點:增加計算開銷。
4. 查詢轉(zhuǎn)換
增強(qiáng)查詢以改進(jìn)檢索:
- 查詢重寫:重新表述模糊的查詢(例如將“登錄問題”改為“解決智能手機(jī)登錄失敗”)。
- 多查詢:生成多個相關(guān)查詢。
- HyDE(假設(shè)文檔嵌入):創(chuàng)建用于檢索的假設(shè)答案。
示例:HyDE生成類似“清除緩存或重置密碼”的假答案,并檢索匹配的塊。
代碼片段(HyDE):
from llama_index import HyDEQueryTransform
hyde = HyDEQueryTransform()
transformed_query = hyde.transform("How do I fix a login issue?")
response = index.as_query_engine().query(transformed_query)
print(response)輸出:“檢查設(shè)置>應(yīng)用>清除緩存;重置密碼?!?/p>
優(yōu)點:捕捉細(xì)微的意圖。
缺點:增加延遲。
5. 圖RAG(GraphRAG)
使用知識圖譜捕獲實體關(guān)系,適用于復(fù)雜查詢。
示例:對于“什么導(dǎo)致登錄問題?”,圖RAG檢索與“應(yīng)用緩存”和“用戶憑據(jù)”相關(guān)聯(lián)的塊。
工作流程:
- 提取實體和關(guān)系。
- 構(gòu)建圖數(shù)據(jù)庫(例如FalkorDB)。
- 查詢圖形并將結(jié)果輸入大型語言模型。
優(yōu)點:擅長多步驟推理。
缺點:設(shè)置復(fù)雜。
6. RAG融合(RAG-Fusion)
將查詢擴(kuò)展到多個視角,執(zhí)行并行搜索,并對結(jié)果進(jìn)行重排序。
示例:生成“清除應(yīng)用緩存”、“重置密碼”等查詢,并檢索不同的塊。
優(yōu)點:覆蓋全面。
缺點:計算成本高。
7. 上下文壓縮
壓縮檢索到的塊,專注于最相關(guān)的部分,在生成前減少噪音。
示例:對于登錄查詢,壓縮從較長的塊中僅提取有關(guān)緩存清除和密碼重置的句子。
代碼片段(使用LlamaIndex):
from llama_index import ContextualCompressionRetriever
retriever = ContextualCompressionRetriever(base_retriever=index.as_retriever())
response = retriever.query("How do I fix a login issue?")
print(response)輸出:“通過設(shè)置>應(yīng)用清除應(yīng)用緩存;通過‘忘記密碼’重置密碼?!?/p>
優(yōu)點:減少不相關(guān)內(nèi)容。
缺點:需要額外處理。
8. 自查詢檢索
使用大型語言模型將復(fù)雜查詢解析為結(jié)構(gòu)化數(shù)據(jù)庫查詢,適用于富含元數(shù)據(jù)的數(shù)據(jù)集。
示例:對于“顯示2025年Android設(shè)備的登錄問題”,大型語言模型生成一個過濾Android和2025年元數(shù)據(jù)的查詢。
代碼片段:
from llama_index import SelfQueryRetriever
retriever = SelfQueryRetriever(index=index, metadata_fields=["device_type", "year"])
response = retriever.query("Show login issues for Android devices in 2025")
print(response)輸出:“對于2025年的Android設(shè)備,通過設(shè)置>應(yīng)用清除緩存或重置密碼?!?/p>
優(yōu)點:處理復(fù)雜的結(jié)構(gòu)化查詢。
缺點:需要富含元數(shù)據(jù)的數(shù)據(jù)。
9. 多文檔代理
使用多個代理,每個代理專門處理文檔的子集,以處理不同的數(shù)據(jù)源。
示例:一個代理處理Android手冊,另一個處理iOS手冊,將結(jié)果結(jié)合起來回答登錄查詢。
代碼片段:
from llama_index import MultiDocumentAgent
agents = [VectorStoreIndex.from_documents(docs).as_query_engine() for docs in [android_docs, ios_docs]]
agent = MultiDocumentAgent(agents)
response = agent.query("How do I fix a login issue?")
print(response)輸出:“在Android上,清除緩存;在iOS上,通過設(shè)置重置密碼?!?/p>
優(yōu)點:可擴(kuò)展到不同的數(shù)據(jù)集。
缺點:協(xié)調(diào)復(fù)雜。
10. 動態(tài)檢索
根據(jù)查詢復(fù)雜度動態(tài)調(diào)整檢索參數(shù)(例如top-k、相似度閾值)。
示例:簡單查詢使用前3個塊;復(fù)雜查詢使用前10個塊。
代碼片段:
from llama_index import DynamicRetriever
retriever = DynamicRetriever(index=index, complexity_estimator=lambda q: len(q.split()))
response = retriever.query("How do I fix a login issue?")
print(response)輸出:“清除緩存或重置密碼?!?/p>
優(yōu)點:適應(yīng)查詢需求。
缺點:需要調(diào)優(yōu)。
11. 遞歸檢索
通過基于初始結(jié)果生成后續(xù)查詢來迭代優(yōu)化檢索。
示例:在檢索到有關(guān)“登錄問題”的塊后,查詢“緩存清除步驟”以加深上下文。
代碼片段:
from llama_index import RecursiveRetriever
retriever = RecursiveRetriever(base_retriever=index.as_retriever())
response = retriever.query("How do I fix a login issue?")
print(response)輸出:“通過設(shè)置>應(yīng)用清除緩存;詳細(xì)步驟:進(jìn)入設(shè)置,選擇應(yīng)用,選擇該應(yīng)用,然后清除緩存。”
優(yōu)點:為復(fù)雜查詢加深上下文。
缺點:增加延遲。
12. 父文檔檢索
檢索較小的塊,但返回其父文檔,以便在生成過程中獲得更豐富的上下文。
示例:檢索有關(guān)登錄問題的句子,但向大型語言模型提供完整的故障排除部分。
代碼片段:
from llama_index import ParentDocumentRetriever
retriever = ParentDocumentRetriever(index=index, parent_splitter=lambda x: x.split("\n\n"))
response = retriever.query("How do I fix a login issue?")
print(response)輸出:“在設(shè)置>應(yīng)用中清除緩存;必要時重置密碼。完整部分:[詳細(xì)故障排除指南]?!?/p>
優(yōu)點:平衡精度和上下文。
缺點:需要分層文檔結(jié)構(gòu)。
測試與評估
為了找到最佳技術(shù),我們將使用智能手機(jī)手冊數(shù)據(jù)集對所有12種技術(shù)進(jìn)行測試,評估指標(biāo)包括:
- 檢索精度:檢索到的相關(guān)塊的百分比。
- 答案相似度:與參考答案的得分(0-5)。
- 延遲:檢索和生成的時間。
- 成本:計算資源。
演示設(shè)置
我們將使用LlamaIndex、OpenAI的GPT-3.5、FAISS和Cohere進(jìn)行重排序。查詢?yōu)椤叭绾谓鉀Q智能手機(jī)上的登錄問題?”
分析
- HyDE和遞歸檢索在精度和答案質(zhì)量上得分最高,但速度較慢。
- 樸素RAG和動態(tài)檢索速度最快,但準(zhǔn)確性較低。
- 重排序和父文檔檢索在準(zhǔn)確性和速度之間取得平衡。
- 多文檔代理在處理不同數(shù)據(jù)集時表現(xiàn)出色,但速度最慢。
- 自查詢對于結(jié)構(gòu)化數(shù)據(jù)非常有用,但需要元數(shù)據(jù)。
選擇最佳技術(shù)
最佳技術(shù)取決于您的優(yōu)先級:
- 速度:樸素RAG、動態(tài)檢索。
- 準(zhǔn)確性:HyDE、遞歸檢索、重排序。
- 復(fù)雜查詢:圖RAG、多文檔代理、自查詢。
- 資源限制:樸素RAG、語義分塊、上下文壓縮。
- 豐富上下文:父文檔檢索、圖RAG。
示例場景:對于客戶支持聊天機(jī)器人,重排序或父文檔檢索提供了良好的平衡。對于具有復(fù)雜查詢的研究工具,圖RAG或遞歸檢索是理想的。
挑戰(zhàn)與提示
- 幻覺:使用清晰的提示使大型語言模型基于檢索到的數(shù)據(jù)生成內(nèi)容。
- 數(shù)據(jù)質(zhì)量:整理數(shù)據(jù)集以減少噪音。
- 可擴(kuò)展性:使用FAISS或FalkorDB等向量數(shù)據(jù)庫。
- 元數(shù)據(jù):為自查詢或多文檔代理提供支持。
總結(jié)一下
對廣泛的RAG技術(shù)的探索表明,每種技術(shù)都有其優(yōu)缺點。樸素RAG是一個很好的起點,因為它簡單且設(shè)置快速,非常適合快速項目。另一方面,像HyDE、圖RAG、遞歸檢索等高級方法在需要更準(zhǔn)確和詳細(xì)的答案時表現(xiàn)出色,特別是對于復(fù)雜或特定的任務(wù)。通過測試這些方法,人們可以找出最適合自己需求的方法,無論優(yōu)先考慮的是速度、精度還是處理棘手問題的能力。
























