RAG / 效能工程

先保持答案不變,再讓檢索更快

一次 lexical 倒排索引實測:在固定語料上逐片核對分數,把加速、品質變動與端到端效能分開判斷。

實作紀錄期間:2026-09-30

當 RAG 查詢變慢,很容易直接想到換模型、加快向量搜尋,或再加一層排序。但在一次效能分析中,我先處理的是既有 lexical 比對:保持原本的計分方式,把逐片掃描改成倒排索引。

這一輪的目標很單純:先證明計算結果沒有變,再討論速度是否值得採用。

先固定比較的條件

我從資料庫備份取出 16,843 個活動片段,以同一份固定語料執行 60 題比較。舊版與新版使用相同的查詢與計分規則,核對的是每一題、每一個片段的分數,並非只看最終前幾名。

倒排索引讓查詢可以先找到相關詞對應的片段,減少不必要的逐片比對。這次沒有把加速與新的排序策略綁在一起,因此較容易判斷結果變化從何而來。

量到了什麼

比較項目原版倒排版
lexical 中位數1,204.90 ms23.32 ms
lexical P951,304.10 ms32.29 ms
60 題逐片分數比較基準全數等價,差異 0

在這份固定語料與題集上,lexical 中位數約減少 98%。這個數字只描述 lexical 階段,不能寫成「完整 RAG 問答快了 98%」。

另一組凍結題集跑實際產品檢索流程,前後都是 48/60。它說明既有缺口仍在,也提醒我:加速成功與召回品質改善,需要分開報告。

有些變更,總分相同仍然不採用

同一輪也比較了較大的向量候選數與 IDF 排序調整。

  • 有效向量候選數從 40 增加到 80、120,題集結果都維持 48/60,因此保留較小的 40。
  • IDF 改變了 16 題的來源順序,其中一題改善、另一題退步,總分仍為 48/60。
  • 因為出現已知退化,IDF 保留為實驗功能,但正式設定關閉。

總分沒變,不代表原本能回答的問題都還答得出來。

逐題檢查的價值在這裡很明顯:平均數或總分可能把改善與退步抵銷,使用者遇到的卻是某一個具體問題。

加速也有成本與限制

這次倒排建表約需 2.40 秒。以 Python tracemalloc 量得索引配置約 346.53 MiB、建表峰值約 420.36 MiB;這不是整個服務的記憶體用量,也不包含所有原生配置。

正式環境另做了 34 題前後觀察,檢索中位數由 1,213 ms 降至 949 ms。不過期間索引仍在更新,前後版本不同,因此我把它列為現場觀察,不拿來當嚴格的同快照因果比較。

原始語料與逐題紀錄未公開。本文保留測試日期、樣本數、量測範圍與限制,數據代表該次實測,不能直接當成其他語料或硬體的效能預期。

下一步要重新看瓶頸

修正後的一筆限定範圍查詢中,lexical 已降到約 2 ms,主要時間轉到 embedding 與向量檢索。這時繼續優化 lexical,可能已不是最有價值的工作。

我會保留這個順序:固定資料與題目、確認結果等價、量測分段耗時、檢查逐題退化,再回到完整使用流程確認收益。

延伸閱讀:RAG 變快了多少?先說清楚量的是哪一段。