一、先把架構擺對:兩段式檢索
重排序不是獨立的檢索方案,它是檢索管線的第二級。1
召回(Recall)
用向量檢索或 BM25 從全量文件裡撈出候選集。這一步要快、要寧濫勿缺,
目標是”正確答案在這批裡”,而不是”正確答案排第一”。
2
精排(Rerank)
把候選集連同 query 一起送進
bge-reranker-v2-m3,逐條打分重排。
這一步要準,目標是把正確答案頂到最前面。3
截斷並送進大模型
取重排後的 Top-3 到 Top-5 拼進 prompt。
這一步決定了最終答案品質——送進去的越準,大模型幻覺越少、上下文成本越低。
為什麼不能跳過召回直接精排:重排序是交叉編碼器,必須拿到 query 才能算分,無法離線預計算。
百萬篇文件逐條打分,成本和延遲都不可接受。召回負責把規模從百萬降到百,精排負責把百排準。
完整可執行示例
下面這段程式碼就是一個最小但完整的兩段式檢索,向量召回用text-embedding-3-small,
精排用 bge-reranker-v2-m3,兩個模型同一個 API易 令牌:
二、召回多少條送進精排?
實測延遲(短文件,每檔 5 次取 P50):
關鍵在於存在約 2 秒的固定開銷:只送 1 篇也要 2 秒。所以候選從 1 加到 100,延遲只多 1.8 秒,
而檢索品質的提升遠大於這 1.8 秒的代價。
真正決定延遲的是 token 總量,不是文件條數。 同樣 50 條候選:
條數相同、延遲差 4.7 倍。這也是下一節「切塊」不會拖慢檢索的原因——
切塊只增加條數,不增加總 token 量。
如果確實要排大量文件(比如離線批處理),拆成多個 ≤100 條的請求,併發控制在 4 以內。
注意拆分不會降低 token 總量,TPM 20,000 依然是總閘門——離線批處理要按分鐘節流。
該配額正在擴容中,有大批次需求可先聯絡 API易客服確認可用額度。
三、長文件必須切塊
這是收益最大的一步預處理。實測資料說明了兩件事: 其一,無關內容會稀釋相關性。 同一句命中內容,後面接不同長度的無關填充:
其二,長文件會抬高噪聲得分。 同一篇不相關文件,短版得分 0.029,接上 450 字無關內容後
漲到 0.121——翻了 4 倍。長噪聲文件更容易擠進 Top-N。
兩者疊加的後果:一篇把答案寫在文末的長文件,會輸給一篇通篇跑題的長文件。
四、閾值怎麼定(別拍腦袋設 0.5)
relevance_score 經 sigmoid 對映到 0–1 區間,看起來很像一個置信度。它不是。
實測跨全部品質用例的得分分佈:
一個 0.5 的固定閾值會:濾掉全部跨語言正確結果、濾掉多數非中文場景的第二名,
同時放行那篇關鍵詞高度重合的干擾文件
(查詢”蘋果公司 2024 財年營業收入”,一篇講蘋果種植收購價的文件拿到了 0.945,排第三)。
注意最後一行:不相關文件的最高分(0.945)高於相關文件的最低分(0.289)。
兩個分佈是重疊的——這從根本上決定了不存在一個”安全”的絕對閾值。
五、否定語義要額外兜底
這是模型的明確弱項。查詢”哪些景點適合冬天去?“,兩篇明確說不適合冬天的文件排到了第 2、第 3, 把真正相關的擠到第 4、第 5,nDCG@3 只有 0.47。 模型匹配的是”冬天 + 景點 + 旅遊”這個話題,沒有理解那個”不”字。 兜底做法:重排序後加一道輕量大模型判斷。用便宜的小模型即可,成本可控:六、多語言與跨語言
實測中 / 英 / 日 / 韓 / 俄 / 法 / 阿拉伯語,以及中↔英跨語言檢索,排序全部正確。 單一模型就能覆蓋多語言知識庫,不需要按語言分別部署。 但要注意分數量級差異:
跨語言場景下正確答案的絕對分低 1–2 個數量級,但排序依然正確。
七、併發、快取與冪等
先算配額預算,再談併發
上游(華為雲 MaaS)給本模型的配額是 TPM 20,000 / RPM 120。 這是接入這個模型時最容易低估的約束——同平臺 BGE-M3 向量化模型是 1,200,000 TPM,差 60 倍。 實測(每組前靜默 70 秒讓配額視窗歸零)分離出兩個互相獨立的機制:
結論一:併發槽位約 4–5 個在途請求。 R1/R2 的 token 消耗只佔 3–4% TPM 卻大面積失敗,
且併發從 10 提到 20 後成功數仍停在 4–5;而 R5 序列 20 次全過。超出槽位的請求直接 429、不排隊。
結論二:TPM 20,000 獨立生效,與併發無關。 R4 完全序列,第 8 個請求在累計 16,093 tokens 時
開始 429,連掛 9 個後窗口滑動恢復:
每分鐘能跑多少次檢索
按實測≈26.9 tokens/文件 折算:
候選數的選擇同時是品質決策和容量決策:候選翻倍,檢索品質提升有限,但吞吐直接減半。
這也解釋了為什麼單請求候選集不能太大——1000 條候選 = 26,867 tokens,
一個請求就吃掉整分鐘預算的 134%,必然 429;2000 條是 269%。
配額正在擴容中:上述 TPM 20,000 是上游給到的初始配額,API易 已在向平臺申請擴容。
如果你的業務量超出上表的測算,請直接聯絡 API易客服評估提升上游配額,
不必按當前數字自行降級方案。
快取
實測同一請求重複 10 次,得分逐位一致(漂移 0)。 只有打亂候選順序重發時才出現 3.7e-4 量級的漂移(bf16 批處理抖動),排序不受影響。 所以結果可以放心快取:- 快取 key 用
query 歸一化 + 候選文件內容雜湊(有序) - 不要把
relevance_score本身當冪等標識或去重 key——換個候選順序它就會變最後幾位 - 高頻重複查詢(FAQ、熱門搜尋)快取命中率通常很高,能同時省掉延遲和上游壓力
八、接入現成框架
引數名與 Cohere Rerank v1 一致(query / documents / top_n / return_documents),
但 documents 只接受字串陣列,傳 [{"text": "..."}] 會返回 400,響應體也沒有 Cohere 的
id / meta 欄位。
九、上線前的檢查清單
正確性
正確性
- 用
results[].index回填原始文件物件,而不是按文本反查 - 長文件已切塊(200–500 字),並按文件聚合取最高分
- 單個「query + 文件」對不超過 8192 tokens,否則會 400
- 含否定/排除語義的查詢有大模型兜底
穩定性
穩定性
- 候選集控制在 100 條以內
- 併發上限設到 4 以內(實測上游槽位約 4–5 個在途請求,超出直接 429 不排隊)
- 按 TPM 20,000 核算過峰值吞吐(100 篇候選約 15 次/分鐘),確認夠業務用
- 實現了 429 退避重試(上游擁塞是瞬時狀態)
- 超時設定 ≥ 60 秒(100 條短文件 P95 約 4.3 秒,但長文件或大候選集會到幾十秒)
- 請求路徑確認是
/v1/rerank——路徑寫錯返回的是 200 + HTML,不是 404 - 模型名拼寫正確且全小寫——寫錯返回的是 503,容易誤判為渠道故障
效果
效果
- 閾值策略用的是 Top-N 或相對閾值,不是拍腦袋的固定值
- 多語言/跨語言場景驗證過分數量級,沒有被低分誤傷
- 標註了一小批真實 query 做過 A/B(開/關重排序),確認指標真的漲了
成本與快取
成本與快取
- 知道
usage.input_tokens/output_tokens恆為 0,用量看prompt_tokens/total_tokens - 知道
top_n和return_documents都不影響用量,所有候選都會過一遍模型 - 成本核算以控制台賬單為準(
prompt_tokens與total_tokens在 100 篇候選時相差約 45%, 本輪測試未能確認實際扣的是哪個) - 高頻查詢接了結果快取