How to Implement Reranking Functionality Using PyLate: A Complete Guide
PyLate provides a dedicated reranking API via pylate.rank.rerank that reorders retrieved documents using the ColBERT scoring function, requiring only query embeddings, document embeddings, and document IDs to produce ranked results.
To implement reranking functionality using PyLate, you leverage the stateless reranking module located in pylate/rank/rank.py. This module integrates seamlessly with the library's ColBERT model implementation, allowing you to refine initial retrieval results by computing token-level similarity scores between queries and candidate documents.
Understanding the PyLate Reranking Architecture
Core Implementation Files
The reranking system in PyLate is distributed across several specialized modules:
pylate/rank/rank.py– Implements the mainrerankfunction,reshape_embeddingsfor input normalization, and theRerankResultTypedDict structure.pylate/scores/scores.py– Containscolbert_scores, the similarity engine that computes the ColBERT scoring matrix.pylate/utils/tensor.py– Providesconvert_to_tensor(aliased asfunc_convert_to_tensorin the rank module) for flexible input conversion.
The Reranking Pipeline Steps
When you call rank.rerank(), the implementation executes the following sequence as defined in pylate/rank/rank.py:
- Input normalization –
reshape_embeddingsexpands 2-D embeddings to 3-D tensors(batch, tokens, dim)to handle single queries or document lists uniformly. - Tensor conversion – Embeddings are converted to
torch.Tensorobjects usingfunc_convert_to_tensor. - Padding – Document embeddings per query are padded to equal length using
torch.nn.utils.rnn.pad_sequence. - Device handling – Tensors move to the specified
device(GPU/CPU) or default to the query tensor's device. - Scoring –
colbert_scorescomputes the similarity matrix, extracts maximal token-wise similarities, and sums across tokens. - Sorting – Scores sort in descending order and pair with original document IDs.
- Result aggregation – Returns lists of
RerankResultdictionaries containingidandscorekeys.
How to Implement Reranking Functionality Using PyLate
Basic Reranking After Retrieval
The standard workflow involves encoding queries and candidate documents, then calling the rerank function:
from pylate import models, rank
# Initialize ColBERT model
model = models.ColBERT(
model_name_or_path="sentence-transformers/all-MiniLM-L6-v2",
device="cpu",
)
# Candidate documents from initial retrieval (e.g., FAISS)
candidate_texts = [
["doc A", "doc B", "doc C"],
["doc X", "doc Y"]
]
candidate_ids = [
[101, 102, 103],
[201, 202]
]
# Encode queries and documents
queries = ["first query", "second query"]
q_emb = model.encode(queries, is_query=True, batch_size=1)
d_emb = model.encode(candidate_texts, is_query=False, batch_size=1)
# Rerank
reranked = rank.rerank(
documents_ids=candidate_ids,
queries_embeddings=q_emb,
documents_embeddings=d_emb,
device="cpu"
)
# Process results
for i, results in enumerate(reranked):
print(f"\nQuery {i+1} ranking:")
for rank_pos, res in enumerate(results, start=1):
print(f" {rank_pos}. doc_id={res['id']} score={res['score']:.4f}")
GPU Acceleration for Reranking
To implement reranking functionality using PyLate on GPU, specify the device parameter:
reranked_gpu = rank.rerank(
documents_ids=candidate_ids,
queries_embeddings=q_emb,
documents_embeddings=d_emb,
device="cuda:0"
)
Automatic Device Detection
If you omit the device parameter, PyLate automatically uses the device of the query embeddings:
# If q_emb is on GPU, reranking executes on GPU automatically
reranked_auto = rank.rerank(
documents_ids=candidate_ids,
queries_embeddings=q_emb,
documents_embeddings=d_emb
)
Advanced Reranking Techniques
Working with RerankResult Types
The RerankResult type is a TypedDict defined in pylate/rank/rank.py. You can use it for type annotation in your own code:
from typing import List
from pylate.rank.rank import RerankResult
def process_rankings(rankings: List[List[RerankResult]]) -> None:
for query_results in rankings:
for result in query_results:
doc_id = result["id"]
score = result["score"]
# Custom processing logic here
Integrating with Existing Retrieval Pipelines
Because the PyLate reranking module is stateless, you can integrate it with any initial retrieval system:
# Example: Using with FAISS initial retrieval
import faiss
import numpy as np
# Assume index and model already initialized
def retrieve_and_rerank(query, k=100):
# Initial FAISS retrieval
q_emb = model.encode([query], is_query=True)
distances, indices = index.search(q_emb, k)
# Fetch candidate texts and embeddings
candidate_texts = [[doc_store[idx] for idx in indices[0]]]
candidate_ids = [indices[0].tolist()]
d_emb = model.encode(candidate_texts, is_query=False)
# Rerank with PyLate
return rank.rerank(
documents_ids=candidate_ids,
queries_embeddings=q_emb,
documents_embeddings=d_emb
)
Summary
- PyLate reranking is implemented in
pylate/rank/rank.pyand provides a stateless API for reordering documents using ColBERT scoring. - The
rerankfunction requires three inputs:documents_ids(nested list),queries_embeddings, anddocuments_embeddings. - ColBERT scoring occurs in
pylate/scores/scores.pyviacolbert_scores, computing token-level maximum similarities summed across dimensions. - The module handles automatic tensor conversion, padding, device placement, and result sorting internally.
- GPU acceleration is available via the
deviceparameter or automatic detection from query embeddings. - Results return as RerankResult TypedDict objects containing
idandscorekeys.
Frequently Asked Questions
What is the difference between retrieval and reranking in PyLate?
Retrieval in PyLate typically involves fast approximate nearest neighbor (ANN) search using indices like FAISS or ScaNN to fetch candidate documents. Reranking occurs after retrieval, using the pylate.rank.rerank function to reorder those candidates by computing precise ColBERT similarity scores between the query and each document. The reranking step is more computationally expensive but provides higher accuracy than initial retrieval alone.
Can I use PyLate reranking with FAISS or ScaNN indices?
Yes, the PyLate reranking module is stateless and designed to integrate with any initial retrieval system, including FAISS, ScaNN, or PyLate's own index wrappers. You perform initial retrieval using your preferred index to obtain candidate document IDs and texts, encode these candidates with the ColBERT model, then pass the embeddings to rank.rerank for final ordering.
How does the ColBERT scoring function work in reranking?
The colbert_scores function in pylate/scores/scores.py computes a similarity matrix between query tokens and document tokens, extracts the maximum similarity for each query token across all document tokens, and sums these maximum values across the token dimension. This "late interaction" approach captures fine-grained token-level relevance while maintaining computational efficiency during the reranking phase.
Is the PyLate reranking module stateful or stateless?
The PyLate reranking module is stateless. It does not maintain internal state between calls; each invocation of rank.rerank processes the provided embeddings and IDs independently. This design makes it straightforward to deploy in distributed systems, serverless functions, or multi-threaded applications where you need to rerank results on demand without managing persistent model state.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →