reranker (text-classification) Β· text Β· WASM Β· ~151 MB
Alibaba's GTE reranker built on the ModernBERT backbone β the 2025 encoder redesign (rotary embeddings, GeGLU, alternating local/global attention) with an 8192-token context. Instead of turning a query and a passage into separate vectors and comparing them, a cross-encoder reads both together and outputs a single relevance score β and because ModernBERT handles long inputs, it reranks whole documents a base-BERT reranker would have to truncate. Give it a query and candidates and watch it re-sort them; then look inside at the raw logit per pair. Nothing leaves your device.
| Model | Alibaba-NLP/gte-reranker-modernbert-base (canonical repo ships the ONNX build in onnx/) |
|---|---|
| Task / pipeline | text-classification used as a cross-encoder reranker (num_labels = 1) |
| Input | a (query, passage) pair encoded together β one relevance logit |
| Architecture | ModernBERT-base (768 hidden, 22 layers, 12 heads) fine-tuned for passage reranking β ModernBertForSequenceClassification |
| Context length | 8192 tokens β reranks long passages/documents without truncation (vs. 512 for a classic BERT reranker) |
| Quantization | q8 (8-bit) ONNX (onnx/model_quantized.onnx) |
| Backend | WebAssembly (runs anywhere; no WebGPU needed) |
| Runtime | Transformers.js 3.7.5 (shared pin) β the modernbert class is built in, no version override |
| Download | ~151 MB (q8), cached after first load |
| Language | English (the GTE-reranker-ModernBERT base is English-focused) |
| License | Apache-2.0 |
| Web APIs | WebAssembly, Web Workers β all Baseline widely available |
Type a query and one candidate passage per line. The model scores each passage against the query and re-sorts them by relevance logit (higher = more relevant). Notice the decoys below share the query's exact words but answer a different question β the cross-encoder keys on meaning, not word overlap.
The one number the model emits per pair is a relevance logit β unbounded, higher is more relevant (we also show its sigmoid as a 0β100% probability). First, the before/after view: the candidates in their original (retrieval) order on the left, and the cross-encoder's reordering on the right β arrows mark what moved. Then a second contrast ranks the same passages by naive shared-word overlap; where the columns disagree, the cross-encoder is using meaning. Several decoys here are packed with the query's words ("Apollo 11", "Moon", "mission") yet answer the wrong question, so word overlap ranks them highly while the cross-encoder pushes them down.
Rerankers are the precision stage of modern search. A fast retriever (a keyword index or embeddings) casts a wide net and returns, say, the top 50 candidates; a cross-encoder then reads each candidate against the query and reorders them with far higher accuracy. GTE-reranker-ModernBERT brings two things to that stage: the 8192-token context of ModernBERT, so it can score long passages and whole documents without chopping them to 512 tokens, and ModernBERT's efficient attention, so it stays light enough to run in a tab. The precise, expensive step happens on-device with nothing sent anywhere.
Rank a handful of passages against a query by cross-encoder relevance.
Two-stage RAG: retrieve a shortlist, then rerank it with ModernBERT for precision.
Keyword-stuffed hard negatives: decoys packed with the query's words that answer the wrong thing.
GTE-ModernBERT embeddings retrieve, GTE-reranker-ModernBERT reorders β same backbone, two stages.
Contrast with the multilingual BGE-reranker-v2-m3: same cross-encoder idea, but this one uses the ModernBERT backbone for an 8192-token context (long-document reranking) where v2-m3 trades context for 100+ language coverage.
A cross-encoder scores queryβpassage pairs; we read the raw logit off the model directly:
import { AutoTokenizer, AutoModelForSequenceClassification } from "@huggingface/transformers";
const model_id = "Alibaba-NLP/gte-reranker-modernbert-base";
const tokenizer = await AutoTokenizer.from_pretrained(model_id);
const model = await AutoModelForSequenceClassification.from_pretrained(model_id, { dtype: "q8" });
// Encode the query with each passage AS A PAIR β [CLS] query [SEP] passage [SEP]:
const inputs = tokenizer(
passages.map(() => query),
{ text_pair: passages, padding: true, truncation: true },
);
const { logits } = await model(inputs); // one relevance logit per pair β higher = more relevant
// sort the passages by logits.data β that's your reranking. ModernBERT's 8192-token context means
// each passage can be a long document, not a truncated snippet.
This page loads the model through the shared loader as a text-classification pipeline,
then reuses pipe.model + pipe.tokenizer to read the raw logits (the pipeline
would squash them through a sigmoid). All inference runs in a Web Worker so ranking never janks the page.