Bi-encoder retrieval (embeddings) is built for recall over millions of chunks; it is mediocre at ordering its own top 50. A cross-encoder reranker reads query and passage together and re-orders a small candidate set with far higher precision — so the 3–5 chunks you actually send to the LLM are the right ones.
Tier: Core · Workflow area: RAG data pipelines
The rule of thumb: if the right passage is usually in your top 50 but not your top 5, reranking beats switching embedding models. In Anthropic's contextual-retrieval measurements, adding reranking pushed the reduction in top-20 retrieval failures to roughly 67%. This playbook drops a reranker between hybrid search (pb-33) and generation, with the latency and cost budget made explicit.
Confirm the reranker will pay for itself. From your golden set (pb-28), compute recall@50 and recall@5 on the current pipeline. Expected decision signal: recall@50 = 0.92, recall@5 = 0.61 → large headroom, proceed. If recall@50 is itself low, fix retrieval first (pb-28/pb-29/pb-33) — a reranker cannot rank what never arrived.
Stand up a local cross-encoder. BGE-reranker runs on CPU for lab scale and modest GPU for production; hosted equivalents are Cohere Rerank and Voyage rerank behind one HTTP call.
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3") # local; hosted: Cohere Rerank / Voyage
def rerank(query: str, candidates: list[dict], top_n: int = 5) -> list[dict]:
scores = reranker.predict([(query, c["content"]) for c in candidates])
ranked = sorted(zip(candidates, scores), key=lambda x: -x[1])
return [{**c, "rerank_score": float(s)} for c, s in ranked[:top_n]]
Wire it as a stage: retrieve wide, rerank narrow. Pull top 20–50 from hybrid search, rerank, pass 3–5 forward. Candidate depth is the main quality/latency knob — sweep 20/30/50.
candidates = hybrid_search(q, top=50) # pb-33, filters applied
context = rerank(q, candidates, top_n=5)
Measure the lift with recall@5 and MRR@5 on the golden set. These are the metrics that prove the step worked, because the reranker's whole job is the top of the list:
Expected shape:
before rerank: recall@5 = 0.61 · MRR@5 = 0.48
after rerank: recall@5 = 0.84 · MRR@5 = 0.74 (candidates from same top-50)
A reranker that moves recall@5 by under ~5 points on real headroom is misapplied — check that candidate texts (not truncated stubs) are being scored, and that the model matches your language mix.
Budget latency and cost explicitly. Measure per-query rerank time at each candidate depth: a cross-encoder scores query×passage pairs, so cost is linear in depth. Typical shape: 50 pairs ≈ 40–150 ms on GPU, 0.5–2 s on CPU; hosted rerank APIs price per 1K searches. Write the chosen point into the retrieval SLA: e.g. "top-30 rerank, p95 ≤ 120 ms, fits the 500 ms retrieval budget." If CPU-bound in production, drop depth to 20 before dropping the reranker.
Use rerank scores as a quality gate, not just an ordering. Cross-encoder scores are roughly calibrated per model; a top result scoring far below the model's typical "relevant" range signals an unanswerable query. Log the top score per query and consider a threshold below which the application says "no good source found" instead of letting the LLM improvise from weak context.
Reranking is the highest-leverage precision fix precisely because it is boring to deploy — no re-index, no schema change, reversible by removing one function call. Exhaust it before any change that touches the index.
A hosted reranker sees the query and the full text of every candidate chunk — for sensitive corpora that is more exposure per query than the embedding API ever had, so client engagements should default to the self-hosted BGE-reranker inside the client boundary; CPU inference at top-20 depth is workable for internal-tool query volumes. If the client approves a hosted reranker, scope the approval explicitly to "queries plus retrieved passages", confirm retention terms, and exclude ACL-restricted document classes from rerank candidates as defense in depth. The eval harness and its recall@5 lift report contain golden-set questions, so they stay inside the client environment like all pb-28 artifacts.