一句話說明

Reranking 是在搜尋拿到一批初步結果之後,用一個更精準的模型重新打分和排序,讓最相關的結果排到最前面。

什麼是 Reranking?

你在知識庫裡搜尋「如何在 Docker 中設定環境變數」,語意搜尋 回傳了 20 篇相關文件。問題是,這 20 篇的排序不一定準確。排第一的可能是一篇講 Docker 整體概念的文章(語意相關但不夠具體),排第五的才是一篇手把手教你設定 ENV 的指南(真正回答你問題的)。

Reranking(重新排序)就是把這 20 篇文件拿出來,用一個更精準的模型逐一評估「這篇文件到底有多回答這個問題」,重新排序後再回傳。排序之後,那篇 ENV 設定指南就會跑到第一位。

為什麼初始搜尋的排序不夠準?因為語意搜尋用的 Embedding 模型是 Bi-Encoder 架構——查詢和文件各自獨立編碼成向量,然後比較向量距離。這個過程很快(可以從百萬筆資料中毫秒級找到結果),但「各自獨立編碼」意味著查詢和文件之間的細微關聯可能被忽略。

Reranking 用的是 Cross-Encoder 架構——把查詢和文件放在一起、同時輸入模型,讓模型看到兩者的交互關係後打分。精準度高很多,但速度慢很多。所以它只適合對初始搜尋回傳的少量候選文件做重新排序,而不適合從頭搜尋整個資料庫。

Bi-Encoder vs Cross-Encoder

理解 Reranking 的關鍵在於理解這兩種架構的差異:

Bi-Encoder(用於初始搜尋)

Bi-Encoder 把查詢和文件分開處理:

查詢 → Encoder → 查詢向量
文件 → Encoder → 文件向量
相似度 = cosine(查詢向量, 文件向量)

文件向量可以預先計算好,存在 向量資料庫 裡。搜尋時只需要把查詢轉成向量,然後在資料庫中做 ANN(近似最近鄰)搜尋。速度非常快,可以在數百萬筆資料中毫秒級完成搜尋。

缺點是查詢和文件的向量是獨立計算的,無法捕捉兩者之間的細微交互關係。

Cross-Encoder(用於 Reranking)

Cross-Encoder 把查詢和文件串在一起處理:

[查詢 + 文件] → Encoder → 相關性分數

模型可以同時看到查詢和文件的每一個詞,捕捉到詞與詞之間的交互關係。例如查詢是「Docker 環境變數」,文件裡寫「容器啟動時透過 -e 參數注入設定值」,Cross-Encoder 可以理解「-e 參數注入設定值」就是在講「Docker 環境變數」的設定方式,但 Bi-Encoder 的獨立編碼可能無法精確捕捉這個對應關係。

缺點是每一對(查詢, 文件)都要從頭算,沒辦法預先計算。如果有 100 萬筆文件,就要跑 100 萬次 Cross-Encoder,完全不實際。所以 Cross-Encoder 只適合對少量候選文件(通常 20-100 筆)做重新排序。

比較項目 Bi-Encoder Cross-Encoder
輸入方式 查詢和文件分開編碼 查詢和文件一起編碼
速度 快(毫秒級搜尋百萬筆) 慢(每對都要從頭算)
精準度 中等
用途 初始搜尋(檢索) 重新排序(精排)
是否可預計算 可以(文件向量存在資料庫) 不行

Reranking 在 RAG 中的角色

在一個典型的 RAG 管道中,Reranking 的位置是在搜尋和生成之間:

使用者查詢 → 初始搜尋(Bi-Encoder,取 top 20-50)→ Reranking(Cross-Encoder,精排 → 取 top 3-5)→ 送進 LLM 生成回答

為什麼不直接把初始搜尋的 top 5 送進 LLM?因為初始搜尋的排序可能不準確。如果你把排序不準的前 5 筆送進 LLM,其中可能有 2-3 筆不太相關,LLM 就可能被這些不相關的資料干擾,產生 幻覺 或給出不精確的回答。

Reranking 確保送進 LLM 的都是真正最相關的文件。對 RAG 的回答品質有顯著的提升。

常見的 Reranking 模型

Cohere Rerank

Cohere 提供的商業 Reranking API。支援多語言(包括中文)。使用方式很簡單,呼叫 API 把查詢和文件清單送進去,回傳重新排序的結果。

import cohere

co = cohere.ClientV2()

results = co.rerank(
    model="rerank-v3.5",
    query="Docker 環境變數設定",
    documents=[
        "Docker 是一個容器化平台...",
        "使用 -e 參數或 ENV 指令設定容器環境變數...",
        "Kubernetes 和 Docker 的差異..."
    ],
    top_n=2
)

for r in results.results:
    print(f"排名 {r.index}: 分數 {r.relevance_score:.4f}")

BGE-Reranker

BAAI(北京智源研究院)開源的 Reranking 模型系列。包括 bge-reranker-v2-m3(多語言)和 bge-reranker-v2-gemma(基於 Gemma)。可以在本地部署,不需要呼叫外部 API。

from FlagEmbedding import FlagReranker

reranker = FlagReranker("BAAI/bge-reranker-v2-m3", use_fp16=True)

scores = reranker.compute_score([
    ["Docker 環境變數設定", "使用 -e 參數或 ENV 指令設定容器環境變數"],
    ["Docker 環境變數設定", "Docker 是一個容器化平台"],
])

cross-encoder/ms-marco

基於 MS MARCO 資料集訓練的 Cross-Encoder 模型。Hugging Face 上有多個變體。主要針對英文優化,中文效果不如 BGE 系列。

Jina Reranker

Jina AI 提供的 Reranking 模型,支援多語言和超長文件(最長 8192 tokens)。有 API 服務也有開源版本。

選擇 Reranking 模型的考量

選模型時需要考慮幾個面向:

語言支援:如果你的資料是繁體中文或中英混合,選多語言模型。Cohere Rerank v3.5 和 BGE-Reranker-v2-m3 對中文的支援都不錯。建議用自己的中文資料實測比較。

部署方式:Cohere 和 Jina 提供雲端 API,用起來簡單但資料會送到外部伺服器。BGE 系列可以本地部署,適合有隱私考量的場景。

延遲要求:Cross-Encoder 的推論速度比 Bi-Encoder 慢得多。在 CPU 上處理 20 筆文件可能需要幾百毫秒到幾秒。如果有 GPU 可以快很多。在延遲敏感的場景,需要控制候選文件的數量(例如只取 top 10 來 rerank,而非 top 50)。

成本:雲端 API 按次計費。Cohere Rerank 目前的定價是每 1,000 次搜尋 $2.00(每次搜尋最多 100 筆文件,超過 500 tokens 的文件會被拆分,每個分段算一筆)。如果搜尋量很大,本地部署可能更划算。

實作範例

LangChain 中加入 Reranking:

from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma(embedding_function=embeddings, persist_directory="./db")

base_retriever = vectorstore.as_retriever(search_kwargs={"k": 20})

reranker = CohereRerank(model="rerank-v3.5", top_n=5)
retriever = ContextualCompressionRetriever(
    base_compressor=reranker,
    base_retriever=base_retriever
)

prompt = ChatPromptTemplate.from_template(
    "根據以下資料回答問題。\n資料:{context}\n問題:{question}"
)
llm = ChatOpenAI(model="gpt-4o-mini")

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
)

answer = chain.invoke("Docker 環境變數怎麼設定?")
print(answer.content)

這段程式碼的流程:先用 Bi-Encoder 搜尋取 top 20 → 用 Cohere Rerank 精排取 top 5 → 把 top 5 文件和問題送進 LLM 生成回答。

台灣使用情境

台灣企業在使用 Reranking 時有幾個特別的考量:

繁體中文效能:目前主流的 Reranking 模型對繁體中文的支援程度不一。Cohere Rerank v3.5 和 BGE-Reranker-v2-m3 都宣稱支援中文,但實際效果需要用自己的繁體中文資料測試。建議準備 20-30 組「查詢 + 正確答案」的測試集來評估。

中英混合文件:台灣的技術文件常常中英混用。Reranking 模型需要能理解「設定 container 的 env variable」和「Docker 環境變數設定」是在講同一件事。多語言模型在這方面表現比較好。

隱私考量:如果你的 RAG 系統處理的是機密文件(法規、財務、醫療紀錄),使用雲端的 Reranking API 意味著文件內容會被送到外部伺服器。建議在這類場景使用本地部署的 BGE 模型。

MIS 和工程師場景:企業的 IT helpdesk 知識庫通常包含大量的錯誤代碼、設定步驟和問題排查指南。Reranking 可以確保使用者搜尋特定問題時,精確的解決方案排在前面,而不是泛泛的概觀文章。搭配 Hybrid Search 效果更好。

安全考量與限制

使用 Reranking 需要注意的風險和限制:

延遲增加:Reranking 會增加搜尋的整體延遲。Cross-Encoder 的推論速度比 Bi-Encoder 慢 10-100 倍(取決於硬體和模型大小)。需要在搜尋品質和回應速度之間取捨。

資料外洩風險:使用雲端 Reranking API 時,文件內容會被送到外部伺服器。需要確認供應商的資料處理政策。

候選數量的平衡:送太少候選文件進 Reranking(例如只送 5 筆),可能會漏掉排名稍後但其實更相關的文件。送太多(例如 100 筆),延遲會大幅增加。通常 20-50 筆是比較好的平衡點。

模型偏見:Reranking 模型的訓練資料可能有偏見。例如訓練資料以英文為主的模型,在處理中文查詢時可能表現不佳。在重要的應用場景,建議用自己的資料做評估。

不是搜尋品質的唯一瓶頸:如果初始搜尋的召回率太低(相關文件根本沒有被搜出來),Reranking 再好也沒用,因為它只能重新排序已經搜到的文件,不能找到沒搜到的。確保初始搜尋的 Chunking 策略和 Embedding 品質是前提。

怎麼開始?

如果你正在建立或改善 RAG 系統,想加入 Reranking:

  1. 先建立評估基準:準備 20-30 組「查詢 + 正確答案」的測試集。記錄目前的搜尋品質(正確文件排第幾名)。

  2. 選一個 Reranking 模型:如果沒有隱私限制,先試 Cohere Rerank API(最簡單)。如果需要本地部署,用 BGE-Reranker-v2-m3。

  3. 決定候選數量:初始搜尋取 top 20,Reranking 後取 top 3-5 送進 LLM。

  4. 測量改善效果:用測試集比較加了 Reranking 前後的搜尋品質。通常會看到 MRR(Mean Reciprocal Rank)有 10-30% 的提升。

  5. 監控延遲:確認加了 Reranking 後的整體延遲在可接受範圍內。如果太慢,減少候選數量或考慮用 GPU。

  6. 搭配 Hybrid Search:Reranking 和 Hybrid Search 搭配使用效果最好。先用 Hybrid Search 取得多元的候選文件,再用 Reranking 精排。

知識檢測

讀完文章後,測試一下你對這個主題的理解。

常見問題

Reranking 和 Embedding 模型的效果差多少?

差距取決於你的資料和查詢類型。一般的經驗是,加了 Reranking 之後,Top-1 的準確率(正確答案排在第一位的比例)通常提升 10-30%。在查詢和文件措辭差異大的場景(例如查詢用口語、文件用正式語言),改善幅度更明顯。

可以用 LLM 做 Reranking 嗎?

可以。用 LLM(如 GPT-4 或 Claude)來判斷「這篇文件和這個查詢有多相關」也是一種做法,有時候被稱為 LLM-as-a-judge。優點是理解能力比 Cross-Encoder 更強。缺點是延遲更高、成本更高,而且受限於 Context Window 大小。適合精確度要求極高、延遲要求不高的場景。

Reranking 需要 GPU 嗎?

不是絕對需要,但強烈建議。Cross-Encoder 在 CPU 上跑 20 筆文件可能需要 1-3 秒,在 GPU 上通常可以壓到 100-300 毫秒。如果你的 RAG 系統需要即時回應,GPU 幾乎是必須的。如果延遲要求不高(例如批次處理),CPU 也能用。

Reranking 後取幾筆文件送進 LLM 比較好?

通常 3-5 筆。送太少可能遺漏有用的資訊。送太多會佔用 LLM 的 context window,增加成本和延遲,而且太多資訊可能反而讓 LLM 回答品質下降(所謂的「迷失在中間」問題——LLM 對排在中間的資訊注意力較低)。具體數量要根據你的文件長度和 LLM 的 context window 來決定。

參考資料