【2026 最新】RAG 向量資料庫一定必要嗎?BM25、Embedding、Hybrid Search 準確率與成本實測

最後更新: ·
RAG 向量資料庫是否必要與 BM25、Embedding、Hybrid Search 實測教學首圖

做 RAG 向量資料庫選型時,最容易花冤枉錢的方式,就是先照著流行架構買齊 embedding、vector DB、hybrid search、reranker,最後才問:答案真的有變準嗎?這些元件每一個都有用,但它們解的是不同問題;堆得愈多,候選數、融合權重、門檻與延遲也愈多。

這篇不做產品排行榜。我們用同一份 SciFact 文件集、同一組 300 個查詢與同一份 relevance qrels,重跑 BM25、exact embedding、RRF hybrid search,以及 hybrid+reranker;再把檢索命中率、索引時間、儲存量與 warm latency 分開。你不必有搜尋背景,也能照著方法替自己的知識庫做一次可重現選型。

先記住這條式子:可用的 RAG = 候選覆蓋率 × 排序品質 × Reader 使用證據的能力。白話說就是:先找得到,再排得對,最後才答得好。任一項接近零,另外兩項再漂亮都救不了。

先說結論:RAG 一定要向量資料庫嗎?不一定

  • 查詢常帶產品名、錯誤碼、法條、料號:先做 BM25 baseline。它便宜、可解釋,精確字詞常是優勢。
  • 使用者會大量改寫、用同義詞或自然問句:加一條 embedding 檢索;小型 corpus 可以先做 exact cosine search,不必立刻買託管向量資料庫。
  • BM25 與 dense 各自找到不同正解:才測 hybrid search。RRF 是好起點,不是免調參的保證書。
  • Recall@50 已高,但前五名仍排錯:才有理由測 reranker。若正解根本沒進候選池,重排模型也變不出來。
  • 需要大量 metadata filter、持續更新、備援、水平擴展與權限治理:這才是 vector database 的營運價值;它和「要不要用 embedding」不是同一題。

真正的答案不是 BM25 或 embedding 二選一,而是先用最小系統建立可重跑的測試,再讓失敗案例決定下一個元件。這和AI 模型評測的原則一樣:先有 golden set,才談架構。

BM25、Embedding 與 Hybrid Search 的檢索原理和優缺點比較圖
BM25 追蹤字詞,embedding 追蹤語意,hybrid 融合兩份排名;三者都有不同的失敗模式。

BM25、Embedding、Hybrid Search 到底差在哪?

BM25:像書後索引,先找「字有沒有出現」

BM25 是 lexical retrieval(字詞檢索)。它不只數某個詞出現幾次,還會看這個詞在整個 corpus 是否稀有、文件是否異常長,並讓重複詞的加分逐漸飽和。像 E1047RFC 9110、股票代號或完整人名,通常都是它容易抓住的「文字指紋」。Lucene 的 BM25Similarity 文件也把詞頻飽和與長度正規化的參數分開說明。

BM25 不是跨引擎完全相同的 raw score。Lucene 10.3.2 預設 k1=1.2b=0.75;本次 rank-bm25 則固定 k1=1.5b=0.75epsilon=0.25,對負 IDF 做 floor。分數只應在同一實作內排序,不要跨引擎直接比大小。

它的弱點也很直接:使用者問「帳號進不去」,文件只寫「登入失敗」,若 tokenizer、斷詞、同義詞與語言分析器沒有處理好,完全相同的意思仍可能對不上。中文不是不能用 BM25,而是不能把英文的空白切詞原封不動搬過來。

Embedding:把意思變成座標,但不等於向量資料庫

Embedding 模型把 query 與文件各自壓成一串數字,再用 cosine 或 dot product 找距離相近的向量。它像把「登入不了」「無法驗證身分」與「sign-in failed」放在語意地圖的鄰近街區,因此比純字詞檢索更能處理改寫。想先理解模型為何能學到這種表示,可以接著讀AI 模型怎麼學習

但 dense retrieval 不是「一定要買 vector DB」的同義詞。Sentence Transformers 官方範例可以直接把 corpus embeddings 放在記憶體做 exact semantic search;pgvector則能在既有 PostgreSQL 內做 exact 或 HNSW/IVFFlat 近似檢索。FAISS 官方定位是 dense-vector similarity search/clustering 函式庫;帳號、HA 與 metadata persistence 要由其他系統提供。

本次 Hybrid 用 RRF 融合名次;校準後也能融合分數

BM25 分數與 cosine 分數沒有共同刻度,直接相加很容易讓某一邊因數值範圍而壓過另一邊。常見做法 RRF(Reciprocal Rank Fusion)只看文件在每份清單的名次:score(d) = Σ 1 / (k + rank(d))RRF 原始論文讓它成為簡單的 baseline;但後續融合研究也發現 RRF 對參數敏感,經 validation 調整的加權融合在該實驗經常更好。

把兩名偵探的名單合併,確實可能多找到線索;也可能把兩邊的誤判一起帶進來。這可能是 hybrid search 有時反而變差的原因之一,而不是系統一定壞掉。

RAG 向量資料庫不是一個元件:先拆成四層

  1. 表示法:文字 token、sparse weights 或 dense embedding,決定系統用什麼訊號找相似。
  2. 檢索演算法:BM25、exact cosine、ANN 或 learned sparse,決定怎麼產生候選。
  3. 索引:倒排索引、Flat、HNSW、IVF,決定搜尋速度、記憶體與是否犧牲 recall。
  4. 資料庫/服務:負責持久化、filter、更新、權限、備援與擴展,解的是營運問題。

所以「RAG 要不要向量資料庫」應改問兩次:我的 query 是否需要語意訊號?我的規模與 SLO 是否需要專門的向量服務?個人筆記或小型團隊知識庫,可能用 PostgreSQL、SQLite 加本機向量,甚至記憶體陣列就夠;跨區服務、億級 chunk、高更新率與複雜 filter,才會把營運能力推到前景。若你正在做個人知識管理,Obsidian+QMD 記憶系統就是先從可控 corpus 出發的另一個例子。

同資料集實測:我們怎麼避免「為了贏而調參」

本次使用 AllenAI SciFactBEIR 打包的 test split:5,183 篇科學摘要、300 個 claim query 與 339 筆 cited-source relevance qrels,沒有抽樣。這 300 題對應原 SciFact 公開 dev claims;BEIR qrels 是題目引用的來源摘要,不等同原資料的逐句 evidence rationale。每題都有至少一筆 qrel,因此這次也無法測 no-answer/拒答。SciFact 很小、英文、以科學主張為主,不能代表中文客服、程式碼或企業文件。

  • 共同 chunks:用 pinned MiniLM tokenizer 把 title+abstract 切成 220 wordpieces、overlap 40,共 11,139 chunks;decode 一次後,三種方法都讀完全相同的字串。Dense 最長 226/256 tokens,reranker pair 最長 288/512,實測零截斷。
  • BM25:rank-bm25 固定 k1=1.5b=0.75epsilon=0.25;小寫 Unicode word tokenizer,不做 stemming、stopword 或同義詞調校。各文件取最高 chunk score,再去重成 doc ranking。
  • Dense:sentence-transformers/all-MiniLM-L6-v2,revision 1110a243fdf4706b3f48f1d95db1a4f5529b4d41;384 維、正規化向量,對所有 chunks 做 exact cosine,不使用 ANN,再以最高 chunk score 排文件。
  • Hybrid:BM25 與 dense 的 doc ranking 各取前 1,000 名,以 RRF k=60 融合;沒有用 test set 找最佳權重。
  • Hybrid+reranker:cross-encoder/ms-marco-MiniLM-L6-v2,revision c5ee24cb16019beea0893ab7796b1df96625c6b8;每篇候選先用 chunk-level RRF 選一段,再重排 hybrid 前 50 篇,其餘順序保留。

共同 chunks 排除了「BM25 讀全文、短上下文 dense 被截斷」的不公平,但也不是完美中立:chunk 邊界與 decoded 文字由 MiniLM tokenizer 定義,會小寫化/正規化,並非原摘要的 byte-identical 文字,天然偏向這個 pipeline 設計。因此以下只能解讀成這組模型、共同表示與參數的結果,不是四個方法家族的永久排名。

品質報 Recall@5(前五名涵蓋多少 qrels 相關摘要)、MRR@10(第一篇相關摘要排多前面)與 nDCG@10(多篇相關摘要的前段排序)。成本報 index build time、序列化 artifact 大小,以及模型和索引已載入後的 warm p50/p95 latency。環境為 Mac mini、Apple M4、16 GB RAM、macOS 26.1,固定 4 個 Torch threads;這是單機 CPU 工程快照,不是雲端報價或跨硬體排行榜。

SciFact shared chunks 上 BM25、Embedding、Hybrid Search 和 reranker 的檢索準確率實測圖
5,183 篇文件切成 11,139 個共同 chunks;qrels 是 cited abstracts,不是 SUPPORT/REFUTE evidence 或回答正確率。

結果一:Reranker 點估計最高,但 Hybrid 不是每個指標都贏

在共同 chunks 下,Hybrid RRF 相對 BM25 的 nDCG@10 從 0.6386 升至 0.6889。以 10,000 次 query-paired bootstrap 檢查,差為 +0.0503,95% CI [0.0266, 0.0746];Recall@5 差 +0.0402,CI [0.0075, 0.0738],兩者都排除零。不過 exact dense 的 Recall@10 是 0.8257,反而高於 hybrid 的 0.8111;hybrid 只是在 R@5、R@100、MRR 與 nDCG 高於兩條單路。

加入 cross-encoder 後,R@5、R@10、MRR 與 nDCG 點估計都最高:nDCG@10 為 0.7137,R@5 為 0.7893。相對 hybrid 的 R@5 差 +0.0386,95% CI [0.0032, 0.0753];但 nDCG 差 +0.0248,CI [−0.0038, 0.0542] 仍跨過零。因此這次較支持 R@5 改善,還不足以宣稱 reranker 能穩定改善所有排序指標,更不能外推成「reranker 必勝」。

結果二:回答正確率不能從 Recall 直接推導

這次本機重跑刻意停在 retrieval layer,沒有另換一個生成模型後把它的偏差混進來,因此不會把「BEIR qrel 的 cited abstract 有進 top-5」改名叫回答正確率。要看固定 reader 的端到端結果,可交叉參考使用 T²-RAGBench 的 2026 年 4 月預印本:它在同一研究設定裡報告 Recall@5 點估計為 BM25 0.644、dense 0.587、hybrid 0.695;GPT-4.1-mini 的 number-match 則是 0.251、0.257、0.282。BM25 的 retrieval recall 較高,答案指標仍略低於 dense。

這不是替 hybrid 頒獎:那份資料是財報長文件與數值問題,結果不能直接搬到你的 chunks。它提醒我們檢索評測與回答評測必須拆開。你還要固定 prompt、context token budget、reader model、temperature,另測答案 exact match/F1、引用正確性與該拒答時能否拒答。這也是Context Engineering比「把更多文件塞進 prompt」更重要的地方。

成本實測:免費套件不等於零成本

BM25、Embedding、Hybrid Search 與 reranker 的索引時間、儲存量和查詢延遲比較圖
本機模型沒有逐次 API 費,仍要計入建索引、儲存、CPU/GPU、重建頻率與維運時間。

在 Apple M4、4 threads、模型 cache 已暖的這次執行裡,共同 chunks 建立與驗證花 4.03 秒,BM25 chunk index 花 0.36 秒,dense 編碼 11,139 chunks 花 83.02 秒;模型載入與首次下載另計。含一份 10.88 MB shared manifest 的 operational artifacts,BM25、dense、hybrid 分別為 20.91、27.99、38.02 MB。BM25 是未最佳化的 Python pickle,不能拿來推論 production 倒排索引一定和向量一樣大。

Warm latency 以 seed 20260801 固定抽 50 題,單次 warm-up 後 sequential 執行;p50 是 BM25 24.59 ms、exact dense 11.80 ms、hybrid 36.14 ms,加入 top-50 reranker 後為 474.77 ms,約是 hybrid 的 13 倍。這只代表這套 Python/NumPy 實作與這台 CPU,不代表 dense 普遍比 BM25 快。模型權重、Python environment、原文、RAM overhead、電力與工程時間都不在 artifact 數字內。

  • 一次性建置:清洗、chunking、BM25 統計或 corpus embedding;模型換版與 chunk 規則改動時要重做。
  • 儲存:文字、metadata、向量欄位、ANN index、WAL 與備份要分列。只算 dimensions × 4 bytes 不是整個資料庫大小。
  • 每次查詢:tokenize、query embedding、ANN/exact search、融合、reranker 與 reader 推論各有延遲。
  • 營運:更新一致性、可觀測性、權限、備援、擴展與工程維護,通常才是託管 vector DB 真正收費的部分。

若你用本機 embedding,直接 API 帳單可以是 0,但硬體、電力與等待時間不是 0。若你用 API,請把「首次 embedding 全 corpus」「每天新增量」「query embedding」分開估算,再加 storage 與 rerank;不要把所有費用統稱成向量資料庫成本。想估本機模型的硬體代價,可搭配LLM 推論引擎選型一起看。

核心實作示意:先跑 BM25、Dense,再加 RRF

先準備三份固定資料:documentsqueriesqrels。一個 query 可以對應多篇正解;另放 no-answer 題,避免系統學會「每題都硬找一篇」。接著在隔離環境安裝:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install \
  rank-bm25==0.2.2 sentence-transformers==5.1.2 \
  numpy==2.0.2 torch==2.8.0 transformers==4.57.6

以下只示意核心 API,不會直接重現上圖;正式 benchmark 還要加入共同 chunking、doc-level 去重、stable tie-break、完整 metrics 與 latency harness,production 則要再補 batching、持久化與錯誤處理:

from rank_bm25 import BM25Okapi
from sentence_transformers import SentenceTransformer
import numpy as np
import re

TOKEN_RE = re.compile(r"(?u)\b\w+\b")
tokens = lambda s: TOKEN_RE.findall(s.lower())  # 中文請換斷詞器
bm25 = BM25Okapi(
    [tokens(doc) for doc in documents], k1=1.5, b=0.75, epsilon=0.25
)

DENSE_REV = "1110a243fdf4706b3f48f1d95db1a4f5529b4d41"
model = SentenceTransformer(
    "sentence-transformers/all-MiniLM-L6-v2", revision=DENSE_REV
)
doc_vecs = model.encode(documents, normalize_embeddings=True)

def retrieve(query, depth=1000):
    bm_rank = np.argsort(
        -bm25.get_scores(tokens(query)), kind="stable"
    )[:depth]
    q_vec = model.encode([query], normalize_embeddings=True)[0]
    de_rank = np.argsort(-(doc_vecs @ q_vec), kind="stable")[:depth]
    return bm_rank, de_rank

RRF 只需融合名次,不碰兩種 raw score:

def rrf(*rankings, k=60):
    score, best_rank = {}, {}
    for ranking in rankings:
        for rank, doc_id in enumerate(ranking, 1):
            score[doc_id] = score.get(doc_id, 0) + 1 / (k + rank)
            best_rank[doc_id] = min(rank, best_rank.get(doc_id, rank))
    return sorted(score, key=lambda d: (-score[d], best_rank[d], d))

切成 train/validation/test:只用 validation 調 k1b、RRF k、融合權重與 rerank depth,最後一次才打開 test。再把 query 分成「精確代號」「同義改寫」「多跳/完整性」「無答案」四桶;總平均不變,某一類使用者仍可能已經被你弄壞。

什麼時候該加 reranker?先看候選上限

Reranker 像決賽評審:cross-encoder 同時閱讀 query 與每篇候選,通常比單看兩個向量的距離更細,但不能替沒進決賽的人補報名。Sentence Transformers 的訓練指南也示範:候選從 top-100 加到 top-200 不必然變好;candidate depth 與訓練資料都要驗證。本次 reranker 以 MS MARCO 訓練、zero-shot 用於 SciFact,結果不代表所有 reranker。

  • 該測:第一階段 Recall@50/100 已高,MRR 或 top-5 precision 仍低;答案只容得下少量 chunks;額外延遲在 SLO 內。
  • 先別加:正解經常不在候選池;gold label 只有一個但其實多個答案都有效;query 與文件語言/領域超出 reranker 訓練分布。
  • 一定要做:同時報「加了多少品質」與「增加多少 p95 latency」,並固定 candidate depth。只報平均準確率會藏掉最慢的使用者。

一個近期 r/Rag 案例中,作者在 69 個 answerable queries 上自報 vector hit@3 為 74%,加入 hybrid 後反降到 55%;作者診斷 ticker 出現在使用者問句,卻不在標準答案模板,BM25 因而拉進錯誤候選。這是很好的除錯故事,不是可外推的 benchmark:資料只有約 250 組 Q&A,單一正解 ID 也曾把其他有效答案算成錯誤。

最新研究怎麼看:BM25 會在規模變大後勝出嗎?

2026 年 7 月更新的預印本 BM25 Wins at Scale,在一個含 511,959 份文件、約 6 億 tokens 的合成企業 corpus 裡,觀察到 BM25 隨規模增加後比固定的 dense 設定更穩。它的重要提醒是:精確名稱、識別碼與「語意很像但事實錯」的誘餌一多,lexical anchor 會重新變重要。

但這篇不是「BM25 永遠贏」的證明。它只測一個 dense model、一個 reader、英文合成公司與 top-5,沒有完整比較 hybrid+reranker。論文所稱約 1,000 萬 tokens 的交叉,是 BM25 相對 raw file-system agent 的點估計交叉,不是 BM25 相對 dense,更不是採用向量資料庫的門檻。更早的 BEIR 跨領域 benchmark在當時評測的十個系統裡,把 BM25 視為 robust baseline;reranking 與 late interaction 平均較好,但計算成本也更高。

RAG 向量資料庫選型決策表:讓失敗案例帶路

依查詢型態、候選召回率與 corpus 規模選擇 BM25、Embedding、Hybrid Search 和 reranker 的決策樹
先依查詢訊號選 retriever,再依實測 latency 決定 exact 或 ANN;vector DB 是最後的營運選擇。

小 corpus 的定義不是固定文件數,而是「exact search 能否放進你的記憶體並達成 p95 SLO」。能達成,就先避免 ANN 的近似誤差與額外複雜度;達不成,再測 HNSW/IVF 的速度與 recall 損失。截至 PostgreSQL 18 core FTS 文件,ts_rank 主要看 matching lexeme frequency,ts_rank_cd 才額外納入 proximity;官方文件明示兩者都不使用全 corpus 的 global information,因此不能直接稱為 BM25。它若已通過你的 test set,就沒有為名詞純度換引擎的必要;要在 PostgreSQL 內做 BM25,可用 extension 或自訂 ranking。

常見問題 FAQ

1. RAG 一定要向量資料庫嗎?

不一定。RAG 需要的是能找出證據的檢索層;BM25、PostgreSQL FTS、記憶體 exact vector search、pgvector 或專用 vector DB 都可能完成。選擇取決於 query 與營運需求。

2. 用 embedding 就一定要 vector DB 嗎?

不用。小型 corpus 可以把向量放在 NumPy/記憶體做 exact search,也能放進 pgvector;專用資料庫是在規模、更新、filter、備援與治理需求增加時才更有價值。

3. PostgreSQL 原生全文檢索就是 BM25 嗎?

不是。ts_rankts_rank_cd 沒有使用 BM25 所需的全 corpus global information。它們仍可能足夠好;要 PostgreSQL 內的 BM25,需另看對應 extension 並重新驗證。

4. Hybrid Search 一定比單一路徑準嗎?

不一定。兩邊若能召回互補的正解,融合才可能增加覆蓋率;其中一路噪音很高時,融合也會把壞候選推進 top-k。用每題 paired 結果,而不只看總平均。

5. Reranker 什麼時候最值得加?

當高深度 recall 已好、前段排序仍差時。先確認正解常在 top-50/100,再看重排後的 top-5 與 p95 latency;否則應先修第一階段 retrieval。

6. 中文 RAG 適合 BM25 嗎?

可以,但斷詞是核心變因。要用適合繁簡中文、領域詞與代碼的 tokenizer,並在真實 query 上測同義詞、混合中英、錯別字和專有名詞;英文 benchmark 不能替你回答。

7. Recall@5 很高,就代表回答一定正確嗎?

不代表。Reader 可能忽略證據、被錯誤 chunk 誘導或算錯;請固定 reader 與 prompt,另測答案、引用與拒答。Retrieval 是必要條件,不是充分條件。

8. 新手的第一版應該怎麼做?

先做 BM25+exact dense 兩條 baseline。準備 50–200 個真實 query、允許多個正解、加入 no-answer 題;比較失敗桶後,再決定要不要 fusion、ANN、reranker 或 vector DB。

給新手的 5 個重點

  1. RAG 的核心是可靠地取回證據,不是擁有某種資料庫。
  2. BM25、embedding 與 hybrid 解不同查詢;先分桶看失敗,不找通用冠軍。
  3. 先測 exact dense,達不到 latency SLO 才加入 ANN,避免一開始就混入近似誤差。
  4. Recall、排序、回答與成本要分層報;不要用一個「準確率」藏起整條 pipeline。
  5. 新增元件要通過同一份 test set;沒有可量化增益,就把它拿掉。

延伸閱讀:把檢索接進真正可維護的 AI 系統

結語:先刪掉架構圖,打開你的查詢紀錄

RAG 向量資料庫不是入場券,BM25 也不是復古替代品。它們只是證據管線中的不同工具。回到那條式子:先找得到,再排得對,最後才答得好。今天就從真實紀錄挑 50 題,標出多個可接受證據與 no-answer,跑 BM25 和 exact dense;只有當失敗案例告訴你「兩邊互補」或「候選有了但排序不對」,才加入 hybrid 或 reranker。你會得到一套更便宜,也更知道為什麼準的 RAG。

ALPHALAB 社群

有問題?來 Telegram 聊

和 Terry、編輯、其他網友一起討論這篇文章。提問、分享觀點,回覆更即時。

加入 Telegram 討論

📩 訂閱 AlphaLab 電子報

每週一封,第一時間收到新文章與投資觀察。

我們不會 spam,隨時可退訂。