Auto-RAG:用于大型語言模型的自主檢索增強生成
單位:中科院計算所
代碼: https://github.com/ictnlp/Auto-RAG
擬解決問題:通過手動構建規則或者few-shot prompting產生的額外推理開銷。
貢獻:提出一種以LLM決策為中心的自主迭代檢索模型
Abstract
迭代檢索是指模型在生成過程中不斷查詢檢索器,以增強檢索到的知識的相關性,從而提高檢索增強生成 (RAG) 的性能的過程。現有工作通常采用小樣本提示或手動構建的規則來實現迭代檢索。這引入了額外的推理開銷,并忽視了大型語言模型 (LLM) 卓越的推理能力。在本文中,我們介紹了 Auto-RAG,這是一種以 LLM 強大的決策能力為中心的自主迭代檢索模型。Auto-RAG 與檢索器進行多輪對話,系統地規劃檢索并優化查詢以獲取有價值的知識。此過程一直持續,直到收集到足夠的外部信息,此時結果將呈現給用戶。為此,我們開發了一種在迭代檢索中自主合成基于推理的決策指令的方法,并對最新的開源 LLM 進行了微調。實驗結果表明,Auto-RAG 能夠與檢索器進行自主迭代交互,有效利用 LLM 卓越的推理和決策能力,從而在六個基準中取得優異的表現。進一步分析表明,Auto-RAG 可以根據問題的難度和檢索到的知識的效用自主調整迭代次數,而無需任何人工干預。此外,Auto-RAG 以自然語言表達迭代檢索過程,增強可解釋性,同時為用戶提供更直觀的體驗。
Introduction
為了解決檢索內容中的噪聲(回答中會有很多不相干的內容)以及復雜查詢(問題簡單,但卻要檢索很多內容。如:行軍路線)。已經提出了迭代檢索(Feng et al., 2023; Chen et al., 2024; Asai et al., 2023) (Yu 等, 2024, p. 1)。當前的迭代過程大多依賴few-shot prompting和人力構建規則,忽視了大語言模型的推理能力。
因此引入Auto-RAG,下圖展示了其如何解決復雜多跳問題的一個具體示例。
Related Work
檢索增強生成的引入是為了解決:
-
LLM對長尾知識保留不足;
-
模型參數中嵌入過時知識。
檢索器缺陷(主要是檢索內容的噪音)解決:
-
改進查詢公式“(Ma et al., 2023)” (Yu 等, 2024, p. 3)
-
增強檢索器“(Karpukhin et al., 2020; Chen et al., 2023)” (Yu 等, 2024, p. 3)
-
改進生成器“(Yoran et al., 2023; Yu et al., 2023)” (Yu 等, 2024, p. 3)
-
后檢索優化“(Yu et al., 2024; Xu et al., 2023)” (Yu 等, 2024, p. 3)
任務復雜性的增加導致單詞檢索難度增大。
-
ITER-RETGEN將輸入問題與上一次迭代生成的輸出連接起來,以形成下一次迭代的新查詢。(僅僅反映現有知識,沒有明確LLM的信息需求)
-
FLARE使用下一個生成的句子作為查詢,根據檢索結果對前一個句子進行提煉。盡管這種方法更精確地識別了 LLM 的信息需求,但其有效性在很大程度上取決于精心制作的few-shot prompt,需要不斷檢索和改進,從而導致大量的人工工作和推理成本增加。
-
Self-RAG訓練 LLM 反思檢索和生成的內容。然而,Self-RAG 只在訓練期間學會機械地預測反射標記,而沒有培養推理能力,這進一步限制了這種方法的有效性。
與上述方法相比,Auto-RAG 充分釋放了 LLM 在迭代檢索過程中基于推理的自主決策的潛力。Auto-RAG 使 LLM 能夠通過推理自主決定何時檢索以及檢索什么。與其他迭代檢索方法相比,Auto-RAG 提供了卓越的性能和更高的效率。
Method
Reasoning-based iterative retrieval
$(X,Y)→[X,R_0?,(Q_t?,D_t?,R_t?)_{1≤t≤T}?,A]$
例子:
原始輸入
X
: "諸葛亮北伐時蜀軍是如何行軍的?"初始推理
R?
: 模型先根據已有知識進行第一步推理,例如:“諸葛亮北伐是三國時期蜀漢對曹魏的軍事行動,總共有數次。這需要進一步確認是哪一次北伐。”
迭代過程(每一輪表示一次信息檢索與推理)
在數據合成期間,2WikiMultihopQA 的 T 設置為 10,Natural Questions設置為 5。
第 1 次迭代:
Q?
: 從 R? 中抽取的信息需求,例如:“諸葛亮第一次北伐的時間、出發地和目標區域?”
D?
: 檢索到的文檔段落,比如:“第一次北伐發生在建興六年(228年),諸葛亮從漢中出發,經由祁山攻打陳倉。”
R?
: 新的推理內容:“第一次北伐路線是從漢中出發,經祁山,目標是陳倉。”
🔄 第 2 次迭代:
Q?
: 進一步需要的信息:“蜀軍途徑哪些地點?是否有記載他們在哪些地方駐扎或作戰?”
D?
: 檢索到的新段落:“北伐軍在途中經過武都、陰平,派遣馬謖駐守街亭,街亭失守導致退兵。”
R?
: 新的推理內容:“行軍路線包括漢中 → 祁山 → 武都 → 陰平 → 街亭,但因街亭失守,北伐失敗。”
注:如果前一次迭代的推理 Rt?1 包含信息需求4,則查詢 Qt 將被采納(標準:預定義了 “however”、“no information”、“find” 和 “refine” 等術語來表示模型的信息需求。如果輸出中出現任何上述內容,則表示需要額外信息),檢索器將為 Qt 提供文檔 Dt。
🎯 最終答案:
A
: 綜合所有推理得出最終結論:“諸葛亮第一次北伐時,蜀軍從漢中出發,沿祁山、武都、陰平一線北上,目標是陳倉,派遣馬謖駐守街亭,但因街亭失守導致北伐失敗。”
Reasoning based planning and query refinement
推理范式
-
Retrieval Planning
-
Information Extraction
-
Answer Inference
需要注意的是,在最初收到用戶的問題時,通常會省略步驟 2和 3。此外,如果發現檢索到的信息完全不相關,則步驟2也被排除在外。這種調整使 LLM 能夠根據實際情況做出明智的判斷,而不僅僅是模仿演示和產生幻覺。用于引出推理的提示在附錄 C.1 中給出。
通過適當的推理過程,LLM 可以根據用戶輸入和以前的檢索計劃迭代優化查詢,不斷適應新的信息要求。為了生成足夠多樣化的查詢集,而不受 few-shot prompt中出現的查詢樣式的限制,我們采用了更靈活的提示方法,如附錄 C.5 所示(這個模板很合適)。
Data Filtering & Formatting
Data Filtering(Algorithm 1)
🔁 執行 Algorithm 1:
第 1 步:初始化
DInst = []
第 2 步:對數據集 D 中每對 (X, Y) 遍歷,這里我們只有一對。
第 3 步:語言模型 M
進行首次推理
R0 = M.predict_reasoning(X)
輸出示例:
“諸葛亮北伐多次,需要先明確是第幾次,才能判斷路線。”
第 4 步:設置輪次計數
t = 1
第 5~18 步:迭代推理和檢索(最多 T 次)
我們設 T = 2
,進行兩輪迭代。
🔁 第一次迭代(t = 1)
Step 6:生成多個查詢 Qgen
Qgen = M.generate_queries(X, R0)
輸出示例:
["諸葛亮第一次北伐發生在哪一年?", "諸葛亮北伐是從哪里出發的?"]
Step 7~11:嘗試找一個 query 能檢索出包含“部分答案”的文檔
-
設
R.retrieve()
找到:
d = "第一次北伐發生在建興六年(228年),從漢中出發,經祁山攻魏。"
識別出包含部分答案(“漢中 → 祁山”),滿足條件:
Qt = "諸葛亮北伐是從哪里出發的?" Dt = d
Step 15:語言模型根據前面內容生成本輪推理
R1 = M.reason(X, R0, [(Qt, Dt)], Qt, Dt)
輸出:
“諸葛亮第一次北伐是從漢中出發,經祁山北上,這是行軍的初始部分。”
Step 16:判斷是否還有信息需求
模型發現還需知道是否經過其他地點,所以繼續迭代。
t = 2
🔁 第二次迭代(t = 2)
Step 6:基于前一輪推理生成新 query
Qgen = M.generate_queries(X, R1)
輸出:
["諸葛亮北伐過程中是否經過街亭?", "蜀軍在哪些地方戰斗或駐扎?"]
Step 8~11:檢索文檔
例如:
d = "蜀軍派馬謖駐守街亭,街亭失守導致全軍撤退。"
識別出是部分答案(街亭事件)。
Qt = "諸葛亮北伐過程中是否經過街亭?" Dt = d
Step 15:生成新的推理
R2 = M.reason(X, R0, [(Q1, D1, R1)], Qt, Dt)
輸出:
“街亭是北伐途中的關鍵戰役地點,蜀軍在此失敗,決定了整個北伐的結局。”
Step 16:判斷是否還需檢索
此時 R2
包含完整的信息,模型判斷無需再提問,跳出循環。
Step 19:生成最終回答
A = M.answer(X, R0, [(Q1, D1, R1), (Q2, D2, R2)])
輸出:
“諸葛亮第一次北伐路線為漢中 → 祁山 → 街亭。街亭失守后,北伐失敗撤退。”
Step 20:驗證是否和真實答案匹配
if A == Y: # 或通過相似度度量近似判斷
? 匹配,加入訓練集。
最終輸出:
DInst.append([X, R0, (Q1, D1, R1), (Q2, D2, R2), A])
🧾 總結輸出結果格式:
{ "X": "諸葛亮北伐時蜀軍是如何行軍的?", "R0": "諸葛亮北伐多次,需要明確是哪次。", "Iterations": [ { "Q": "諸葛亮北伐是從哪里出發的?", "D": "第一次北伐發生在建興六年(228年),從漢中出發,經祁山攻魏。", "R": "北伐路線從漢中出發,經祁山北上。" }, { "Q": "諸葛亮北伐過程中是否經過街亭?", "D": "蜀軍派馬謖駐守街亭,街亭失守導致全軍撤退。", "R": "街亭是北伐途中的關鍵戰役地點,蜀軍在此失敗后撤退。" } ], "A": "諸葛亮第一次北伐路線為漢中 → 祁山 → 街亭。街亭失守后,北伐失敗撤退。" }
Data Formatting
類似于一個多輪對話生成
Training
有監督
Inference
為了避免無休止的推理而無法生成答案采用Algorithm2,在到達一定迭代次數的時候獲取參數知識
Experiment
數據集:Natural Questions & 2WikiMultihopQA
推理過程:Qwen1.5-32B-Chat
重寫查詢:Llama-3-8B-Instruct
沒有Baseline,選取zero-shot模型的Naive RAG作為Baseline。對比結果見
“Table 1: Main results on six benchmarks. Auto-RAG consistently outperforms all baselines.” (Yu 等, 2024, p. 7)
Analysis
不同數量文檔和不同迭代次數上AutoRAG的表現。可以看出(a)(b)數據集是單跳數據集終止的輪數較快,而Hotpot問題終止的輪數叫慢,體現模型的自適應性很強。
如圖 4 所示,在每次迭代中提供不同數量的文檔對整體 QA 性能有一定的影響。在這三項任務中,每次迭代提供三個文檔會產生出色的結果,這表明為 Auto-RAG 提供適當大小的文檔是有益的。我們還將 AutoRAG 與無檢索方法 (Naive Gen) 和標準 RAG 進行了比較。Auto-RAG 在每次迭代的不同文檔計數上始終優于它們。值得注意的是,Auto-RAG 表現出比 Standard RAG 更小的性能波動,證明了其對獵犬的卓越穩健性。
消融實驗表明推理模塊確實有用,few-shot也要比zero-shot要好
數據規模越大越好,收斂也更快。
表現整體更好,檢索速度較慢,輪數也適中。
Conclusion
在本文中,我們介紹了 Auto-RAG,這是一種以 LLM 強大的決策能力為中心的自主迭代檢索模型。Auto-RAG 通過多輪對話與檢索器交互,系統地規劃檢索和優化查詢以獲取有價值的知識,直到獲得足夠的外部信息,此時結果將呈現給用戶。為此,我們開發了一種在迭代檢索中自主合成基于推理的決策指令的方法,并對最新的開源 LLM 進行了微調。分析結果表明,Auto-RAG 不僅取得了出色的性能,而且保留了高度的可解釋性,為用戶提供了更直觀的體驗。