Reranker 插拔進來之後,fallback 真的有在保護你嗎?
最近在看 memory hybrid search 的 reranker 架構,翻了一下相關的實作,有幾個地方讓我想多記一下,因為踩坑的可能性不低。
背景是這樣:hybrid search 本來內建用 MMR 做 reranking,後來有人把它重構成可插拔的架構,MMR 變成 bundled plugin,同時新增了一個 external reranker plugin,可以把 query 和 candidate memory snippets POST 到外部 HTTP endpoint,讓 operator 接自己的 reranker 服務(例如 Cohere 相容的 API)。
設計思路本身是對的,extension surface 清楚,plugin registry 也有雛形。但我在看 runReranker / mergeHybridResults 這段流程的時候,發現一個讓我有點不安的地方。
Fallback 只在 throw 的時候才會觸發
extensions/memory-core/src/memory/hybrid.ts 的邏輯大概是:呼叫 primary reranker,如果它 throw,就 fallback 回 MMR。這個設計直觀,但問題在於「reranker 回了 200,但結果是空陣列,或是裡面的 id 全部對不上 candidate pool」這種情況。
這時候 fallback 不會觸發,因為沒有 exception。mergeHybridResults 收到空的 usable ids,hybrid search 就直接回空結果,而且整個流程被當成「成功 rerank」,不會有任何警告。
換句話說,這是一個 fail-open 的行為,但它假裝自己是 fail-safe。
我自己在接外部 API 的時候踩過類似的坑,不是 400 不是 500,就是 200 + 空資料,然後 UI 那邊顯示「搜尋無結果」,花了一個多小時才發現問題在 reranker 那層而不是 query 本身。這種 bug 很難 debug,因為沒有錯誤訊息可以追。
extensions/memory-external-reranker/src/reranker.ts 那邊應該要做的是:拿到 response 之後,先 validate usable ids 是不是 non-empty 且和 candidate ids 有交集,如果沒有,就當成 degraded state,主動 throw 或回傳一個 fallback signal,讓 mergeHybridResults 可以判斷。
localhost reranker 示範沒提 allowPrivateNetwork
這個比較短但也值得留意。文件示範用 http://localhost:11434(看起來像是 Ollama 之類的本機服務)當 reranker endpoint,但沒有說明需要 opt-in allowPrivateNetwork。
問題是 SSRF guard 預設會擋 private network range(127.x.x.x、10.x.x.x、192.168.x.x 等),所以如果你照著文件設定,直接跑會撞牆,而且錯誤訊息可能不夠明確,你不一定知道是 SSRF guard 擋掉的。
這不是說設計有問題,SSRF guard 存在是合理的。但示範文件沒有說「你需要在 config 裡打開 allowPrivateNetwork 才能用 localhost endpoint」,這對不熟悉 network policy 的人來說會卡一陣子。
Memory Egress 問題
最後一個,也是我覺得最值得認真對待的:external reranker plugin 的行為是把 user query 和 candidate memory snippets POST 到 operator-configured endpoint。
這意味著 memory 裡的內容會離開 OpenClaw 的處理環境,傳到外部服務。如果那個 endpoint 是你自己架的服務,問題不大。但如果
是接第三方 API(包括雲端 Cohere),那 memory 裡的東西就出去了。
在 skill 開發或 plugin 開發的脈絡下,這個 egress 行為需要在文件層面明確說清楚,讓 operator 在決定要不要接外部 reranker 的時候,知道自己是在做一個 data-out 的決策,不只是一個「換個 reranker 演算法」的決策。
我說這些不是要否定這個架構設計,pluggable reranker 本身是值得的方向,extension surface 的思路也對。只是這三個地方如果沒有補齊,在 production 環境用的時候會有意料之外的問題。
如果你有在寫自己的 memory skill 或 retrieval plugin,建議先把這幾個邊界條件想清楚再接上去。
作者:jiaweiOrz