計算 RRF 時,保留各份搜尋結果的名次,將每份文件的
1 / (常數 + 名次)加總後再排序;原本的檢索分數不直接相加。
Elastic 的 Reciprocal Rank Fusion(RRF)範例有五份文件,文字搜尋與向量搜尋各自回傳一份排名。RAG 的混合檢索會用 RRF 合併這樣的搜尋結果,下面用文件 ID 對照兩份名次:
| 文件 ID | 文字搜尋名次 | 向量搜尋名次 |
|---|---|---|
| 4 | 1 | 沒出現 |
| 3 | 2 | 1 |
| 2 | 3 | 2 |
| 1 | 4 | 3 |
| 5 | 沒出現 | 4 |
文件 4 在文字搜尋排第一,向量搜尋卻沒有它。範例裡,文件 4 沒有向量欄位,因此只出現在文字結果中。文件 2 則是兩邊都找到,文字排第三、向量排第二。兩份清單是分開排序的,文字的第三名只表示前面有兩份文件;向量的第二名也只描述向量結果中的順序。先保留這兩份名次,RRF 會用名次產生新的分數。
表格裡的「沒出現」也需要留著。文件 4 的向量名次不能填成第五名,或是直接接在已經找到的文件後面。向量搜尋並沒有回傳它,從那份結果就拿不到它的位置。合併時能使用的資料,是表格中已經有名次的那些欄位。
名次的加總
RRF 對每份文件計算:
RRF(d) = Σ [1 / (c + rank_L(d))], L: d ∈ L
L 是其中一份搜尋結果,名次從 1 起算;文件有出現在那份結果裡,才加上該項分數。這裡用 c 表示 RRF 的常數,Elastic API 的參數名稱是 rank_constant。官方範例把它設為 1,目前產品預設值則是 60。
套回文件 4,文字第一名提供的分數是 1 / (1 + 1) = 0.5。向量結果沒有文件 4,也就沒有第二筆分數,所以合併分數仍是 0.5。缺少向量不會讓文件從混合結果中消失,它還有文字搜尋找到的名次。
文件 2 的文字名次雖然較後面,卻有兩筆分數可以加總。文字第三名得到 1 / (1 + 3),向量第二名得到 1 / (1 + 2),加起來約 0.5833,比文件 4 的 0.5 高。因此文件 2 在合併後排到文件 4 前面。同份文件出現在兩邊,計算時會把兩筆分數都加進去,不需要選其中較高的那筆,也不會因為內容重複就只留第一次找到的名次。
不過,光是兩邊都有找到,並沒有保證一定排在前面。名次較後面的項目,代入公式後分母較大,對加總的貢獻就較小。文件 2 在這個例子裡得到的分數,來自表上的第三名與第二名;若名次改變,就得照改變後的位置重新計算。原始檢索分數沒有放進公式,只要各份清單內的順序不變,這次加總就不變。
再看文件 3,文字第二名加上向量第一名,得到約 0.8333。範例最後只回傳三份文件,順序是 3、2、4。
候選範圍
這個計算要先拿到各份搜尋結果。Elastic 用 rank_window_size 決定每份結果有多少候選參加 RRF,再用 size 決定最後回傳多少份文件。前者限制輸入清單,後者裁切合併後的清單。
如果各份候選結果只保留前兩名,文件 2 就只剩向量第二名,文字第三名被截掉了。計算時少了文字搜尋提供的那筆分數,合併結果也會改變。只調整最後回傳的文件數,不會補回已經截掉的名次。對照搜尋結果時,可以先看看文件在哪些輸入清單裡,再核對加總是否符合那些名次。
本文的數字來自 Elastic 的小範例,適合拿來核對 RRF 的計算;換成自己的文件後,哪些結果對提問有幫助,還是得搭配實際的問題與搜尋結果來看。
