構建 LLM 應用:高級 RAG(第十部分)

作者:Vipra Singh

編譯:ronghuaiyang

導讀

現在,請跟隨我們一起踏上另一段探索之旅,進入高級 RAG 技術的迷人世界。

歡迎回到我們關於高級檢索增強生成(RAG)技術系列的最新篇章!在本系列的前九部分中,我們深入探討了 RAG,解析了檢索機制與生成模型之間的精妙互動。從掌握生成模型的基礎知識到通過大型語言模型(LLMs)探索前沿技術,我們覆蓋了廣闊的概念與方法領域。現在,請跟隨我們一起踏上另一段探索之旅,進入高級 RAG 技術的迷人世界。

一份最近的調查報告對檢索增強生成(RAG)進行了總結,提出了三種近期演變的範式:

RAG 過程應用於問題回答的一個典型實例,主要包含三個步驟。1)索引。文檔被分割成片段,編碼爲向量,並存儲在向量數據庫中。2)檢索。根據語義相似性,檢索與問題最相關的 Top k 個片段。3)生成。將原始問題和檢索到的片段一起輸入到 LLM 中,生成最終答案。

Naive RAG

標準的 RAG 流程包括將文本分割成片段,使用 Transformer 編碼器模型將這些片段嵌入到向量中,對這些向量進行索引,隨後爲 LLM 構造一個提示。這個提示指導模型根據用戶的查詢,在搜索階段收集的上下文中生成回覆。

在運行時,使用相同的編碼器模型將用戶的查詢向量化,利用這個向量對索引進行搜索,找出排名前 k 的結果,從數據庫中提取相應的文本片段,並將它們作爲上下文輸入到 LLM 的提示中。

下面是 RAG 如何增強 ChatGPT 的一個例子。

一個 RAG 如何使 ChatGPT 受益的例子是,它解決了超出訓練數據範圍的問題,生成了正確的結果。

現在,讓我們來看看簡單 RAG 存在的問題。

Naive RAG 的問題

簡單 RAG 存在問題(紅色虛線框)。

如上圖所示,簡單 RAG 在上述三個步驟中都存在問題(紅色虛線框),有很大的優化空間。

索引

檢索

生成

**需要注意的是,這些問題的原因可能是多方面的。例如,**如果給用戶的最終迴應包含無關內容,這可能不僅僅是因爲 LLM 的問題。根本原因可能是 PDF 文檔提取不精確,或者嵌入模型無法準確捕捉語義,等等。

轉向高級 RAG

簡單與高級 RAG 的區別

隨着基礎 RAG 侷限性的顯現,推動了更復雜系統的開發。高級 RAG 模型融合了更復雜的檢索技術,更好地整合檢索到的信息,並通常具備迭代優化檢索和生成過程的能力。

高級 RAG 的關鍵特徵:

高級 RAG 範式包含了一系列旨在解決基礎 RAG 已知侷限性的技術。RAG 的基礎工作流程始於創建包含外部資源的索引。該索引充當基礎,通過基於特定查詢的檢索模型來檢索相關信息。最後一步涉及一個生成器模型,它將檢索到的信息與查詢相結合,生成所需的輸出。

RAG 範式在該領域內組織研究,提供了一個簡單卻強大的框架來提升 LLM 性能。RAG 的核心在於其搜索機制,這是生成高質量結果的關鍵。因此,從檢索的角度來看,該範式被劃分爲四個主要階段:預檢索、檢索、後檢索生成

一個統一的 RAG 框架,包括基本工作流程和範式。

預檢索優化

預檢索優化專注於數據索引優化和查詢優化。數據索引優化技術旨在以有助於我們提升檢索效率的方式存儲數據,具體包括:

檢索優化

檢索階段的目標是識別最相關的上下文。通常,檢索基於向量搜索,計算查詢與索引數據之間的語義相似性。因此,大多數檢索優化技術圍繞着嵌入模型展開:

除了向量搜索外,還有其他的檢索技術,比如混合搜索,通常指的是結合向量搜索與基於關鍵詞的搜索的概念。如果我們的檢索需要精確的關鍵詞匹配,這種檢索技術會很有用。

後檢索優化

後檢索階段旨在優化最初檢索到的文檔,以提升文本生成的質量。這一階段包括重排序和過濾,各自旨在優化文檔選擇,以便於最終的生成任務。

重排序

高級 RAG 技術

現在我們將更深入地探討高級 RAG 技術的概覽。下面是一個示意圖,描繪了核心步驟和所涉及的算法。爲了保持圖示的可讀性,省略了一些邏輯循環和複雜的多步驟代理行爲。

一些高級 RAG 架構的關鍵組成部分。這更像是對可用工具的選擇,而非固定藍圖。

方案中的綠色元素是後續討論的核心 RAG 技術,藍色元素代表文本。並非所有高級 RAG 理念都易於在一個方案中可視化,例如,各種擴大上下文的方法就被省略了——我們將在後面逐步深入探討。

現在,我們來討論這些技術。

預檢索技術

PDF 解析

對於 RAG 而言,從文檔中提取信息是不可避免的場景。確保從源頭高效地提取內容對於提升最終輸出的質量至關重要。

不應低估這一過程。在實施 RAG 時,解析過程中信息提取的不足會導致 PDF 文件中所含信息的理解和利用受到限制。

下圖展示瞭解析過程在 RAG 中的位置:

解析過程(紅色框)在 RAG 中的位置。

在實際工作中,非結構化數據遠比結構化數據更爲普遍。如果這些海量數據無法被解析,它們的巨大價值就無法得到體現。

在非結構化數據中,PDF 文檔佔據了大多數。有效處理 PDF 文檔也能極大地輔助管理其他類型的非結構化文檔。

本文主要介紹解析 PDF 文件的方法。它提供了算法和建議,用於有效解析 PDF 文檔並儘可能多地提取有用信息。

解析 PDF 的挑戰

PDF 文檔是無結構文檔的典型代表,然而,從 PDF 文檔中提取信息是一個充滿挑戰的過程。

**與其說 PDF 是一種數據格式,不如說它更像是一系列打印指令的集合。**一個 PDF 文件由一系列指示組成,告訴 PDF 閱讀器或打印機如何在屏幕上或紙上顯示符號。這與 HTML 和 docx 等文件格式形成對比,後者使用諸如<p>, <w:p>, <table><w:tbl> 等標籤來組織不同的邏輯結構,如下面的圖所示:

Html vs PDF

解析 PDF 文檔的難點在於精確提取整個頁面的佈局,並將內容,包括表格、標題、段落和圖像,轉化爲文檔的文本表示。 這個過程涉及到處理文本提取的不準確性、圖像識別以及表中行 - 列關係的混淆等問題。

如何解析 PDF 文檔

通常,有三種方法來解析 PDF:

基於規則的方法

最具代表性的工具之一是 pypdf,這是一種廣泛使用的基於規則的解析器。它是 LangChain 和 LlamaIndex 中解析 PDF 的標準方法。

下面是嘗試使用 pypdf 解析論文 “Attention Is All You Need” 第 6 頁的例子。原始頁面如下圖所示:

“Attention Is All You Need” 論文的第 6 頁

代碼如下:

import PyPDF2
filename = "1706.03762.pdf"
pdf_file = open(filename, 'rb')

reader = PyPDF2.PdfReader(pdf_file)

page_num = 5
page = reader.pages[page_num]
text = page.extract_text()

print('--------------------------------------------------')
print(text)

pdf_file.close()

執行結果爲 (後面省略了):

(py) $ pip list | grep pypdf
pypdf                    3.17.4
pypdfium2                4.26.0

(py) pypdf_test.py
--------------------------------------------------
Table 1: Maximum path lengths, per-layer complexity and minimum number of sequential operations
for different layer types. nis the sequence length, dis the representation dimension, kis the kernel
size of convolutions and rthe size of the neighborhood in restricted self-attention.
Layer Type Complexity per Layer Sequential Maximum Path Length
Operations
Self-Attention O(n2·d) O(1) O(1)
Recurrent O(n·d2) O(n) O(n)
Convolutional O(k·n·d2) O(1) O(logk(n))
Self-Attention (restricted) O(r·n·d) O(1) O(n/r)
3.5 Positional Encoding
Since our model contains no recurrence and no convolution, in order for the model to make use of the
order of the sequence, we must inject some information about the relative or absolute position of the
tokens in the sequence. To this end, we add "positional encodings" to the input embeddings at the
bottoms of the encoder and decoder stacks. The positional encodings have the same dimension dmodel
as the embeddings, so that the two can be summed. There are many choices of positional encodings,
learned and fixed [9].
In this work, we use sine and cosine functions of different frequencies:
PE(pos,2i)=sin(pos/100002i/d model)
PE(pos,2i+1)=cos(pos/100002i/d model)
where posis the position and iis the dimension. That is, each dimension of the positional encoding
corresponds to a sinusoid. The wavelengths form a geometric progression from 2πto10000 ·2π. We
chose this function because we hypothesized it would allow the model to easily learn to attend by
relative positions, since for any fixed offset k,PEpos+kcan be represented as a linear function of
PEpos.
...
...
...
基於PyPDF檢測的結果,我們觀察到它將PDF中的字符序列串行化爲一個長序列,而不保留結構性信息。換句話說,它將文檔的每一行視爲由換行符“`\n`”分隔的序列,這導致無法準確識別段落或表格。

這一侷限性是基於規則方法的固有特性。

基於深度學習模型的方法

該方法的優勢在於它能夠準確識別整個文檔的佈局,包括表格和段落。它甚至能夠理解表格內的結構。這意味着它可以將文檔分割成定義明確、完整的信息單元,同時保持預期的意義和結構。

然而,也存在一些侷限。對象檢測和 OCR 階段可能耗時較長。因此,建議使用 GPU 或其他加速設備,並採用多進程和多線程進行處理。

這種方法涉及目標檢測和 OCR 模型,我已經測試了幾種代表性開源框架:

框架展示了 PP-StructureV2。它包含兩個子系統:佈局信息提取和關鍵信息提取。

上下文增強

這裏的概念是在爲了提高搜索質量而檢索更小片段的同時,添加周圍上下文供 LLM 進行推理。有兩種選擇——通過圍繞較小檢索片段的句子來擴展上下文,或者遞歸地將文檔拆分爲包含較小子片段的多個較大父片段。

句子窗口檢索

在這個方案中,文檔中的每個句子都被單獨嵌入,這爲查詢到上下文餘弦距離搜索提供了極高的準確性。爲了在檢索到最相關的單個句子後更好地進行推理,我們通過在檢索到的句子前後各擴展 k 個句子來擴大上下文窗口,然後將這個擴展後的上下文發送給 LLM。

藍色部分是在索引中搜索時找到的句子嵌入,而整個黑色加綠色的段落被送入 LLM,以便在對提供的查詢進行推理時擴大其上下文。

自動合併檢索器(即父文檔檢索器)

這裏的想法與句子窗口檢索器非常相似——搜索更細粒度的信息,然後在將這些上下文傳遞給 LLM 進行推理之前,擴展上下文窗口。文檔被拆分成更小的子塊,這些子塊指向更大的父塊。

文檔被拆分成層次化的塊,然後最小的葉塊被髮送到索引。在檢索時,我們檢索 k 個葉塊,如果有 n 個塊指向同一個父塊,我們就用這個父塊替換它們,並將其發送到 LLM 進行答案生成。

在檢索時首先獲取較小的塊,然後如果在檢索到的前 k 個塊中有超過 n 個塊鏈接到同一個父節點(較大的塊),我們用這個父節點替換傳給 LLM 的上下文——就像自動將幾個檢索到的塊合併成一個較大的父塊,因此得名此方法。需要注意的是——搜索只在子節點索引中進行。

查詢重寫

在檢索增強生成(RAG)中,我們經常會遇到用戶原始查詢的問題,比如措辭不準確或缺乏語義信息。例如,像 “2020 年的 NBA 冠軍是洛杉磯湖人隊!告訴我什麼是 LangChain 框架?” 這樣的查詢,如果直接搜索,可能會從 LLM 得到不正確或無法回答的響應。

因此,將用戶查詢的語義空間與文檔的語義空間對齊至關重要。查詢重寫技術可以有效地解決這個問題。它在 RAG 中的作用如下圖所示:

查詢重寫(紅色虛線框)在 RAG 中的應用

從位置的角度來看,查詢重寫是一種檢索前的方法。請注意,這個圖表大致描繪了查詢重寫在 RAG 中的位置。在下一節中,我們將看到一些算法可能會改進這一過程。

查詢重寫是使查詢和文檔語義對齊的關鍵技術。例如:

讓我們深入探討這些方法的細節。

假設文檔嵌入(HyDE)

論文 “Precise Zero-Shot Dense Retrieval without Relevance Labels” 提出了一種基於假設文檔嵌入(HyDE)的方法,主要過程如下圖所示:

以下是 HyDE 模型的示意圖。顯示了文檔片段。HyDE 在不改變底層 GPT-3 和 Contriever/mContriever 模型的情況下,服務於所有類型的查詢。

總之,儘管 HyDE 引入了一種新的查詢重寫方法,但它確實存在一些侷限性。它並不依賴於查詢嵌入的相似性,而是強調一個文檔與另一個文檔之間的相似性。然而,如果語言模型對主題不夠熟悉,可能不會總是產生最佳結果,這可能導致錯誤增加。

重寫 - 檢索 - 閱讀

這個想法來源於論文 “Query Rewriting for Retrieval-Augmented Large Language Models”。它認爲,原始查詢,特別是在現實世界場景中,可能並不總是適合 LLM 進行檢索的最佳選擇。

因此,論文建議我們應該首先使用 LLM 來重寫查詢。然後應該進行檢索和答案生成,而不是直接從原始查詢檢索內容並生成答案,如圖 4(b) 所示。

圖 4:從左至右,(a) 標準的先檢索再閱讀方法,(b) 使用 LLM 作爲我們的重寫 - 檢索 - 閱讀管道中的查詢重寫器,以及 (c) 我們的帶有可訓練重寫器的管道

爲了說明查詢重寫如何影響上下文檢索和預測性能,請考慮以下示例:“2020 年的 NBA 冠軍是洛杉磯湖人隊!告訴我 LangChain 框架是什麼?” 這個查詢通過重寫被準確地處理。

Step-Back Prompting

STEP-BACK PROMPTING 是一種簡單的提示技巧,它使 LLM 能夠進行抽象,從包含具體細節的實例中提煉出高層次的概念和基本原理。其核心思想是定義 “回退問題”,即從原始問題衍生出的更爲抽象的問題。

例如,如果一個查詢包含大量細節,LLM 很難檢索到相關事實來解決任務。如下面圖中的第一個例子所示,對於物理問題 “如果溫度增加 2 倍,體積增加 8 倍,理想氣體的壓力 P 會發生什麼變化?” 當直接對問題進行推理時,LLM 可能會偏離理想氣體定律的第一原則。

同樣,由於具體時間範圍的限制,“Estella Leopold 在 1954 年 8 月至 11 月期間去了哪所學校?” 這個問題直接回答起來很困難。

上圖展示了通過概念和原則引導的兩步抽象和推理的 STEP-BACK PROMPTING。頂部:一個高中物理 MMLU 的例子,其中通過抽象檢索到了理想氣體定律的第一原則。底部:一個來自 TimeQA 的例子,其中教育歷史的高層次概念是抽象的結果。左邊:PaLM-2L 未能回答原始問題。Chain-of-Thought 提示在中間推理步驟中遇到了錯誤(突出顯示爲紅色)。右邊:通過 STEP-BACK PROMPTING,PaLM-2L 成功地回答了問題。

在這兩個例子中,提出一個更廣泛的問題可以幫助模型有效地回答特定的查詢。我們不必直接問 “Estela Leopold 在某個特定時間去了哪所學校”,而是可以詢問 “Estela Leopold 的教育歷史”。

這個更寬泛的主題涵蓋了原始問題,並能提供所有必要的信息來推斷 “Estela Leopold 在某個特定時間去了哪所學校。” 值得注意的是,這些更寬泛的問題通常比原始的具體問題更容易回答。

從這種抽象中得出的推理有助於防止上圖(左)中描述的 “思維鏈” 中的中間步驟出現錯誤。

總之,STEP-BACK PROMPTING 涉及兩個基本步驟:

Query2doc

Query2doc: Query Expansion with Large Language Models 介紹了 query2doc。它使用來自 LLM 的幾個提示生成僞文檔,然後將它們與原始查詢結合,創建一個新的查詢,如下面圖所示:

上圖展示了 query2doc 的少量示例提示。出於空間原因,我們省略了一些上下文示例。

在密集檢索中,新查詢,標記爲q+,是原始查詢 (q) 和僞文檔 (d’) 的簡單串聯,由[SEP]分隔:q+ = concat(q, [SEP], d’)

Query2doc 認爲,HyDE 隱含地假設真實文檔和僞文檔用不同的詞彙表達了相同的語義,這可能對某些查詢不成立。

Query2doc 與 HyDE 的另一個區別在於,Query2doc 訓練了一個監督的密集檢索器,如論文中所述。

目前,在 Langchain 或 LlamaIndex 中尚未發現 query2doc 的復現。

ITER-RETGEN

ITER-RETGEN 方法利用生成的內容指導檢索。它在 Retrieve-Read-Retrieve-Read 流程中迭代實施 “檢索增強生成” 和“生成增強檢索”。

ITER-RETGEN 迭代執行檢索和生成。在每一次迭代中,ITER-RETGEN 利用上一次迭代的模型輸出作爲特定的上下文,幫助檢索更多相關知識,這可能有助於改善模型生成(例如,在此圖中糾正 Hesse Hogan 的身高)。爲了簡潔起見,我們只在此圖中展示了兩次迭代。實心箭頭連接查詢與檢索到的知識,虛線箭頭表示檢索增強生成。

如上圖所示,對於給定的問題q和檢索語料庫D = {d},其中d代表一個段落,ITER-RETGEN 連續執行T次檢索生成。

在每次迭代t中,我們首先使用上一次迭代的生成yt-1,將其與q結合,檢索出最相關的 k 個段落。接下來,我們提示 LLMM生成一個輸出yt,該輸出將檢索到的段落(表示爲Dyt-1||q)和q融入提示中。因此,每一次迭代可以公式化如下:

最後的輸出yt將作爲最終響應生成。

與 Query2doc 類似,目前在 Langchain 或 LlamaIndex 中尚未找到 ITER-RETGEN 的復現。

語義切片

在解析文檔之後,我們可以獲得結構化或半結構化的數據。當前的主要任務是將它們分解成更小的片段以提取詳細特徵,然後將這些特徵嵌入以表示其語義。它在 RAG 中的位置如下面圖所示。

在 RAG 中 Chunking 過程(紅色框)的位置

最常見的切片方法是基於規則的,採用諸如固定切片大小或相鄰切片重疊的技術。對於多級文檔,我們可以使用 Langchain 提供 d 的 RecursiveCharacterTextSplitter。這允許定義多級分隔符。

然而,在實際應用中,由於預定義規則的剛性(切片大小或重疊部分的大小),基於規則的切片方法很容易導致檢索上下文不完整或包含噪聲的切片大小過大的問題。

因此,對於切片,最優雅的方法顯然是基於語義進行切片語義切片旨在確保每個切片包含儘可能多的語義獨立信息。

本文探討了語義切片的方法,解釋了它們的原理和應用。我們將介紹三種類型的方法:

基於嵌入的方法

LlamaIndex 和 Langchain 都提供了一種基於嵌入的語義切片器。算法的思想或多或少是相同的。

基於模型的方法

簡單的 BERT

回想 BERT 的預訓練過程。設計了一個二元分類任務,Next Sentence Prediction(NSP),用來教會模型兩個句子間的關係。這裏,同時輸入兩個句子到 BERT,模型預測第二個句子是否跟在第一個句子後面。

我們可以將這一原理應用於設計一個簡單的切片方法。對於一個文檔,將其分割成句子。然後,使用滑動窗口將兩個相鄰的句子輸入到 BERT 模型中進行 NSP 判斷,如下圖所示:

使用 BERT 進行分塊

如果預測得分低於預設閾值,表明這兩句話之間存在較弱的語義關係。這可以作爲文本的分割點,如上圖中句子 2 和句子 3 之間的示例所示。

這種方法的優點是無需訓練或微調即可直接使用。

然而,這種方法在確定文本分割點時只考慮前後句子,忽略了更遠片段的信息。此外,該方法的預測效率相對較低。

跨段注意力

論文 Text Segmentation by Cross Segment Attention 提出了關於跨段注意力的三種模型,如下圖所示:

在跨段 BERT 模型(左圖)中,我們向模型輸入潛在段落分割點周圍的局部上下文:左側和右側各k個 token。在 BERT+Bi-LSTM 模型(中圖)中,我們首先使用 BERT 模型對每個句子進行編碼,然後將句子表示輸入到 Bi-LSTM 中。在層次 BERT 模型(右圖)中,我們首先使用 BERT 對每個句子進行編碼,然後將輸出的句子表示輸入到另一個基於變換器的模型中。

上圖 (a) 展示了跨段 BERT 模型,它將文本分割定義爲逐句分類任務。潛在分割點的上下文(兩側的k個 token)被輸入到模型中。與[CLS]對應的隱藏狀態被傳遞給 softmax 分類器,以決定在潛在分割點處是否進行分割。

論文還提出了另外兩種模型。一種使用 BERT 模型獲取每個句子的向量表示。然後,將多個連續句子的這些向量表示輸入到 Bi-LSTM(圖 (b))或另一個 BERT(圖 ©)中,以預測每個句子是否是文本分割邊界。

當時,這三種模型達到了最先進的結果,如以下圖所示

在文本分割和話語分割測試集上的結果

然而,到目前爲止,只發現了這篇論文的訓練實現。尚未發現可用於推斷的公開模型。

SeqModel

跨段模型獨立向量化每個句子,沒有考慮到更廣泛的上下文信息。在 SeqModel 中提出了進一步的改進,詳情請見論文 “Sequence Model with Self-Adaptive Sliding Window for Efficient Spoken Document Segmentation”。

SeqModel 使用 BERT 同時編碼多個句子,先在計算句子向量之前建模更長上下文內的依賴關係。然後預測每句話後是否進行文本分割。此外,該模型利用自適應滑動窗方法來提高推斷速度,而不犧牲準確性。SeqModel 的示意圖如以下圖所示:

提出的 SeqModel 架構和用於推斷的自適應滑動窗方法

基於 LLM 的方法

論文 Dense X Retrieval: What Retrieval Granularity Should We Use? 引入了一種新的檢索單元,稱爲命題。命題被定義爲文本中的原子表達,每個都封裝了一個獨特的事實,並以簡潔、自包含的自然語言格式呈現。

那麼,我們如何獲得這種所謂的命題呢?在論文中,這是通過構建提示和與 LLM 交互實現的。

LlamaIndex 和 Langchain 都已經實現了相關的算法,以下演示使用 LlamaIndex。

總的來說,使用 LLM 構建命題的這種切片方法已經實現了更精細的切片。它與原始節點形成了一種從小到大的索引結構,從而爲語義切片提供了一種新思路。

然而,這種方法依賴於 LLM,成本相對較高。

如果條件允許,可以持續關注並監控基於 LLM 的方法。

數據修改

**增強檢索雙重指導調優(RA-DIT)**和 **RECITation 增強生成(RECITE)**強調通過內部數據修改進行增強。

RA-DIT 區分了 LLM 和檢索器的微調數據集,旨在加強 LLM 的情境理解能力和檢索器與查詢的對齊能力。

而 RECITE 則利用段落提示和合成的問題 - 段落對來增加其生成的背誦和響應的多樣性和相關性。這種方法旨在擴大模型的知識庫並提高其響應的準確性。

**改進零樣本評估的通用提示檢索(UPRISE)生成而非檢索(GENREAD)**針對外部數據的精煉。

UPRISE 將原始任務數據轉換爲結構化格式,並細化提示的選擇,以改善檢索結果。

相比之下,GENREAD 使用的基於聚類的提示方法從問題生成文檔並將它們聚類以消除無關數據,用各種上下文洞察豐富輸入。這種技術旨在通過提供更豐富的信息集來提升生成模型的性能。

此外,KnowledGPT 致力於通過實體鏈接在原始文本數據中添加結構化、語義豐富的信息。這個豐富過程不僅使數據結構更加緊密,使其更容易接受查詢,而且提高了模型的檢索效率。它利用精確的鏈接知識來增強模型的理解力及其生成相關響應的能力,從而改善其整體表現。

查詢路由

查詢路由是 LLM 驅動決策的關鍵步驟,根據用戶查詢決定下一步行動——選項通常包括總結、執行鍼對某些數據索引的搜索,或嘗試多種不同路徑,然後將輸出綜合爲單一答案。

查詢路由器也用於選擇索引,或者更廣泛地說,選擇要發送用戶查詢的數據存儲——無論是我們有多個數據源,例如,經典的向量存儲和圖形數據庫或關係數據庫,還是我們有一個索引層次結構——對於多文檔存儲,一個相當典型的案例是一個摘要索引和另一個文檔片段向量的索引。

定義查詢路由器包括設置它可以做出的選擇。路由選項的選擇是通過 LLM 調用完成的,返回的結果以預定義的格式用於將查詢路由到給定索引,或者,如果我們正在談論同族行爲,到子鏈或甚至其他代理,如下圖的 \ 多文檔代理方案所示。

LlamaIndex 和 LangChain 都支持查詢路由器。

檢索技術

融合檢索 / 混合搜索

這是一個相對較老的想法,即結合兩全其美——傳統的基於關鍵詞的舊式搜索——像 tf-idf 這樣的稀疏檢索算法,或是搜索行業標準的 BM25——以及現代的語義或向量搜索,並將它們在一個檢索結果中結合起來。唯一的技巧在於正確地組合具有不同相似度分數的檢索結果——這個問題通常藉助互惠排名融合算法解決,重新排序檢索結果以供最終輸出。

在 LangChain 中,這是通過 Ensemble Retriever 類實現的,它結合了我們定義的一系列檢索器,例如 faiss 向量索引和基於 BM25 的檢索器,並使用 RRF 進行重新排序。

在 LlamaIndex 中,這是以非常類似的方式完成的。

混合或融合搜索通常能提供更好的檢索結果,因爲結合了兩種互補的搜索算法,同時考慮了查詢與存儲文檔之間的語義相似性和關鍵詞匹配。

後檢索技術

提示壓縮

RAG 流程可能會遇到兩個問題:

LLM 的提示壓縮是一種解決這些問題的方法。本質上,目標是從提示中保留關鍵信息,使輸入標記更具價值。這種方法提高了模型的性能並降低了成本。正如下圖右下角所示。

RAG 中的提示壓縮(右下角)。如紫色虛線所示,一些壓縮器也可以直接應用於檢索到的上下文中

值得注意的是,如上圖中的紫色虛線所示,一些壓縮器也可以直接應用於檢索到的上下文中。

總體而言,提示壓縮方法可以分爲四大類:

鑑於第四種類型的方法最初是爲 ViT 或 BERT 等較小的模型提出的,本文將介紹前三類方法中代表性算法的原理。

選擇上下文

下圖展示了 LLM 無需完整上下文或全部對話歷史即可響應用戶查詢。即使省略了相關信息,LLM 仍能產生預期的響應。這可能歸因於 LLM 從上下文線索和預訓練期間獲得的先驗知識中推斷缺失信息的能力。

LLM 能夠在刪除了較少信息含量的內容後仍然正確回答

因此,有可能通過過濾掉較少信息含量的內容來優化上下文長度,而不會影響性能。這是 Selective Context 的關鍵洞見。

Selective Context 使用小型語言模型(SLM)來確定給定上下文中詞彙單元(如句子、短語或令牌)的自信息。然後,它利用這些自信息來評估它們的信息量。通過有選擇地保留自信息較高的內容,Selective Context 爲 LLM 提供了更精簡、更高效的上下文表示,而不會影響它們在不同任務上的表現。

LLMLingua

LLMLingua 指出,Selective Context 常常忽視了壓縮內容間的相互聯繫以及 LLM 與用於提示壓縮的小型語言模型之間的關聯。LLMLingua 正是針對這些問題提出了精確解決方案。

具體來說,如下面的圖所示,LLMLingua 使用預算控制器來動態分配不同的壓縮比例給原始提示的不同組件,如指令、演示和問題。它還進行粗粒度、演示級別的壓縮,以保持高壓縮比下的語義完整性。此外,LLMLingua 引入了 token 級迭代算法,用於細粒度的提示壓縮。

提出的 LLMLingua 框架

與 Selective Context 相比,LLMLingua 在考慮 token 之間的條件依賴關係的同時,能更有效地保留提示中的關鍵信息。它可以將提示壓縮 20 倍。

迭代 token 級提示壓縮(ITPC)

使用困惑度進行提示壓縮存在一個固有限制:獨立性假設。這個假設將提示中的每個 token 視爲獨立的。換句話說,一個 token 出現的概率只依賴於前一個 token,與其他 token 無關。

這一假設的問題在於,它忽略了自然語言中 token 之間通常存在的複雜依賴關係,這些依賴關係對於理解上下文和保持語義完整性至關重要。

這種忽略可能導致在壓縮過程中丟失關鍵信息。例如,在高壓縮比的情況下,如果一個令牌在上下文中提供了關鍵的推理步驟或邏輯連接,僅僅根據其困惑度來決定是否保留這個 token 可能會導致推理過程的不完整。

爲了解決這個問題,LLMLingua 引入了迭代 token 級提示壓縮(ITPC)算法。這種方法不再僅僅依賴於 token 的獨立概率,而是在提示壓縮過程中更精確地評估每個 token 的重要性。它通過迭代處理提示中的每個片段,並考慮當前上下文中每個 token 的條件概率,從而有助於更好地保留 token 之間的依賴關係。

下圖詳細展示了 ITPC 的步驟:

ITPC 算法的詳細步驟

通過這一過程,ITPC 算法能夠在保持提示語義完整性的前提下有效壓縮提示的長度,從而降低 LLM 的推理成本。

指令調優

上圖(提出的 LLMLingua 方法框架)展示了指令調優也是 LLMLingua 中的一個關鍵步驟。其目的是最小化用於壓縮提示的小型語言模型與 LLM 之間的分佈差異。

下圖展示了指令調優的步驟:

指令微調步驟

LongLLMLingua

LLMLingua 的問題在於,在壓縮過程中沒有考慮到用戶的提問,這可能導致保留了一些無關緊要的信息。

LongLLMLingua 着眼於解決這一問題,通過在壓縮過程中融入用戶的提問來優化處理。

LongLLMLingua 框架

正如上圖所示,LongLLMLingua 提出四個新組件來增強 LLMs 對關鍵信息的感知:

AutoCompressor

與前述方法不同,AutoCompressor 採用了一種基於軟提示(soft prompt)的方法。

它通過擴展詞彙表並利用 “摘要 token” 和“摘要向量”,智能地微調現有模型,高效地濃縮上下文信息,從而實現對文本內容的有效壓縮而不損失核心意義。

AutoCompressor 通過遞歸生成摘要向量來處理長文檔,這些向量作爲軟提示傳遞給所有後續段落

上方的圖表呈現了 AutoCompressor 的架構,其運行步驟如下:

  1. 擴充詞彙:這個步驟涉及向模型現有的詞彙中加入 “摘要 token”。這些 token 讓模型有能力將大量的信息濃縮進較小的向量中。

  2. 分割文檔:將待處理的文檔劃分爲若干小段,每段末尾附加上摘要 token。這些 token 同時攜帶了前面段落的摘要信息,形成了摘要累積的效果。

  3. 微調訓練:採用無監督訓練法,利用 “下一個詞預測” 的任務來對模型進行微調。該任務的目標是基於當前詞之前的詞和當前段落之前各段落的摘要向量,預測下一個詞。

  4. 反向傳播:AutoCompressor 使用時間反向傳播 (BPTT) 和梯度檢查點技術對每個段落進行操作,以減少計算圖的規模。對整個文檔進行反向傳播,使得模型能夠學習到完整上下文的關聯性。

LLMLingua-2

LLMLingua-2 指出,依據因果語言模型(如 LLaMa-7B)通過刪除 token 或詞彙單位來壓縮提示時存在以下兩個問題:

  1. 用於確定信息熵的小型語言模型與提示壓縮的目標並不一致。

  2. 它僅利用了單向上下文,可能無法涵蓋提示壓縮所需的所有信息。

這些問題的核心在於,信息熵可能並非壓縮效果的最佳衡量標準。

下圖展示了 LLMLingua-2 的整體架構:

LLMLingua-2 的概覽

爲了解決第一個問題,LLMLingua-2 引入了數據蒸餾過程。這一過程從大型語言模型中提煉知識,壓縮提示而不丟失關鍵信息。同時,它構建了一個提取式文本壓縮數據集。在該數據集上的訓練有助於使小型語言模型在提示壓縮上有效對齊。

針對第二個問題,LLMLingua-2 將提示壓縮視爲一個 token 分類問題。這種做法確保了壓縮後的提示對原始提示的保真度。它使用變壓器編碼器作爲基礎架構,從完整的雙向上下文中捕捉所有必要的信息,用於提示壓縮。

RECOMP (檢索、壓縮、前置)

RECOMP 引入了兩類經過訓練的壓縮器:抽取式抽象式。抽取式壓縮器從檢索到的文檔中挑選有用句子,而抽象式壓縮器則綜合多文檔信息生成摘要。

下方圖表顯示了壓縮器在 RECOMP 中的位置。

RECOMP 的架構

抽取式壓縮器

對於輸入文檔集中的n個句子[s1, s2, …, sn],我們訓練一個雙編碼器模型。此模型將句子si和輸入序列x嵌入固定維度的表示中。這些表示的內積指示了將si添加到輸入x中以生成目標輸出序列對大型語言模型的好處。

壓縮器產生的最終摘要s由內積排名前N的句子組成。

抽象式壓縮器

抽象式壓縮器是一個編碼器 - 解碼器模型。它接受輸入序列x和檢索到的文檔集合的拼接,並輸出一個摘要s

該方法涉及使用大型語言模型(如 GPT-3)生成訓練數據集,過濾這些數據,然後使用過濾後的數據集訓練編碼器 - 解碼器模型。

在討論的方法中,LongLLMLingua 可能是更優的選擇。我們已經在研究項目中實現了它。此外,也可以嘗試 LLMLingua-2,它在速度和內存使用方面具有優勢。

再排序

再排序在檢索增強生成(RAG)過程中扮演着關鍵角色。在簡單的 RAG 方法中,可能會檢索出大量上下文,但並非所有上下文都一定與問題相關。再排序允許重新排序和篩選文檔,將相關文檔置於前列,從而提高 RAG 的有效性。

再排序介紹

在 RAG 中,再排序的任務是對檢索到的上下文進行相關性評估,優先選擇那些(標記爲紅色框)最可能提供準確且相關信息的上下文

如上圖所示,再排序的任務就像是一個智能過濾器。當檢索器從索引集合中檢索出多個上下文時,這些上下文對用戶查詢的相關性可能各不相同。有些上下文可能高度相關(紅色框高亮),而其他一些可能只是略微相關甚至完全不相關(綠色和藍色框高亮)。

再排序的任務就是評估這些上下文的相關性,並優先考慮那些最有可能提供準確且相關答案的上下文。這使得大型語言模型在生成答案時可以優先考慮這些排名靠前的上下文,從而提高響應的準確性和質量。

簡單來說,再排序就像在開卷考試中幫助我們從一堆學習資料中選擇最相關的參考材料,以便我們能夠更高效、更準確地回答問題。

本文描述的再排序方法主要可以分爲以下兩類:

使用再排序模型作爲再排序器

與嵌入模型不同,再排序模型將查詢和上下文作爲輸入,直接輸出相似度得分而非嵌入向量。值得注意的是,再排序模型是通過交叉熵損失進行優化的,這意味着相關性得分不限於某一特定範圍,甚至可以是負數。

目前可用的再排序模型並不多。一種選擇是 Cohere 提供的在線模型,可以通過 API 訪問。還有開源模型,如 bge-reranker-base 和 bge-reranker-large 等。

下方圖表展示了使用命中率(Hit Rate)和平均倒排秩(Mean Reciprocal Rank, MRR)指標的評估結果:

使用 Hit Rate 和 Mean Reciprocal Rank (MRR) 度量的評估結果

從這一評估結果我們可以看出:

使用 LLM 作爲再排序器

涉及 LLM 的現有再排序方法大致可歸爲三類:使用再排序任務對 LLM 進行微調、引導 LLM 進行再排序、以及在訓練期間使用 LLM 進行數據增強。

引導 LLM 進行再排序的方法成本較低。以下是使用 RankGPT 的一個示例,它已被集成到 LlamaIndex。

RankGPT 的理念是使用 LLM(如 ChatGPT、GPT-4 或其他 LLM)進行零樣本列表式段落再排序。它應用了排列生成策略和滑動窗口策略,以高效地對段落進行再排序。

如下方圖表所示,論文提出了三種可行的方法。

利用 LLM 進行零樣本段落再排序的三種指令類型。灰色和黃色塊分別表示模型的輸入和輸出。(a)查詢生成依賴於 LLM 的日誌概率,根據段落生成查詢。(b)相關性生成指導 LLM 輸出相關性判斷。(c)排列生成對一組段落生成排序列表。

前兩種方法屬於傳統方式,其中,對每份文檔給出一個分數,隨後根據這一分數對所有段落進行排序。

第三種方法,即排列生成,是在本論文中提出的。**具體而言,這種方法不依賴於外部評分,而是直接對段落進行端到端的排序。**換言之,它直接利用 LLM 的語義理解能力對所有候選段落進行相關性排序。

然而,通常候選文檔的數量非常龐大,而 LLM 的輸入是有限的。因此,往往無法一次性輸入所有文本。爲解決這一問題,論文中提出了一種滑動窗口策略。通過將候選段落分組,每次只處理一小批段落,從而降低單次處理的文本量。這種方法不僅解決了輸入限制問題,還提高了處理效率,使得大規模文檔集的再排序成爲可能。

利用滑動窗口進行段落再排序的示意圖,窗口大小爲 4,步長爲 2,對 8 個段落進行再排序。藍色代表前兩個窗口,黃色代表最後一個窗口。滑動窗口按從後向前的順序應用,意味着前一個窗口的前 2 個段落將參與下一個窗口的再排序。

因此,如上圖所示,引入了一種滑動窗口方法,其理念類似於冒泡排序。每次僅對前4個文本進行排序,然後移動窗口,對接下來的4個文本進行排序。遍歷完整個文本後,我們可以得到表現最優的頂部文本。

過濾

**知識鏈(COK)**介紹了漸進式理由修正技術,旨在通過檢索到的知識迭代優化理由。這種方法構成了一種持續優化過程,顯著提升了用於內容生成的信息的相關性和質量。

Self-RAG 引入了一種自我反思機制,以高效地過濾掉不相關的內容。通過運用批判性 token,這種方法評估了檢索到的段落的相關性、支持性和實用性,確保只有高質量信息被整合到內容生成的過程中。

我們的 Token 過濾方法概覽。在此,將兩個段落視作解碼器模塊的輸入。在生成 token t 時,在解碼層 l 和 l+1 之間執行 Token 過濾操作。利用第 l 層的 token t 表示,計算所有輸入 token 的交叉注意力。接着,從輸入中篩選掉排名最低的 token(標記爲黃色),僅使用排名最高的輸入 token 來生成後續的每一個 token。

此外,結合 Token 過濾的解碼器融合(FiD-TF)(上圖)和 RECOMP 致力於從檢索到的文檔中剔除不相關或冗餘的 token 和信息。FiD-TF 採用動態機制識別並剔除不必要的 token,從而提高信息處理的效率。相比之下,RECOMP 將文檔壓縮成精簡的摘要,專注於選擇最相關的內容用於生成過程。這些方法通過確保僅使用相關和支持性的信息,簡化了內容生成的工作流程,從而提升生成內容的整體質量和相關性。

Self-RAG

讓我們考慮一個常見的場景:參加開卷考試。我們通常有兩種策略:

顯然,方法 1 是更優選的。方法 2 可能耗時,且容易引入不相關或錯誤的信息,這可能導致混淆和錯誤,甚至在原本理解的領域也會出錯。

然而,方法 2 正是經典 RAG 流程的體現,而方法 1 代表了 self-RAG 流程,這也是本文將進一步探討的內容。

下方圖表對比了 RAG 和 self-RAG 主要流程:

Self-RAG 的概述,Self-RAG(右圖)學會按需檢索、批判和生成文本段落,以增強整體生成質量、事實性和可驗證性

Self-RAG 包含三個步驟:

  1. 按需檢索:當模型需要檢索時,例如面對 “美國各州名稱是如何得來的?” 這樣的查詢(上圖右上角),模型的輸出將包含一個[Retrieve]token。這表明需要檢索與查詢相關的內容。相反,當要求寫一篇 “關於我最好的暑假的文章”(上圖右下角)時,模型選擇直接生成答案,無需檢索。

  2. 並行生成:模型利用提示和檢索到的內容生成輸出。在整個過程中,三種類型的反思令牌指示檢索內容的相關性。

  3. 評估與選擇:對第二步中生成的內容進行評估,並選擇最佳段落作爲輸出。

修正 RAG

考慮一個常見的情景:參加開卷考試。通常,我們有三種策略:

方法 1 涉及 self-RAG,而方法 2 則是經典 RAG 流程。

最後,方法 3,即 Corrective Retrieval Augmented Generation (CRAG),是本文將要介紹的內容。

CRAG 的動機

示例說明,低質量的檢索器傾向於引入大量不相關信息,阻礙生成器獲取準確知識,甚至可能誤導生成器。

上方圖表說明,大多數傳統的 RAG 方法並未考慮文檔與問題的相關性,僅僅是合併檢索到的文檔。這可能引入不相關信息,阻礙模型獲得準確知識,甚至誤導模型,導致幻覺問題的出現。

此外,大多數傳統的 RAG 方法將檢索到的整篇文檔作爲輸入。然而,這些檢索到的文檔中的大量文本對於生成而言往往是不必要的,不應同等程度地參與到 RAG 中。

CRAG 的核心理念

CRAG 設計了一個輕量級的檢索評估器,用於評估針對特定查詢檢索到的文檔的整體質量。它還利用網絡搜索作爲輔助工具,以改善檢索結果。

CRAG 具有即插即用的特點,能夠無縫集成到基於 RAG 的各種方法中。整體架構如下方圖表所示。

CRAG 在 RAG 中的位置(紅色虛線框)。設計了一個檢索評估器來評估檢索到的文檔與輸入的相關性。它還估計了一個置信度水平,這可以觸發不同的知識檢索行爲,即{Correct, Incorrect, Ambiguous}。此處,“x” 代表查詢。

如上圖所示,CRAG 通過引入檢索評估器來評估檢索到的文檔與查詢之間的關係,從而增強了傳統的 RAG。

有 3 種可能的判斷結果。

最後,處理過的信息被傳遞給 LLM 以生成響應。下方圖表正式描繪了這一過程。

需要注意的是,網絡搜索並不直接使用用戶的輸入查詢進行搜索。相反,它構建一個提示,以少量示例的方式呈現給 GPT-3.5 Turbo,以獲取用於搜索的查詢。

CRAG 與 self-RAG 的區別:

四個數據集測試集上的總體評估結果。結果依據生成的 LLMs 進行分類。粗體數字表示在所有方法和 LLMs 中最佳的表現。灰色粗體分數表示使用特定 LLM 時的最佳表現。* 表示由 CRAG 復現的結果,否則除了我們的結果外,其餘結果引用自原始論文。

檢索評估器的改進

檢索評估器可以被視爲一個評分分類模型。這個模型用於確定查詢和文檔的相關性,類似於 RAG 中的再排序模型。

此類相關性判斷模型可以通過整合更多符合現實場景的特徵來改進。例如,科學論文問答的 RAG 包含許多專業術語,而旅遊領域的 RAG 則傾向於有更多的口語化用戶查詢。

通過在檢索評估器的訓練數據中加入場景特徵,它可以更好地評估檢索到的文檔的相關性。其他特徵,如用戶意圖和編輯距離,也可以被納入,如下方圖表所示:

在 CRAG 中通過整合額外特徵來改進檢索評估器的訓練

此外,考慮到 T5-Large 取得的結果,輕量級模型似乎也能達到不錯的效果。這爲小規模團隊或公司在應用 CRAG 上帶來了希望。

檢索評估器的得分和閾值

正如前面所述,閾值因不同種類的數據而異。而且,我們可以發現ambiguousincorrect的閾值基本上在 - 0.9 左右,這表明檢索到的知識大多與查詢相關。完全拋棄這些檢索到的知識,僅僅依賴網絡搜索可能並非明智之舉。

RAG 融合

RAG-Fusion 首先使用大型語言模型生成多個衍生查詢。這一步驟擴展了對初始用戶輸入的理解,確保了從多角度全面探索查詢主題。接下來,向量搜索爲原始查詢及其衍生查詢找到相關文檔,彙編了一系列相關的信息。

在文檔檢索之後,Reciprocal Rank Fusion(RRF)算法根據相關性重新排序這些文檔。這些文檔隨後被整合成一個全面且相關的信息源。

在最後階段,這個綜合數據集及所有查詢都被大型語言模型處理。模型將這些輸入綜合,創造出條理清晰、與上下文相關性強的迴應。通過這一系統性的方法,RAG-Fusion 提升了迴應的準確性和全面性,顯著提高了對用戶查詢回答的質量。

讓我們總結並並列比較這三種方法:

生成技術

增強

**展示 - 搜索 - 預測(DSP)引入了一個框架,旨在生成多個檢索查詢以彙總和回答問題,從多個段落中聚合信息。該框架利用多種搜索組合(CombSUM)**計算不同檢索列表中段落的累積概率得分,從而從多個來源彙編全面的響應。

**可插拔獎勵驅動上下文適配器(PRCA)**描述了一個獎勵驅動階段,其中,基於生成器的反饋細化蒸餾上下文。通過強化學習,此階段根據提供相關上下文所獲得的獎勵調整 PRCA 的參數。目標是微調提取的上下文,以滿足生成器的具體需求,從而優化生成過程。

**檢索並插入(REPLUG)**提出了一種方法,在黑盒 LM 進行最終預測之前,將檢索到的文檔附加到輸入上下文中。它引入了一種集成策略,以並行編碼檢索到的文檔,克服了 LM 上下文長度的限制,並通過分配更多計算資源提高了準確性。這種方法通過確保 LM 能夠訪問更廣泛的相關信息,改進了生成過程。

RECITE 實施了一種自一致性技術,涉及獨立生成多個複述,並採用多數投票系統確定最合適的答案。這種方法旨在提高答案的可靠性和準確性,從而提高輸出的質量和可信度。

定製

**參數化知識引導(PKG)**框架代表了一種定製 LM 輸出的方法。通過使用預訓練模型內部生成背景知識,PKG 消除了對傳統外部檢索過程的需求。這種方法直接在生成步驟中整合領域或任務特定知識,顯著增強了 LM 產生針對特定上下文或需求量身定製的響應的能力。

Self-RAG 提供了一種策略,即在可定製的解碼算法中融入反思令牌。這種技術允許根據特定任務動態調整模型的檢索和生成行爲,促進更靈活的響應生成。根據需求,這種方法可以在準確性或創造性之間進行調整,提供生成滿足多樣化需求的輸出的靈活性。

**子圖檢索增強生成(SURGE)**通過應用圖 - 文本對比學習實現了定製。該方法確保生成的對話響應與檢索到的子圖中包含的知識緊密對齊,產生具體、相關且深深植根於對話上下文的響應。通過保持檢索到的知識和生成文本之間的一致性,SURGE 能夠產生精確反映子圖詳細知識的輸出,增強了響應的相關性和特定性。

聊天引擎

構建一個能夠對單一查詢進行多次工作的出色 RAG 系統,下一個重要步驟是聊天邏輯,考慮到對話上下文,就像在 LLM 時代之前的經典聊天機器人中一樣。這是爲了支持後續問題、指代或與先前對話上下文相關的任意用戶命令。通過查詢壓縮技術,將聊天上下文與用戶查詢一起考慮來解決這個問題。

如同以往,有幾種方法可用於上述上下文壓縮——一個流行且相對簡單的 ContextChatEngine,首先檢索與用戶查詢相關的上下文,然後將其與來自_內存_緩衝區的聊天曆史一起發送給 LLM,以便在生成下一個答案時 LLM 能夠了解先前的上下文。

稍微複雜一點的情況是 CondensePlusContextMode——在每次交互中,聊天曆史和最近的消息被壓縮成一個新的查詢,然後這個查詢進入索引,檢索到的上下文與原始用戶消息一起傳遞給 LLM 以生成答案。

值得注意的是,LlamaIndex 也支持基於 OpenAI 代理的聊天引擎,提供更靈活的聊天模式,Langchain 也支持功能 API,爲創建更智能、更適應用戶需求的聊天體驗提供了可能。

RAG 中的代理

自首個 LLM(大型語言模型)API 發佈以來,代理(由 Langchain 和 LlamaIndex 支持)幾乎就已存在——其理念是爲具有推理能力的 LLM 提供一系列工具及待完成的任務。這些工具可能包括確定性的函數,如任何代碼函數、外部 API,甚至是其他代理——這種 LLM 鏈式調用的想法正是 LangChain 命名的由來。

代理本身就是一個龐大的主題,在 RAG 概覽中深入探討這一主題是不可能的,因此我將繼續討論基於代理的多文檔檢索案例,在 OpenAI 助手這一站稍作停留,因爲它是一個相對較新的事物,最近在 OpenAI 開發者大會上以 GPT 的身份亮相,並在下面描述的 RAG 系統背後運作。

OpenAI 助手基本上實現了圍繞 LLM 所需的許多工具,這些工具我們之前在開源領域已有——聊天曆史記錄、知識存儲、文檔上傳界面以及也許最重要的,函數調用 API。後者提供了將自然語言轉化爲對外部工具或數據庫查詢的 API 調用的能力。

在 LlamaIndex 中,有一個 OpenAIAgent 類,將這種高級邏輯與 ChatEngine 和 QueryEngine 類結合,提供基於知識和情境感知的聊天功能,以及在一次對話回合中多次調用 OpenAI 函數的能力,這確實帶來了智能代理行爲。

讓我們看一下多文檔代理架構——一個相當複雜的設置,涉及對每份文檔初始化一個代理 (OpenAIAgent),它能夠進行文檔摘要和經典的問答機制,以及一個頂層代理,負責向文檔代理路由查詢併合成最終答案。

每個文檔代理有兩個工具——向量存儲索引和摘要索引,根據路由的查詢決定使用哪一個。而對於頂層代理,所有文檔代理都是可敬重的工具。

此架構展示了先進的 RAG 結構,其中每個參與的代理都會做出大量的路由決策。這種方法的優勢在於能夠比較不同文檔及其摘要中描述的不同解決方案或實體,同時涵蓋了經典單文檔摘要和問答機制——這基本上覆蓋了最常見的與文檔集合聊天的使用場景。

圖示說明了多文檔代理的方案,涉及查詢路由和代理行爲模式。

這種複雜方案的缺點可以從圖中猜測到——由於代理內部與 LLM 的多次來回迭代,它的速度有點慢。需要注意的是,LLM 調用始終是 RAG 管道中最耗時的操作——搜索設計上是爲了優化速度。

編碼器與 LLM 微調

這種方法涉及對我們 RAG 管道中的兩個深度學習模型之一進行微調——即負責嵌入質量從而影響上下文檢索質量的 Transformer 編碼器,或者負責最佳利用所提供的上下文回答用戶查詢的 LLM——幸運的是,後者是一個很好的少量樣本學習者。

如今的一大優勢是,可以使用像 GPT-4 這樣的高端 LLM 生成高質量的合成數據集。但我們應該始終意識到,採用由專業研究團隊在精心收集、清理和驗證的大數據集上訓練的開源模型,並使用小規模的合成數據集快速微調,可能會在總體上限制模型的能力。

編碼器微調

我也對編碼器微調的方法持有些許懷疑態度,因爲最新的爲搜索優化的 Transformer 編碼器效率相當高。因此,我在 LlamaIndex 筆記本設置中測試了 bge-large-en-v1.5(撰寫本文時 MTEB 排行榜排名前四)微調後性能提升的情況,結果表明檢索質量提高了 2%。雖然沒有戲劇性的變化,但瞭解這個選項是好的,尤其是在我們有針對狹窄領域數據集構建 RAG 的情況下。

排序器微調

另一種久經考驗的選擇是使用交叉編碼器對檢索到的結果進行重新排序,如果我們對基礎編碼器完全不信任的話。其工作方式如下——我們將查詢和檢索出的前 k 個文本片段傳遞給交叉編碼器,通過 SEP 標記分隔,並對其進行微調,使其對相關片段輸出 1,對非相關片段輸出 0。在此教程中可以找到此類微調過程的一個好例子,結果顯示通過交叉編碼器微調,配對得分提高了 4%。

LLM 微調

最近,OpenAI 開始提供 LLM 微調 API,而 LlamaIndex 有一篇關於在 RAG 設置下微調 GPT-3.5-turbo 的教程,目的是 “提煉” 部分 GPT-4 的知識。這裏的思路是,從一份文檔出發,使用 GPT-3.5-turbo 生成一系列問題,然後利用 GPT-4 基於文檔內容生成這些問題的答案(構建一個 GPT4 驅動的 RAG 管道),最後在問題 - 答案對的數據集上對 GPT-3.5-turbo 進行微調。用於評估 RAG 管道的 Ragas 框架顯示,** 在忠實度指標上提高了 5%**,這意味着微調後的 GPT 3.5-turbo 模型比原始模型更好地利用了所提供的上下文生成答案。

一種更爲複雜的方法在最近的論文中提出,即 RA-DIT:Retrieval Augmented Dual Instruction Tuning ,由 Meta AI Research 提出,提出了一種技術,可以在查詢、上下文和答案的三元組上同時微調 LLM 和檢索器(在原論文中是雙重編碼器)。這項技術既被用來通過微調 API 微調 OpenAI 的 LLM,也被用來微調 Llama2 開源模型(在原論文中),結果是在知識密集型任務的指標上提高了約 5%(與帶有 RAG 的 Llama2 65B 相比),在常識推理任務上也提高了幾個百分點。

評估

多個框架用於評估 RAG 系統的性能,它們共同的理念是擁有幾個獨立的指標,比如整體答案相關性、答案基於事實的程度、忠實度以及檢索到的上下文相關性

不同 RAG 評估框架的對比

前面提到的 Ragas 使用了忠實度和答案相關性作爲生成答案的質量指標,並使用經典的上下文精確度和召回率來評估 RAG 方案中的檢索部分。

一個非常簡單的檢索器評估流程的好例子可以在這裏找到,並且它在編碼器微調部分被應用。一個更先進的方法,不僅考慮了命中率,還考慮了平均倒數排名(Mean Reciprocal Rank),這是搜索引擎常用的一項指標,同時也考慮了生成答案的指標,如忠實度和相關性,這個方法在 OpenAI 的 cookbook 中有所展示。

LangChain 擁有一套相當先進的評估框架 LangSmith,其中可以實現自定義評估器,此外,它監控運行在我們 RAG 管道內的痕跡,以便讓我們的系統更加透明。

如果我們在使用 LlamaIndex 構建,有一個 rag_evaluator llama pack,提供了一個快速工具,讓我們能夠使用公共數據集評估我們的管道。

結論

我們嘗試概述了 RAG 的核心算法方法,並通過圖解一些方法,希望能激發在我們的 RAG 管道中嘗試新想法的靈感,或者向大家介紹今年發明的衆多技術中的一些。

還有很多其他值得考慮的事情,例如基於網絡搜索的 RAG(LlamaIndex 的 RAGs、webLangChain 等),深入探索代理架構(以及一些關於 LLM 長期記憶的想法。

除了答案相關性和忠實度之外,RAG 系統的主要生產挑戰是速度,特別是在我們採用更靈活的基於代理的方案時,但這將是另一篇文章的主題。這種流式特徵,ChatGPT 和其他大多數助手使用的,不僅僅是隨機的賽博朋克風格,而是一種縮短感知答案生成時間的方式。

英文原文:https://medium.com/@vipra_singh/building-llm-applications-advanced-rag-part-10-ec0fe735aeb1

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/D1jXVZ47QZyp8UDXx15UEQ