{"notes":[{"id":"retrieval-augmented-generation/rag","category":"retrieval-augmented-generation","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"RAG","subtitle":"怎麼是塊抹布？","author":"Z. Yuan","paperDate":"2020-05-22","publishedOn":"2026-05-17","world":"external/rag","paperTitle":"Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks","paperUrl":"https://arxiv.org/abs/2005.11401","bibliography":{"title":"Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks","authors":["Patrick Lewis","Ethan Perez","Aleksandra Piktus","Fabio Petroni","Vladimir Karpukhin","Naman Goyal","Heinrich Küttler","Mike Lewis","Wen-tau Yih","Tim Rocktäschel","Sebastian Riedel","Douwe Kiela"],"url":"https://arxiv.org/abs/2005.11401","pdfUrl":"https://arxiv.org/pdf/2005.11401v4","codeUrl":null,"preprint":{"id":"2005.11401","submittedOn":"2020-05-22","url":"https://arxiv.org/abs/2005.11401"},"publication":{"venue":"NeurIPS","year":2020,"kind":"conference","url":"https://proceedings.neurips.cc/paper/2020/hash/6b493230205f780e1bc26945df7481e5-Abstract.html"},"citation":"@misc{retrievalaugmentedgenerationrag2020,\n  title = {{Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks}},\n  author = {Patrick Lewis and Ethan Perez and Aleksandra Piktus and Fabio Petroni and Vladimir Karpukhin and Naman Goyal and Heinrich Küttler and Mike Lewis and Wen-tau Yih and Tim Rocktäschel and Sebastian Riedel and Douwe Kiela},\n  year = {2020},\n  eprint = {2005.11401},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2005.11401}\n}\n","citationPath":"/content/papers/citations/retrieval-augmented-generation/rag.85ab2502cd0c.bib"},"thumbnail":{"src":"/content/papers/assets/05c7bcd1d2c3f13c0726dfa7180e85f043b7cd64a0c61fa595b954d979a6550e.png","width":1122,"height":358},"locale":"zh-hant","path":"/content/papers/zh-hant/retrieval-augmented-generation/rag.cd7a66cb6bc1.md","headings":[{"id":"定義問題","text":"定義問題","depth":2},{"id":"解決問題","text":"解決問題","depth":2},{"id":"模型架構","text":"模型架構","depth":3},{"id":"外部記憶2100-萬段維基百科","text":"外部記憶：2,100 萬段維基百科","depth":3},{"id":"文件是一個機率變數","text":"文件是一個機率變數","depth":3},{"id":"沒有標註檢索器怎麼學","text":"沒有標註，檢索器怎麼學？","depth":3},{"id":"推論時怎麼解碼","text":"推論時怎麼解碼？","depth":3},{"id":"討論","text":"討論","depth":2},{"id":"開放域問答","text":"開放域問答","depth":3},{"id":"jeopardy-出題拼裝兩份文件","text":"Jeopardy 出題：拼裝兩份文件","depth":3},{"id":"學出來的檢索比較好嗎","text":"學出來的檢索，比較好嗎？","depth":3},{"id":"換一份索引知識就更新了","text":"換一份索引，知識就更新了","depth":3},{"id":"幾個沒那麼順利的地方","text":"幾個沒那麼順利的地方","depth":3},{"id":"結論","text":"結論","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[]}],"text":"這幾年只要聊到「讓語言模型讀公司文件」，十之八九會聽到 RAG 這個詞。\n\n這個名字的出處，就是這篇 2020 年的論文。\n\n不過 rag 這個英文單字，原意是抹布、破布。一個後來紅遍整個 AI 圈的技術，名字直譯過來就是「抹布」，實在讓人哭笑不得。\n\n第一作者 Patrick Lewis 後來在 [**NVIDIA 的訪談**](https://blogs.nvidia.com/blog/what-is-retrieval-augmented-generation/)裡，也為這個不太好聽的縮寫道歉：早知道會流傳這麼廣，他們一定會多花點心思取名字；原本也打算想個好聽的，只是寫論文時沒有人想到更好的。\n\n名字就這樣留了下來。\n\n但如果你是從 ChatGPT 之後才認識 RAG，讀這篇論文可能會有點意外。現在常說的 RAG，多半是「找幾段文字，貼進提示詞，交給大型語言模型回答」。這篇論文裡的 RAG，用的是 4 億參數的 BART，檢索器和生成器一起訓練，而檢索到的文件被當成一個**機率變數**來處理。\n\n這篇筆記，我們就回到這個名字最初指的東西。\n\n## 定義問題\n\n2020 年前後，預訓練語言模型已經被發現能在參數裡記住不少事實知識。像 T5 這樣的模型，不給任何參考資料，直接問它問題，也能答對一部分。\n\n這種做法叫做 **closed-book**，像是閉卷考試：知識全在腦袋裡。\n\n閉卷有幾個麻煩：\n\n1. **知識難以更新**。世界變了，模型參數裡的知識不會跟著變，只能重新訓練。\n2. **說不出依據**。模型答對了，你也不知道它是從哪裡學到的。\n3. **會一本正經地編造**。也就是後來大家常說的「幻覺」。\n\n另一條路是讓模型帶著外部資料應試，也就是 **open-book**。在這之前，REALM、ORQA 已經把可微分的檢索器接上遮罩語言模型，但只用在**抽取式問答**：答案必須是原文中的一段文字，模型負責把它框出來。\n\n作者想做的事更廣：\n\n- **能不能讓一般的生成模型（seq2seq）也帶著一份可檢索的外部記憶，而且用同一套方法微調到各種任務上？**\n\n還有一個條件讓這件事變得困難：訓練資料只有「問題」和「答案」，沒有人標註「該去找哪一份文件」。\n\n那檢索器要怎麼學？\n\n## 解決問題\n\n### 模型架構\n\n[![RAG 架構總覽：Query Encoder 把輸入編碼成 q(x)，以 MIPS 從 Document Index 找出 top-K 文件，再交給 Generator 並對文件邊際化](/content/papers/assets/05c7bcd1d2c3f13c0726dfa7180e85f043b7cd64a0c61fa595b954d979a6550e.png)](/content/papers/assets/05c7bcd1d2c3f13c0726dfa7180e85f043b7cd64a0c61fa595b954d979a6550e.png)\n\n*原論文 Figure 1，取自 [**v4 PDF 第 2 頁**](https://arxiv.org/pdf/2005.11401v4#page=2)。左側為三種任務的輸入，右側為對應輸出。*\n\n這張圖由左往右讀。\n\n最左邊是輸入 $x$，可以是一個問題（「定義中耳」）、一句待查核的陳述，或是 Jeopardy 出題用的答案詞（「神曲」）。\n\n綠色框是**檢索器** $p_\\eta$。Query Encoder 先把輸入轉成向量 $q(x)$；Document Index 裡存著每份文件預先算好的向量 $d(z)$。MIPS 從裡面挑出最相關的幾份文件 $z_1,\\dots,z_4$。\n\n藍色框是**生成器** $p_\\theta$，把輸入和每份文件分別串起來，產生答案。最後的「Marginalize」把多份文件的結果合成一個預測。\n\n圖頂那條虛線箭頭寫著「End-to-End Backprop through **q** and $p_\\theta$」：訓練時，梯度會一路傳回 Query Encoder 和生成器。注意，這裡沒有寫到 Document Index。這點等一下會再提。\n\n作者把這兩塊稱為兩種記憶：\n\n- **參數記憶（parametric memory）**：生成器的參數，也就是 BART 自己記住的知識。\n- **非參數記憶（non-parametric memory）**：外部的文件索引，可以直接替換。\n\n### 外部記憶：2,100 萬段維基百科\n\n外部知識只有一份：2018 年 12 月的英文維基百科。\n\n每篇條目切成不重疊的 100 字（word）段落，總共約 2,100 萬份「文件」。每份文件用文件編碼器算出向量，存進 FAISS 建好的索引裡。\n\n檢索器採用 [**DPR**](https://arxiv.org/abs/2004.04906)（Dense Passage Retriever）。它有兩個 BERT-base 編碼器，一個編問題、一個編文件，相關程度就是兩個向量的內積：\n\n$$\np_\\eta(z\\mid x)\\propto \\exp\\!\\left(d(z)^\\top q(x)\\right),\\quad d(z)=\\text{BERT}_d(z),\\ q(x)=\\text{BERT}_q(x)\n$$\n\n從 2,100 萬個向量裡找出內積最大的前 $K$ 個，就是 **MIPS**（Maximum Inner Product Search，最大內積搜尋）問題。\n\n\n> [!TIP]\n> \n> **2,100 萬個向量，每次都要全部算一遍嗎？**\n> \n> 不用。作者用 FAISS 搭配 HNSW（Hierarchical Navigable Small World）近似搜尋：先把向量組成多層的鄰近圖，查詢時沿著圖往目標靠近，不必和每個向量都算內積。代價是結果可能不是精確的前 $K$ 名，換來的是次線性的查詢時間。\n> \n> 附錄還提到，整份索引有 153 億個數值，可以用 8 位元精度存放，降低記憶體和硬碟用量。\n\n\n生成器用 BART-large，約 4 億參數。把輸入 $x$ 和文件 $z$ 接起來，交給它生成答案，做法就這麼簡單。\n\n### 文件是一個機率變數\n\n接下來是這篇論文最關鍵的部分。\n\n前面說過，訓練資料沒有標註「哪份文件才是對的」。作者的處理方式是：**不決定**。把檢索到的文件 $z$ 當成一個看不到的隱變數（latent variable），對可能的文件全部加權平均。\n\n檢索器給出每份文件的機率 $p_\\eta(z\\mid x)$；生成器在每份文件的條件下，給出答案的機率 $p_\\theta(y\\mid x,z)$。兩者相乘再加總，就是答案的機率。\n\n至於「怎麼加總」，作者給了兩個版本。\n\n**RAG-Sequence**：整個答案綁定同一份文件。先算每份文件條件下整句的機率，再對文件加權：\n\n$$\np_{\\text{RAG-Sequence}}(y\\mid x)\\approx\\sum_{z\\in\\text{top-}k}p_\\eta(z\\mid x)\\prod_{i}^{N}p_\\theta(y_i\\mid x,z,y_{1:i-1})\n$$\n\n**RAG-Token**：每個 token 都可以參考不同的文件。每一步先對文件加權，得到這個 token 的機率，再把所有 token 連乘：\n\n$$\np_{\\text{RAG-Token}}(y\\mid x)\\approx\\prod_{i}^{N}\\sum_{z\\in\\text{top-}k}p_\\eta(z\\mid x)\\,p_\\theta(y_i\\mid x,z,y_{1:i-1})\n$$\n\n兩條式子只差在 $\\sum$ 和 $\\prod$ 的順序。順序不同，結果差在哪裡？\n\n我們用一組小數字算一次。\n\n假設檢索器找到兩份文件，給 doc1 的機率是 0.6，doc2 是 0.4。答案有兩個 token：\n\n- 在 doc1 條件下，生成器給第 1 個 token 0.9、第 2 個 token 0.2。\n- 在 doc2 條件下，正好反過來：第 1 個 token 0.3、第 2 個 token 0.8。\n\n也就是說，答案前半段的資訊在 doc1，後半段的資訊在 doc2。\n\n```python\n# 檢索器給兩份文件的機率\np_z = {\"doc1\": 0.6, \"doc2\": 0.4}\n\n# 生成器在各文件條件下，產生兩個答案 token 的機率\np_y = {\n    \"doc1\": [0.9, 0.2],  # 第 1 個 token 很像 doc1 的內容，第 2 個不像\n    \"doc2\": [0.3, 0.8],  # 反過來\n}\n\n# RAG-Sequence：整句綁定同一份文件，再對文件加權\nseq = sum(p_z[z] * p_y[z][0] * p_y[z][1] for z in p_z)\n\n# RAG-Token：每個 token 各自對文件加權，再連乘\ntok = 1.0\nfor i in range(2):\n    tok *= sum(p_z[z] * p_y[z][i] for z in p_z)\n\nprint(f\"RAG-Sequence: {seq:.4f}\")\nprint(f\"RAG-Token:    {tok:.4f}\")\n\n# RAG-Sequence: 0.2040\n# RAG-Token:    0.2904\n```\n\nRAG-Sequence 要求同一份文件撐起整個答案：doc1 撐得起前半、撐不起後半，doc2 反之，兩邊都打折。\n\nRAG-Token 則是第 1 個 token 主要靠 doc1，第 2 個 token 主要靠 doc2，所以這個「拼裝」答案的機率比較高。\n\n這也是後面實驗裡，RAG-Token 在 Jeopardy 出題表現較好的原因，我們到討論時會看到實際的例子。\n\n\n> [!NOTE]\n> \n> **分類任務呢？**\n> \n> 若把分類標籤當成長度為 1 的答案，例如事實查核的「支持」、「反駁」、「資訊不足」，只有一個 token，$\\sum$ 和 $\\prod$ 的順序就沒差了，兩種 RAG 完全相同。\n\n\n### 沒有標註，檢索器怎麼學？\n\n訓練目標很單純：讓正確答案的邊際機率越大越好，也就是最小化 $-\\log p(y\\mid x)$。\n\n回頭看上面的式子。$p_\\eta(z\\mid x)$ 出現在加總裡，所以梯度會傳到它。如果某份文件讓生成器更容易產生正確答案，增加這份文件的機率，就能提高整體的邊際機率。訓練下來，檢索器就學會多給這類文件一點分數。\n\n沒有人告訴它哪份文件是對的，它從「哪份文件有幫上忙」學到了。\n\n不過，作者只更新**問題編碼器** $\\text{BERT}_q$ 和 BART，**文件編碼器和索引保持凍結**。\n\n原因很實際：文件編碼器一改，2,100 萬份文件的向量都要重算、索引要重建。REALM 在預訓練時會定期重建索引，作者發現不做這一步，成績也夠好。\n\n\n> [!TIP]\n> \n> **「端到端訓練檢索器」的常見誤解**\n> \n> 有些介紹會說 RAG 把檢索器端到端訓練了。精確地說，訓練時更新的是問題那一側；文件那一側從 DPR 初始化後就沒動過。而 DPR 本身已經用 Natural Questions 和 TriviaQA 的檢索標註訓練過，作者在結果段落也主動提醒了這一點。\n\n\n### 推論時怎麼解碼？\n\nRAG-Token 每一步都會算出下一個 token 的機率，可以直接套進一般的 beam search。\n\nRAG-Sequence 比較麻煩：整句的機率沒辦法拆成每個 token 的機率。作者的做法是對每份文件各跑一次 beam search，收集所有候選答案，再補算每個候選在其他文件下的機率，最後加權加總，稱為「Thorough Decoding」。\n\n候選一多，補算的前向計算會很可觀，所以另有一個近似版本「Fast Decoding」：某份文件的 beam 裡沒出現過的候選，就當作在那份文件下機率為 0，省掉補算。\n\n## 討論\n\n### 開放域問答\n\n作者在四個開放域問答資料集上測試：Natural Questions（NQ）、TriviaQA（TQA）、WebQuestions（WQ）與 CuratedTrec（CT），指標是答案完全相符的比例（Exact Match）。\n\n[![原論文 Table 1：閉卷的 T5、開卷的 REALM 與 DPR，以及 RAG-Token、RAG-Sequence 在 NQ、TQA、WQ、CT 的測試分數](/content/papers/assets/e4210dd8d6a0578d12df7e28472ad4aec7137a2aa87c895aad1e7044d0bfcdd6.png)](/content/papers/assets/e4210dd8d6a0578d12df7e28472ad4aec7137a2aa87c895aad1e7044d0bfcdd6.png)\n\n*原論文 Table 1，取自 [**v4 PDF 第 6 頁**](https://arxiv.org/pdf/2005.11401v4#page=6)。TQA 左欄為標準開放域測試集，右欄為 TQA-Wiki 測試集。*\n\n表分成三段。上面是閉卷的 T5，中間是開卷的 REALM 和 DPR，最下面是 RAG。\n\n在 NQ 上，RAG-Sequence 拿到 44.5，閉卷的 T5-11B 是 34.5。\n\n這個比較要看一下參數量。T5-11B 有 110 億個可訓練參數；RAG 全部加起來約 6.26 億（兩個 BERT-base 編碼器各 1.1 億，其中文件編碼器其實沒有訓練，加上 BART 的約 4 億）。附錄提到，參數量最接近的 T5-large（7.7 億）在 NQ 只有 28.9。\n\n另一個比較對象是 DPR 的問答系統，它還多用了一個 cross-encoder 重排序和抽取式閱讀器。RAG 不用這兩樣，NQ 還高出 3 分。\n\n生成式的答案還有一個抽取式做不到的好處：文件裡只有線索、沒有答案原文時，模型仍可能生成正確答案。在 NQ 上，正確答案不在任何檢索文件裡的題目，RAG 仍答對了 11.8%；抽取式模型在這種情況必然是 0%。\n\n### Jeopardy 出題：拼裝兩份文件\n\nJeopardy 是美國的益智節目，題目形式比較特別：給一個答案，要寫出對應的提示句。例如答案是「The World Cup」，提示可能是「1986 年，墨西哥成為第一個兩度主辦這項國際賽事的國家」。\n\n這種提示句常常把兩件事放在一起，正好可以檢驗 RAG-Token 的拼裝能力。下圖是輸入「Hemingway」、檢索五份文件時，每生成一個 token，模型認為是哪份文件在幫忙：\n\n[![RAG-Token 為輸入 Hemingway 生成 Jeopardy 題目時，各 token 對五份文件的後驗機率熱圖](/content/papers/assets/bc3d0fd74e0299ec9fc8eae15768959cef1e43472643f9449c1f7002164a42db.png)](/content/papers/assets/bc3d0fd74e0299ec9fc8eae15768959cef1e43472643f9449c1f7002164a42db.png)\n\n*原論文 Figure 2，取自 [**v4 PDF 第 7 頁**](https://arxiv.org/pdf/2005.11401v4#page=7)。橫軸為生成的 token，縱軸為五份檢索文件；顏色越深，後驗機率越高。*\n\n左邊列出兩份文件：Document 1 提到《戰地春夢》（A Farewell to Arms），Document 2 提到《太陽依舊升起》（The Sun Also Rises）。\n\n看右邊的熱圖。生成「Sun」的時候，Doc 2 那一列特別深；生成「A」、開始寫「A Farewell to Arms」的時候，換成 Doc 1 最深。\n\n這就是我們剛才手算的情況：一句話的前後段，分別由不同文件支撐。\n\n還有一個有趣的細節：書名的第一個 token 生出來之後，熱圖就變淡了。作者的解讀是，後面的字 BART 自己就會接。他們把「\"The Sun」單獨餵給沒有檢索的 BART，它真的接出了完整書名。作者說這是兩種記憶在合作：檢索到的文件把模型帶到對的方向，參數裡的知識負責把話說完。\n\n人工評估在 452 組 BART 與 RAG-Token 的出題中比較事實正確性：認為 BART 較正確的只有 7.1%，認為 RAG 較正確的有 42.7%（依原論文 Table 4）。\n\n### 學出來的檢索，比較好嗎？\n\n作者做了兩組消融：把檢索器凍結不訓練，以及直接換成 BM25 關鍵字檢索。\n\n以 NQ 開發集的 RAG-Sequence 為例（Table 6）：\n\n1. **換成 BM25**：31.8。\n2. **凍結檢索器**：41.2。\n3. **一起訓練**：44.0。\n\n學出來的檢索在問答任務上幫助很大。\n\n但 FEVER 事實查核是例外：BM25 的三分類準確率 75.1，略高於學習檢索的 74.5。作者推測，FEVER 的陳述大多圍繞特定實體，名字一對上就找得到，很適合關鍵字比對。\n\n### 換一份索引，知識就更新了\n\n這個實驗最能說明外部記憶的用處。\n\n作者另外用 2016 年 12 月的維基百科建了一份索引，再準備 82 位在 2016 到 2018 年間換人的世界領袖，用「Who is {position}?」問模型，例如「Who is the President of Peru?」。\n\n| 索引 | 問 2016 年的領袖 | 問 2018 年的領袖 |\n| --- | ---: | ---: |\n| 2016 年索引 | 70% | 4% |\n| 2018 年索引 | 12% | 68% |\n\n*整理自原論文 §4.5。*\n\n索引和問題的年份對上，大約七成答對；對不上，正確率就掉到個位數或一成出頭。\n\n模型參數一個都沒動，只換了外部記憶，答案就跟著換了。這正是閉卷模型做不到的事。\n\n### 幾個沒那麼順利的地方\n\n1. **檢索不是越多越好**。NQ 上，RAG-Sequence 的成績隨測試時取回的文件數增加而上升；RAG-Token 則在 10 份左右達到高峰。\n2. **檢索可能崩潰**。附錄提到，在故事生成等任務的初步實驗中，檢索器會學到不管輸入是什麼都回傳同一批文件；生成器接著學會忽略文件，整個模型退化成普通的 BART。作者推測，這類任務對事實知識的需求不明顯，或是答案太長，傳回檢索器的梯度不夠有用。\n3. **有些問題維基百科本來就答不了**。MS-MARCO 裡有「加州 Volcano 現在天氣如何？」這種題目。作者觀察到，模型對這類較難從檢索受益的問題，會固定取回某一組文件。\n\n## 結論\n\n這篇論文把一個預訓練的生成模型和一份可檢索的外部記憶接在一起，用同一套方法微調到問答、出題和事實查核上。\n\n它最有說服力的幾件事：\n\n1. **小模型加外部記憶，打贏大很多的閉卷模型**。NQ 上 6.26 億參數的 RAG-Sequence 拿到 44.5，110 億參數的 T5-11B 是 34.5。\n2. **不需要標註該找哪份文件**。把文件當成隱變數邊際化，檢索器就能從答案的機率學到該找什麼。\n3. **換索引就能更新知識**。2016 和 2018 年的索引互換，領袖問題的答案跟著改變，模型參數不用動。\n\n回頭看現在常說的 RAG，「先檢索、再把文件交給生成器」與「外部記憶可以替換」這兩個想法一路留了下來。另一半，也就是檢索器和生成器一起訓練、對文件做邊際化，在後來以提示詞拼接為主的大型語言模型應用裡就少見多了；模型大到難以微調，檢索器也常換成現成的 embedding 模型或搜尋引擎。\n\n這是後來的發展，不是這篇論文的主張。\n\n名字倒是一直沒換。\n","imageSizes":{"/content/papers/assets/05c7bcd1d2c3f13c0726dfa7180e85f043b7cd64a0c61fa595b954d979a6550e.png":{"width":1122,"height":358},"/content/papers/assets/e4210dd8d6a0578d12df7e28472ad4aec7137a2aa87c895aad1e7044d0bfcdd6.png":{"width":561,"height":375},"/content/papers/assets/bc3d0fd74e0299ec9fc8eae15768959cef1e43472643f9449c1f7002164a42db.png":{"width":1122,"height":210}}}
