Late-interaction reranking (ColBERT & beyond)
Not every retrieval stack needs a cross-encoder reranker. Late-interaction models such as ColBERT score query–document pairs with token-level interactions while keeping embeddings cacheable — often a better fit than bi-encoders and cheaper than full cross-encoders at scale.
What late-interaction means
A bi-encoder embeds the query and each document independently — fast, but no token-level matching. A cross-encoder feeds query + document through one transformer and outputs a single relevance score — accurate, but you pay full inference per pair.
Late-interaction sits between them: you still pre-compute document token embeddings offline, but at query time you run a cheap interaction (typically MaxSim — max cosine per query token) between query tokens and document tokens. You get finer matching than a single vector dot product without scoring every pair with a full cross-encoder.
Cross-encoder vs late-interaction vs bi-encoder
| Architecture | Precompute docs? | Query-time cost | Typical use |
|---|---|---|---|
| Bi-encoder | Yes (1 vector/doc) | Very low | Stage-1 recall over millions |
| Late-interaction (ColBERT) | Yes (token vectors/doc) | Low–medium | Stage-1 or stage-1.5; lexical-ish precision |
| Cross-encoder reranker | No | High per pair | Stage-2 on 50–100 candidates |
Many 2026 stacks chain them: bi-encoder or hybrid recall → optional ColBERT rescore on hundreds → cross-encoder rerank on dozens. See hybrid retrieval + rerank for the merge step.
When to skip cross-encoder rerank
Cross-encoder reranking pays off when your shortlist is small (≤100) and order quality matters for downstream LLM prompts. Consider not adding one when:
- Late-interaction already fixes order. ColBERTv2 or SPLADE++ on your eval set beats retrieval-only NDCG@10 — the marginal gain from a cross-encoder may be tiny.
- Latency budget is sub-50 ms. You cannot afford another transformer pass after retrieval; invest in better embeddings or late-interaction instead.
- Candidate count is huge per query. Reranking 500+ passages with a cross-encoder is slow; use late-interaction to prune to 50 first.
- Instruction-shaped queries. Newer APIs (e.g. Contextual AI instruction rerankers) bake task context into the score — a generic cross-encoder may underperform without prompt engineering.
- Multilingual with one strong bi-encoder. Models like Qwen3-Embedding + a tuned reranker may suffice; always measure on your labels.
Rule of thumb: if Recall@50 is low, fix retrieval — no reranker architecture invents missing chunks.
ColBERTv2 in practice
# pip install -U "sentence-transformers>=6"
# Rescore first-stage candidates with ColBERTv2's token-level MaxSim,
# keep the top 50 for an optional cross-encoder pass
from sentence_transformers import MultiVectorEncoder
colbert = MultiVectorEncoder("colbert-ir/colbertv2.0")
query = "reset API key"
candidates = [...] # e.g. the top 200 from BM25 or a bi-encoder
q = colbert.encode_query([query]) # queries and documents are encoded
d = colbert.encode_document(candidates) # differently: use both methods
scores = colbert.similarity(q, d)[0] # one MaxSim score per candidate
top50 = [candidates[i] for i in scores.argsort(descending=True)[:50].tolist()]
# Pass top50 to bge-reranker or Cohere for final ordering
Since version 6.0 (August 2026), sentence-transformers loads ColBERT-style models directly — Stanford ColBERT checkpoints like colbert-ir/colbertv2.0, PyLate models and ColPali-style visual retrievers — through MultiVectorEncoder (release notes). We ran the snippet above on sentence-transformers 6.1.0 in October 2026. Used this way, rescoring what your first stage returns, it needs no index at all; to search a whole corpus with ColBERT itself you would build a compressed index such as PLAID (LightOn’s fast-plaid), as the release notes explain.
ColBERT shines on keyword-heavy corpora (support KBs, legal clauses, SKUs) where bi-encoders blur exact tokens. It does not run in our browser demo — different inference path — but belongs on your architecture comparison checklist.
How to pick an architecture
Millions of docs, tight latency?
→ bi-encoder (+ BM25 hybrid if lexical matters)
Recall OK but order noisy, 100–1000 candidates?
→ late-interaction (ColBERT) OR widen cross-encoder input
Top 50–100 need LLM-grade precision?
→ cross-encoder rerank (bge, Cohere, Jina, mxbai…)
Task-specific instructions in the query?
→ instruction-following hosted rerank (Contextual AI, etc.)
Unsure?
→ 30 labelled queries + NDCG@5 before/after each stage
Emerging open cross-encoders such as Qwen3-Reranker compete with bge on multilingual stacks; pair them with late-interaction when you need both scale and precision.
See cross-encoder rerank in the browser
Our demo shows stage-2 cross-encoder scoring — compare it with the bi-encoder proxy column to see what late-interaction or hybrid retrieval would need to fix.
Open the demo →