Intermediate7 min read10 of 40

Cross-Encoder Reranking - Precise Relevance Scoring

Re-score retrieved candidates with a cross-encoder model that jointly encodes query and document for highly accurate relevance ranking.

Read first:Reranking

Overview

Cross-Encoder Reranking is a two-stage retrieval strategy that pairs a fast bi-encoder for initial candidate retrieval with a high-accuracy cross-encoder for precise relevance scoring. The cross-encoder reads query and document together, letting every token in the query attend to every token in the document — producing much richer relevance signals than bi-encoder embeddings alone.

Pattern #4 in the 37 RAG Patterns Collection

flowchart TD
  Q[Query] --> BI[Bi-encoder: embed query fast]
  BI --> RC["Recall stage: top-50 candidates from vector index"]
  RC --> CE{"Cross-encoder: jointly score each query+chunk pair — slower but accurate"}
  CE --> SR[Sort by cross-encoder score]
  SR --> TOP[Top-5 reranked results]
  TOP --> LLM[Generate]

The Problem

Bi-encoders encode query and document independently, then compare their embeddings with a dot product or cosine similarity:

Query: encode("What causes inflation?") → vector_q Document: encode("Inflation is caused by…") → vector_d Score: cosine(vector_q, vector_d) = 0.72

This is fast — but the query and document never see each other during encoding, so subtle relevance signals are lost. A document that contains the exact right answer buried in a long paragraph may score lower than a shorter document full of topically related but non-answering content.

Query: "What is the penalty for late tax filing in Germany?" Bi-encoder top result: "German tax system overview" (score 0.81) → Topically close but never mentions penalties Actual best answer: "§152 AO — Late filing carries a surcharge of up to 10% of assessed tax." (score 0.74) → Buried in a statutory reference document, ranked #12

Solution

A cross-encoder reads [QUERY + DOCUMENT] as a single concatenated input, so every attention head can relate query tokens to document tokens directly:

Stage 1 — Bi-encoder retrieval (fast, ~10ms) Query → top-100 candidate documents Stage 2 — Cross-encoder reranking (precise, ~200ms for 100 docs) [Query + Doc_1] → relevance score 0.94 [Query + Doc_2] → relevance score 0.87 … [Query + Doc_100] → relevance score 0.31 → Sort, keep top-5

Implementation

python
from sentence_transformers import CrossEncoder

# Load cross-encoder model
# ms-marco-MiniLM-L-6-v2: fast (6-layer), good for production
# ms-marco-electra-base: slower, highest accuracy
cross_encoder = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

def rerank(query: str, candidates: list[dict], top_k: int = 5) -> list[dict]:
    """
    Re-score a candidate list with a cross-encoder and return top_k results.
    candidates: list of {"content": str, "source": str, ...}
    """
    # Build (query, passage) pairs
    pairs = [(query, doc["content"]) for doc in candidates]

    # Cross-encoder scores — single forward pass over all pairs
    scores = cross_encoder.predict(pairs)

    # Attach scores and sort descending
    for doc, score in zip(candidates, scores):
        doc["rerank_score"] = float(score)

    ranked = sorted(candidates, key=lambda d: d["rerank_score"], reverse=True)
    return ranked[:top_k]


def cross_encoder_rag(query: str) -> tuple[str, dict]:
    # Stage 1: bi-encoder retrieval — broad recall
    candidates = vector_store.search(query, top_k=100)

    # Stage 2: cross-encoder reranking — precise relevance
    top_docs = rerank(query, candidates, top_k=5)

    # Generate answer from the reranked context
    context = "\n\n".join(doc["content"] for doc in top_docs)
    response = llm.generate(f"Context: {context}\n\nQuestion: {query}")

    return response, {
        "candidates_retrieved": len(candidates),
        "docs_after_rerank": len(top_docs),
        "top_score": top_docs[0]["rerank_score"] if top_docs else None,
    }

Choosing a Cross-Encoder Model

python
# Speed-optimised (6-layer MiniLM, ~2ms/pair on CPU)
fast_model = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

# Accuracy-optimised (ELECTRA-base, ~8ms/pair on CPU)
accurate_model = CrossEncoder("cross-encoder/ms-marco-electra-base")

# Multilingual (mMiniLM, supports 100+ languages)
multilingual_model = CrossEncoder("cross-encoder/mmarco-mMiniLMv2-L12-H384-v1")

Complete Notebook

Run the full implementation:

Cross-Encoder Reranking AWS Notebook

Includes:

  • Bi-encoder vs cross-encoder latency benchmarks
  • Model comparison (MiniLM vs ELECTRA vs mMiniLM)
  • AWS Bedrock integration with Amazon Rerank
  • Batch scoring optimisation

Performance

MetricBi-Encoder Only+ Cross-Encoder Rerank
Precision@562%78%
MRR@100.610.79
Latency~10ms~210ms
Cost/query$0.002$0.006

Cross-encoder reranking adds ~200ms but raises Precision@5 by 16 percentage points.

When to Use

Best For

  • High-stakes search — legal, medical, financial queries where the top result must be correct
  • Small candidate sets — retrieving 50–200 candidates to rerank (not 10,000+)
  • Latency budget allows — sub-500ms total is achievable with MiniLM models
  • Domain-specific corpora — fine-tuned cross-encoders outperform general embeddings

Combine With

  • Fusion Retrieval (#3) — run RRF across multiple retrievers first, then rerank the merged candidates for both diverse recall and precise ranking
  • Contextual Compression (#6) — compress the top-5 reranked documents before passing to the LLM to cut token costs

Related Papers

  • ColBERT (Khattab & Zaharia, 2020): Late interaction model that approximates cross-encoder quality at retrieval speed — arxiv.org/abs/2004.12832
  • MonoT5 (Nogueira et al., 2021): T5-based cross-encoder that frames reranking as a text-to-text task — arxiv.org/abs/2101.05667

Next Steps

  1. Try it: Run the notebook
  2. Upgrade recall: Combine with Fusion Retrieval (#3) to diversify candidates before reranking
  3. Cut costs: Pipe reranked results through Contextual Compression (#6)
  4. Go production: Fine-tune the cross-encoder on domain-specific query-passage pairs

Part of: 37 RAG Patterns Collection See also: Complete Pattern Index

Go Deeper With Live Instruction

Covered in depth in our llm engineering program.