隨着大語言模型(LLM)技術的發展,RAG(Retrieval Augmented Generation)技術得到了廣泛探討和研究,越來越多的高級 RAG 檢索方法也隨之被人發現,相對於普通的 RAG 檢索,高級 RAG 通過更深化的技術細節、更復雜的搜索策略,提供出了更準確、更相關、更豐富的信息檢索結果。本文首先討論這些技術,並基於 Milvus 給出一個實現案例。
01.初級 RAG
初級 RAG 的定義
初級 RAG 研究範式代表了最早的方法論,在 ChatGPT 廣泛採用後不久就取得了重要地位。初級 RAG 遵循傳統的流程,包括索引創建(Indexing)、檢索(Retrieval)和生成(Generation),常常被描繪成一個“檢索—讀取”框架,其工作流包括三個關鍵步驟:
-
語料庫被劃分爲離散的塊,然後使用編碼器模型構建向量索引。
-
RAG 根據查詢與索引塊(Indexed Chunk)的向量相似度識別並對塊進行檢索。
-
模型根據檢索塊(Retrieved Chunk)中獲取的上下文信息生成答案。
初級 RAG 的侷限性
初級 RAG 在三個關鍵領域面臨着顯著挑戰:"檢索"、"生成"和"增強"。
初級 RAG 的檢索質量存在許多問題,例如低精度和低召回率等。低精度會導致檢索到的塊無法對齊,以及幻覺等潛在問題。低召回率會導致無法檢索到所有的相關塊,從而導致LLM的回覆不夠全面。此外,使用老舊的信息進一步加劇了問題,可能導致不準確的檢索結果。
生成回覆質量面臨着幻覺挑戰,即 LLM 生成的答案並沒有基於所提供的上下文,和上下文不相關,或者生成的回覆存在着包含有害或歧視內容的潛在風險。
在增強過程中,初級 RAG 在如何有效地將檢索到的段落的上下文與當前生成任務進行整合方面也面臨着不小的挑戰。低效的整合可能導致輸出不連貫或破碎化。冗餘和重複也是一個棘手的問題,特別是當多個檢索到的段落包含相似信息時,生成的回覆中可能會出現重複的內容。
02.高級 RAG
爲了解決初級 RAG 的不足,高級 RAG 誕生了,並有針對性地進行了功能增強。首先討論這些技術,這些技術可被歸類爲檢索前優化、檢索中優化和檢索後優化。
檢索前優化
檢索前的優化關注數據索引優化以及查詢優化,數據索引優化技術旨在以提高檢索效率的方式存儲數據:
-
滑動窗口:在數據塊之間使用重疊,這是最簡單的技術之一。
-
增強數據粒度:應用數據清理技術,例如移除不相關信息、確認事實準確性、更新過時信息等。
-
添加元數據:如用於過濾的日期、目的或章節信息等。
-
優化索引結構涉及不同的數據索引策略:如調整塊大小或使用多索引策略。本文我們將實現的一種技術是句子窗口檢索,它在檢索時嵌入單個句子,並在推斷時用更大的文本窗口替換它們。
檢索中優化
檢索階段主要是識別最相關的上下文。通常,檢索是基於向量搜索,它計算查詢和索引數據之間的語義相似性。因此,大多數檢索優化技術都圍繞着 embedding 模型:
-
微調 embedding 模型:定製化 embedding 模型到特定領域上下文,特別是針對具有發展性或罕見術語的領域。例如,
BAAI/bge-small-en
是一個高性能 embedding 模型,可以進行微調。 -
動態 embedding:適應詞語使用中的上下文,不同於使用每個詞一個向量的靜態embedding。例如,OpenAI 的
embeddings-ada-02
是一個複雜的動態embedding模型,捕捉到上下文理解。除了向量搜索之外,還有其他檢索技術,如混合搜索(hybrid search),通常指的是將向量搜索與基於關鍵詞的搜索相結合的概念。如果檢索需要精確的關鍵詞匹配,這種檢索技術很有益處。
檢索後優化
對檢索到的上下文內容,我們會遇到如上下文超出窗口限制或上下文引入的噪音,它們會分散對於關鍵信息的注意力:
-
Prompt 壓縮:通過移除無關並突出重要上下文來減少整體Prompt長度。
-
重排(Re-ranking):使用機器學習模型重新計算檢索到的上下文的相關性得分。
檢索後優化技術包括:
03.基於 Milvus + LlamaIndex 實現高級 RAG
我們實現的高級 RAG,使用了 OpenAI 的語言模型,託管於 Hugging Face的 BAAI重排模型,以及 Milvus 向量數據庫。
創建 Milvus 索引
from llama_index.core import VectorStoreIndex
from llama_index.vector_stores.milvus import MilvusVectorStore
from llama_index.core import StorageContext
vector_store = MilvusVectorStore(dim=1536,
uri="http://localhost:19530",
collection_name='advance_rag',
overwrite=True,
enable_sparse=True,
hybrid_ranker="RRFRanker",
hybrid_ranker_params={"k": 60})
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(
nodes,
storage_context=storage_context
)
索引優化示例:句子窗口檢索
我們使用 LlamaIndex裏的 SentenceWindowNodeParser 實現句子窗口檢索技術。
from llama_index.core.node_parser import SentenceWindowNodeParser
node_parser = SentenceWindowNodeParser.from_defaults(
window_size=3,
window_metadata_key="window",
original_text_metadata_key="original_text",
)
SentenceWindowNodeParser 執行兩項操作:
它將文檔分隔成單獨的句子,這些句子進行embedding。
對每個句子,它創建一個上下文窗口。如果指定 window_size = 3,那麼生成的窗口將包含三個句子,從嵌入句子的前一個句子開始,跨越到之後的一個句子。該窗口將作爲元數據存儲。在檢索期間,將返回與查詢最匹配的句子。檢索後,你需要通過定義一個 MetadataReplacementPostProcessor
並在 node_postprocessors
列表中使用它,來將句子替換爲來自元數據的整個窗口。
from llama_index.core.postprocessor import MetadataReplacementPostProcessor
postproc = MetadataReplacementPostProcessor(
target_metadata_key="window"
)
...
query_engine = index.as_query_engine(
node_postprocessors = [postproc],
)
檢索優化示例:混合搜索
在 LlamaIndex 中實現混合搜索僅需對查詢引擎進行兩個參數的更改,前提是底層向量數據庫支持混合搜索查詢。Milvus2.4 版本之前不支持混合搜索(hybrid search),不過在最近發佈的2.4版本,這個功能已經支持。
query_engine = index.as_query_engine(
vector_store_query_mode="hybrid", #Milvus 2.4開始支持, 在2.4版本之前使用 Default
)
檢索後優化示例:重排(Re-ranking)
高級 RAG 中添加一個重排器(Re-ranking)僅需三個簡單步驟:
首先,定義一個重排(Re-ranking)模型,使用 Hugging Face 上的 BAAI/bge-reranker-base
。
在查詢引擎中,將重排模型添加到 node_postprocessors
列表中。
增加查詢引擎中的 similarity_top_k
以檢索更多的上下文片段,經過重排後可以減少到 top_n。
from llama_index.core.postprocessor import SentenceTransformerRerank
rerank = SentenceTransformerRerank(
top_n = 3,
model = "BAAI/bge-reranker-base"
)
...
query_engine = index.as_query_engine(
similarity_top_k = 3,
node_postprocessors = [rerank],
...,
)
詳細實現代碼參見百度網盤鏈接: https://pan.baidu.com/s/1Cj_Fmy9-SiQFMFNUmO0OZQ?pwd=r2i1 提取碼: r2i1