跳至主要内容

【AI】RAG 是什麼?搞懂檢索增強生成

為什麼需要 RAG?

平常個人在用 AI 應用時(ex: ChatGPT),大部分既有知識都能夠得到答案,這取決於 LLM 在訓練時所用的資料。不過如果問到沒有訓練過的內容,例如:公司內部文件、最新消息等等,通常就得不到甚麼有用的答案了,甚至有時候還會一本正經地亂回答,講得煞有其事,實際上根本是編出來的。

這是因為 LLM 的知識在訓練完之後就固定住了,不會再更新,而且也沒辦法即時去查詢這類私有、即時的資料。

想解決這個問題,直覺會想到兩種做法:

  • 把新資料重新拿去訓練模型(Fine-tuning
  • 每次都把整份文件塞進 Prompt 裡面一起問(Long Context

不過這兩種做法都有明顯的限制。重新訓練模型成本很高,而且資料一有更新就要重來一次;把整份文件塞進 Prompt,則會受限於 Token 數量上限,而且文件一多,成本跟延遲都會直接爆掉。

所以就有了 RAG 這個折衷的做法。

RAG 是什麼?

RAG(Retrieval-Augmented Generation)直翻的話是「檢索增強生成」,不過光看翻譯還是不知道是甚麼意思。

簡單來說,RAG 就是在 LLM 回答問題之前,先去外部的資料庫裡面把跟問題相關的資料找出來,再把這些資料一起塞給 LLM 當作參考,讓它根據這些資料來回答

也就是說,RAG 並不是在改模型本身,而是在「問問題」跟「模型回答」中間,多插了一個「找資料」的步驟。

補充

名字裡的三個字剛好對應三個動作:

  • Retrieval(檢索):先去資料庫找跟問題相關的資料
  • Augmented(增強):把找到的資料塞進 Prompt,補強 LLM 原本沒有的知識
  • Generation(生成):LLM 根據補強後的內容產生答案

RAG 的運作流程

整體流程大概可以拆成兩個階段,一個是「事前準備」,一個是「問答當下」。

階段一:建立知識庫(索引)

這階段是事先做好的,不是每次問問題才做:

  1. 收集文件:把公司內部文件、PDF、網頁等等原始資料收集起來
  2. 切割文件(Chunking):把長文件切成一小段一小段,方便之後檢索
  3. 向量化(Embedding):用 Embedding 模型把每個片段轉成一串數字(向量),這串數字可以代表這段文字的語意
  4. 存進向量資料庫:把這些向量存進 Vector Database(例如 PineconeMilvusChroma 這類的工具)
補充:Embedding 模型是什麼?

上面第 3 步提到的 Embedding 模型,就是專門負責把文字轉成向量的模型,簡單來說,就是把一段文字丟進去,吐出一串代表這段文字語意的數字。

那這個「向量化」實際上是怎麼做到的呢?現在主流的 Embedding 模型底層都是用 Transformer 架構,先把一段文字拆成一個一個的 Token,再透過裡面的 Self-Attention(自注意力)機制,讓每個 Token 去參考句子裡其他 Token 的資訊,最後整合成一串固定長度的向量。也因為有考慮到上下文,同一個詞在不同句子裡轉出來的向量也會不一樣,例如「蘋果」在「我吃了一顆蘋果」跟「蘋果發表新手機」這兩句裡,轉出來的向量就會差很多,這也是為什麼現在的 Embedding 比早期 Word2Vec 這種「一個詞固定一個向量」的做法準確更多。

常見的 Embedding 模型有:

  • OpenAI text-embedding-3:最多人用,直接呼叫 API 就好,不用自己架
  • Cohere Embed:支援多語言,品質也不錯
  • BGE-M3:開源、可以自己部署,多語言檢索能力算是開源裡數一數二強的
  • Voyage AI:主打針對 RAG 場景優化過

要選哪個,還是要看場景,簡單串接就用 OpenAI 或 Cohere 這類 API,想要自己掌控資料不外流,就會考慮 BGE-M3 這種開源自架的選項。

階段二:問答(檢索 + 生成)

這階段才是使用者實際問問題的時候:

  1. 使用者輸入問題
  2. 把問題也轉成向量
  3. 拿這個向量去向量資料庫裡面,找出語意最相近的幾個文件片段
  4. 把這些片段跟原本的問題一起組成 Prompt,送給 LLM
  5. LLM 根據這些補充資料生成答案

用文字可能有點抽象,來畫一下流程:

使用者問題


轉成向量 ──▶ 向量資料庫(比對相似度)
│ │
│ 找出相關文件片段
│ │
▼ ▼
組合成 Prompt(問題 + 相關資料)


LLM 生成答案

是不是比想像中單純很多?其實核心概念就是「先查資料,再回答」,跟我們自己寫報告的時候會先查資料再下筆的邏輯是一樣的。

Embedding 跟 Rerank 差在哪

前面的流程圖裡面,檢索的部分只用了 Embedding 去比對相似度,不過實務上光靠 Embedding 常常不夠準,所以還會多加一道 Rerank(重新排序)的步驟。

Embedding 是把文字轉成向量的過程,靠的是「語意相近的文字,向量的距離也會相近」這個特性。用 Embedding 去檢索的時候,是把使用者問題的向量,跟資料庫裡每個片段的向量一個一個算距離(例如 Cosine Similarity),取距離最近的前 N 筆回來。

不過這邊有個問題:Embedding 是獨立幫問題跟每個文件片段各自算一次向量,兩者在轉換的過程中完全沒有互相參考,所以距離近不代表真的相關,只是「語意上看起來像」而已。而且為了應付大量資料,Embedding 檢索通常會抓比較寬的候選範圍(例如先抓 Top 50),準確度自然就會打折扣。

Rerank 就是在 Embedding 檢索完之後,多加的一層精修。做法是把問題跟每一筆候選片段兩兩配對,一起丟進 Rerank 模型裡面重新評分,因為是兩兩一起看,模型可以真的判斷這段文字跟問題的關聯性,而不是只看向量距離,所以準確度會比單純 Embedding 高上不少。

雖然聽起來 Rerank 比較準,但這邊的準並不是沒有代價——因為要一筆一筆算,Rerank 沒辦法像 Embedding 一樣直接掃過全部資料庫,所以常見的做法是:先用 Embedding 從全部資料裡快速篩出一批候選(例如 Top 50),再用 Rerank 從候選裡精挑出真正相關的幾筆(例如 Top 5),兩個搭配起來用,兼顧速度跟準確度。

比較項目EmbeddingRerank
運作方式問題跟文件各自轉向量,比對距離問題跟文件兩兩配對,一起評分
速度快,可以先建好索引直接查慢,每次都要重新計算
準確度普通,只是語意上相近較高,能判斷真正的關聯性
適合場景從大量資料裡快速篩出候選從少量候選裡精挑最相關的結果
使用時機檢索的第一步檢索之後、送進 LLM 之前的第二步

所以完整一點的 RAG 檢索流程,其實是「Embedding 粗篩 → Rerank 精選 → 送進 LLM」,把 Rerank 塞在原本流程圖裡「找出相關文件片段」跟「組合成 Prompt」中間。

使用 RAG 要注意的地方

RAG 雖然可以減少「幻覺(Hallucination)」,但這邊的減少並不是完全消除。如果檢索到的資料不相關,或是切割文件的方式切得不好,LLM 還是有可能根據錯誤的參考資料生出不準確的答案。所以 Chunking 的策略、Embedding 模型的選擇,其實都會直接影響最後回答的品質喔。

而且檢索出來的內容也不是塞越多越好,還是會受限於 LLM 的 Context Window(上下文長度),所以怎麼挑出「最相關」而不是「全部塞進去」,也是實作 RAG 系統時要拿捏的地方。

總結

項目RAGFine-tuning
更新知識的方式更新資料庫即可,即時生效要重新訓練模型
成本較低(不用重訓模型)較高(要 GPU 訓練資源)
資料來源可追溯可以,能標出參考了哪些文件不行,知識已經融進模型參數裡
適合場景常變動的私有資料、需要引用來源想改變模型的語氣、行為模式
  • RAG 全名是 Retrieval-Augmented Generation(檢索增強生成),核心概念是「先查資料,再讓 LLM 回答」
  • 分成兩個階段:事先建立向量資料庫(索引),以及問答當下的檢索 + 生成
  • 檢索通常會搭配 Embedding 粗篩、Rerank 精選,兼顧速度跟準確度
  • 比起 Fine-tuning,RAG 更新知識的成本低、也能追溯回答的資料來源
  • 不過檢索品質會直接影響回答品質,Chunking 跟 Embedding 的選擇都要花心思調整

之後有機會再來紀錄實際串一個 RAG 系統的過程,有任何問題都歡迎在底下留言~

參考資料