{
  "@context": "https://schema.org",
  "@id": "https://aggr.aymericbeaumet.com/items/huggingface-co/2026-05-19-introducing-the-ettin-reranker-family/#webpage",
  "@type": [
    "WebPage",
    "ArchiveComponent"
  ],
  "articleBody": "## TL;DR\n\nToday I'm releasing six new [Sentence Transformers](https://sbert.net/) CrossEncoder rerankers, state-of-the-art at their respective sizes, built on top of the [Ettin](https://huggingface.co/collections/jhu-clsp/encoders-vs-decoders-the-ettin-suite) ModernBERT encoders, together with the data and full training recipe that produced them:\n\n- [`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)\n- [`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)\n- [`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)\n- [`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)\n- [`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)\n- [`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)\n\nThe models were trained with a **distillation recipe**: pointwise MSE on [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2) scores over [`cross-encoder/ettin-reranker-v1-data`](https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data), which is a subset of [`lightonai/embeddings-pre-training`](https://huggingface.co/datasets/lightonai/embeddings-pre-training) mixed with a reranked subset of [`lightonai/embeddings-fine-tuning`](https://huggingface.co/datasets/lightonai/embeddings-fine-tuning).\n\n[![Our six rerankers paired with embeddinggemma-300m on MTEB(eng, v2) Retrieval](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png)\n\n*Our six rerankers paired with [`google/embeddinggemma-300m`](https://huggingface.co/google/embeddinggemma-300m) on MTEB(eng, v2) Retrieval. See [Results](https://huggingface.co/blog/ettin-reranker#results) for five more embedder pairings.*\n\nIf you're new to rerankers and want the \"why\" first, jump to [What is a reranker, and why pair one with an embedder?](https://huggingface.co/blog/ettin-reranker#what-is-a-reranker-and-why-pair-one-with-an-embedder). If you just want to plug a model in, jump to [Usage](https://huggingface.co/blog/ettin-reranker#usage). If you want to train your own, jump to [Training](https://huggingface.co/blog/ettin-reranker#training).\n\n> I bootstrapped the training recipe below with the new [`train-sentence-transformers` Agent Skill](https://github.com/huggingface/sentence-transformers/tree/main/skills) shipped in [Sentence Transformers v5.5.0](https://github.com/huggingface/sentence-transformers/releases/tag/v5.5.0). Install it with `hf skills add train-sentence-transformers [--global] [--claude]` and ask your AI coding agent (Claude Code, Codex, Cursor, Gemini CLI, ...) to fine-tune a `SentenceTransformer`, `CrossEncoder`, or `SparseEncoder` model on your data.\n\n## Table of contents\n\n- [What is a reranker, and why pair one with an embedder?](https://huggingface.co/blog/ettin-reranker#what-is-a-reranker-and-why-pair-one-with-an-embedder)\n- [Usage](https://huggingface.co/blog/ettin-reranker#usage)\n  - [End-to-end retrieve-then-rerank pipeline](https://huggingface.co/blog/ettin-reranker#end-to-end-retrieve-then-rerank-pipeline)\n- [Architecture Details](https://huggingface.co/blog/ettin-reranker#architecture-details)\n- [Results](https://huggingface.co/blog/ettin-reranker#results)\n  - [MTEB(eng, v2) Retrieval](https://huggingface.co/blog/ettin-reranker#mtebeng-v2-retrieval)\n  - [Speed](https://huggingface.co/blog/ettin-reranker#speed)\n- [Training](https://huggingface.co/blog/ettin-reranker#training)\n  - [Distillation recipe](https://huggingface.co/blog/ettin-reranker#distillation-recipe)\n  - [Dataset](https://huggingface.co/blog/ettin-reranker#dataset)\n  - [Training Arguments](https://huggingface.co/blog/ettin-reranker#training-arguments)\n  - [Evaluation](https://huggingface.co/blog/ettin-reranker#evaluation)\n  - [Overall Training Script](https://huggingface.co/blog/ettin-reranker#overall-training-script)\n- [Conclusion](https://huggingface.co/blog/ettin-reranker#conclusion)\n- [Acknowledgements](https://huggingface.co/blog/ettin-reranker#acknowledgements)\n\n## What is a reranker, and why pair one with an embedder?\n\nA reranker (a.k.a. pointwise cross-encoder) is a neural model that takes a `(query, document)` pair and outputs a single relevance score. Unlike an embedding model, which encodes the query and document separately and computes their similarity from the two embedding vectors, a reranker lets the two texts attend to each other through every transformer layer. That joint encoding is more accurate but also more expensive: the model has to be run once per `(query, document)` pair rather than once per text.\n\nBecause cross-encoders are too expensive to run over a full corpus, the common production pattern is **retrieve-then-rerank**: a fast embedding model retrieves the top-K candidates (cheap), then a cross-encoder re-orders just those K with high accuracy. The total cost stays bounded while the final ranking is much closer to what an exhaustive cross-encoder pass would produce.\n\n[![Embedding vs Reranker Models](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/train-reranker/embedding_vs_reranker_model.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/train-reranker/embedding_vs_reranker_model.png)\n\n> Throughout this blogpost I'll use \"reranker\" and \"cross-encoder\" interchangeably.\n\n## Usage\n\nThe released models are normal Sentence Transformers `CrossEncoder` models, so you can use them with just 3 lines of code:\n\n```python\nfrom sentence_transformers import CrossEncoder\n\nmodel = CrossEncoder(\"cross-encoder/ettin-reranker-32m-v1\")\nscores = model.predict([\n    (\"Where was Apple founded?\", \"Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.\"),\n    (\"Where was Apple founded?\", \"The Fuji apple is an apple cultivar developed in the late 1930s and brought to market in 1962.\"),\n])\nprint(scores)\n# [11.393298  2.968891]   <- larger means more relevant\n```\n\nFor a query and a list of candidates, you can also use `rank` to get back sorted indices and scores:\n\n```python\nranked = model.rank(\n    query=\"Which planet is known as the Red Planet?\",\n    documents=[\n        \"Venus is often called Earth's twin because of its similar size and proximity.\",\n        \"Mars, known for its reddish appearance, is often referred to as the Red Planet.\",\n        \"Jupiter, the largest planet in our solar system, has a prominent red spot.\",\n        \"Saturn, famous for its rings, is sometimes mistaken for the Red Planet.\",\n    ],\n    top_k=4,\n    return_documents=True,\n)\nfor r in ranked:\n    print(f\"({r['score']:.2f}): {r['text']}\")\n# (10.82): Mars, known for its reddish appearance, is often referred to as the Red Planet.\n# (9.86): Saturn, famous for its rings, is sometimes mistaken for the Red Planet.\n# (8.55): Jupiter, the largest planet in our solar system, has a prominent red spot.\n# (6.21): Venus is often called Earth's twin because of its similar size and proximity.\n```\n\nYou can swap [`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1) for any other size to trade quality for speed. All six accept up to 8K tokens of context (useful for long-document reranking) thanks to ModernBERT's long-context pre-training.\n\nIt is recommended to install [`kernels`](https://github.com/huggingface/kernels) and set `model_kwargs={\"dtype\": \"bfloat16\", \"attn_implementation\": \"flash_attention_2\"}` for the highest throughput. See the [Speed](https://huggingface.co/blog/ettin-reranker#speed) section below for more details, but in general you can expect a 1.7x-8.3x speedup over default loading depending on model size and sequence length.\n\n```python\nfrom sentence_transformers import CrossEncoder\n\nmodel = CrossEncoder(\n    \"cross-encoder/ettin-reranker-32m-v1\",\n    model_kwargs={\"dtype\": \"bfloat16\", \"attn_implementation\": \"flash_attention_2\"},\n)\n```\n\n### End-to-end retrieve-then-rerank pipeline\n\nA complete example with a fast embedder for retrieval and the reranker for the final ordering:\n\n```python\nfrom sentence_transformers import SentenceTransformer, CrossEncoder\n\n# Fast retrieval with a static embedder (sub-millisecond on CPU per query)\nembedder = SentenceTransformer(\"sentence-transformers/static-retrieval-mrl-en-v1\")\nreranker = CrossEncoder(\"cross-encoder/ettin-reranker-68m-v1\")\n\ncorpus = [\n    \"Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.\",\n    \"The Fuji apple is an apple cultivar developed in the late 1930s.\",\n    \"Steve Jobs introduced the iPhone in 2007 at Macworld.\",\n    \"Macintosh computers were sold by Apple from 1984 onward.\",\n    # ... thousands or millions more in production\n]\nquery = \"Where was Apple founded?\"\n\n# Step 1: encode + retrieve top-100\nquery_emb = embedder.encode_query(query, convert_to_tensor=True)\ncorpus_emb = embedder.encode_document(corpus, convert_to_tensor=True)\nscores = embedder.similarity(query_emb, corpus_emb)[0]\ntop_k_idx = scores.topk(min(100, len(corpus))).indices.tolist()\n\n# Step 2: rerank\ntop_k_docs = [corpus[i] for i in top_k_idx]\nranked = reranker.rank(query, top_k_docs, top_k=5, return_documents=True)\nfor r in ranked:\n    print(f\"({r['score']:.2f}): {r['text']}\")\n# (11.63): Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.\n# (4.71): Steve Jobs introduced the iPhone in 2007 at Macworld.\n# (1.96): The Fuji apple is an apple cultivar developed in the late 1930s.\n# (1.49): Macintosh computers were sold by Apple from 1984 onward.\n```\n\nThis is the same shape used by most modern search systems. The retriever decides what enters the funnel, the reranker decides what wins.\n\n## Architecture Details\n\nAll six rerankers share the same architecture and differ only in their backbone size. The backbone is one of the six [Ettin encoders](https://huggingface.co/blog/ettin) from Johns Hopkins University's Ettin suite. These are ModernBERT-style models with unpadded attention, RoPE positional encodings, GeGLU, and 2T tokens of open-license pre-training, supporting up to 8192 tokens of context.\n\nOn top of each encoder, the reranker uses a 4-module classification head that mirrors `ModernBertForSequenceClassification` but is built from Sentence Transformers' modular components. The underlying `Transformer` is a plain `AutoModel` rather than `AutoModelForSequenceClassification`, which lets us use sequence unpadding for variable-length inputs for Flash Attention 2. At medium-document sequence lengths this is a 1.7x-8.3x speedup over fp32+SDPA depending on model size (see [Speed](https://huggingface.co/blog/ettin-reranker#speed) for the full benchmark):\n\n```\n1. Transformer(FA2)\n2. Pooling(cls)\n3. Dense(H, H, bias=False, GELU)\n4. LayerNorm(H)\n5. Dense(H, 1, scores)\n```\n\nIn my ablations, CLS pooling outperformed mean pooling. That was a little surprising. ModernBERT uses global attention only every third layer and the other two-thirds use local-window attention that cannot reach CLS from distant positions. Empirically, those few global layers carry enough signal to make CLS the better pooling choice.\n\n| Model                                                                                                  | Backbone                                                                             | Hidden size | Layers | Params (head incl.) |\n| ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ----------- | ------ | ------------------- |\n| [`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)   | [`jhu-clsp/ettin-encoder-17m`](https://huggingface.co/jhu-clsp/ettin-encoder-17m)   | 256         | 7      | 17.6M               |\n| [`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)   | [`jhu-clsp/ettin-encoder-32m`](https://huggingface.co/jhu-clsp/ettin-encoder-32m)   | 384         | 10     | 32.8M               |\n| [`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)   | [`jhu-clsp/ettin-encoder-68m`](https://huggingface.co/jhu-clsp/ettin-encoder-68m)   | 512         | 19     | 68.6M               |\n| [`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1) | [`jhu-clsp/ettin-encoder-150m`](https://huggingface.co/jhu-clsp/ettin-encoder-150m) | 768         | 22     | 150.9M              |\n| [`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1) | [`jhu-clsp/ettin-encoder-400m`](https://huggingface.co/jhu-clsp/ettin-encoder-400m) | 1024        | 28     | 401.6M              |\n| [`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)     | [`jhu-clsp/ettin-encoder-1b`](https://huggingface.co/jhu-clsp/ettin-encoder-1b)     | 1792        | 28     | 1.00B               |\n\nAll six models are released under the **Apache 2.0** license, matching the Ettin encoders.\n\n## Results\n\n### MTEB(eng, v2) Retrieval\n\nI ran each released model through the full [`MTEB(eng, v2)` Retrieval benchmark](https://github.com/embeddings-benchmark/mteb) (10 tasks, top-100 reranked) using MTEB's [two-stage reranking flow](https://embeddings-benchmark.github.io/mteb/get_started/advanced_usage/two_stage_reranking/), pairing each reranker with six embedding models that span the speed/quality spectrum:\n\n| Embedding Model                                                                                                                | Active params | Retriever-only NDCG@10 |\n| ------------------------------------------------------------------------------------------------------------------------------ | ------------- | ---------------------- |\n| [`sentence-transformers/static-retrieval-mrl-en-v1`](https://huggingface.co/sentence-transformers/static-retrieval-mrl-en-v1) | 0M            | 0.3495                 |\n| [`sentence-transformers/all-MiniLM-L6-v2`](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2)                     | 23M           | 0.4292                 |\n| [`BAAI/bge-small-en-v1.5`](https://huggingface.co/BAAI/bge-small-en-v1.5)                                                     | 33M           | 0.5149                 |\n| [`nomic-ai/nomic-embed-text-v1.5`](https://huggingface.co/nomic-ai/nomic-embed-text-v1.5)                                     | 137M          | 0.5226                 |\n| [`google/embeddinggemma-300m`](https://huggingface.co/google/embeddinggemma-300m)                                             | 308M          | 0.5463                 |\n| [`jinaai/jina-embeddings-v5-text-small-retrieval`](https://huggingface.co/jinaai/jina-embeddings-v5-text-small-retrieval)     | 596M          | 0.5980                 |\n\nThe **dashed retriever-only line** in each chart below is the headline number to beat. Anything below it means the reranker actively hurts the pipeline on average:\n\n|                                                                                                                                                                                                                                                                                                                                                                      |                                                                                                                                                                                                                                                                                                                                                                                                             |\n| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [![MTEB(eng, v2) Retrieval with static-retrieval-mrl-en-v1 + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_static-retrieval-mrl-en-v1.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_static-retrieval-mrl-en-v1.png) | [![MTEB(eng, v2) Retrieval with all-MiniLM-L6-v2 + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_all-MiniLM-L6-v2.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_all-MiniLM-L6-v2.png)                                                                      |\n| [![MTEB(eng, v2) Retrieval with bge-small-en-v1.5 + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_bge-small-en-v1.5.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_bge-small-en-v1.5.png)                            | [![MTEB(eng, v2) Retrieval with nomic-embed-text-v1.5 + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_nomic-embed-text-v1.5.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_nomic-embed-text-v1.5.png)                                                       |\n| [![MTEB(eng, v2) Retrieval with embeddinggemma-300m + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png)                      | [![MTEB(eng, v2) Retrieval with jina-embeddings-v5-text-small-retrieval + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_jina-embeddings-v5-text-small-retrieval.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_jina-embeddings-v5-text-small-retrieval.png) |\n\nFull table of results (click to expand)\n\nMean NDCG@10 over the 6 embedder pairings, sorted descending. Our six models are in **bold**, and the teacher [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2) is underlined.\n\n| Reranker                                                                                                                         | Params    | MTEB(eng, v2) Retrieval NDCG@10 |\n| -------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------- |\n| [`Qwen/Qwen3-Reranker-4B`](https://huggingface.co/Qwen/Qwen3-Reranker-4B)†                                                      | 4.02B     | 0.6367                          |\n| [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2)                             | 1.54B     | 0.6115                          |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1.00B** | **0.6114**                      |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **401M**  | **0.6091**                      |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **151M**  | **0.5994**                      |\n| [`Qwen/Qwen3-Reranker-0.6B`](https://huggingface.co/Qwen/Qwen3-Reranker-0.6B)                                                   | 596M      | 0.5940                          |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M      | 0.5920                          |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68.6M** | **0.5915**                      |\n| [`jinaai/jina-reranker-m0`](https://huggingface.co/jinaai/jina-reranker-m0)                                                     | 2.44B     | 0.5856                          |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M      | 0.5843                          |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32.8M** | **0.5779**                      |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M      | 0.5656                          |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17.6M** | **0.5576**                      |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M      | 0.5526                          |\n| [`zeroentropy/zerank-2-reranker`](https://huggingface.co/zeroentropy/zerank-2-reranker)†                                        | 4.02B     | 0.5300                          |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M      | 0.5098                          |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22.7M     | 0.5082                          |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33.4M     | 0.5066                          |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M      | 0.5063                          |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19.2M     | 0.4979                          |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70.8M     | 0.4968                          |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M      | 0.4890                          |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M      | 0.4865                          |\n\n† Capped to `max_seq_length=8192` (the 4B Qwen3-based rerankers don't fit on a single H100 80GB at native context). Native-context evaluation is likely higher.\n\nFull table of NanoBEIR results (click to expand)\n\n[NanoBEIR](https://huggingface.co/collections/sentence-transformers/nanobeir-with-bm25-rankings) is a fast 13-dataset subset of [BEIR](https://github.com/beir-cellar/beir) that uses 50 queries per dataset against up to 5000 documents each. NanoBEIR is what `metric_for_best_model` was set to during training (see [Evaluation](https://huggingface.co/blog/ettin-reranker#evaluation)), and what I used to guide the experimentation.\n\n| Reranker                                                                                                                         | Params    | NanoBEIR mean NDCG@10 |\n| -------------------------------------------------------------------------------------------------------------------------------- | --------- | --------------------- |\n| [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2)                             | 1.54B     | 0.7318                |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1.00B** | **0.7237**            |\n| [`jinaai/jina-reranker-m0`](https://huggingface.co/jinaai/jina-reranker-m0)                                                     | 2.44B     | 0.7197                |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **401M**  | **0.7193**            |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M      | 0.7162                |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **151M**  | **0.7086**            |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M      | 0.7017                |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M      | 0.6971                |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68.6M** | **0.6915**            |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M      | 0.6909                |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32.8M** | **0.6825**            |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17.6M** | **0.6746**            |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M      | 0.6488                |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M      | 0.6379                |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33.4M     | 0.6369                |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22.7M     | 0.6312                |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19.2M     | 0.6298                |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M      | 0.6231                |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70.8M     | 0.6136                |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M      | 0.6027                |\n\nThe smallest model I'm releasing, our 17M, beats the 33M `ms-marco-MiniLM-L12-v2` by +0.051 NDCG@10 (0.5576 vs 0.5066) on MTEB and +0.038 (0.6746 vs 0.6369) on NanoBEIR at roughly half the parameter count. The 32M beats the 568M `BAAI/bge-reranker-v2-m3` by +0.025 (0.5779 vs 0.5526) on MTEB, a 17x parameter gap. If you've been using one of the legacy MiniLM rerankers as the default in your retrieve-then-rerank stack, swapping in our 17M (or 32M) is a low-risk drop-in replacement, with a noticeable quality bump on both benchmarks.\n\nMoving up the table, our 150M is the strongest reranker I tested in the under-600M range on MTEB, edging out the recent `Qwen/Qwen3-Reranker-0.6B` (596M) by +0.005 (0.5994 vs 0.5940) and beating every BAAI bge-reranker variant by 0.03 to 0.05. The 68M is also worth a mention: at 0.5915 it lands almost exactly on `Qwen3-Reranker-0.6B` (0.5940) while using a ninth of the parameters.\n\nAt the top of the released range, our 1B model closely tracks its teacher. It comes within 0.0001 of the 1.54B `mxbai-rerank-large-v2` on MTEB (0.6114 vs 0.6115) and within 0.008 on NanoBEIR, despite distilling from a model 54% larger than itself. The distillation effectively closes the gap to the teacher, which is what I was hoping to see going into this release.\n\nThe overall strongest reranker in the comparison is `Qwen/Qwen3-Reranker-4B` at 0.6367 MTEB, +0.025 above our 1B model. Closing that gap from the current recipe would likely require distilling from a stronger teacher (our teacher itself sits below `Qwen3-Reranker-4B`). For most retrieve-then-rerank workloads, our 1B at a quarter of the parameters (see [Speed](https://huggingface.co/blog/ettin-reranker#speed)) is a much more practical pick.\n\n### Speed\n\nQuality numbers are only half of what matters for a reranker. The other half is whether its latency fits inside the budget you have between retrieval and showing results to the user. Let me walk through what I measured.\n\nI benchmarked all six released models against thirteen public rerankers (strong baselines up to about 1B parameters) on a single NVIDIA H100 80GB. The queries and documents come from [`sentence-transformers/natural-questions`](https://huggingface.co/datasets/sentence-transformers/natural-questions) at its natural document-length distribution: most NQ answers are short, some are long. Documents are truncated at `max_length=512` to avoid giving the older models an unfair advantage. Each model uses its best supported attention implementation: Flash Attention 2 wherever the architecture supports it (BERT, XLM-RoBERTa, ModernBERT, Qwen2), SDPA where it doesn't, and eager for DeBERTa-v2 (which currently has neither FA2 nor SDPA support in `transformers`).\n\nFor every model an auto-batch search starts at batch size 8 and doubles until the GPU runs out of memory. At each batch size I run three timed passes and keep the median throughput, so a single unlucky run doesn't drag the number around. The reported throughput is at whichever batch size won.\n\n**Table 1.** Throughput in pairs per second, all in `bfloat16`. Our six rerankers are in **bold**.\n\n| Model                                                                                                                            | Params   | Attn  | pairs / second |\n| -------------------------------------------------------------------------------------------------------------------------------- | -------- | ----- | -------------- |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17M**  | FA2   | **7517**       |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32M**  | FA2   | **6602**       |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68M**  | FA2   | **4913**       |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19M      | FA2   | 4029           |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22M      | FA2   | 3817           |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33M      | FA2   | 3311           |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **150M** | FA2   | **3237**       |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M     | FA2   | 2858           |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70M      | eager | 2636           |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M     | eager | 1953           |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **400M** | FA2   | **1738**       |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M     | FA2   | 1659           |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M     | FA2   | 1569           |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M     | FA2   | 1418           |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M     | FA2   | 1404           |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1B**   | FA2   | **928**        |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M     | eager | 867            |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M     | FA2   | 809            |\n| [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2)                             | 1.5B     | FA2   | 387            |\n\nOur 17M is the fastest reranker in the whole comparison, at 7517 pairs per second. That's almost twice the throughput of `ms-marco-MiniLM-L6-v2` (3817) and faster even than the smaller `ms-marco-MiniLM-L4-v2` (4029). And as you saw in the MTEB table earlier, our 17M is also more accurate than every MiniLM variant. If you're currently running a MiniLM cross-encoder, swapping to our 17M is a one-line change that improves both your latency and search quality.\n\nOur 150M is an even more interesting comparison, because there are two direct architectural peers at exactly 150M parameters: [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base) and [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2). Both are built on the same ModernBERT-base backbone. Our 150M runs at 3237 pairs per second, while the two peers come in at 1418 and 1404 respectively, for a 2.3x speed gap.\n\nAll three 150M models use Flash Attention 2, but the two peers load through `AutoModelForSequenceClassification`, which keeps the inputs padded. So attention itself runs the FA2 kernel, but the rest of the model is still doing dense compute on padding tokens that don't contribute anything. Our modular `Transformer` module (see [Architecture Details](https://huggingface.co/blog/ettin-reranker#architecture-details) above) propagates unpadded inputs all the way through the model, so every layer only spends compute on real tokens. That's the difference between getting some of FA2's benefit and getting all of it.\n\nAt the bottom of the table, our 1B model hits 928 pairs per second, which is 2.4x faster than the 1.54B teacher `mxbai-rerank-large-v2` (387 pairs per second) while matching its MTEB score within 0.0001. The teacher is Qwen2-based with a prompt-template overhead per pair, so the distilled student inherits the teacher's calibration and judgement but skips all the runtime baggage. This is honestly the most satisfying single number in the whole release for me.\n\nOne unfortunate note: the DeBERTa-v2-based `mxbai-rerank-{xsmall,base,large}-v1` series ends up much slower than the rest of the table because DeBERTa-v2 currently supports neither Flash Attention 2 nor SDPA in `transformers`. The 70M `mxbai-rerank-xsmall-v1` runs at 2636 pairs per second, about half the throughput of our 68M at almost the same parameter count. The models themselves are perfectly fine, they just don't get to use modern attention kernels.\n\nSame benchmark on a consumer GPU (RTX 3090, 24 GB)\n\nIf you're self-hosting on a consumer card rather than a datacenter GPU, here's the same throughput sweep on an RTX 3090. Same benchmark setup as Table 1: `bfloat16`, best-supported attention per model, three-trial median throughput at the largest batch that fits.\n\n| Model                                                                                                                            | Params   | Best attn | pairs / second |\n| -------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | -------------- |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17M**  | FA2       | **9008**       |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19M      | FA2       | 5071           |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32M**  | FA2       | **4497**       |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22M      | FA2       | 4234           |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33M      | FA2       | 2847           |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68M**  | FA2       | **1916**       |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70M      | eager     | 1677           |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M     | FA2       | 1329           |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **150M** | FA2       | **982**        |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M     | eager     | 772            |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M     | FA2       | 598            |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M     | FA2       | 586            |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M     | FA2       | 448            |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M     | FA2       | 436            |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **400M** | FA2       | **429**        |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M     | eager     | 266            |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M     | FA2       | 221            |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1B**   | FA2       | **189**        |\n| [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2)                             | 1.5B     | FA2       | 69             |\n\nOur 17M is still the fastest model in the table at 9008 pairs per second, actually higher than its H100 number, which suggests that at tiny sizes raw compute isn't the bottleneck and the H100's extra muscle doesn't translate. The middle of the table reshuffles a bit, with the MiniLM rerankers overtaking our 32M and 68M, and the 1B slipping behind `mxbai-rerank-base-v2` (189 vs 221 pairs per second). Our 150M model still holds a solid lead over the two 150M ModernBERT-based peers, and the teacher-replacement story still holds, with our 1B at 2.7x the throughput of the 1.5B `mxbai-rerank-large-v2` (189 vs 69 pairs per second).\n\nSame benchmark on CPU (Intel Core i7-13700K)\n\n| Model                                                                                                                            | Params   | Best attn | pairs / second |\n| -------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | -------------- |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17M**  | SDPA      | **267.4**      |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19M      | SDPA      | 206.2          |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22M      | SDPA      | 143.9          |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32M**  | SDPA      | **92.5**       |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33M      | SDPA      | 75.9           |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70M      | eager     | 38.9           |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68M**  | SDPA      | **31.2**       |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M     | SDPA      | 19.2           |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M     | SDPA      | 14.7           |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M     | SDPA      | 14.5           |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **150M** | SDPA      | **14.0**       |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M     | eager     | 13.4           |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M     | SDPA      | 6.2            |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M     | SDPA      | 6.0            |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **400M** | SDPA      | **5.2**        |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M     | eager     | 4.3            |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M     | SDPA      | 3.5            |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1B**   | SDPA      | **2.1**        |\n\nOn CPU, we can't take advantage of bf16, Flash Attention 2, or unpadding, so the latency story is a bit simpler: the higher the parameter count, the slower the model. The 17M model is considerably faster than `ms-marco-MiniLM-L6-v2` (267.4 vs 143.9 pairs per second) and even faster than the smaller `ms-marco-MiniLM-L4-v2` (206.2). As expected, our 150M model lands alongside the two 150M peers (14.0 vs 14.5 and 14.7 pairs per second) now that unpadding no longer applies. If you're CPU-bound, our 17M and 32M are the practical picks.\n\nTo explain where the speed comes from, the next table sweeps `fp32+SDPA`, `bf16+SDPA`, and `bf16+FA2` for our six models using the same bench config. The FA2 column is split in two: one with the inputs still padded (what a wrapped model would see) and one with unpadded inputs (what our modular `Transformer` actually does). The rightmost column is what our models use by default when FA2 is enabled.\n\n**Table 2.** Precision and attention ablation for the six released sizes at `max_length=512` on natural NQ documents. Each cell shows pairs / second with the multiplier relative to `fp32+SDPA` in parentheses, and peak GPU memory on the second line. The rightmost column (in **bold**) is the configuration our models use by default when FA2 is enabled.\n\n| Model                                                                                    | Params | fp32+SDPA           | bf16+SDPA           | bf16+FA2 w. padding | **bf16+FA2 w.o. padding**   |\n| ---------------------------------------------------------------------------------------- | ------ | ------------------- | ------------------- | ------------------- | --------------------------- |\n| [`ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)   | 17M    | 4402 (1.00x) 0.8 GB | 4523 (1.03x) 2.2 GB | 3744 (0.85x) 1.9 GB | **7517 (1.71x)** **1.4 GB** |\n| [`ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)   | 32M    | 3307 (1.00x) 1.2 GB | 4357 (1.32x) 1.6 GB | 3040 (0.92x) 2.9 GB | **6602 (2.00x)** **1.1 GB** |\n| [`ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)   | 68M    | 1364 (1.00x) 1.0 GB | 2861 (2.10x) 2.2 GB | 2003 (1.47x) 2.0 GB | **4913 (3.60x)** **1.5 GB** |\n| [`ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1) | 150M   | 671 (1.00x) 1.6 GB  | 1942 (2.90x) 1.8 GB | 1396 (2.08x) 3.1 GB | **3237 (4.83x)** **1.4 GB** |\n| [`ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1) | 400M   | 266 (1.00x) 2.5 GB  | 1113 (4.18x) 1.8 GB | 864 (3.25x) 2.7 GB  | **1738 (6.53x)** **2.2 GB** |\n| [`ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)     | 1B     | 112 (1.00x) 4.6 GB  | 630 (5.60x) 2.8 GB  | 522 (4.64x) 3.6 GB  | **928 (8.26x)** **4.5 GB**  |\n\nThe total speedup from `bf16+FA2 w.o. padding` over the `fp32+SDPA` baseline grows sharply with model size, from 1.71x on the 17M to 8.26x on the 1B. Most of that growth comes from `bf16` alone: the `fp32+SDPA` to `bf16+SDPA` step gives the 17M only a 1.03x speedup but gives the 1B a full 5.60x speedup, also due to the lowered memory cost allowing for bigger batch sizes. In short, `bfloat16` is the biggest single contributor to the overall speedup.\n\nUnexpectedly, turning on FA2 while the inputs are still padded is actually slower than `bf16+SDPA` at every size in the release. The FA2 kernel prefers an unpadded format, and when you feed it padded inputs you pay the bookkeeping overhead of converting between formats while still spending compute on the padding tokens themselves. So the `bf16+FA2 w. padding` column is roughly what you'd measure if you swapped `sdpa` for `flash_attention_2` in `model_kwargs` without changing anything else about the model loader. This is the situation that `gte-reranker-modernbert-base` and `granite-embedding-reranker-english-r2` from Table 1 are in.\n\nLastly, going from `bf16+FA2 w. padding` to `bf16+FA2 w.o. padding` is worth between 1.78x (1B) and 2.45x (68M) of additional throughput, and it also cuts peak memory considerably, allowing for higher batch sizes.\n\nSo my recommendation is simple: enable `bf16` and FA2 together. The six Ettin rerankers will use unpadded inputs by default, since that's what the modular `Transformer` module from the [Architecture Details](https://huggingface.co/blog/ettin-reranker#architecture-details) section is set up for. The full snippet is the same as in the [Usage](https://huggingface.co/blog/ettin-reranker#usage) section above:\n\n```python\nfrom sentence_transformers import CrossEncoder\n\nmodel = CrossEncoder(\n    \"cross-encoder/ettin-reranker-150m-v1\",\n    model_kwargs={\n        \"dtype\": \"bfloat16\",\n        \"attn_implementation\": \"flash_attention_2\",  # See tip below\n    },\n)\n```\n\n> Use `pip install kernels` to install FA2. It ships pre-built kernels for a wide range of GPU architectures, CUDA versions, and operating systems.\n\nOne caveat for other CrossEncoders: the full speedup is only available for models built with a modular `Transformer` like the Ettin rerankers. Applying the same two flags to a CrossEncoder that loads through `AutoModelForSequenceClassification` lands you in the slower `bf16+FA2 w. padding` column of Table 2 instead.\n\n## Training\n\nThe training script below started as the output of the new [`train-sentence-transformers` Agent Skill](https://github.com/huggingface/sentence-transformers/tree/main/skills), shipped in [Sentence Transformers v5.5.0](https://github.com/huggingface/sentence-transformers/releases/tag/v5.5.0). If you use an AI coding agent (Claude Code, Codex, Cursor, Gemini CLI, ...), you can install the skill and ask it to fine-tune a `SentenceTransformer`, `CrossEncoder`, or `SparseEncoder` model on your data. The skill carries version-aware guidance for base model selection, loss and evaluator choice, hard-negative mining, distillation, LoRA, Matryoshka, multilingual training, and static embeddings, plus template scripts for each model type.\n\n```bash\nhf skills add train-sentence-transformers --claude   # symlinks into .claude/skills/\nhf skills add train-sentence-transformers --global   # under ~/.agents/skills/\n```\n\nA prompt like *\"Fine-tune a cross-encoder reranker on `(query, document)` pairs from my dataset, mine hard negatives, and push to my Hub repo\"* will produce a runnable script you can then iterate on. That's how I started working on the recipe below.\n\nAll six rerankers were trained with the same single-stage recipe. Only the learning rate and the per-device batch size vary per model size. The full training script is ~150 lines and uses one published dataset.\n\nThe recipe converged after a single sweep across model sizes. Each size's learning rate was tuned by a small grid search on a ~15% subset of the final training data, and the resulting LRs transferred cleanly to the full-data runs without re-tuning. No per-size tuning beyond LR was needed.\n\n### Distillation recipe\n\nMost published reranker recipes train on human-labeled relevance triples (a query, one positive document, and optionally hard negatives) with a contrastive, pointwise, pairwise, or listwise loss like [`MultipleNegativesRankingLoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#multiplenegativesrankingloss), [`BinaryCrossEntropyLoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#binarycrossentropyloss), [`RankNetLoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#ranknetloss), or [`LambdaLoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#lambdaloss), respectively. See my earlier [Training and Finetuning Reranker Models with Sentence Transformers](https://huggingface.co/blog/train-reranker) blogpost, for example.\n\nBut this approach has a few practical and theoretical drawbacks. First, positives need to be human-labeled, which is expensive and slow to scale across many domains. Second, the model only ever sees a label for the small subset of `(query, document)` pairs that someone went through. Especially after hard negative mining, you end up with a lot of false negatives, e.g. as shown in [Hard Negatives, Hard Lessons](https://arxiv.org/abs/2505.16967). Third, the binary nature of this labeling doesn't match reality, where some documents are simply more relevant than others.\n\nI took a different route here: pointwise MSE distillation from an existing strong teacher reranker. The setup is simple enough to describe in three lines:\n\n- **Teacher**: [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2) (1.54B parameters).\n- **Loss**: [`MSELoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#mseloss) on the raw teacher logits (range ~\\[−12, 22\\]), i.e. without rescaling.\n- **Training data**: ~143M `(query, document, teacher_score)` triples.\n\n### Dataset\n\nI've released the training data as a single Hugging Face dataset, [`cross-encoder/ettin-reranker-v1-data`](https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data), assembled from two sources. Each source is kept as its own split so the provenance is transparent:\n\n1. LightOn pre-training data ([`lightonai/embeddings-pre-training`](https://huggingface.co/datasets/lightonai/embeddings-pre-training), non-curated): 32 splits covering broad-domain text similarity signal (MTP, FW-EDU, Reddit, PAQ, S2ORC, Amazon, Wikipedia, MS MARCO, etc.). I limit the number of samples for some of the splits, resulting in ~110M `(query, document, similarity)` triples in total.\n2. Rescored retrieval data from [`lightonai/embeddings-fine-tuning`](https://huggingface.co/datasets/lightonai/embeddings-fine-tuning): 7 splits (`msmarco`, `hotpotqa`, `trivia`, `nq`, `squadv2`, `fiqa`, `fever`). The source dataset has up to 2048 candidate documents per query (initially scored with [`Alibaba-NLP/gte-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-modernbert-base)), which I rescored with [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2) and uploaded as [`cross-encoder/lightonai-embeddings-fine-tuning-reranked-v1`](https://huggingface.co/datasets/cross-encoder/lightonai-embeddings-fine-tuning-reranked-v1). That dataset subsamples each query's 2048 candidates down to 256 using the [Jang et al.](https://arxiv.org/abs/2604.04734) quantile-anchor recipe (all positives + top-16 hard + ~239 quantile-anchor stratified). For training, I pick 64 of those 256 per query: 32 from the score-sorted head (the positive plus the hardest negatives) and 32 medium-difficulty negatives sampled from a band further down the teacher's ranking. See the [dataset card](https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data) for the exact rank positions.\n\nTotal: ~143M `(query, document, score)` triples, plus a held-out 5K-row eval split (the tail of `quora`) that drives the in-training eval loss.\n\n### Training Arguments\n\nMost hyperparameters are constant across model sizes:\n\n```python\nCrossEncoderTrainingArguments(\n    num_train_epochs=1,                    # I chose more data over more epochs\n    per_device_train_batch_size=...,       # global_batch_size // world_size (see table below)\n    gradient_accumulation_steps=1,\n    learning_rate=...,                     # per-size, see table\n    warmup_ratio=0.03,                     # ~3% linear warmup, then linear decay (default)\n    bf16=True,                             # FA2 + bf16 throughout\n    eval_strategy=\"steps\",\n    eval_steps=0.05,                       # NanoBEIR every 5% of training\n    save_strategy=\"steps\",\n    save_steps=0.05,\n    save_total_limit=5,\n    load_best_model_at_end=True,\n    metric_for_best_model=\"eval_NanoBEIR_R100_mean_ndcg@10\",\n    seed=12,\n)\n```\n\nOnly the learning rate and global batch size very per model size.\n\n| Size | Learning rate | Global batch size |\n| ---- | ------------- | ----------------- |\n| 17m  | 2.4e-4        | 1024              |\n| 32m  | 1.2e-4        | 512               |\n| 68m  | 3e-5          | 256               |\n| 150m | 1.5e-5        | 192               |\n| 400m | 7e-6          | 256               |\n| 1b   | 3e-6          | 512               |\n\n`global_batch_size` is `per_device_batch_size x world_size x gradient_accumulation_steps`. On a single 8-GPU node, the 1024 global batch for 17m means `per_device=128`. On 8 nodes, it means `per_device=8`. The training script computes `per_device_batch_size` from `global_batch_size // world_size` so the same script works at any node count. The global batch size could be made more consistent, but I found that the above values worked well and didn't want to retune them just for the sake of consistency.\n\n### Evaluation\n\nI monitored NanoBEIR mean NDCG@10 during training (eval every 5% of steps) and used it as the `metric_for_best_model` for `load_best_model_at_end`. NanoBEIR is fast, so I could afford it 20 times per training run. After training, I evaluated both the best checkpoint (according to NanoBEIR) and the last checkpoint on the full MTEB(eng, v2) Retrieval benchmark. The final release checkpoint was the one that did best on MTEB. The NanoBEIR-preferred checkpoint won for all sizes except 68m, where the last checkpoint was slightly stronger.\n\n### Overall Training Script\n\nThe complete script (what every released model was trained with) is a single file. Only `ENCODER_SIZE` changes per run, and everything else is automatic:\n\n```python\nfrom __future__ import annotations\n\nimport logging\nimport os\nfrom pathlib import Path\n\nimport torch\nimport torch.nn as nn\nfrom datasets import concatenate_datasets, get_dataset_config_names, load_dataset\n\nfrom sentence_transformers import CrossEncoder\nfrom sentence_transformers.base.modules import Dense\nfrom sentence_transformers.cross_encoder import (\n    CrossEncoderModelCardData,\n    CrossEncoderTrainer,\n    CrossEncoderTrainingArguments,\n)\nfrom sentence_transformers.cross_encoder.evaluation import CrossEncoderNanoBEIREvaluator\nfrom sentence_transformers.cross_encoder.losses import MSELoss\nfrom sentence_transformers.sentence_transformer.modules import LayerNorm, Pooling, Transformer\n\nlogging.basicConfig(level=logging.INFO, format=\"%(asctime)s %(message)s\", datefmt=\"%H:%M:%S\")\nlogging.getLogger(\"httpx\").setLevel(logging.WARNING)\n\n# Per-size config. I swept the learning rates with these global (effective) batch sizes,\n# also by incorporating accum_steps\nCONFIGS: dict[str, dict] = {\n    \"17m\":  {\"base_model_name\": \"jhu-clsp/ettin-encoder-17m\",  \"learning_rate\": 2.4e-4, \"global_batch_size\": 1024},\n    \"32m\":  {\"base_model_name\": \"jhu-clsp/ettin-encoder-32m\",  \"learning_rate\": 1.2e-4, \"global_batch_size\": 512},\n    \"68m\":  {\"base_model_name\": \"jhu-clsp/ettin-encoder-68m\",  \"learning_rate\": 3e-5,   \"global_batch_size\": 256},\n    \"150m\": {\"base_model_name\": \"jhu-clsp/ettin-encoder-150m\", \"learning_rate\": 1.5e-5, \"global_batch_size\": 192},\n    \"400m\": {\"base_model_name\": \"jhu-clsp/ettin-encoder-400m\", \"learning_rate\": 7e-6,   \"global_batch_size\": 256},\n    \"1b\":   {\"base_model_name\": \"jhu-clsp/ettin-encoder-1b\",   \"learning_rate\": 3e-6,   \"global_batch_size\": 512},\n}\nENCODER_SIZE = \"17m\"\n\ndef main() -> None:\n    config = CONFIGS[ENCODER_SIZE]\n    encoder_id = config[\"base_model_name\"]\n    learning_rate = config[\"learning_rate\"]\n    global_batch_size = config[\"global_batch_size\"]\n\n    world_size = int(os.environ.get(\"WORLD_SIZE\", 1))\n    per_device_batch_size = global_batch_size // world_size\n    dataloader_workers = 0 if world_size > 8 else 4\n    run_name = f\"ettin-reranker-{ENCODER_SIZE}-lr{learning_rate:.0e}\"\n\n    # 1. Load a model to finetune with model card data\n    # The model mirrors ModernBertForSequenceClassification, but with a 'headless' Transformer that just loads\n    # AutoModel. This allows for unpadding with FA2, which isn't possible with AutoModelForSequenceClassification.\n    # This speeds up training considerably, while heavily reducing memory usage.\n    torch.manual_seed(12)\n    transformer = Transformer(encoder_id, model_kwargs={\"attn_implementation\": \"flash_attention_2\"})\n    transformer.model.config.num_labels = 1\n    embedding_dimension = transformer.get_embedding_dimension()\n    pooling = Pooling(embedding_dimension=embedding_dimension, pooling_mode=\"cls\")\n    dense_inner = Dense(\n        in_features=embedding_dimension, out_features=embedding_dimension, bias=False,\n        activation_function=nn.GELU(),\n        module_input_name=\"sentence_embedding\", module_output_name=\"sentence_embedding\",\n    )\n    norm = LayerNorm(dimension=embedding_dimension)\n    dense_score = Dense(\n        in_features=embedding_dimension, out_features=1, bias=True,\n        activation_function=nn.Identity(),\n        module_input_name=\"sentence_embedding\", module_output_name=\"scores\",\n    )\n    model = CrossEncoder(\n        modules=[transformer, pooling, dense_inner, norm, dense_score],\n        num_labels=1,\n        activation_fn=nn.Identity(),\n        model_card_data=CrossEncoderModelCardData(\n            model_name=f\"Ettin Reranker {ENCODER_SIZE} distilled from mxbai-rerank-large-v2\",\n            language=\"en\",\n            license=\"apache-2.0\",\n        ),\n    )\n    actual_attn = getattr(model[0].model.config, \"_attn_implementation\", None)\n    if not (actual_attn and \"flash\" in actual_attn.lower()):\n        logging.warning(f\"FA2 may not be active (attn_impl={actual_attn!r}); training will be slower.\")\n\n    # 2. Load the dataset. Each config is one source subset (32 lighton + 7 rerank retrieval\n    # domains). The held-out eval rows live as the 'validation' split of the 'quora' config.\n    dataset_repo = \"cross-encoder/ettin-reranker-v1-data\"\n    train_pieces = []\n    eval_dataset = None\n    for config_name in get_dataset_config_names(dataset_repo):\n        dataset = load_dataset(dataset_repo, config_name)\n        train_pieces.append(dataset[\"train\"])\n        if \"validation\" in dataset:\n            eval_dataset = dataset[\"validation\"]\n    train_dataset = concatenate_datasets(train_pieces)\n    print(train_dataset)\n\n    # 3. Define a loss function\n    loss = MSELoss(model)\n\n    # 4. Specify training arguments\n    args = CrossEncoderTrainingArguments(\n        output_dir=f\"models/{run_name}\",\n        num_train_epochs=1,\n        per_device_train_batch_size=per_device_batch_size,\n        per_device_eval_batch_size=per_device_batch_size,\n        gradient_accumulation_steps=1,\n        learning_rate=learning_rate,\n        warmup_ratio=0.03,\n        bf16=True,\n        eval_strategy=\"steps\",\n        eval_steps=0.05,\n        save_strategy=\"steps\",\n        save_steps=0.05,\n        save_total_limit=5,\n        logging_steps=0.025,\n        logging_first_step=True,\n        load_best_model_at_end=True,\n        metric_for_best_model=\"eval_NanoBEIR_R100_mean_ndcg@10\",\n        dataloader_num_workers=dataloader_workers,\n        run_name=run_name,\n        seed=12,\n    )\n\n    # 5. Create an evaluator\n    evaluator = CrossEncoderNanoBEIREvaluator(\n        dataset_names=[\"msmarco\", \"nfcorpus\", \"nq\", \"fiqa2018\", \"touche2020\", \"scifact\",\n                       \"hotpotqa\", \"arguana\", \"fever\", \"dbpedia\", \"climatefever\", \"scidocs\",\n                       \"quoraretrieval\"],\n        batch_size=per_device_batch_size,\n        always_rerank_positives=False,\n        show_progress_bar=False,\n    )\n\n    # 6. Create a trainer\n    trainer = CrossEncoderTrainer(\n        model=model,\n        args=args,\n        train_dataset=train_dataset,\n        eval_dataset=eval_dataset,\n        loss=loss,\n        evaluator=evaluator,\n    )\n\n    # 7. Evaluate before training\n    if trainer.is_world_process_zero():\n        with torch.autocast(device_type=\"cuda\", dtype=torch.bfloat16):\n            evaluator(model)\n\n    # 8. Train\n    trainer.train()\n\n    # 9. Evaluate the final model\n    if trainer.is_world_process_zero():\n        with torch.autocast(device_type=\"cuda\", dtype=torch.bfloat16):\n            evaluator(model)\n\n    # 10. Save the final model\n    final_dir = f\"models/{run_name}/final\"\n    model.save_pretrained(final_dir)\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\nFor multi-node training (anything past 17m/32m), launch the same script with `torchrun`:\n\n```bash\n# Single-node (17m, 32m): defaults work\npython train.py\n\n# Multi-node 4n setup for 150m, preserves global_batch_size=192:\ntorchrun --nproc_per_node=8 --nnodes=4 ... train.py\n```\n\n## Conclusion\n\nThe ettin-reranker-v1 family, trained with a single simple recipe, is state-of-the-art at every released size up to 1B parameters. Pointwise MSE distillation from a strong teacher onto a broad-domain and retrieval-specific mix scales cleanly from 17M to 1B parameters, with only the learning rate and per-device batch size changing between sizes.\n\nEvery ettin-reranker-v1 model beats the `ms-marco-MiniLM-L*-v2` family by a comfortable margin on MTEB and NanoBEIR. `cross-encoder/ettin-reranker-150m-v1` is the strongest mid-tier reranker I tested in the under-600M range, `cross-encoder/ettin-reranker-400m-v1` lands within 0.0024 of the 1.54B teacher's MTEB score, and `cross-encoder/ettin-reranker-1b-v1` matches that teacher within 0.0001.\n\nEverything in one place:\n\n- **Models**:\n  - [`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)\n  - [`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)\n  - [`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)\n  - [`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)\n  - [`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)\n  - [`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)\n- **Dataset**: [`cross-encoder/ettin-reranker-v1-data`](https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data) with ~143M `(query, document, label)` triples, kept as 39 named splits so the provenance of every row is visible.\n- **Training script**: the ~150 lines in [Overall Training Script](https://huggingface.co/blog/ettin-reranker#overall-training-script) above, which is the same script used for all six models.\n\nIf you build something on top of these, please let me know! I'd genuinely love to see what people do with them, and if you manage to train better rerankers using the released data, even better. The recipe is intentionally simple, partly so that there's plenty of headroom for someone else to improve it. Train a stronger teacher and the same script can keep producing better students.\n\n## Acknowledgements\n\nI'd like to thank the Ettin team (Orion Weller, Kathryn Ricci, Marc Marone, Antoine Chaffin, Dawn Lawrie, and Benjamin Van Durme) for [building the base encoders](https://huggingface.co/blog/ettin) that these rerankers are built on, the LightOn team (Antoine Chaffin, Raphael Sourty, Paulo Moura, and Amélie Chatelain) for [their work on the training data collection](https://huggingface.co/blog/lightonai/denseon-lateon), and the Mixedbread AI team (Xianming Li, Aamir Shakir, Rui Huang, Tsz-fung Andrew Lee, Julius Lipp, Benjamin Clavié, and Jing Li) for [their work on the teacher model](https://arxiv.org/abs/2506.03487).\n\n## Citation\n\nIf you use the ettin-reranker-v1 family or any of the released artifacts, please cite this blogpost:\n\n```bibtex\n@misc{aarsen2026ettin-reranker,\n    title = \"Introducing the Ettin Reranker Family\",\n    author = \"Aarsen, Tom\",\n    year = \"2026\",\n    publisher = \"Hugging Face\",\n    url = \"https://huggingface.co/blog/ettin-reranker\",\n}\n```\n",
  "authors": [],
  "captured_at": "2026-10-19T01:26:53.998049939+00:00",
  "category": "ai",
  "content_html": "<h2>TL;DR</h2>\n<p>Today I'm releasing six new <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://sbert.net/\">Sentence Transformers</a> CrossEncoder rerankers, state-of-the-art at their respective sizes, built on top of the <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/collections/jhu-clsp/encoders-vs-decoders-the-ettin-suite\">Ettin</a> ModernBERT encoders, together with the data and full training recipe that produced them:</p>\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>cross-encoder/ettin-reranker-17m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>cross-encoder/ettin-reranker-68m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>cross-encoder/ettin-reranker-150m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>cross-encoder/ettin-reranker-400m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>cross-encoder/ettin-reranker-1b-v1</code></a></li>\n</ul>\n<p>The models were trained with a <strong>distillation recipe</strong>: pointwise MSE on <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2\"><code>mixedbread-ai/mxbai-rerank-large-v2</code></a> scores over <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data\"><code>cross-encoder/ettin-reranker-v1-data</code></a>, which is a subset of <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/lightonai/embeddings-pre-training\"><code>lightonai/embeddings-pre-training</code></a> mixed with a reranked subset of <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/lightonai/embeddings-fine-tuning\"><code>lightonai/embeddings-fine-tuning</code></a>.</p>\n<p><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png\" alt=\"Our six rerankers paired with embeddinggemma-300m on MTEB(eng, v2) Retrieval\" loading=\"eager\" decoding=\"async\" fetchpriority=\"high\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture></a></p>\n<p><em>Our six rerankers paired with <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/google/embeddinggemma-300m\"><code>google/embeddinggemma-300m</code></a> on MTEB(eng, v2) Retrieval. See <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#results\">Results</a> for five more embedder pairings.</em></p>\n<p>If you're new to rerankers and want the &quot;why&quot; first, jump to <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#what-is-a-reranker-and-why-pair-one-with-an-embedder\">What is a reranker, and why pair one with an embedder?</a>. If you just want to plug a model in, jump to <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#usage\">Usage</a>. If you want to train your own, jump to <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#training\">Training</a>.</p>\n<blockquote>\n<p>I bootstrapped the training recipe below with the new <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/huggingface/sentence-transformers/tree/main/skills\"><code>train-sentence-transformers</code> Agent Skill</a> shipped in <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/huggingface/sentence-transformers/releases/tag/v5.5.0\">Sentence Transformers v5.5.0</a>. Install it with <code>hf skills add train-sentence-transformers [--global] [--claude]</code> and ask your AI coding agent (Claude Code, Codex, Cursor, Gemini CLI, ...) to fine-tune a <code>SentenceTransformer</code>, <code>CrossEncoder</code>, or <code>SparseEncoder</code> model on your data.</p>\n</blockquote>\n<h2>Table of contents</h2>\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#what-is-a-reranker-and-why-pair-one-with-an-embedder\">What is a reranker, and why pair one with an embedder?</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#usage\">Usage</a>\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#end-to-end-retrieve-then-rerank-pipeline\">End-to-end retrieve-then-rerank pipeline</a></li>\n</ul>\n</li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#architecture-details\">Architecture Details</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#results\">Results</a>\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#mtebeng-v2-retrieval\">MTEB(eng, v2) Retrieval</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#speed\">Speed</a></li>\n</ul>\n</li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#training\">Training</a>\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#distillation-recipe\">Distillation recipe</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#dataset\">Dataset</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#training-arguments\">Training Arguments</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#evaluation\">Evaluation</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#overall-training-script\">Overall Training Script</a></li>\n</ul>\n</li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#conclusion\">Conclusion</a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#acknowledgements\">Acknowledgements</a></li>\n</ul>\n<h2>What is a reranker, and why pair one with an embedder?</h2>\n<p>A reranker (a.k.a. pointwise cross-encoder) is a neural model that takes a <code>(query, document)</code> pair and outputs a single relevance score. Unlike an embedding model, which encodes the query and document separately and computes their similarity from the two embedding vectors, a reranker lets the two texts attend to each other through every transformer layer. That joint encoding is more accurate but also more expensive: the model has to be run once per <code>(query, document)</code> pair rather than once per text.</p>\n<p>Because cross-encoders are too expensive to run over a full corpus, the common production pattern is <strong>retrieve-then-rerank</strong>: a fast embedding model retrieves the top-K candidates (cheap), then a cross-encoder re-orders just those K with high accuracy. The total cost stays bounded while the final ranking is much closer to what an exhaustive cross-encoder pass would produce.</p>\n<p><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/train-reranker/embedding_vs_reranker_model.png\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/train-reranker/embedding_vs_reranker_model.png\" alt=\"Embedding vs Reranker Models\" loading=\"lazy\" decoding=\"async\" fetchpriority=\"low\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture></a></p>\n<blockquote>\n<p>Throughout this blogpost I'll use &quot;reranker&quot; and &quot;cross-encoder&quot; interchangeably.</p>\n</blockquote>\n<h2>Usage</h2>\n<p>The released models are normal Sentence Transformers <code>CrossEncoder</code> models, so you can use them with just 3 lines of code:</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoder</span></span>\n\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoder</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">cross-encoder/ettin-reranker-32m-v1<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">scores</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">predict</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span>\n    <span class=\"syntax-meta syntax-group syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Where was Apple founded?<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-tuple syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-group syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Where was Apple founded?<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-tuple syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">The Fuji apple is an apple cultivar developed in the late 1930s and brought to market in 1962.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n<span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-function syntax-builtin syntax-python\">print</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">scores</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> [11.393298  2.968891]   &lt;- larger means more relevant\n</span></span></span></code></pre>\n<p>For a query and a list of candidates, you can also use <code>rank</code> to get back sorted indices and scores:</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">ranked</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">rank</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n    <span class=\"syntax-variable syntax-parameter syntax-python\">query</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Which planet is known as the Red Planet?<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">documents</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span>\n        <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Venus is often called Earth&#39;s twin because of its similar size and proximity.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n        <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Mars, known for its reddish appearance, is often referred to as the Red Planet.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n        <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Jupiter, the largest planet in our solar system, has a prominent red spot.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n        <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Saturn, famous for its rings, is sometimes mistaken for the Red Planet.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n    <span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">top_k</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">4</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">return_documents</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-statement syntax-for syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-for syntax-python\">for</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">r</span> <span class=\"syntax-meta syntax-statement syntax-for syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-for syntax-in syntax-python\">in</span></span></span><span class=\"syntax-meta syntax-statement syntax-for syntax-python\"> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">ranked</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-for syntax-python\">:</span></span>\n    <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-function syntax-builtin syntax-python\">print</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-storage syntax-type syntax-string syntax-python\">f</span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">(</span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">r</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-single syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&#39;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-single syntax-python\">score<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&#39;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span></span><span class=\"syntax-meta syntax-format-spec syntax-python\"><span class=\"syntax-constant syntax-other syntax-format-spec syntax-python\">:.2f</span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">): </span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">r</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-single syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&#39;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-single syntax-python\">text<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&#39;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> (10.82): Mars, known for its reddish appearance, is often referred to as the Red Planet.\n</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> (9.86): Saturn, famous for its rings, is sometimes mistaken for the Red Planet.\n</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> (8.55): Jupiter, the largest planet in our solar system, has a prominent red spot.\n</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> (6.21): Venus is often called Earth&#39;s twin because of its similar size and proximity.\n</span></span></span></code></pre>\n<p>You can swap <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a> for any other size to trade quality for speed. All six accept up to 8K tokens of context (useful for long-document reranking) thanks to ModernBERT's long-context pre-training.</p>\n<p>It is recommended to install <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/huggingface/kernels\"><code>kernels</code></a> and set <code>model_kwargs={&quot;dtype&quot;: &quot;bfloat16&quot;, &quot;attn_implementation&quot;: &quot;flash_attention_2&quot;}</code> for the highest throughput. See the <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#speed\">Speed</a> section below for more details, but in general you can expect a 1.7x-8.3x speedup over default loading depending on model size and sequence length.</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoder</span></span>\n\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoder</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">cross-encoder/ettin-reranker-32m-v1<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">model_kwargs</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">dtype<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">bfloat16<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">attn_implementation<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">flash_attention_2<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n</span></span></code></pre>\n<h3>End-to-end retrieve-then-rerank pipeline</h3>\n<p>A complete example with a fast embedder for retrieval and the reranker for the final ordering:</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">SentenceTransformer</span><span class=\"syntax-punctuation syntax-separator syntax-import-list syntax-python\">,</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoder</span></span>\n\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Fast retrieval with a static embedder (sub-millisecond on CPU per query)\n</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedder</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">SentenceTransformer</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">sentence-transformers/static-retrieval-mrl-en-v1<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">reranker</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoder</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">cross-encoder/ettin-reranker-68m-v1<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">corpus</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">The Fuji apple is an apple cultivar developed in the late 1930s.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Steve Jobs introduced the iPhone in 2007 at Macworld.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Macintosh computers were sold by Apple from 1984 onward.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> ... thousands or millions more in production\n</span><span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span>\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">query</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Where was Apple founded?<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span>\n\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Step 1: encode + retrieve top-100\n</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">query_emb</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedder</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">encode_query</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">query</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">convert_to_tensor</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">corpus_emb</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedder</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">encode_document</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">corpus</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">convert_to_tensor</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">scores</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedder</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">similarity</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">query_emb</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">corpus_emb</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">0</span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span>\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">top_k_idx</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">scores</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">topk</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-function syntax-builtin syntax-python\">min</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">100</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-function syntax-builtin syntax-python\">len</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">corpus</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">indices</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">tolist</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Step 2: rerank\n</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">top_k_docs</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">corpus</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">i</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span> <span class=\"syntax-meta syntax-expression syntax-generator syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-for syntax-generator syntax-python\">for</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">i</span> <span class=\"syntax-keyword syntax-control syntax-flow syntax-for syntax-in syntax-python\">in</span></span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">top_k_idx</span></span><span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span>\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">ranked</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">reranker</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">rank</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">query</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">top_k_docs</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">top_k</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">5</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">return_documents</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-statement syntax-for syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-for syntax-python\">for</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">r</span> <span class=\"syntax-meta syntax-statement syntax-for syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-for syntax-in syntax-python\">in</span></span></span><span class=\"syntax-meta syntax-statement syntax-for syntax-python\"> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">ranked</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-for syntax-python\">:</span></span>\n    <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-function syntax-builtin syntax-python\">print</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-storage syntax-type syntax-string syntax-python\">f</span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">(</span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">r</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-single syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&#39;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-single syntax-python\">score<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&#39;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span></span><span class=\"syntax-meta syntax-format-spec syntax-python\"><span class=\"syntax-constant syntax-other syntax-format-spec syntax-python\">:.2f</span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">): </span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">r</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-single syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&#39;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-single syntax-python\">text<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&#39;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> (11.63): Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.\n</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> (4.71): Steve Jobs introduced the iPhone in 2007 at Macworld.\n</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> (1.96): The Fuji apple is an apple cultivar developed in the late 1930s.\n</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> (1.49): Macintosh computers were sold by Apple from 1984 onward.\n</span></span></span></code></pre>\n<p>This is the same shape used by most modern search systems. The retriever decides what enters the funnel, the reranker decides what wins.</p>\n<h2>Architecture Details</h2>\n<p>All six rerankers share the same architecture and differ only in their backbone size. The backbone is one of the six <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin\">Ettin encoders</a> from Johns Hopkins University's Ettin suite. These are ModernBERT-style models with unpadded attention, RoPE positional encodings, GeGLU, and 2T tokens of open-license pre-training, supporting up to 8192 tokens of context.</p>\n<p>On top of each encoder, the reranker uses a 4-module classification head that mirrors <code>ModernBertForSequenceClassification</code> but is built from Sentence Transformers' modular components. The underlying <code>Transformer</code> is a plain <code>AutoModel</code> rather than <code>AutoModelForSequenceClassification</code>, which lets us use sequence unpadding for variable-length inputs for Flash Attention 2. At medium-document sequence lengths this is a 1.7x-8.3x speedup over fp32+SDPA depending on model size (see <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#speed\">Speed</a> for the full benchmark):</p>\n<pre><code><span class=\"code-snippet\">1. Transformer(FA2)\n2. Pooling(cls)\n3. Dense(H, H, bias=False, GELU)\n4. LayerNorm(H)\n5. Dense(H, 1, scores)\n</span></code></pre>\n<p>In my ablations, CLS pooling outperformed mean pooling. That was a little surprising. ModernBERT uses global attention only every third layer and the other two-thirds use local-window attention that cannot reach CLS from distant positions. Empirically, those few global layers carry enough signal to make CLS the better pooling choice.</p>\n<table>\n<thead>\n<tr>\n<th>Model</th>\n<th>Backbone</th>\n<th>Hidden size</th>\n<th>Layers</th>\n<th>Params (head incl.)</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>cross-encoder/ettin-reranker-17m-v1</code></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jhu-clsp/ettin-encoder-17m\"><code>jhu-clsp/ettin-encoder-17m</code></a></td>\n<td>256</td>\n<td>7</td>\n<td>17.6M</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jhu-clsp/ettin-encoder-32m\"><code>jhu-clsp/ettin-encoder-32m</code></a></td>\n<td>384</td>\n<td>10</td>\n<td>32.8M</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>cross-encoder/ettin-reranker-68m-v1</code></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jhu-clsp/ettin-encoder-68m\"><code>jhu-clsp/ettin-encoder-68m</code></a></td>\n<td>512</td>\n<td>19</td>\n<td>68.6M</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>cross-encoder/ettin-reranker-150m-v1</code></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jhu-clsp/ettin-encoder-150m\"><code>jhu-clsp/ettin-encoder-150m</code></a></td>\n<td>768</td>\n<td>22</td>\n<td>150.9M</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>cross-encoder/ettin-reranker-400m-v1</code></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jhu-clsp/ettin-encoder-400m\"><code>jhu-clsp/ettin-encoder-400m</code></a></td>\n<td>1024</td>\n<td>28</td>\n<td>401.6M</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>cross-encoder/ettin-reranker-1b-v1</code></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jhu-clsp/ettin-encoder-1b\"><code>jhu-clsp/ettin-encoder-1b</code></a></td>\n<td>1792</td>\n<td>28</td>\n<td>1.00B</td>\n</tr>\n</tbody>\n</table>\n<p>All six models are released under the <strong>Apache 2.0</strong> license, matching the Ettin encoders.</p>\n<h2>Results</h2>\n<h3>MTEB(eng, v2) Retrieval</h3>\n<p>I ran each released model through the full <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/embeddings-benchmark/mteb\"><code>MTEB(eng, v2)</code> Retrieval benchmark</a> (10 tasks, top-100 reranked) using MTEB's <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://embeddings-benchmark.github.io/mteb/get_started/advanced_usage/two_stage_reranking/\">two-stage reranking flow</a>, pairing each reranker with six embedding models that span the speed/quality spectrum:</p>\n<table>\n<thead>\n<tr>\n<th>Embedding Model</th>\n<th>Active params</th>\n<th>Retriever-only NDCG@10</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/sentence-transformers/static-retrieval-mrl-en-v1\"><code>sentence-transformers/static-retrieval-mrl-en-v1</code></a></td>\n<td>0M</td>\n<td>0.3495</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2\"><code>sentence-transformers/all-MiniLM-L6-v2</code></a></td>\n<td>23M</td>\n<td>0.4292</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-small-en-v1.5\"><code>BAAI/bge-small-en-v1.5</code></a></td>\n<td>33M</td>\n<td>0.5149</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/nomic-ai/nomic-embed-text-v1.5\"><code>nomic-ai/nomic-embed-text-v1.5</code></a></td>\n<td>137M</td>\n<td>0.5226</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/google/embeddinggemma-300m\"><code>google/embeddinggemma-300m</code></a></td>\n<td>308M</td>\n<td>0.5463</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jinaai/jina-embeddings-v5-text-small-retrieval\"><code>jinaai/jina-embeddings-v5-text-small-retrieval</code></a></td>\n<td>596M</td>\n<td>0.5980</td>\n</tr>\n</tbody>\n</table>\n<p>The <strong>dashed retriever-only line</strong> in each chart below is the headline number to beat. Anything below it means the reranker actively hurts the pipeline on average:</p>\n<table>\n<thead>\n<tr>\n<th></th>\n<th></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_static-retrieval-mrl-en-v1.png\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_static-retrieval-mrl-en-v1.png\" alt=\"MTEB(eng, v2) Retrieval with static-retrieval-mrl-en-v1 + reranker\" loading=\"lazy\" decoding=\"async\" fetchpriority=\"low\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_all-MiniLM-L6-v2.png\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_all-MiniLM-L6-v2.png\" alt=\"MTEB(eng, v2) Retrieval with all-MiniLM-L6-v2 + reranker\" loading=\"lazy\" decoding=\"async\" fetchpriority=\"low\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture></a></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_bge-small-en-v1.5.png\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_bge-small-en-v1.5.png\" alt=\"MTEB(eng, v2) Retrieval with bge-small-en-v1.5 + reranker\" loading=\"lazy\" decoding=\"async\" fetchpriority=\"low\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_nomic-embed-text-v1.5.png\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_nomic-embed-text-v1.5.png\" alt=\"MTEB(eng, v2) Retrieval with nomic-embed-text-v1.5 + reranker\" loading=\"lazy\" decoding=\"async\" fetchpriority=\"low\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture></a></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png\" alt=\"MTEB(eng, v2) Retrieval with embeddinggemma-300m + reranker\" loading=\"lazy\" decoding=\"async\" fetchpriority=\"low\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture></a></td>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_jina-embeddings-v5-text-small-retrieval.png\"><picture class=\"article-picture article-picture-fallback\" style=\"--image-ratio:16 / 9\"><img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_jina-embeddings-v5-text-small-retrieval.png\" alt=\"MTEB(eng, v2) Retrieval with jina-embeddings-v5-text-small-retrieval + reranker\" loading=\"lazy\" decoding=\"async\" fetchpriority=\"low\" referrerpolicy=\"no-referrer\" class=\"progressive-image\"></picture></a></td>\n</tr>\n</tbody>\n</table>\n<p>Full table of results (click to expand)</p>\n<p>Mean NDCG@10 over the 6 embedder pairings, sorted descending. Our six models are in <strong>bold</strong>, and the teacher <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2\"><code>mixedbread-ai/mxbai-rerank-large-v2</code></a> is underlined.</p>\n<table>\n<thead>\n<tr>\n<th>Reranker</th>\n<th>Params</th>\n<th>MTEB(eng, v2) Retrieval NDCG@10</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Qwen/Qwen3-Reranker-4B\"><code>Qwen/Qwen3-Reranker-4B</code></a>†</td>\n<td>4.02B</td>\n<td>0.6367</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2\"><code>mixedbread-ai/mxbai-rerank-large-v2</code></a></td>\n<td>1.54B</td>\n<td>0.6115</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>cross-encoder/ettin-reranker-1b-v1</code></a></strong></td>\n<td><strong>1.00B</strong></td>\n<td><strong>0.6114</strong></td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>cross-encoder/ettin-reranker-400m-v1</code></a></strong></td>\n<td><strong>401M</strong></td>\n<td><strong>0.6091</strong></td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>cross-encoder/ettin-reranker-150m-v1</code></a></strong></td>\n<td><strong>151M</strong></td>\n<td><strong>0.5994</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Qwen/Qwen3-Reranker-0.6B\"><code>Qwen/Qwen3-Reranker-0.6B</code></a></td>\n<td>596M</td>\n<td>0.5940</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2\"><code>mixedbread-ai/mxbai-rerank-base-v2</code></a></td>\n<td>494M</td>\n<td>0.5920</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>cross-encoder/ettin-reranker-68m-v1</code></a></strong></td>\n<td><strong>68.6M</strong></td>\n<td><strong>0.5915</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jinaai/jina-reranker-m0\"><code>jinaai/jina-reranker-m0</code></a></td>\n<td>2.44B</td>\n<td>0.5856</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base\"><code>Alibaba-NLP/gte-reranker-modernbert-base</code></a></td>\n<td>150M</td>\n<td>0.5843</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a></strong></td>\n<td><strong>32.8M</strong></td>\n<td><strong>0.5779</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2\"><code>ibm-granite/granite-embedding-reranker-english-r2</code></a></td>\n<td>150M</td>\n<td>0.5656</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>cross-encoder/ettin-reranker-17m-v1</code></a></strong></td>\n<td><strong>17.6M</strong></td>\n<td><strong>0.5576</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-v2-m3\"><code>BAAI/bge-reranker-v2-m3</code></a></td>\n<td>568M</td>\n<td>0.5526</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/zeroentropy/zerank-2-reranker\"><code>zeroentropy/zerank-2-reranker</code></a>†</td>\n<td>4.02B</td>\n<td>0.5300</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-large\"><code>BAAI/bge-reranker-large</code></a></td>\n<td>560M</td>\n<td>0.5098</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2\"><code>cross-encoder/ms-marco-MiniLM-L6-v2</code></a></td>\n<td>22.7M</td>\n<td>0.5082</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2\"><code>cross-encoder/ms-marco-MiniLM-L12-v2</code></a></td>\n<td>33.4M</td>\n<td>0.5066</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1\"><code>mixedbread-ai/mxbai-rerank-large-v1</code></a></td>\n<td>435M</td>\n<td>0.5063</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2\"><code>cross-encoder/ms-marco-MiniLM-L4-v2</code></a></td>\n<td>19.2M</td>\n<td>0.4979</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1\"><code>mixedbread-ai/mxbai-rerank-xsmall-v1</code></a></td>\n<td>70.8M</td>\n<td>0.4968</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-base\"><code>BAAI/bge-reranker-base</code></a></td>\n<td>278M</td>\n<td>0.4890</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1\"><code>mixedbread-ai/mxbai-rerank-base-v1</code></a></td>\n<td>184M</td>\n<td>0.4865</td>\n</tr>\n</tbody>\n</table>\n<p>† Capped to <code>max_seq_length=8192</code> (the 4B Qwen3-based rerankers don't fit on a single H100 80GB at native context). Native-context evaluation is likely higher.</p>\n<p>Full table of NanoBEIR results (click to expand)</p>\n<p><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/collections/sentence-transformers/nanobeir-with-bm25-rankings\">NanoBEIR</a> is a fast 13-dataset subset of <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/beir-cellar/beir\">BEIR</a> that uses 50 queries per dataset against up to 5000 documents each. NanoBEIR is what <code>metric_for_best_model</code> was set to during training (see <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#evaluation\">Evaluation</a>), and what I used to guide the experimentation.</p>\n<table>\n<thead>\n<tr>\n<th>Reranker</th>\n<th>Params</th>\n<th>NanoBEIR mean NDCG@10</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2\"><code>mixedbread-ai/mxbai-rerank-large-v2</code></a></td>\n<td>1.54B</td>\n<td>0.7318</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>cross-encoder/ettin-reranker-1b-v1</code></a></strong></td>\n<td><strong>1.00B</strong></td>\n<td><strong>0.7237</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/jinaai/jina-reranker-m0\"><code>jinaai/jina-reranker-m0</code></a></td>\n<td>2.44B</td>\n<td>0.7197</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>cross-encoder/ettin-reranker-400m-v1</code></a></strong></td>\n<td><strong>401M</strong></td>\n<td><strong>0.7193</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2\"><code>mixedbread-ai/mxbai-rerank-base-v2</code></a></td>\n<td>494M</td>\n<td>0.7162</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>cross-encoder/ettin-reranker-150m-v1</code></a></strong></td>\n<td><strong>151M</strong></td>\n<td><strong>0.7086</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base\"><code>Alibaba-NLP/gte-reranker-modernbert-base</code></a></td>\n<td>150M</td>\n<td>0.7017</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-v2-m3\"><code>BAAI/bge-reranker-v2-m3</code></a></td>\n<td>568M</td>\n<td>0.6971</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>cross-encoder/ettin-reranker-68m-v1</code></a></strong></td>\n<td><strong>68.6M</strong></td>\n<td><strong>0.6915</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2\"><code>ibm-granite/granite-embedding-reranker-english-r2</code></a></td>\n<td>150M</td>\n<td>0.6909</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a></strong></td>\n<td><strong>32.8M</strong></td>\n<td><strong>0.6825</strong></td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>cross-encoder/ettin-reranker-17m-v1</code></a></strong></td>\n<td><strong>17.6M</strong></td>\n<td><strong>0.6746</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1\"><code>mixedbread-ai/mxbai-rerank-large-v1</code></a></td>\n<td>435M</td>\n<td>0.6488</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-large\"><code>BAAI/bge-reranker-large</code></a></td>\n<td>560M</td>\n<td>0.6379</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2\"><code>cross-encoder/ms-marco-MiniLM-L12-v2</code></a></td>\n<td>33.4M</td>\n<td>0.6369</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2\"><code>cross-encoder/ms-marco-MiniLM-L6-v2</code></a></td>\n<td>22.7M</td>\n<td>0.6312</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2\"><code>cross-encoder/ms-marco-MiniLM-L4-v2</code></a></td>\n<td>19.2M</td>\n<td>0.6298</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1\"><code>mixedbread-ai/mxbai-rerank-base-v1</code></a></td>\n<td>184M</td>\n<td>0.6231</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1\"><code>mixedbread-ai/mxbai-rerank-xsmall-v1</code></a></td>\n<td>70.8M</td>\n<td>0.6136</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-base\"><code>BAAI/bge-reranker-base</code></a></td>\n<td>278M</td>\n<td>0.6027</td>\n</tr>\n</tbody>\n</table>\n<p>The smallest model I'm releasing, our 17M, beats the 33M <code>ms-marco-MiniLM-L12-v2</code> by +0.051 NDCG@10 (0.5576 vs 0.5066) on MTEB and +0.038 (0.6746 vs 0.6369) on NanoBEIR at roughly half the parameter count. The 32M beats the 568M <code>BAAI/bge-reranker-v2-m3</code> by +0.025 (0.5779 vs 0.5526) on MTEB, a 17x parameter gap. If you've been using one of the legacy MiniLM rerankers as the default in your retrieve-then-rerank stack, swapping in our 17M (or 32M) is a low-risk drop-in replacement, with a noticeable quality bump on both benchmarks.</p>\n<p>Moving up the table, our 150M is the strongest reranker I tested in the under-600M range on MTEB, edging out the recent <code>Qwen/Qwen3-Reranker-0.6B</code> (596M) by +0.005 (0.5994 vs 0.5940) and beating every BAAI bge-reranker variant by 0.03 to 0.05. The 68M is also worth a mention: at 0.5915 it lands almost exactly on <code>Qwen3-Reranker-0.6B</code> (0.5940) while using a ninth of the parameters.</p>\n<p>At the top of the released range, our 1B model closely tracks its teacher. It comes within 0.0001 of the 1.54B <code>mxbai-rerank-large-v2</code> on MTEB (0.6114 vs 0.6115) and within 0.008 on NanoBEIR, despite distilling from a model 54% larger than itself. The distillation effectively closes the gap to the teacher, which is what I was hoping to see going into this release.</p>\n<p>The overall strongest reranker in the comparison is <code>Qwen/Qwen3-Reranker-4B</code> at 0.6367 MTEB, +0.025 above our 1B model. Closing that gap from the current recipe would likely require distilling from a stronger teacher (our teacher itself sits below <code>Qwen3-Reranker-4B</code>). For most retrieve-then-rerank workloads, our 1B at a quarter of the parameters (see <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#speed\">Speed</a>) is a much more practical pick.</p>\n<h3>Speed</h3>\n<p>Quality numbers are only half of what matters for a reranker. The other half is whether its latency fits inside the budget you have between retrieval and showing results to the user. Let me walk through what I measured.</p>\n<p>I benchmarked all six released models against thirteen public rerankers (strong baselines up to about 1B parameters) on a single NVIDIA H100 80GB. The queries and documents come from <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/sentence-transformers/natural-questions\"><code>sentence-transformers/natural-questions</code></a> at its natural document-length distribution: most NQ answers are short, some are long. Documents are truncated at <code>max_length=512</code> to avoid giving the older models an unfair advantage. Each model uses its best supported attention implementation: Flash Attention 2 wherever the architecture supports it (BERT, XLM-RoBERTa, ModernBERT, Qwen2), SDPA where it doesn't, and eager for DeBERTa-v2 (which currently has neither FA2 nor SDPA support in <code>transformers</code>).</p>\n<p>For every model an auto-batch search starts at batch size 8 and doubles until the GPU runs out of memory. At each batch size I run three timed passes and keep the median throughput, so a single unlucky run doesn't drag the number around. The reported throughput is at whichever batch size won.</p>\n<p><strong>Table 1.</strong> Throughput in pairs per second, all in <code>bfloat16</code>. Our six rerankers are in <strong>bold</strong>.</p>\n<table>\n<thead>\n<tr>\n<th>Model</th>\n<th>Params</th>\n<th>Attn</th>\n<th>pairs / second</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>cross-encoder/ettin-reranker-17m-v1</code></a></strong></td>\n<td><strong>17M</strong></td>\n<td>FA2</td>\n<td><strong>7517</strong></td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a></strong></td>\n<td><strong>32M</strong></td>\n<td>FA2</td>\n<td><strong>6602</strong></td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>cross-encoder/ettin-reranker-68m-v1</code></a></strong></td>\n<td><strong>68M</strong></td>\n<td>FA2</td>\n<td><strong>4913</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2\"><code>cross-encoder/ms-marco-MiniLM-L4-v2</code></a></td>\n<td>19M</td>\n<td>FA2</td>\n<td>4029</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2\"><code>cross-encoder/ms-marco-MiniLM-L6-v2</code></a></td>\n<td>22M</td>\n<td>FA2</td>\n<td>3817</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2\"><code>cross-encoder/ms-marco-MiniLM-L12-v2</code></a></td>\n<td>33M</td>\n<td>FA2</td>\n<td>3311</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>cross-encoder/ettin-reranker-150m-v1</code></a></strong></td>\n<td><strong>150M</strong></td>\n<td>FA2</td>\n<td><strong>3237</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-base\"><code>BAAI/bge-reranker-base</code></a></td>\n<td>278M</td>\n<td>FA2</td>\n<td>2858</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1\"><code>mixedbread-ai/mxbai-rerank-xsmall-v1</code></a></td>\n<td>70M</td>\n<td>eager</td>\n<td>2636</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1\"><code>mixedbread-ai/mxbai-rerank-base-v1</code></a></td>\n<td>184M</td>\n<td>eager</td>\n<td>1953</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>cross-encoder/ettin-reranker-400m-v1</code></a></strong></td>\n<td><strong>400M</strong></td>\n<td>FA2</td>\n<td><strong>1738</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-large\"><code>BAAI/bge-reranker-large</code></a></td>\n<td>560M</td>\n<td>FA2</td>\n<td>1659</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-v2-m3\"><code>BAAI/bge-reranker-v2-m3</code></a></td>\n<td>568M</td>\n<td>FA2</td>\n<td>1569</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base\"><code>Alibaba-NLP/gte-reranker-modernbert-base</code></a></td>\n<td>150M</td>\n<td>FA2</td>\n<td>1418</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2\"><code>ibm-granite/granite-embedding-reranker-english-r2</code></a></td>\n<td>150M</td>\n<td>FA2</td>\n<td>1404</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>cross-encoder/ettin-reranker-1b-v1</code></a></strong></td>\n<td><strong>1B</strong></td>\n<td>FA2</td>\n<td><strong>928</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1\"><code>mixedbread-ai/mxbai-rerank-large-v1</code></a></td>\n<td>435M</td>\n<td>eager</td>\n<td>867</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2\"><code>mixedbread-ai/mxbai-rerank-base-v2</code></a></td>\n<td>494M</td>\n<td>FA2</td>\n<td>809</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2\"><code>mixedbread-ai/mxbai-rerank-large-v2</code></a></td>\n<td>1.5B</td>\n<td>FA2</td>\n<td>387</td>\n</tr>\n</tbody>\n</table>\n<p>Our 17M is the fastest reranker in the whole comparison, at 7517 pairs per second. That's almost twice the throughput of <code>ms-marco-MiniLM-L6-v2</code> (3817) and faster even than the smaller <code>ms-marco-MiniLM-L4-v2</code> (4029). And as you saw in the MTEB table earlier, our 17M is also more accurate than every MiniLM variant. If you're currently running a MiniLM cross-encoder, swapping to our 17M is a one-line change that improves both your latency and search quality.</p>\n<p>Our 150M is an even more interesting comparison, because there are two direct architectural peers at exactly 150M parameters: <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base\"><code>Alibaba-NLP/gte-reranker-modernbert-base</code></a> and <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2\"><code>ibm-granite/granite-embedding-reranker-english-r2</code></a>. Both are built on the same ModernBERT-base backbone. Our 150M runs at 3237 pairs per second, while the two peers come in at 1418 and 1404 respectively, for a 2.3x speed gap.</p>\n<p>All three 150M models use Flash Attention 2, but the two peers load through <code>AutoModelForSequenceClassification</code>, which keeps the inputs padded. So attention itself runs the FA2 kernel, but the rest of the model is still doing dense compute on padding tokens that don't contribute anything. Our modular <code>Transformer</code> module (see <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#architecture-details\">Architecture Details</a> above) propagates unpadded inputs all the way through the model, so every layer only spends compute on real tokens. That's the difference between getting some of FA2's benefit and getting all of it.</p>\n<p>At the bottom of the table, our 1B model hits 928 pairs per second, which is 2.4x faster than the 1.54B teacher <code>mxbai-rerank-large-v2</code> (387 pairs per second) while matching its MTEB score within 0.0001. The teacher is Qwen2-based with a prompt-template overhead per pair, so the distilled student inherits the teacher's calibration and judgement but skips all the runtime baggage. This is honestly the most satisfying single number in the whole release for me.</p>\n<p>One unfortunate note: the DeBERTa-v2-based <code>mxbai-rerank-{xsmall,base,large}-v1</code> series ends up much slower than the rest of the table because DeBERTa-v2 currently supports neither Flash Attention 2 nor SDPA in <code>transformers</code>. The 70M <code>mxbai-rerank-xsmall-v1</code> runs at 2636 pairs per second, about half the throughput of our 68M at almost the same parameter count. The models themselves are perfectly fine, they just don't get to use modern attention kernels.</p>\n<p>Same benchmark on a consumer GPU (RTX 3090, 24 GB)</p>\n<p>If you're self-hosting on a consumer card rather than a datacenter GPU, here's the same throughput sweep on an RTX 3090. Same benchmark setup as Table 1: <code>bfloat16</code>, best-supported attention per model, three-trial median throughput at the largest batch that fits.</p>\n<table>\n<thead>\n<tr>\n<th>Model</th>\n<th>Params</th>\n<th>Best attn</th>\n<th>pairs / second</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>cross-encoder/ettin-reranker-17m-v1</code></a></strong></td>\n<td><strong>17M</strong></td>\n<td>FA2</td>\n<td><strong>9008</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2\"><code>cross-encoder/ms-marco-MiniLM-L4-v2</code></a></td>\n<td>19M</td>\n<td>FA2</td>\n<td>5071</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a></strong></td>\n<td><strong>32M</strong></td>\n<td>FA2</td>\n<td><strong>4497</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2\"><code>cross-encoder/ms-marco-MiniLM-L6-v2</code></a></td>\n<td>22M</td>\n<td>FA2</td>\n<td>4234</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2\"><code>cross-encoder/ms-marco-MiniLM-L12-v2</code></a></td>\n<td>33M</td>\n<td>FA2</td>\n<td>2847</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>cross-encoder/ettin-reranker-68m-v1</code></a></strong></td>\n<td><strong>68M</strong></td>\n<td>FA2</td>\n<td><strong>1916</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1\"><code>mixedbread-ai/mxbai-rerank-xsmall-v1</code></a></td>\n<td>70M</td>\n<td>eager</td>\n<td>1677</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-base\"><code>BAAI/bge-reranker-base</code></a></td>\n<td>278M</td>\n<td>FA2</td>\n<td>1329</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>cross-encoder/ettin-reranker-150m-v1</code></a></strong></td>\n<td><strong>150M</strong></td>\n<td>FA2</td>\n<td><strong>982</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1\"><code>mixedbread-ai/mxbai-rerank-base-v1</code></a></td>\n<td>184M</td>\n<td>eager</td>\n<td>772</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2\"><code>ibm-granite/granite-embedding-reranker-english-r2</code></a></td>\n<td>150M</td>\n<td>FA2</td>\n<td>598</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base\"><code>Alibaba-NLP/gte-reranker-modernbert-base</code></a></td>\n<td>150M</td>\n<td>FA2</td>\n<td>586</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-large\"><code>BAAI/bge-reranker-large</code></a></td>\n<td>560M</td>\n<td>FA2</td>\n<td>448</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-v2-m3\"><code>BAAI/bge-reranker-v2-m3</code></a></td>\n<td>568M</td>\n<td>FA2</td>\n<td>436</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>cross-encoder/ettin-reranker-400m-v1</code></a></strong></td>\n<td><strong>400M</strong></td>\n<td>FA2</td>\n<td><strong>429</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1\"><code>mixedbread-ai/mxbai-rerank-large-v1</code></a></td>\n<td>435M</td>\n<td>eager</td>\n<td>266</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2\"><code>mixedbread-ai/mxbai-rerank-base-v2</code></a></td>\n<td>494M</td>\n<td>FA2</td>\n<td>221</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>cross-encoder/ettin-reranker-1b-v1</code></a></strong></td>\n<td><strong>1B</strong></td>\n<td>FA2</td>\n<td><strong>189</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2\"><code>mixedbread-ai/mxbai-rerank-large-v2</code></a></td>\n<td>1.5B</td>\n<td>FA2</td>\n<td>69</td>\n</tr>\n</tbody>\n</table>\n<p>Our 17M is still the fastest model in the table at 9008 pairs per second, actually higher than its H100 number, which suggests that at tiny sizes raw compute isn't the bottleneck and the H100's extra muscle doesn't translate. The middle of the table reshuffles a bit, with the MiniLM rerankers overtaking our 32M and 68M, and the 1B slipping behind <code>mxbai-rerank-base-v2</code> (189 vs 221 pairs per second). Our 150M model still holds a solid lead over the two 150M ModernBERT-based peers, and the teacher-replacement story still holds, with our 1B at 2.7x the throughput of the 1.5B <code>mxbai-rerank-large-v2</code> (189 vs 69 pairs per second).</p>\n<p>Same benchmark on CPU (Intel Core i7-13700K)</p>\n<table>\n<thead>\n<tr>\n<th>Model</th>\n<th>Params</th>\n<th>Best attn</th>\n<th>pairs / second</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>cross-encoder/ettin-reranker-17m-v1</code></a></strong></td>\n<td><strong>17M</strong></td>\n<td>SDPA</td>\n<td><strong>267.4</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2\"><code>cross-encoder/ms-marco-MiniLM-L4-v2</code></a></td>\n<td>19M</td>\n<td>SDPA</td>\n<td>206.2</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2\"><code>cross-encoder/ms-marco-MiniLM-L6-v2</code></a></td>\n<td>22M</td>\n<td>SDPA</td>\n<td>143.9</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a></strong></td>\n<td><strong>32M</strong></td>\n<td>SDPA</td>\n<td><strong>92.5</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2\"><code>cross-encoder/ms-marco-MiniLM-L12-v2</code></a></td>\n<td>33M</td>\n<td>SDPA</td>\n<td>75.9</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1\"><code>mixedbread-ai/mxbai-rerank-xsmall-v1</code></a></td>\n<td>70M</td>\n<td>eager</td>\n<td>38.9</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>cross-encoder/ettin-reranker-68m-v1</code></a></strong></td>\n<td><strong>68M</strong></td>\n<td>SDPA</td>\n<td><strong>31.2</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-base\"><code>BAAI/bge-reranker-base</code></a></td>\n<td>278M</td>\n<td>SDPA</td>\n<td>19.2</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base\"><code>Alibaba-NLP/gte-reranker-modernbert-base</code></a></td>\n<td>150M</td>\n<td>SDPA</td>\n<td>14.7</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2\"><code>ibm-granite/granite-embedding-reranker-english-r2</code></a></td>\n<td>150M</td>\n<td>SDPA</td>\n<td>14.5</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>cross-encoder/ettin-reranker-150m-v1</code></a></strong></td>\n<td><strong>150M</strong></td>\n<td>SDPA</td>\n<td><strong>14.0</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1\"><code>mixedbread-ai/mxbai-rerank-base-v1</code></a></td>\n<td>184M</td>\n<td>eager</td>\n<td>13.4</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-large\"><code>BAAI/bge-reranker-large</code></a></td>\n<td>560M</td>\n<td>SDPA</td>\n<td>6.2</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/BAAI/bge-reranker-v2-m3\"><code>BAAI/bge-reranker-v2-m3</code></a></td>\n<td>568M</td>\n<td>SDPA</td>\n<td>6.0</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>cross-encoder/ettin-reranker-400m-v1</code></a></strong></td>\n<td><strong>400M</strong></td>\n<td>SDPA</td>\n<td><strong>5.2</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1\"><code>mixedbread-ai/mxbai-rerank-large-v1</code></a></td>\n<td>435M</td>\n<td>eager</td>\n<td>4.3</td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2\"><code>mixedbread-ai/mxbai-rerank-base-v2</code></a></td>\n<td>494M</td>\n<td>SDPA</td>\n<td>3.5</td>\n</tr>\n<tr>\n<td><strong><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>cross-encoder/ettin-reranker-1b-v1</code></a></strong></td>\n<td><strong>1B</strong></td>\n<td>SDPA</td>\n<td><strong>2.1</strong></td>\n</tr>\n</tbody>\n</table>\n<p>On CPU, we can't take advantage of bf16, Flash Attention 2, or unpadding, so the latency story is a bit simpler: the higher the parameter count, the slower the model. The 17M model is considerably faster than <code>ms-marco-MiniLM-L6-v2</code> (267.4 vs 143.9 pairs per second) and even faster than the smaller <code>ms-marco-MiniLM-L4-v2</code> (206.2). As expected, our 150M model lands alongside the two 150M peers (14.0 vs 14.5 and 14.7 pairs per second) now that unpadding no longer applies. If you're CPU-bound, our 17M and 32M are the practical picks.</p>\n<p>To explain where the speed comes from, the next table sweeps <code>fp32+SDPA</code>, <code>bf16+SDPA</code>, and <code>bf16+FA2</code> for our six models using the same bench config. The FA2 column is split in two: one with the inputs still padded (what a wrapped model would see) and one with unpadded inputs (what our modular <code>Transformer</code> actually does). The rightmost column is what our models use by default when FA2 is enabled.</p>\n<p><strong>Table 2.</strong> Precision and attention ablation for the six released sizes at <code>max_length=512</code> on natural NQ documents. Each cell shows pairs / second with the multiplier relative to <code>fp32+SDPA</code> in parentheses, and peak GPU memory on the second line. The rightmost column (in <strong>bold</strong>) is the configuration our models use by default when FA2 is enabled.</p>\n<table>\n<thead>\n<tr>\n<th>Model</th>\n<th>Params</th>\n<th>fp32+SDPA</th>\n<th>bf16+SDPA</th>\n<th>bf16+FA2 w. padding</th>\n<th><strong>bf16+FA2 w.o. padding</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>ettin-reranker-17m-v1</code></a></td>\n<td>17M</td>\n<td>4402 (1.00x) 0.8 GB</td>\n<td>4523 (1.03x) 2.2 GB</td>\n<td>3744 (0.85x) 1.9 GB</td>\n<td><strong>7517 (1.71x)</strong> <strong>1.4 GB</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>ettin-reranker-32m-v1</code></a></td>\n<td>32M</td>\n<td>3307 (1.00x) 1.2 GB</td>\n<td>4357 (1.32x) 1.6 GB</td>\n<td>3040 (0.92x) 2.9 GB</td>\n<td><strong>6602 (2.00x)</strong> <strong>1.1 GB</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>ettin-reranker-68m-v1</code></a></td>\n<td>68M</td>\n<td>1364 (1.00x) 1.0 GB</td>\n<td>2861 (2.10x) 2.2 GB</td>\n<td>2003 (1.47x) 2.0 GB</td>\n<td><strong>4913 (3.60x)</strong> <strong>1.5 GB</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>ettin-reranker-150m-v1</code></a></td>\n<td>150M</td>\n<td>671 (1.00x) 1.6 GB</td>\n<td>1942 (2.90x) 1.8 GB</td>\n<td>1396 (2.08x) 3.1 GB</td>\n<td><strong>3237 (4.83x)</strong> <strong>1.4 GB</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>ettin-reranker-400m-v1</code></a></td>\n<td>400M</td>\n<td>266 (1.00x) 2.5 GB</td>\n<td>1113 (4.18x) 1.8 GB</td>\n<td>864 (3.25x) 2.7 GB</td>\n<td><strong>1738 (6.53x)</strong> <strong>2.2 GB</strong></td>\n</tr>\n<tr>\n<td><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>ettin-reranker-1b-v1</code></a></td>\n<td>1B</td>\n<td>112 (1.00x) 4.6 GB</td>\n<td>630 (5.60x) 2.8 GB</td>\n<td>522 (4.64x) 3.6 GB</td>\n<td><strong>928 (8.26x)</strong> <strong>4.5 GB</strong></td>\n</tr>\n</tbody>\n</table>\n<p>The total speedup from <code>bf16+FA2 w.o. padding</code> over the <code>fp32+SDPA</code> baseline grows sharply with model size, from 1.71x on the 17M to 8.26x on the 1B. Most of that growth comes from <code>bf16</code> alone: the <code>fp32+SDPA</code> to <code>bf16+SDPA</code> step gives the 17M only a 1.03x speedup but gives the 1B a full 5.60x speedup, also due to the lowered memory cost allowing for bigger batch sizes. In short, <code>bfloat16</code> is the biggest single contributor to the overall speedup.</p>\n<p>Unexpectedly, turning on FA2 while the inputs are still padded is actually slower than <code>bf16+SDPA</code> at every size in the release. The FA2 kernel prefers an unpadded format, and when you feed it padded inputs you pay the bookkeeping overhead of converting between formats while still spending compute on the padding tokens themselves. So the <code>bf16+FA2 w. padding</code> column is roughly what you'd measure if you swapped <code>sdpa</code> for <code>flash_attention_2</code> in <code>model_kwargs</code> without changing anything else about the model loader. This is the situation that <code>gte-reranker-modernbert-base</code> and <code>granite-embedding-reranker-english-r2</code> from Table 1 are in.</p>\n<p>Lastly, going from <code>bf16+FA2 w. padding</code> to <code>bf16+FA2 w.o. padding</code> is worth between 1.78x (1B) and 2.45x (68M) of additional throughput, and it also cuts peak memory considerably, allowing for higher batch sizes.</p>\n<p>So my recommendation is simple: enable <code>bf16</code> and FA2 together. The six Ettin rerankers will use unpadded inputs by default, since that's what the modular <code>Transformer</code> module from the <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#architecture-details\">Architecture Details</a> section is set up for. The full snippet is the same as in the <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#usage\">Usage</a> section above:</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoder</span></span>\n\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoder</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">cross-encoder/ettin-reranker-150m-v1<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">model_kwargs</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span>\n        <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">dtype<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">bfloat16<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>\n        <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">attn_implementation<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">flash_attention_2<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>  <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> See tip below\n</span>    <span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n</span></span></code></pre>\n<blockquote>\n<p>Use <code>pip install kernels</code> to install FA2. It ships pre-built kernels for a wide range of GPU architectures, CUDA versions, and operating systems.</p>\n</blockquote>\n<p>One caveat for other CrossEncoders: the full speedup is only available for models built with a modular <code>Transformer</code> like the Ettin rerankers. Applying the same two flags to a CrossEncoder that loads through <code>AutoModelForSequenceClassification</code> lands you in the slower <code>bf16+FA2 w. padding</code> column of Table 2 instead.</p>\n<h2>Training</h2>\n<p>The training script below started as the output of the new <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/huggingface/sentence-transformers/tree/main/skills\"><code>train-sentence-transformers</code> Agent Skill</a>, shipped in <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/huggingface/sentence-transformers/releases/tag/v5.5.0\">Sentence Transformers v5.5.0</a>. If you use an AI coding agent (Claude Code, Codex, Cursor, Gemini CLI, ...), you can install the skill and ask it to fine-tune a <code>SentenceTransformer</code>, <code>CrossEncoder</code>, or <code>SparseEncoder</code> model on your data. The skill carries version-aware guidance for base model selection, loss and evaluator choice, hard-negative mining, distillation, LoRA, Matryoshka, multilingual training, and static embeddings, plus template scripts for each model type.</p>\n<pre><code class=\"language-bash\"><span class=\"code-snippet\" data-language=\"Shell\"><span class=\"syntax-source syntax-shell syntax-bash\"><span class=\"syntax-meta syntax-function-call syntax-shell\"><span class=\"syntax-variable syntax-function syntax-shell\">hf</span></span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-shell\"> skills add train-sentence-transformers<span class=\"syntax-variable syntax-parameter syntax-option syntax-shell\"><span class=\"syntax-punctuation syntax-definition syntax-parameter syntax-shell\"> --</span>claude   <span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-begin syntax-shell\">#</span></span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\"> symlinks into .claude/skills/</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\">\n</span></span></span><span class=\"syntax-meta syntax-function-call syntax-shell\"><span class=\"syntax-variable syntax-function syntax-shell\">hf</span></span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-shell\"> skills add train-sentence-transformers<span class=\"syntax-variable syntax-parameter syntax-option syntax-shell\"><span class=\"syntax-punctuation syntax-definition syntax-parameter syntax-shell\"> --</span>global   <span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-begin syntax-shell\">#</span></span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\"> under ~/.agents/skills/</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\">\n</span></span></span></span></span></code></pre>\n<p>A prompt like <em>&quot;Fine-tune a cross-encoder reranker on <code>(query, document)</code> pairs from my dataset, mine hard negatives, and push to my Hub repo&quot;</em> will produce a runnable script you can then iterate on. That's how I started working on the recipe below.</p>\n<p>All six rerankers were trained with the same single-stage recipe. Only the learning rate and the per-device batch size vary per model size. The full training script is ~150 lines and uses one published dataset.</p>\n<p>The recipe converged after a single sweep across model sizes. Each size's learning rate was tuned by a small grid search on a ~15% subset of the final training data, and the resulting LRs transferred cleanly to the full-data runs without re-tuning. No per-size tuning beyond LR was needed.</p>\n<h3>Distillation recipe</h3>\n<p>Most published reranker recipes train on human-labeled relevance triples (a query, one positive document, and optionally hard negatives) with a contrastive, pointwise, pairwise, or listwise loss like <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://sbert.net/docs/package_reference/cross_encoder/losses.html#multiplenegativesrankingloss\"><code>MultipleNegativesRankingLoss</code></a>, <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://sbert.net/docs/package_reference/cross_encoder/losses.html#binarycrossentropyloss\"><code>BinaryCrossEntropyLoss</code></a>, <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://sbert.net/docs/package_reference/cross_encoder/losses.html#ranknetloss\"><code>RankNetLoss</code></a>, or <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://sbert.net/docs/package_reference/cross_encoder/losses.html#lambdaloss\"><code>LambdaLoss</code></a>, respectively. See my earlier <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/train-reranker\">Training and Finetuning Reranker Models with Sentence Transformers</a> blogpost, for example.</p>\n<p>But this approach has a few practical and theoretical drawbacks. First, positives need to be human-labeled, which is expensive and slow to scale across many domains. Second, the model only ever sees a label for the small subset of <code>(query, document)</code> pairs that someone went through. Especially after hard negative mining, you end up with a lot of false negatives, e.g. as shown in <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://arxiv.org/abs/2505.16967\">Hard Negatives, Hard Lessons</a>. Third, the binary nature of this labeling doesn't match reality, where some documents are simply more relevant than others.</p>\n<p>I took a different route here: pointwise MSE distillation from an existing strong teacher reranker. The setup is simple enough to describe in three lines:</p>\n<ul>\n<li><strong>Teacher</strong>: <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2\"><code>mixedbread-ai/mxbai-rerank-large-v2</code></a> (1.54B parameters).</li>\n<li><strong>Loss</strong>: <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://sbert.net/docs/package_reference/cross_encoder/losses.html#mseloss\"><code>MSELoss</code></a> on the raw teacher logits (range ~[−12, 22]), i.e. without rescaling.</li>\n<li><strong>Training data</strong>: ~143M <code>(query, document, teacher_score)</code> triples.</li>\n</ul>\n<h3>Dataset</h3>\n<p>I've released the training data as a single Hugging Face dataset, <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data\"><code>cross-encoder/ettin-reranker-v1-data</code></a>, assembled from two sources. Each source is kept as its own split so the provenance is transparent:</p>\n<ol>\n<li>LightOn pre-training data (<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/lightonai/embeddings-pre-training\"><code>lightonai/embeddings-pre-training</code></a>, non-curated): 32 splits covering broad-domain text similarity signal (MTP, FW-EDU, Reddit, PAQ, S2ORC, Amazon, Wikipedia, MS MARCO, etc.). I limit the number of samples for some of the splits, resulting in ~110M <code>(query, document, similarity)</code> triples in total.</li>\n<li>Rescored retrieval data from <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/lightonai/embeddings-fine-tuning\"><code>lightonai/embeddings-fine-tuning</code></a>: 7 splits (<code>msmarco</code>, <code>hotpotqa</code>, <code>trivia</code>, <code>nq</code>, <code>squadv2</code>, <code>fiqa</code>, <code>fever</code>). The source dataset has up to 2048 candidate documents per query (initially scored with <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/Alibaba-NLP/gte-modernbert-base\"><code>Alibaba-NLP/gte-modernbert-base</code></a>), which I rescored with <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2\"><code>mixedbread-ai/mxbai-rerank-large-v2</code></a> and uploaded as <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/cross-encoder/lightonai-embeddings-fine-tuning-reranked-v1\"><code>cross-encoder/lightonai-embeddings-fine-tuning-reranked-v1</code></a>. That dataset subsamples each query's 2048 candidates down to 256 using the <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://arxiv.org/abs/2604.04734\">Jang et al.</a> quantile-anchor recipe (all positives + top-16 hard + ~239 quantile-anchor stratified). For training, I pick 64 of those 256 per query: 32 from the score-sorted head (the positive plus the hardest negatives) and 32 medium-difficulty negatives sampled from a band further down the teacher's ranking. See the <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data\">dataset card</a> for the exact rank positions.</li>\n</ol>\n<p>Total: ~143M <code>(query, document, score)</code> triples, plus a held-out 5K-row eval split (the tail of <code>quora</code>) that drives the in-training eval loss.</p>\n<h3>Training Arguments</h3>\n<p>Most hyperparameters are constant across model sizes:</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoderTrainingArguments</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n    <span class=\"syntax-variable syntax-parameter syntax-python\">num_train_epochs</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>                    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> I chose more data over more epochs\n</span>    <span class=\"syntax-variable syntax-parameter syntax-python\">per_device_train_batch_size</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">...</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>       <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> global_batch_size // world_size (see table below)\n</span>    <span class=\"syntax-variable syntax-parameter syntax-python\">gradient_accumulation_steps</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">learning_rate</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">...</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>                     <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> per-size, see table\n</span>    <span class=\"syntax-variable syntax-parameter syntax-python\">warmup_ratio</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">0<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>03</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>                     <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> ~3% linear warmup, then linear decay (default)\n</span>    <span class=\"syntax-variable syntax-parameter syntax-python\">bf16</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>                             <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> FA2 + bf16 throughout\n</span>    <span class=\"syntax-variable syntax-parameter syntax-python\">eval_strategy</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">steps<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">eval_steps</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">0<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>05</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>                       <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> NanoBEIR every 5% of training\n</span>    <span class=\"syntax-variable syntax-parameter syntax-python\">save_strategy</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">steps<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">save_steps</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">0<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>05</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">save_total_limit</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">5</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">load_best_model_at_end</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">metric_for_best_model</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">eval_NanoBEIR_R100_mean_ndcg@10<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    <span class=\"syntax-variable syntax-parameter syntax-python\">seed</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">12</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n</span></span></code></pre>\n<p>Only the learning rate and global batch size very per model size.</p>\n<table>\n<thead>\n<tr>\n<th>Size</th>\n<th>Learning rate</th>\n<th>Global batch size</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>17m</td>\n<td>2.4e-4</td>\n<td>1024</td>\n</tr>\n<tr>\n<td>32m</td>\n<td>1.2e-4</td>\n<td>512</td>\n</tr>\n<tr>\n<td>68m</td>\n<td>3e-5</td>\n<td>256</td>\n</tr>\n<tr>\n<td>150m</td>\n<td>1.5e-5</td>\n<td>192</td>\n</tr>\n<tr>\n<td>400m</td>\n<td>7e-6</td>\n<td>256</td>\n</tr>\n<tr>\n<td>1b</td>\n<td>3e-6</td>\n<td>512</td>\n</tr>\n</tbody>\n</table>\n<p><code>global_batch_size</code> is <code>per_device_batch_size x world_size x gradient_accumulation_steps</code>. On a single 8-GPU node, the 1024 global batch for 17m means <code>per_device=128</code>. On 8 nodes, it means <code>per_device=8</code>. The training script computes <code>per_device_batch_size</code> from <code>global_batch_size // world_size</code> so the same script works at any node count. The global batch size could be made more consistent, but I found that the above values worked well and didn't want to retune them just for the sake of consistency.</p>\n<h3>Evaluation</h3>\n<p>I monitored NanoBEIR mean NDCG@10 during training (eval every 5% of steps) and used it as the <code>metric_for_best_model</code> for <code>load_best_model_at_end</code>. NanoBEIR is fast, so I could afford it 20 times per training run. After training, I evaluated both the best checkpoint (according to NanoBEIR) and the last checkpoint on the full MTEB(eng, v2) Retrieval benchmark. The final release checkpoint was the one that did best on MTEB. The NanoBEIR-preferred checkpoint won for all sizes except 68m, where the last checkpoint was slightly stronger.</p>\n<h3>Overall Training Script</h3>\n<p>The complete script (what every released model was trained with) is a single file. Only <code>ENCODER_SIZE</code> changes per run, and everything else is automatic:</p>\n<pre><code class=\"language-python\"><span class=\"code-snippet\" data-language=\"Python\"><span class=\"syntax-source syntax-python\"><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">__future__</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">annotations</span></span>\n\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">logging</span></span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">os</span></span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">pathlib</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">Path</span></span>\n\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">torch</span></span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">torch</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">nn</span></span> <span class=\"syntax-keyword syntax-control syntax-import syntax-as syntax-python\">as</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">nn</span></span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">datasets</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">concatenate_datasets</span><span class=\"syntax-punctuation syntax-separator syntax-import-list syntax-python\">,</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">get_dataset_config_names</span><span class=\"syntax-punctuation syntax-separator syntax-import-list syntax-python\">,</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">load_dataset</span></span>\n\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoder</span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">base</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">modules</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">Dense</span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">cross_encoder</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-punctuation syntax-section syntax-import-list syntax-begin syntax-python\">(</span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\">\n    <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoderModelCardData</span><span class=\"syntax-punctuation syntax-separator syntax-import-list syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoderTrainer</span><span class=\"syntax-punctuation syntax-separator syntax-import-list syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoderTrainingArguments</span><span class=\"syntax-punctuation syntax-separator syntax-import-list syntax-python\">,</span>\n<span class=\"syntax-punctuation syntax-section syntax-import-list syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">cross_encoder</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">evaluation</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">CrossEncoderNanoBEIREvaluator</span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">cross_encoder</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">losses</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">MSELoss</span></span>\n<span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-from syntax-python\">from</span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-meta syntax-import-source syntax-python\"> <span class=\"syntax-meta syntax-import-path syntax-python\"><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformers</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">sentence_transformer</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-import-name syntax-python\">modules</span></span> <span class=\"syntax-meta syntax-statement syntax-import syntax-python\"><span class=\"syntax-keyword syntax-control syntax-import syntax-python\">import</span></span></span></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"></span><span class=\"syntax-meta syntax-statement syntax-import syntax-python\"> <span class=\"syntax-meta syntax-generic-name syntax-python\">LayerNorm</span><span class=\"syntax-punctuation syntax-separator syntax-import-list syntax-python\">,</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">Pooling</span><span class=\"syntax-punctuation syntax-separator syntax-import-list syntax-python\">,</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">Transformer</span></span>\n\n<span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">logging</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">basicConfig</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">level</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">logging</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-variable syntax-other syntax-constant syntax-python\">INFO</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">format</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-constant syntax-other syntax-placeholder syntax-python\">%(<span class=\"syntax-variable syntax-other syntax-placeholder syntax-python\">asctime</span>)s</span> <span class=\"syntax-constant syntax-other syntax-placeholder syntax-python\">%(<span class=\"syntax-variable syntax-other syntax-placeholder syntax-python\">message</span>)s</span><span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">datefmt</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-constant syntax-other syntax-placeholder syntax-python\">%H</span>:<span class=\"syntax-constant syntax-other syntax-placeholder syntax-python\">%M</span>:<span class=\"syntax-constant syntax-other syntax-placeholder syntax-python\">%S</span><span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n<span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">logging</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">getLogger</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">httpx<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">setLevel</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">logging</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-variable syntax-other syntax-constant syntax-python\">WARNING</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> Per-size config. I swept the learning rates with these global (effective) batch sizes,\n</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> also by incorporating accum_steps\n</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-other syntax-constant syntax-python\">CONFIGS</span></span><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-variable syntax-python\">:</span> <span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">dict</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">str</span></span>, <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">dict</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">17m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span>  <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">base_model_name<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">jhu-clsp/ettin-encoder-17m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>  <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">learning_rate<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">2<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>4e-4</span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">global_batch_size<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1024</span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">32m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span>  <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">base_model_name<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">jhu-clsp/ettin-encoder-32m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>  <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">learning_rate<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">1<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>2e-4</span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">global_batch_size<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">512</span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">68m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span>  <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">base_model_name<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">jhu-clsp/ettin-encoder-68m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>  <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">learning_rate<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">3e-5</span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>   <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">global_batch_size<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">256</span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">150m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">base_model_name<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">jhu-clsp/ettin-encoder-150m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">learning_rate<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">1<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>5e-5</span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">global_batch_size<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">192</span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">400m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">base_model_name<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">jhu-clsp/ettin-encoder-400m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">learning_rate<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">7e-6</span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>   <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">global_batch_size<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">256</span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>\n    <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">1b<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span>   <span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">base_model_name<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">jhu-clsp/ettin-encoder-1b<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>   <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">learning_rate<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">3e-6</span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>   <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">global_batch_size<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">512</span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span><span class=\"syntax-punctuation syntax-separator syntax-dictionary-or-set syntax-python\">,</span>\n<span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span>\n<span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-other syntax-constant syntax-python\">ENCODER_SIZE</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">17m<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span>\n\n<span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-storage syntax-type syntax-function syntax-python\">def</span> <span class=\"syntax-entity syntax-name syntax-function syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">main</span></span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-begin syntax-python\">(</span></span><span class=\"syntax-meta syntax-function syntax-parameters syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-parameters syntax-end syntax-python\">)</span></span><span class=\"syntax-meta syntax-function syntax-python\"> </span><span class=\"syntax-meta syntax-function syntax-annotation syntax-return syntax-python\"><span class=\"syntax-punctuation syntax-separator syntax-annotation syntax-return syntax-python\">-&gt;</span> <span class=\"syntax-constant syntax-language syntax-python\">None</span></span><span class=\"syntax-meta syntax-function syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-function syntax-begin syntax-python\">:</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">config</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-other syntax-constant syntax-python\">CONFIGS</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-other syntax-constant syntax-python\">ENCODER_SIZE</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">encoder_id</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">config</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">base_model_name<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">learning_rate</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">config</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">learning_rate<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">global_batch_size</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">config</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">global_batch_size<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span>\n\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">world_size</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-type syntax-python\">int</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">os</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">environ</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">get</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">WORLD_SIZE<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">per_device_batch_size</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">global_batch_size</span></span> <span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-python\">/</span><span class=\"syntax-keyword syntax-operator syntax-arithmetic syntax-python\">/</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">world_size</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataloader_workers</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">0</span> <span class=\"syntax-meta syntax-statement syntax-if syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-conditional syntax-python\">if</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">world_size</span></span> <span class=\"syntax-keyword syntax-operator syntax-comparison syntax-python\">&gt;</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">8</span> <span class=\"syntax-keyword syntax-control syntax-flow syntax-else syntax-inline syntax-python\">else</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">4</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">run_name</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-storage syntax-type syntax-string syntax-python\">f</span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">ettin-reranker-</span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-other syntax-constant syntax-python\">ENCODER_SIZE</span></span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">-lr</span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">learning_rate</span></span></span><span class=\"syntax-meta syntax-format-spec syntax-python\"><span class=\"syntax-constant syntax-other syntax-format-spec syntax-python\">:.0e</span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 1. Load a model to finetune with model card data\n</span>    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> The model mirrors ModernBertForSequenceClassification, but with a &#39;headless&#39; Transformer that just loads\n</span>    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> AutoModel. This allows for unpadding with FA2, which isn&#39;t possible with AutoModelForSequenceClassification.\n</span>    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> This speeds up training considerably, while heavily reducing memory usage.\n</span>    <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">torch</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">manual_seed</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">12</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">transformer</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">Transformer</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">encoder_id</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">model_kwargs</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-structure syntax-dictionary-or-set syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-begin syntax-python\">{</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">attn_implementation<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-python\">:</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">flash_attention_2<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-section syntax-dictionary-or-set syntax-end syntax-python\">}</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">transformer</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">config</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">num_labels</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1</span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedding_dimension</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">transformer</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">get_embedding_dimension</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">pooling</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">Pooling</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">embedding_dimension</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedding_dimension</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">pooling_mode</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">cls<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dense_inner</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">Dense</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n        <span class=\"syntax-variable syntax-parameter syntax-python\">in_features</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedding_dimension</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">out_features</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedding_dimension</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">bias</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">False</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">activation_function</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">nn</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">GELU</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">module_input_name</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">sentence_embedding<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">module_output_name</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">sentence_embedding<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    </span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">norm</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">LayerNorm</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">dimension</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedding_dimension</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dense_score</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">Dense</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n        <span class=\"syntax-variable syntax-parameter syntax-python\">in_features</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">embedding_dimension</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">out_features</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">bias</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">activation_function</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">nn</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">Identity</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">module_input_name</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">sentence_embedding<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">module_output_name</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">scores<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    </span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoder</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n        <span class=\"syntax-variable syntax-parameter syntax-python\">modules</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">transformer</span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">pooling</span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dense_inner</span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">norm</span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dense_score</span></span><span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">num_labels</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">activation_fn</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">nn</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">Identity</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">model_card_data</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoderModelCardData</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n            <span class=\"syntax-variable syntax-parameter syntax-python\">model_name</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-storage syntax-type syntax-string syntax-python\">f</span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">Ettin Reranker </span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-other syntax-constant syntax-python\">ENCODER_SIZE</span></span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"> distilled from mxbai-rerank-large-v2<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n            <span class=\"syntax-variable syntax-parameter syntax-python\">language</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">en<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n            <span class=\"syntax-variable syntax-parameter syntax-python\">license</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">apache-2.0<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        </span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    </span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">actual_attn</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-function syntax-builtin syntax-python\">getattr</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">0</span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">config</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">_attn_implementation<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-constant syntax-language syntax-python\">None</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-statement syntax-if syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-conditional syntax-python\">if</span> <span class=\"syntax-keyword syntax-operator syntax-logical syntax-python\">not</span> <span class=\"syntax-meta syntax-group syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-group syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">actual_attn</span></span> <span class=\"syntax-keyword syntax-operator syntax-logical syntax-python\">and</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">flash<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span> <span class=\"syntax-keyword syntax-operator syntax-logical syntax-python\">in</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">actual_attn</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">lower</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-section syntax-group syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-conditional syntax-python\">:</span></span>\n        <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">logging</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">warning</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-storage syntax-type syntax-string syntax-python\">f</span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">FA2 may not be active (attn_impl=</span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">actual_attn</span></span></span><span class=\"syntax-storage syntax-modifier syntax-conversion syntax-python\">!r</span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">); training will be slower.<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 2. Load the dataset. Each config is one source subset (32 lighton + 7 rerank retrieval\n</span>    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> domains). The held-out eval rows live as the &#39;validation&#39; split of the &#39;quora&#39; config.\n</span>    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataset_repo</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">cross-encoder/ettin-reranker-v1-data<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">train_pieces</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span><span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">eval_dataset</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-constant syntax-language syntax-python\">None</span>\n    <span class=\"syntax-meta syntax-statement syntax-for syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-for syntax-python\">for</span> <span class=\"syntax-meta syntax-generic-name syntax-python\">config_name</span> <span class=\"syntax-meta syntax-statement syntax-for syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-for syntax-in syntax-python\">in</span></span></span><span class=\"syntax-meta syntax-statement syntax-for syntax-python\"> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">get_dataset_config_names</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataset_repo</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-for syntax-python\">:</span></span>\n        <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataset</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">load_dataset</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataset_repo</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">config_name</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n        <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">train_pieces</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">append</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataset</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">train<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n        <span class=\"syntax-meta syntax-statement syntax-if syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-conditional syntax-python\">if</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">validation<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span> <span class=\"syntax-keyword syntax-operator syntax-logical syntax-python\">in</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataset</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-conditional syntax-python\">:</span></span>\n            <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">eval_dataset</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataset</span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-begin syntax-python\">[</span></span><span class=\"syntax-meta syntax-item-access syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">validation<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span></span><span class=\"syntax-meta syntax-item-access syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-brackets syntax-end syntax-python\">]</span></span>\n    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">train_dataset</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">concatenate_datasets</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">train_pieces</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n    <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-function syntax-builtin syntax-python\">print</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">train_dataset</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 3. Define a loss function\n</span>    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">loss</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">MSELoss</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 4. Specify training arguments\n</span>    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">args</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoderTrainingArguments</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n        <span class=\"syntax-variable syntax-parameter syntax-python\">output_dir</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-storage syntax-type syntax-string syntax-python\">f</span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">models/</span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">run_name</span></span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">num_train_epochs</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">per_device_train_batch_size</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">per_device_batch_size</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">per_device_eval_batch_size</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">per_device_batch_size</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">gradient_accumulation_steps</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">1</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">learning_rate</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">learning_rate</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">warmup_ratio</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">0<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>03</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">bf16</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">eval_strategy</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">steps<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">eval_steps</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">0<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>05</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">save_strategy</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">steps<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">save_steps</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">0<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>05</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">save_total_limit</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">5</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">logging_steps</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-float syntax-python\">0<span class=\"syntax-punctuation syntax-separator syntax-decimal syntax-python\">.</span>025</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">logging_first_step</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">load_best_model_at_end</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">True</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">metric_for_best_model</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">eval_NanoBEIR_R100_mean_ndcg@10<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">dataloader_num_workers</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">dataloader_workers</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">run_name</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">run_name</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">seed</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-numeric syntax-integer syntax-decimal syntax-python\">12</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    </span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 5. Create an evaluator\n</span>    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">evaluator</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoderNanoBEIREvaluator</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n        <span class=\"syntax-variable syntax-parameter syntax-python\">dataset_names</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-structure syntax-list syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-list syntax-begin syntax-python\">[</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">msmarco<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">nfcorpus<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">nq<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">fiqa2018<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">touche2020<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">scifact<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n                       <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">hotpotqa<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">arguana<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">fever<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">dbpedia<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">climatefever<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">scidocs<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-list syntax-python\">,</span>\n                       <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">quoraretrieval<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-section syntax-list syntax-end syntax-python\">]</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">batch_size</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">per_device_batch_size</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">always_rerank_positives</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">False</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">show_progress_bar</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-constant syntax-language syntax-python\">False</span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    </span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 6. Create a trainer\n</span>    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">trainer</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">CrossEncoderTrainer</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\">\n        <span class=\"syntax-variable syntax-parameter syntax-python\">model</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">args</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">args</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">train_dataset</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">train_dataset</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">eval_dataset</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">eval_dataset</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">loss</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">loss</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n        <span class=\"syntax-variable syntax-parameter syntax-python\">evaluator</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">evaluator</span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span>\n    </span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 7. Evaluate before training\n</span>    <span class=\"syntax-meta syntax-statement syntax-if syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-conditional syntax-python\">if</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">trainer</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">is_world_process_zero</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-conditional syntax-python\">:</span></span>\n        <span class=\"syntax-meta syntax-statement syntax-with syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-with syntax-python\">with</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">torch</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">autocast</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">device_type</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">cuda<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">dtype</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">torch</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">bfloat16</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-with syntax-python\">:</span></span>\n            <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">evaluator</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 8. Train\n</span>    <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">trainer</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">train</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 9. Evaluate the final model\n</span>    <span class=\"syntax-meta syntax-statement syntax-if syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-conditional syntax-python\">if</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">trainer</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">is_world_process_zero</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-conditional syntax-python\">:</span></span>\n        <span class=\"syntax-meta syntax-statement syntax-with syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-with syntax-python\">with</span> <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">torch</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">autocast</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-variable syntax-parameter syntax-python\">device_type</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">cuda<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-separator syntax-arguments syntax-python\">,</span> <span class=\"syntax-variable syntax-parameter syntax-python\">dtype</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">torch</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span><span class=\"syntax-meta syntax-generic-name syntax-python\">bfloat16</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-with syntax-python\">:</span></span>\n            <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">evaluator</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n    <span class=\"syntax-comment syntax-line syntax-number-sign syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-python\">#</span> 10. Save the final model\n</span>    <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">final_dir</span></span> <span class=\"syntax-keyword syntax-operator syntax-assignment syntax-python\">=</span> <span class=\"syntax-storage syntax-type syntax-string syntax-python\">f</span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-interpolated syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">models/</span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-begin syntax-python\">{</span><span class=\"syntax-source syntax-python syntax-embedded\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">run_name</span></span></span></span><span class=\"syntax-meta syntax-interpolation syntax-python\"><span class=\"syntax-punctuation syntax-section syntax-interpolation syntax-end syntax-python\">}</span></span><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">/final<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span>\n    <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">model</span><span class=\"syntax-punctuation syntax-accessor syntax-dot syntax-python\">.</span></span><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">save_pretrained</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-meta syntax-generic-name syntax-python\">final_dir</span></span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n\n\n<span class=\"syntax-meta syntax-statement syntax-if syntax-python\"><span class=\"syntax-keyword syntax-control syntax-flow syntax-conditional syntax-python\">if</span> <span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-support syntax-variable syntax-magic syntax-python\">__name__</span></span> <span class=\"syntax-keyword syntax-operator syntax-comparison syntax-python\">==</span> <span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-python\">&quot;</span></span></span><span class=\"syntax-meta syntax-string syntax-python\"><span class=\"syntax-string syntax-quoted syntax-double syntax-python\">__main__<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-python\">&quot;</span></span></span><span class=\"syntax-punctuation syntax-section syntax-block syntax-conditional syntax-python\">:</span></span>\n    <span class=\"syntax-meta syntax-function-call syntax-python\"><span class=\"syntax-meta syntax-qualified-name syntax-python\"><span class=\"syntax-variable syntax-function syntax-python\">main</span></span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-begin syntax-python\">(</span><span class=\"syntax-punctuation syntax-section syntax-arguments syntax-end syntax-python\">)</span></span>\n</span></span></code></pre>\n<p>For multi-node training (anything past 17m/32m), launch the same script with <code>torchrun</code>:</p>\n<pre><code class=\"language-bash\"><span class=\"code-snippet\" data-language=\"Shell\"><span class=\"syntax-source syntax-shell syntax-bash\"><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-begin syntax-shell\">#</span></span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\"> Single-node (17m, 32m): defaults work</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\">\n</span><span class=\"syntax-meta syntax-function-call syntax-shell\"><span class=\"syntax-variable syntax-function syntax-shell\">python</span></span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-shell\"> train.py</span>\n\n<span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\"><span class=\"syntax-punctuation syntax-definition syntax-comment syntax-begin syntax-shell\">#</span></span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\"> Multi-node 4n setup for 150m, preserves global_batch_size=192:</span><span class=\"syntax-comment syntax-line syntax-number-sign syntax-shell\">\n</span><span class=\"syntax-meta syntax-function-call syntax-shell\"><span class=\"syntax-variable syntax-function syntax-shell\">torchrun</span></span><span class=\"syntax-meta syntax-function-call syntax-arguments syntax-shell\"><span class=\"syntax-variable syntax-parameter syntax-option syntax-shell\"><span class=\"syntax-punctuation syntax-definition syntax-parameter syntax-shell\"> --</span>nproc_per_node</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-option syntax-shell\">=</span>8<span class=\"syntax-variable syntax-parameter syntax-option syntax-shell\"><span class=\"syntax-punctuation syntax-definition syntax-parameter syntax-shell\"> --</span>nnodes</span><span class=\"syntax-keyword syntax-operator syntax-assignment syntax-option syntax-shell\">=</span>4 ... train.py</span>\n</span></span></code></pre>\n<h2>Conclusion</h2>\n<p>The ettin-reranker-v1 family, trained with a single simple recipe, is state-of-the-art at every released size up to 1B parameters. Pointwise MSE distillation from a strong teacher onto a broad-domain and retrieval-specific mix scales cleanly from 17M to 1B parameters, with only the learning rate and per-device batch size changing between sizes.</p>\n<p>Every ettin-reranker-v1 model beats the <code>ms-marco-MiniLM-L*-v2</code> family by a comfortable margin on MTEB and NanoBEIR. <code>cross-encoder/ettin-reranker-150m-v1</code> is the strongest mid-tier reranker I tested in the under-600M range, <code>cross-encoder/ettin-reranker-400m-v1</code> lands within 0.0024 of the 1.54B teacher's MTEB score, and <code>cross-encoder/ettin-reranker-1b-v1</code> matches that teacher within 0.0001.</p>\n<p>Everything in one place:</p>\n<ul>\n<li><strong>Models</strong>:\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-17m-v1\"><code>cross-encoder/ettin-reranker-17m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-32m-v1\"><code>cross-encoder/ettin-reranker-32m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-68m-v1\"><code>cross-encoder/ettin-reranker-68m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-150m-v1\"><code>cross-encoder/ettin-reranker-150m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-400m-v1\"><code>cross-encoder/ettin-reranker-400m-v1</code></a></li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/cross-encoder/ettin-reranker-1b-v1\"><code>cross-encoder/ettin-reranker-1b-v1</code></a></li>\n</ul>\n</li>\n<li><strong>Dataset</strong>: <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data\"><code>cross-encoder/ettin-reranker-v1-data</code></a> with ~143M <code>(query, document, label)</code> triples, kept as 39 named splits so the provenance of every row is visible.</li>\n<li><strong>Training script</strong>: the ~150 lines in <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin-reranker#overall-training-script\">Overall Training Script</a> above, which is the same script used for all six models.</li>\n</ul>\n<p>If you build something on top of these, please let me know! I'd genuinely love to see what people do with them, and if you manage to train better rerankers using the released data, even better. The recipe is intentionally simple, partly so that there's plenty of headroom for someone else to improve it. Train a stronger teacher and the same script can keep producing better students.</p>\n<h2>Acknowledgements</h2>\n<p>I'd like to thank the Ettin team (Orion Weller, Kathryn Ricci, Marc Marone, Antoine Chaffin, Dawn Lawrie, and Benjamin Van Durme) for <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/ettin\">building the base encoders</a> that these rerankers are built on, the LightOn team (Antoine Chaffin, Raphael Sourty, Paulo Moura, and Amélie Chatelain) for <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://huggingface.co/blog/lightonai/denseon-lateon\">their work on the training data collection</a>, and the Mixedbread AI team (Xianming Li, Aamir Shakir, Rui Huang, Tsz-fung Andrew Lee, Julius Lipp, Benjamin Clavié, and Jing Li) for <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://arxiv.org/abs/2506.03487\">their work on the teacher model</a>.</p>\n<h2>Citation</h2>\n<p>If you use the ettin-reranker-v1 family or any of the released artifacts, please cite this blogpost:</p>\n<pre><code class=\"language-bibtex\"><span class=\"code-snippet\" data-language=\"Bibtex\"><span class=\"syntax-text syntax-bibtex\"><span class=\"syntax-meta syntax-entry syntax-braces syntax-bibtex\"><span class=\"syntax-keyword syntax-other syntax-entry-type syntax-bibtex\"><span class=\"syntax-punctuation syntax-definition syntax-keyword syntax-bibtex\">@</span>misc</span><span class=\"syntax-punctuation syntax-section syntax-entry syntax-begin syntax-bibtex\">{</span><span class=\"syntax-entity syntax-name syntax-type syntax-entry-key syntax-bibtex\">aarsen2026ettin-reranker</span>,\n    <span class=\"syntax-meta syntax-key-assignment syntax-bibtex\"><span class=\"syntax-string syntax-unquoted syntax-key syntax-bibtex\">title</span> <span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-bibtex\">=</span> <span class=\"syntax-string syntax-quoted syntax-double syntax-bibtex\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-bibtex\">&quot;</span>Introducing the Ettin Reranker Family<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-bibtex\">&quot;</span></span></span>,\n    <span class=\"syntax-meta syntax-key-assignment syntax-bibtex\"><span class=\"syntax-string syntax-unquoted syntax-key syntax-bibtex\">author</span> <span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-bibtex\">=</span> <span class=\"syntax-string syntax-quoted syntax-double syntax-bibtex\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-bibtex\">&quot;</span>Aarsen, Tom<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-bibtex\">&quot;</span></span></span>,\n    <span class=\"syntax-meta syntax-key-assignment syntax-bibtex\"><span class=\"syntax-string syntax-unquoted syntax-key syntax-bibtex\">year</span> <span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-bibtex\">=</span> <span class=\"syntax-string syntax-quoted syntax-double syntax-bibtex\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-bibtex\">&quot;</span>2026<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-bibtex\">&quot;</span></span></span>,\n    <span class=\"syntax-meta syntax-key-assignment syntax-bibtex\"><span class=\"syntax-string syntax-unquoted syntax-key syntax-bibtex\">publisher</span> <span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-bibtex\">=</span> <span class=\"syntax-string syntax-quoted syntax-double syntax-bibtex\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-bibtex\">&quot;</span>Hugging Face<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-bibtex\">&quot;</span></span></span>,\n    <span class=\"syntax-meta syntax-key-assignment syntax-bibtex\"><span class=\"syntax-string syntax-unquoted syntax-key syntax-bibtex\">url</span> <span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-bibtex\">=</span> <span class=\"syntax-string syntax-quoted syntax-double syntax-bibtex\"><span class=\"syntax-punctuation syntax-definition syntax-string syntax-begin syntax-bibtex\">&quot;</span>https://huggingface.co/blog/ettin-reranker<span class=\"syntax-punctuation syntax-definition syntax-string syntax-end syntax-bibtex\">&quot;</span></span></span>,\n<span class=\"syntax-punctuation syntax-section syntax-entry syntax-end syntax-bibtex\">}</span></span>\n</span></span></code></pre>\n",
  "content_markdown": "## TL;DR\n\nToday I'm releasing six new [Sentence Transformers](https://sbert.net/) CrossEncoder rerankers, state-of-the-art at their respective sizes, built on top of the [Ettin](https://huggingface.co/collections/jhu-clsp/encoders-vs-decoders-the-ettin-suite) ModernBERT encoders, together with the data and full training recipe that produced them:\n\n- [`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)\n- [`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)\n- [`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)\n- [`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)\n- [`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)\n- [`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)\n\nThe models were trained with a **distillation recipe**: pointwise MSE on [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2) scores over [`cross-encoder/ettin-reranker-v1-data`](https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data), which is a subset of [`lightonai/embeddings-pre-training`](https://huggingface.co/datasets/lightonai/embeddings-pre-training) mixed with a reranked subset of [`lightonai/embeddings-fine-tuning`](https://huggingface.co/datasets/lightonai/embeddings-fine-tuning).\n\n[![Our six rerankers paired with embeddinggemma-300m on MTEB(eng, v2) Retrieval](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png)\n\n*Our six rerankers paired with [`google/embeddinggemma-300m`](https://huggingface.co/google/embeddinggemma-300m) on MTEB(eng, v2) Retrieval. See [Results](https://huggingface.co/blog/ettin-reranker#results) for five more embedder pairings.*\n\nIf you're new to rerankers and want the \"why\" first, jump to [What is a reranker, and why pair one with an embedder?](https://huggingface.co/blog/ettin-reranker#what-is-a-reranker-and-why-pair-one-with-an-embedder). If you just want to plug a model in, jump to [Usage](https://huggingface.co/blog/ettin-reranker#usage). If you want to train your own, jump to [Training](https://huggingface.co/blog/ettin-reranker#training).\n\n> I bootstrapped the training recipe below with the new [`train-sentence-transformers` Agent Skill](https://github.com/huggingface/sentence-transformers/tree/main/skills) shipped in [Sentence Transformers v5.5.0](https://github.com/huggingface/sentence-transformers/releases/tag/v5.5.0). Install it with `hf skills add train-sentence-transformers [--global] [--claude]` and ask your AI coding agent (Claude Code, Codex, Cursor, Gemini CLI, ...) to fine-tune a `SentenceTransformer`, `CrossEncoder`, or `SparseEncoder` model on your data.\n\n## Table of contents\n\n- [What is a reranker, and why pair one with an embedder?](https://huggingface.co/blog/ettin-reranker#what-is-a-reranker-and-why-pair-one-with-an-embedder)\n- [Usage](https://huggingface.co/blog/ettin-reranker#usage)\n  - [End-to-end retrieve-then-rerank pipeline](https://huggingface.co/blog/ettin-reranker#end-to-end-retrieve-then-rerank-pipeline)\n- [Architecture Details](https://huggingface.co/blog/ettin-reranker#architecture-details)\n- [Results](https://huggingface.co/blog/ettin-reranker#results)\n  - [MTEB(eng, v2) Retrieval](https://huggingface.co/blog/ettin-reranker#mtebeng-v2-retrieval)\n  - [Speed](https://huggingface.co/blog/ettin-reranker#speed)\n- [Training](https://huggingface.co/blog/ettin-reranker#training)\n  - [Distillation recipe](https://huggingface.co/blog/ettin-reranker#distillation-recipe)\n  - [Dataset](https://huggingface.co/blog/ettin-reranker#dataset)\n  - [Training Arguments](https://huggingface.co/blog/ettin-reranker#training-arguments)\n  - [Evaluation](https://huggingface.co/blog/ettin-reranker#evaluation)\n  - [Overall Training Script](https://huggingface.co/blog/ettin-reranker#overall-training-script)\n- [Conclusion](https://huggingface.co/blog/ettin-reranker#conclusion)\n- [Acknowledgements](https://huggingface.co/blog/ettin-reranker#acknowledgements)\n\n## What is a reranker, and why pair one with an embedder?\n\nA reranker (a.k.a. pointwise cross-encoder) is a neural model that takes a `(query, document)` pair and outputs a single relevance score. Unlike an embedding model, which encodes the query and document separately and computes their similarity from the two embedding vectors, a reranker lets the two texts attend to each other through every transformer layer. That joint encoding is more accurate but also more expensive: the model has to be run once per `(query, document)` pair rather than once per text.\n\nBecause cross-encoders are too expensive to run over a full corpus, the common production pattern is **retrieve-then-rerank**: a fast embedding model retrieves the top-K candidates (cheap), then a cross-encoder re-orders just those K with high accuracy. The total cost stays bounded while the final ranking is much closer to what an exhaustive cross-encoder pass would produce.\n\n[![Embedding vs Reranker Models](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/train-reranker/embedding_vs_reranker_model.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/train-reranker/embedding_vs_reranker_model.png)\n\n> Throughout this blogpost I'll use \"reranker\" and \"cross-encoder\" interchangeably.\n\n## Usage\n\nThe released models are normal Sentence Transformers `CrossEncoder` models, so you can use them with just 3 lines of code:\n\n```python\nfrom sentence_transformers import CrossEncoder\n\nmodel = CrossEncoder(\"cross-encoder/ettin-reranker-32m-v1\")\nscores = model.predict([\n    (\"Where was Apple founded?\", \"Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.\"),\n    (\"Where was Apple founded?\", \"The Fuji apple is an apple cultivar developed in the late 1930s and brought to market in 1962.\"),\n])\nprint(scores)\n# [11.393298  2.968891]   <- larger means more relevant\n```\n\nFor a query and a list of candidates, you can also use `rank` to get back sorted indices and scores:\n\n```python\nranked = model.rank(\n    query=\"Which planet is known as the Red Planet?\",\n    documents=[\n        \"Venus is often called Earth's twin because of its similar size and proximity.\",\n        \"Mars, known for its reddish appearance, is often referred to as the Red Planet.\",\n        \"Jupiter, the largest planet in our solar system, has a prominent red spot.\",\n        \"Saturn, famous for its rings, is sometimes mistaken for the Red Planet.\",\n    ],\n    top_k=4,\n    return_documents=True,\n)\nfor r in ranked:\n    print(f\"({r['score']:.2f}): {r['text']}\")\n# (10.82): Mars, known for its reddish appearance, is often referred to as the Red Planet.\n# (9.86): Saturn, famous for its rings, is sometimes mistaken for the Red Planet.\n# (8.55): Jupiter, the largest planet in our solar system, has a prominent red spot.\n# (6.21): Venus is often called Earth's twin because of its similar size and proximity.\n```\n\nYou can swap [`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1) for any other size to trade quality for speed. All six accept up to 8K tokens of context (useful for long-document reranking) thanks to ModernBERT's long-context pre-training.\n\nIt is recommended to install [`kernels`](https://github.com/huggingface/kernels) and set `model_kwargs={\"dtype\": \"bfloat16\", \"attn_implementation\": \"flash_attention_2\"}` for the highest throughput. See the [Speed](https://huggingface.co/blog/ettin-reranker#speed) section below for more details, but in general you can expect a 1.7x-8.3x speedup over default loading depending on model size and sequence length.\n\n```python\nfrom sentence_transformers import CrossEncoder\n\nmodel = CrossEncoder(\n    \"cross-encoder/ettin-reranker-32m-v1\",\n    model_kwargs={\"dtype\": \"bfloat16\", \"attn_implementation\": \"flash_attention_2\"},\n)\n```\n\n### End-to-end retrieve-then-rerank pipeline\n\nA complete example with a fast embedder for retrieval and the reranker for the final ordering:\n\n```python\nfrom sentence_transformers import SentenceTransformer, CrossEncoder\n\n# Fast retrieval with a static embedder (sub-millisecond on CPU per query)\nembedder = SentenceTransformer(\"sentence-transformers/static-retrieval-mrl-en-v1\")\nreranker = CrossEncoder(\"cross-encoder/ettin-reranker-68m-v1\")\n\ncorpus = [\n    \"Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.\",\n    \"The Fuji apple is an apple cultivar developed in the late 1930s.\",\n    \"Steve Jobs introduced the iPhone in 2007 at Macworld.\",\n    \"Macintosh computers were sold by Apple from 1984 onward.\",\n    # ... thousands or millions more in production\n]\nquery = \"Where was Apple founded?\"\n\n# Step 1: encode + retrieve top-100\nquery_emb = embedder.encode_query(query, convert_to_tensor=True)\ncorpus_emb = embedder.encode_document(corpus, convert_to_tensor=True)\nscores = embedder.similarity(query_emb, corpus_emb)[0]\ntop_k_idx = scores.topk(min(100, len(corpus))).indices.tolist()\n\n# Step 2: rerank\ntop_k_docs = [corpus[i] for i in top_k_idx]\nranked = reranker.rank(query, top_k_docs, top_k=5, return_documents=True)\nfor r in ranked:\n    print(f\"({r['score']:.2f}): {r['text']}\")\n# (11.63): Apple Inc. was founded in Cupertino, California in 1976 by Steve Jobs, Steve Wozniak, and Ronald Wayne.\n# (4.71): Steve Jobs introduced the iPhone in 2007 at Macworld.\n# (1.96): The Fuji apple is an apple cultivar developed in the late 1930s.\n# (1.49): Macintosh computers were sold by Apple from 1984 onward.\n```\n\nThis is the same shape used by most modern search systems. The retriever decides what enters the funnel, the reranker decides what wins.\n\n## Architecture Details\n\nAll six rerankers share the same architecture and differ only in their backbone size. The backbone is one of the six [Ettin encoders](https://huggingface.co/blog/ettin) from Johns Hopkins University's Ettin suite. These are ModernBERT-style models with unpadded attention, RoPE positional encodings, GeGLU, and 2T tokens of open-license pre-training, supporting up to 8192 tokens of context.\n\nOn top of each encoder, the reranker uses a 4-module classification head that mirrors `ModernBertForSequenceClassification` but is built from Sentence Transformers' modular components. The underlying `Transformer` is a plain `AutoModel` rather than `AutoModelForSequenceClassification`, which lets us use sequence unpadding for variable-length inputs for Flash Attention 2. At medium-document sequence lengths this is a 1.7x-8.3x speedup over fp32+SDPA depending on model size (see [Speed](https://huggingface.co/blog/ettin-reranker#speed) for the full benchmark):\n\n```\n1. Transformer(FA2)\n2. Pooling(cls)\n3. Dense(H, H, bias=False, GELU)\n4. LayerNorm(H)\n5. Dense(H, 1, scores)\n```\n\nIn my ablations, CLS pooling outperformed mean pooling. That was a little surprising. ModernBERT uses global attention only every third layer and the other two-thirds use local-window attention that cannot reach CLS from distant positions. Empirically, those few global layers carry enough signal to make CLS the better pooling choice.\n\n| Model                                                                                                  | Backbone                                                                             | Hidden size | Layers | Params (head incl.) |\n| ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ----------- | ------ | ------------------- |\n| [`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)   | [`jhu-clsp/ettin-encoder-17m`](https://huggingface.co/jhu-clsp/ettin-encoder-17m)   | 256         | 7      | 17.6M               |\n| [`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)   | [`jhu-clsp/ettin-encoder-32m`](https://huggingface.co/jhu-clsp/ettin-encoder-32m)   | 384         | 10     | 32.8M               |\n| [`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)   | [`jhu-clsp/ettin-encoder-68m`](https://huggingface.co/jhu-clsp/ettin-encoder-68m)   | 512         | 19     | 68.6M               |\n| [`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1) | [`jhu-clsp/ettin-encoder-150m`](https://huggingface.co/jhu-clsp/ettin-encoder-150m) | 768         | 22     | 150.9M              |\n| [`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1) | [`jhu-clsp/ettin-encoder-400m`](https://huggingface.co/jhu-clsp/ettin-encoder-400m) | 1024        | 28     | 401.6M              |\n| [`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)     | [`jhu-clsp/ettin-encoder-1b`](https://huggingface.co/jhu-clsp/ettin-encoder-1b)     | 1792        | 28     | 1.00B               |\n\nAll six models are released under the **Apache 2.0** license, matching the Ettin encoders.\n\n## Results\n\n### MTEB(eng, v2) Retrieval\n\nI ran each released model through the full [`MTEB(eng, v2)` Retrieval benchmark](https://github.com/embeddings-benchmark/mteb) (10 tasks, top-100 reranked) using MTEB's [two-stage reranking flow](https://embeddings-benchmark.github.io/mteb/get_started/advanced_usage/two_stage_reranking/), pairing each reranker with six embedding models that span the speed/quality spectrum:\n\n| Embedding Model                                                                                                                | Active params | Retriever-only NDCG@10 |\n| ------------------------------------------------------------------------------------------------------------------------------ | ------------- | ---------------------- |\n| [`sentence-transformers/static-retrieval-mrl-en-v1`](https://huggingface.co/sentence-transformers/static-retrieval-mrl-en-v1) | 0M            | 0.3495                 |\n| [`sentence-transformers/all-MiniLM-L6-v2`](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2)                     | 23M           | 0.4292                 |\n| [`BAAI/bge-small-en-v1.5`](https://huggingface.co/BAAI/bge-small-en-v1.5)                                                     | 33M           | 0.5149                 |\n| [`nomic-ai/nomic-embed-text-v1.5`](https://huggingface.co/nomic-ai/nomic-embed-text-v1.5)                                     | 137M          | 0.5226                 |\n| [`google/embeddinggemma-300m`](https://huggingface.co/google/embeddinggemma-300m)                                             | 308M          | 0.5463                 |\n| [`jinaai/jina-embeddings-v5-text-small-retrieval`](https://huggingface.co/jinaai/jina-embeddings-v5-text-small-retrieval)     | 596M          | 0.5980                 |\n\nThe **dashed retriever-only line** in each chart below is the headline number to beat. Anything below it means the reranker actively hurts the pipeline on average:\n\n|                                                                                                                                                                                                                                                                                                                                                                      |                                                                                                                                                                                                                                                                                                                                                                                                             |\n| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [![MTEB(eng, v2) Retrieval with static-retrieval-mrl-en-v1 + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_static-retrieval-mrl-en-v1.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_static-retrieval-mrl-en-v1.png) | [![MTEB(eng, v2) Retrieval with all-MiniLM-L6-v2 + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_all-MiniLM-L6-v2.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_all-MiniLM-L6-v2.png)                                                                      |\n| [![MTEB(eng, v2) Retrieval with bge-small-en-v1.5 + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_bge-small-en-v1.5.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_bge-small-en-v1.5.png)                            | [![MTEB(eng, v2) Retrieval with nomic-embed-text-v1.5 + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_nomic-embed-text-v1.5.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_nomic-embed-text-v1.5.png)                                                       |\n| [![MTEB(eng, v2) Retrieval with embeddinggemma-300m + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_embeddinggemma-300m.png)                      | [![MTEB(eng, v2) Retrieval with jina-embeddings-v5-text-small-retrieval + reranker](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_jina-embeddings-v5-text-small-retrieval.png)](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ettin-reranker/mteb_ndcg10_jina-embeddings-v5-text-small-retrieval.png) |\n\nFull table of results (click to expand)\n\nMean NDCG@10 over the 6 embedder pairings, sorted descending. Our six models are in **bold**, and the teacher [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2) is underlined.\n\n| Reranker                                                                                                                         | Params    | MTEB(eng, v2) Retrieval NDCG@10 |\n| -------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------- |\n| [`Qwen/Qwen3-Reranker-4B`](https://huggingface.co/Qwen/Qwen3-Reranker-4B)†                                                      | 4.02B     | 0.6367                          |\n| [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2)                             | 1.54B     | 0.6115                          |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1.00B** | **0.6114**                      |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **401M**  | **0.6091**                      |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **151M**  | **0.5994**                      |\n| [`Qwen/Qwen3-Reranker-0.6B`](https://huggingface.co/Qwen/Qwen3-Reranker-0.6B)                                                   | 596M      | 0.5940                          |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M      | 0.5920                          |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68.6M** | **0.5915**                      |\n| [`jinaai/jina-reranker-m0`](https://huggingface.co/jinaai/jina-reranker-m0)                                                     | 2.44B     | 0.5856                          |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M      | 0.5843                          |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32.8M** | **0.5779**                      |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M      | 0.5656                          |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17.6M** | **0.5576**                      |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M      | 0.5526                          |\n| [`zeroentropy/zerank-2-reranker`](https://huggingface.co/zeroentropy/zerank-2-reranker)†                                        | 4.02B     | 0.5300                          |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M      | 0.5098                          |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22.7M     | 0.5082                          |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33.4M     | 0.5066                          |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M      | 0.5063                          |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19.2M     | 0.4979                          |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70.8M     | 0.4968                          |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M      | 0.4890                          |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M      | 0.4865                          |\n\n† Capped to `max_seq_length=8192` (the 4B Qwen3-based rerankers don't fit on a single H100 80GB at native context). Native-context evaluation is likely higher.\n\nFull table of NanoBEIR results (click to expand)\n\n[NanoBEIR](https://huggingface.co/collections/sentence-transformers/nanobeir-with-bm25-rankings) is a fast 13-dataset subset of [BEIR](https://github.com/beir-cellar/beir) that uses 50 queries per dataset against up to 5000 documents each. NanoBEIR is what `metric_for_best_model` was set to during training (see [Evaluation](https://huggingface.co/blog/ettin-reranker#evaluation)), and what I used to guide the experimentation.\n\n| Reranker                                                                                                                         | Params    | NanoBEIR mean NDCG@10 |\n| -------------------------------------------------------------------------------------------------------------------------------- | --------- | --------------------- |\n| [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2)                             | 1.54B     | 0.7318                |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1.00B** | **0.7237**            |\n| [`jinaai/jina-reranker-m0`](https://huggingface.co/jinaai/jina-reranker-m0)                                                     | 2.44B     | 0.7197                |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **401M**  | **0.7193**            |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M      | 0.7162                |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **151M**  | **0.7086**            |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M      | 0.7017                |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M      | 0.6971                |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68.6M** | **0.6915**            |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M      | 0.6909                |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32.8M** | **0.6825**            |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17.6M** | **0.6746**            |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M      | 0.6488                |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M      | 0.6379                |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33.4M     | 0.6369                |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22.7M     | 0.6312                |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19.2M     | 0.6298                |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M      | 0.6231                |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70.8M     | 0.6136                |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M      | 0.6027                |\n\nThe smallest model I'm releasing, our 17M, beats the 33M `ms-marco-MiniLM-L12-v2` by +0.051 NDCG@10 (0.5576 vs 0.5066) on MTEB and +0.038 (0.6746 vs 0.6369) on NanoBEIR at roughly half the parameter count. The 32M beats the 568M `BAAI/bge-reranker-v2-m3` by +0.025 (0.5779 vs 0.5526) on MTEB, a 17x parameter gap. If you've been using one of the legacy MiniLM rerankers as the default in your retrieve-then-rerank stack, swapping in our 17M (or 32M) is a low-risk drop-in replacement, with a noticeable quality bump on both benchmarks.\n\nMoving up the table, our 150M is the strongest reranker I tested in the under-600M range on MTEB, edging out the recent `Qwen/Qwen3-Reranker-0.6B` (596M) by +0.005 (0.5994 vs 0.5940) and beating every BAAI bge-reranker variant by 0.03 to 0.05. The 68M is also worth a mention: at 0.5915 it lands almost exactly on `Qwen3-Reranker-0.6B` (0.5940) while using a ninth of the parameters.\n\nAt the top of the released range, our 1B model closely tracks its teacher. It comes within 0.0001 of the 1.54B `mxbai-rerank-large-v2` on MTEB (0.6114 vs 0.6115) and within 0.008 on NanoBEIR, despite distilling from a model 54% larger than itself. The distillation effectively closes the gap to the teacher, which is what I was hoping to see going into this release.\n\nThe overall strongest reranker in the comparison is `Qwen/Qwen3-Reranker-4B` at 0.6367 MTEB, +0.025 above our 1B model. Closing that gap from the current recipe would likely require distilling from a stronger teacher (our teacher itself sits below `Qwen3-Reranker-4B`). For most retrieve-then-rerank workloads, our 1B at a quarter of the parameters (see [Speed](https://huggingface.co/blog/ettin-reranker#speed)) is a much more practical pick.\n\n### Speed\n\nQuality numbers are only half of what matters for a reranker. The other half is whether its latency fits inside the budget you have between retrieval and showing results to the user. Let me walk through what I measured.\n\nI benchmarked all six released models against thirteen public rerankers (strong baselines up to about 1B parameters) on a single NVIDIA H100 80GB. The queries and documents come from [`sentence-transformers/natural-questions`](https://huggingface.co/datasets/sentence-transformers/natural-questions) at its natural document-length distribution: most NQ answers are short, some are long. Documents are truncated at `max_length=512` to avoid giving the older models an unfair advantage. Each model uses its best supported attention implementation: Flash Attention 2 wherever the architecture supports it (BERT, XLM-RoBERTa, ModernBERT, Qwen2), SDPA where it doesn't, and eager for DeBERTa-v2 (which currently has neither FA2 nor SDPA support in `transformers`).\n\nFor every model an auto-batch search starts at batch size 8 and doubles until the GPU runs out of memory. At each batch size I run three timed passes and keep the median throughput, so a single unlucky run doesn't drag the number around. The reported throughput is at whichever batch size won.\n\n**Table 1.** Throughput in pairs per second, all in `bfloat16`. Our six rerankers are in **bold**.\n\n| Model                                                                                                                            | Params   | Attn  | pairs / second |\n| -------------------------------------------------------------------------------------------------------------------------------- | -------- | ----- | -------------- |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17M**  | FA2   | **7517**       |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32M**  | FA2   | **6602**       |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68M**  | FA2   | **4913**       |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19M      | FA2   | 4029           |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22M      | FA2   | 3817           |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33M      | FA2   | 3311           |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **150M** | FA2   | **3237**       |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M     | FA2   | 2858           |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70M      | eager | 2636           |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M     | eager | 1953           |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **400M** | FA2   | **1738**       |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M     | FA2   | 1659           |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M     | FA2   | 1569           |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M     | FA2   | 1418           |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M     | FA2   | 1404           |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1B**   | FA2   | **928**        |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M     | eager | 867            |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M     | FA2   | 809            |\n| [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2)                             | 1.5B     | FA2   | 387            |\n\nOur 17M is the fastest reranker in the whole comparison, at 7517 pairs per second. That's almost twice the throughput of `ms-marco-MiniLM-L6-v2` (3817) and faster even than the smaller `ms-marco-MiniLM-L4-v2` (4029). And as you saw in the MTEB table earlier, our 17M is also more accurate than every MiniLM variant. If you're currently running a MiniLM cross-encoder, swapping to our 17M is a one-line change that improves both your latency and search quality.\n\nOur 150M is an even more interesting comparison, because there are two direct architectural peers at exactly 150M parameters: [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base) and [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2). Both are built on the same ModernBERT-base backbone. Our 150M runs at 3237 pairs per second, while the two peers come in at 1418 and 1404 respectively, for a 2.3x speed gap.\n\nAll three 150M models use Flash Attention 2, but the two peers load through `AutoModelForSequenceClassification`, which keeps the inputs padded. So attention itself runs the FA2 kernel, but the rest of the model is still doing dense compute on padding tokens that don't contribute anything. Our modular `Transformer` module (see [Architecture Details](https://huggingface.co/blog/ettin-reranker#architecture-details) above) propagates unpadded inputs all the way through the model, so every layer only spends compute on real tokens. That's the difference between getting some of FA2's benefit and getting all of it.\n\nAt the bottom of the table, our 1B model hits 928 pairs per second, which is 2.4x faster than the 1.54B teacher `mxbai-rerank-large-v2` (387 pairs per second) while matching its MTEB score within 0.0001. The teacher is Qwen2-based with a prompt-template overhead per pair, so the distilled student inherits the teacher's calibration and judgement but skips all the runtime baggage. This is honestly the most satisfying single number in the whole release for me.\n\nOne unfortunate note: the DeBERTa-v2-based `mxbai-rerank-{xsmall,base,large}-v1` series ends up much slower than the rest of the table because DeBERTa-v2 currently supports neither Flash Attention 2 nor SDPA in `transformers`. The 70M `mxbai-rerank-xsmall-v1` runs at 2636 pairs per second, about half the throughput of our 68M at almost the same parameter count. The models themselves are perfectly fine, they just don't get to use modern attention kernels.\n\nSame benchmark on a consumer GPU (RTX 3090, 24 GB)\n\nIf you're self-hosting on a consumer card rather than a datacenter GPU, here's the same throughput sweep on an RTX 3090. Same benchmark setup as Table 1: `bfloat16`, best-supported attention per model, three-trial median throughput at the largest batch that fits.\n\n| Model                                                                                                                            | Params   | Best attn | pairs / second |\n| -------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | -------------- |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17M**  | FA2       | **9008**       |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19M      | FA2       | 5071           |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32M**  | FA2       | **4497**       |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22M      | FA2       | 4234           |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33M      | FA2       | 2847           |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68M**  | FA2       | **1916**       |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70M      | eager     | 1677           |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M     | FA2       | 1329           |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **150M** | FA2       | **982**        |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M     | eager     | 772            |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M     | FA2       | 598            |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M     | FA2       | 586            |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M     | FA2       | 448            |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M     | FA2       | 436            |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **400M** | FA2       | **429**        |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M     | eager     | 266            |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M     | FA2       | 221            |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1B**   | FA2       | **189**        |\n| [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2)                             | 1.5B     | FA2       | 69             |\n\nOur 17M is still the fastest model in the table at 9008 pairs per second, actually higher than its H100 number, which suggests that at tiny sizes raw compute isn't the bottleneck and the H100's extra muscle doesn't translate. The middle of the table reshuffles a bit, with the MiniLM rerankers overtaking our 32M and 68M, and the 1B slipping behind `mxbai-rerank-base-v2` (189 vs 221 pairs per second). Our 150M model still holds a solid lead over the two 150M ModernBERT-based peers, and the teacher-replacement story still holds, with our 1B at 2.7x the throughput of the 1.5B `mxbai-rerank-large-v2` (189 vs 69 pairs per second).\n\nSame benchmark on CPU (Intel Core i7-13700K)\n\n| Model                                                                                                                            | Params   | Best attn | pairs / second |\n| -------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | -------------- |\n| **[`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)**                         | **17M**  | SDPA      | **267.4**      |\n| [`cross-encoder/ms-marco-MiniLM-L4-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L4-v2)                             | 19M      | SDPA      | 206.2          |\n| [`cross-encoder/ms-marco-MiniLM-L6-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L6-v2)                             | 22M      | SDPA      | 143.9          |\n| **[`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)**                         | **32M**  | SDPA      | **92.5**       |\n| [`cross-encoder/ms-marco-MiniLM-L12-v2`](https://huggingface.co/cross-encoder/ms-marco-MiniLM-L12-v2)                           | 33M      | SDPA      | 75.9           |\n| [`mixedbread-ai/mxbai-rerank-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-xsmall-v1)                           | 70M      | eager     | 38.9           |\n| **[`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)**                         | **68M**  | SDPA      | **31.2**       |\n| [`BAAI/bge-reranker-base`](https://huggingface.co/BAAI/bge-reranker-base)                                                       | 278M     | SDPA      | 19.2           |\n| [`Alibaba-NLP/gte-reranker-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-reranker-modernbert-base)                   | 150M     | SDPA      | 14.7           |\n| [`ibm-granite/granite-embedding-reranker-english-r2`](https://huggingface.co/ibm-granite/granite-embedding-reranker-english-r2) | 150M     | SDPA      | 14.5           |\n| **[`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)**                       | **150M** | SDPA      | **14.0**       |\n| [`mixedbread-ai/mxbai-rerank-base-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v1)                               | 184M     | eager     | 13.4           |\n| [`BAAI/bge-reranker-large`](https://huggingface.co/BAAI/bge-reranker-large)                                                     | 560M     | SDPA      | 6.2            |\n| [`BAAI/bge-reranker-v2-m3`](https://huggingface.co/BAAI/bge-reranker-v2-m3)                                                     | 568M     | SDPA      | 6.0            |\n| **[`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)**                       | **400M** | SDPA      | **5.2**        |\n| [`mixedbread-ai/mxbai-rerank-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v1)                             | 435M     | eager     | 4.3            |\n| [`mixedbread-ai/mxbai-rerank-base-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-base-v2)                               | 494M     | SDPA      | 3.5            |\n| **[`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)**                           | **1B**   | SDPA      | **2.1**        |\n\nOn CPU, we can't take advantage of bf16, Flash Attention 2, or unpadding, so the latency story is a bit simpler: the higher the parameter count, the slower the model. The 17M model is considerably faster than `ms-marco-MiniLM-L6-v2` (267.4 vs 143.9 pairs per second) and even faster than the smaller `ms-marco-MiniLM-L4-v2` (206.2). As expected, our 150M model lands alongside the two 150M peers (14.0 vs 14.5 and 14.7 pairs per second) now that unpadding no longer applies. If you're CPU-bound, our 17M and 32M are the practical picks.\n\nTo explain where the speed comes from, the next table sweeps `fp32+SDPA`, `bf16+SDPA`, and `bf16+FA2` for our six models using the same bench config. The FA2 column is split in two: one with the inputs still padded (what a wrapped model would see) and one with unpadded inputs (what our modular `Transformer` actually does). The rightmost column is what our models use by default when FA2 is enabled.\n\n**Table 2.** Precision and attention ablation for the six released sizes at `max_length=512` on natural NQ documents. Each cell shows pairs / second with the multiplier relative to `fp32+SDPA` in parentheses, and peak GPU memory on the second line. The rightmost column (in **bold**) is the configuration our models use by default when FA2 is enabled.\n\n| Model                                                                                    | Params | fp32+SDPA           | bf16+SDPA           | bf16+FA2 w. padding | **bf16+FA2 w.o. padding**   |\n| ---------------------------------------------------------------------------------------- | ------ | ------------------- | ------------------- | ------------------- | --------------------------- |\n| [`ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)   | 17M    | 4402 (1.00x) 0.8 GB | 4523 (1.03x) 2.2 GB | 3744 (0.85x) 1.9 GB | **7517 (1.71x)** **1.4 GB** |\n| [`ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)   | 32M    | 3307 (1.00x) 1.2 GB | 4357 (1.32x) 1.6 GB | 3040 (0.92x) 2.9 GB | **6602 (2.00x)** **1.1 GB** |\n| [`ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)   | 68M    | 1364 (1.00x) 1.0 GB | 2861 (2.10x) 2.2 GB | 2003 (1.47x) 2.0 GB | **4913 (3.60x)** **1.5 GB** |\n| [`ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1) | 150M   | 671 (1.00x) 1.6 GB  | 1942 (2.90x) 1.8 GB | 1396 (2.08x) 3.1 GB | **3237 (4.83x)** **1.4 GB** |\n| [`ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1) | 400M   | 266 (1.00x) 2.5 GB  | 1113 (4.18x) 1.8 GB | 864 (3.25x) 2.7 GB  | **1738 (6.53x)** **2.2 GB** |\n| [`ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)     | 1B     | 112 (1.00x) 4.6 GB  | 630 (5.60x) 2.8 GB  | 522 (4.64x) 3.6 GB  | **928 (8.26x)** **4.5 GB**  |\n\nThe total speedup from `bf16+FA2 w.o. padding` over the `fp32+SDPA` baseline grows sharply with model size, from 1.71x on the 17M to 8.26x on the 1B. Most of that growth comes from `bf16` alone: the `fp32+SDPA` to `bf16+SDPA` step gives the 17M only a 1.03x speedup but gives the 1B a full 5.60x speedup, also due to the lowered memory cost allowing for bigger batch sizes. In short, `bfloat16` is the biggest single contributor to the overall speedup.\n\nUnexpectedly, turning on FA2 while the inputs are still padded is actually slower than `bf16+SDPA` at every size in the release. The FA2 kernel prefers an unpadded format, and when you feed it padded inputs you pay the bookkeeping overhead of converting between formats while still spending compute on the padding tokens themselves. So the `bf16+FA2 w. padding` column is roughly what you'd measure if you swapped `sdpa` for `flash_attention_2` in `model_kwargs` without changing anything else about the model loader. This is the situation that `gte-reranker-modernbert-base` and `granite-embedding-reranker-english-r2` from Table 1 are in.\n\nLastly, going from `bf16+FA2 w. padding` to `bf16+FA2 w.o. padding` is worth between 1.78x (1B) and 2.45x (68M) of additional throughput, and it also cuts peak memory considerably, allowing for higher batch sizes.\n\nSo my recommendation is simple: enable `bf16` and FA2 together. The six Ettin rerankers will use unpadded inputs by default, since that's what the modular `Transformer` module from the [Architecture Details](https://huggingface.co/blog/ettin-reranker#architecture-details) section is set up for. The full snippet is the same as in the [Usage](https://huggingface.co/blog/ettin-reranker#usage) section above:\n\n```python\nfrom sentence_transformers import CrossEncoder\n\nmodel = CrossEncoder(\n    \"cross-encoder/ettin-reranker-150m-v1\",\n    model_kwargs={\n        \"dtype\": \"bfloat16\",\n        \"attn_implementation\": \"flash_attention_2\",  # See tip below\n    },\n)\n```\n\n> Use `pip install kernels` to install FA2. It ships pre-built kernels for a wide range of GPU architectures, CUDA versions, and operating systems.\n\nOne caveat for other CrossEncoders: the full speedup is only available for models built with a modular `Transformer` like the Ettin rerankers. Applying the same two flags to a CrossEncoder that loads through `AutoModelForSequenceClassification` lands you in the slower `bf16+FA2 w. padding` column of Table 2 instead.\n\n## Training\n\nThe training script below started as the output of the new [`train-sentence-transformers` Agent Skill](https://github.com/huggingface/sentence-transformers/tree/main/skills), shipped in [Sentence Transformers v5.5.0](https://github.com/huggingface/sentence-transformers/releases/tag/v5.5.0). If you use an AI coding agent (Claude Code, Codex, Cursor, Gemini CLI, ...), you can install the skill and ask it to fine-tune a `SentenceTransformer`, `CrossEncoder`, or `SparseEncoder` model on your data. The skill carries version-aware guidance for base model selection, loss and evaluator choice, hard-negative mining, distillation, LoRA, Matryoshka, multilingual training, and static embeddings, plus template scripts for each model type.\n\n```bash\nhf skills add train-sentence-transformers --claude   # symlinks into .claude/skills/\nhf skills add train-sentence-transformers --global   # under ~/.agents/skills/\n```\n\nA prompt like *\"Fine-tune a cross-encoder reranker on `(query, document)` pairs from my dataset, mine hard negatives, and push to my Hub repo\"* will produce a runnable script you can then iterate on. That's how I started working on the recipe below.\n\nAll six rerankers were trained with the same single-stage recipe. Only the learning rate and the per-device batch size vary per model size. The full training script is ~150 lines and uses one published dataset.\n\nThe recipe converged after a single sweep across model sizes. Each size's learning rate was tuned by a small grid search on a ~15% subset of the final training data, and the resulting LRs transferred cleanly to the full-data runs without re-tuning. No per-size tuning beyond LR was needed.\n\n### Distillation recipe\n\nMost published reranker recipes train on human-labeled relevance triples (a query, one positive document, and optionally hard negatives) with a contrastive, pointwise, pairwise, or listwise loss like [`MultipleNegativesRankingLoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#multiplenegativesrankingloss), [`BinaryCrossEntropyLoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#binarycrossentropyloss), [`RankNetLoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#ranknetloss), or [`LambdaLoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#lambdaloss), respectively. See my earlier [Training and Finetuning Reranker Models with Sentence Transformers](https://huggingface.co/blog/train-reranker) blogpost, for example.\n\nBut this approach has a few practical and theoretical drawbacks. First, positives need to be human-labeled, which is expensive and slow to scale across many domains. Second, the model only ever sees a label for the small subset of `(query, document)` pairs that someone went through. Especially after hard negative mining, you end up with a lot of false negatives, e.g. as shown in [Hard Negatives, Hard Lessons](https://arxiv.org/abs/2505.16967). Third, the binary nature of this labeling doesn't match reality, where some documents are simply more relevant than others.\n\nI took a different route here: pointwise MSE distillation from an existing strong teacher reranker. The setup is simple enough to describe in three lines:\n\n- **Teacher**: [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2) (1.54B parameters).\n- **Loss**: [`MSELoss`](https://sbert.net/docs/package_reference/cross_encoder/losses.html#mseloss) on the raw teacher logits (range ~\\[−12, 22\\]), i.e. without rescaling.\n- **Training data**: ~143M `(query, document, teacher_score)` triples.\n\n### Dataset\n\nI've released the training data as a single Hugging Face dataset, [`cross-encoder/ettin-reranker-v1-data`](https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data), assembled from two sources. Each source is kept as its own split so the provenance is transparent:\n\n1. LightOn pre-training data ([`lightonai/embeddings-pre-training`](https://huggingface.co/datasets/lightonai/embeddings-pre-training), non-curated): 32 splits covering broad-domain text similarity signal (MTP, FW-EDU, Reddit, PAQ, S2ORC, Amazon, Wikipedia, MS MARCO, etc.). I limit the number of samples for some of the splits, resulting in ~110M `(query, document, similarity)` triples in total.\n2. Rescored retrieval data from [`lightonai/embeddings-fine-tuning`](https://huggingface.co/datasets/lightonai/embeddings-fine-tuning): 7 splits (`msmarco`, `hotpotqa`, `trivia`, `nq`, `squadv2`, `fiqa`, `fever`). The source dataset has up to 2048 candidate documents per query (initially scored with [`Alibaba-NLP/gte-modernbert-base`](https://huggingface.co/Alibaba-NLP/gte-modernbert-base)), which I rescored with [`mixedbread-ai/mxbai-rerank-large-v2`](https://huggingface.co/mixedbread-ai/mxbai-rerank-large-v2) and uploaded as [`cross-encoder/lightonai-embeddings-fine-tuning-reranked-v1`](https://huggingface.co/datasets/cross-encoder/lightonai-embeddings-fine-tuning-reranked-v1). That dataset subsamples each query's 2048 candidates down to 256 using the [Jang et al.](https://arxiv.org/abs/2604.04734) quantile-anchor recipe (all positives + top-16 hard + ~239 quantile-anchor stratified). For training, I pick 64 of those 256 per query: 32 from the score-sorted head (the positive plus the hardest negatives) and 32 medium-difficulty negatives sampled from a band further down the teacher's ranking. See the [dataset card](https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data) for the exact rank positions.\n\nTotal: ~143M `(query, document, score)` triples, plus a held-out 5K-row eval split (the tail of `quora`) that drives the in-training eval loss.\n\n### Training Arguments\n\nMost hyperparameters are constant across model sizes:\n\n```python\nCrossEncoderTrainingArguments(\n    num_train_epochs=1,                    # I chose more data over more epochs\n    per_device_train_batch_size=...,       # global_batch_size // world_size (see table below)\n    gradient_accumulation_steps=1,\n    learning_rate=...,                     # per-size, see table\n    warmup_ratio=0.03,                     # ~3% linear warmup, then linear decay (default)\n    bf16=True,                             # FA2 + bf16 throughout\n    eval_strategy=\"steps\",\n    eval_steps=0.05,                       # NanoBEIR every 5% of training\n    save_strategy=\"steps\",\n    save_steps=0.05,\n    save_total_limit=5,\n    load_best_model_at_end=True,\n    metric_for_best_model=\"eval_NanoBEIR_R100_mean_ndcg@10\",\n    seed=12,\n)\n```\n\nOnly the learning rate and global batch size very per model size.\n\n| Size | Learning rate | Global batch size |\n| ---- | ------------- | ----------------- |\n| 17m  | 2.4e-4        | 1024              |\n| 32m  | 1.2e-4        | 512               |\n| 68m  | 3e-5          | 256               |\n| 150m | 1.5e-5        | 192               |\n| 400m | 7e-6          | 256               |\n| 1b   | 3e-6          | 512               |\n\n`global_batch_size` is `per_device_batch_size x world_size x gradient_accumulation_steps`. On a single 8-GPU node, the 1024 global batch for 17m means `per_device=128`. On 8 nodes, it means `per_device=8`. The training script computes `per_device_batch_size` from `global_batch_size // world_size` so the same script works at any node count. The global batch size could be made more consistent, but I found that the above values worked well and didn't want to retune them just for the sake of consistency.\n\n### Evaluation\n\nI monitored NanoBEIR mean NDCG@10 during training (eval every 5% of steps) and used it as the `metric_for_best_model` for `load_best_model_at_end`. NanoBEIR is fast, so I could afford it 20 times per training run. After training, I evaluated both the best checkpoint (according to NanoBEIR) and the last checkpoint on the full MTEB(eng, v2) Retrieval benchmark. The final release checkpoint was the one that did best on MTEB. The NanoBEIR-preferred checkpoint won for all sizes except 68m, where the last checkpoint was slightly stronger.\n\n### Overall Training Script\n\nThe complete script (what every released model was trained with) is a single file. Only `ENCODER_SIZE` changes per run, and everything else is automatic:\n\n```python\nfrom __future__ import annotations\n\nimport logging\nimport os\nfrom pathlib import Path\n\nimport torch\nimport torch.nn as nn\nfrom datasets import concatenate_datasets, get_dataset_config_names, load_dataset\n\nfrom sentence_transformers import CrossEncoder\nfrom sentence_transformers.base.modules import Dense\nfrom sentence_transformers.cross_encoder import (\n    CrossEncoderModelCardData,\n    CrossEncoderTrainer,\n    CrossEncoderTrainingArguments,\n)\nfrom sentence_transformers.cross_encoder.evaluation import CrossEncoderNanoBEIREvaluator\nfrom sentence_transformers.cross_encoder.losses import MSELoss\nfrom sentence_transformers.sentence_transformer.modules import LayerNorm, Pooling, Transformer\n\nlogging.basicConfig(level=logging.INFO, format=\"%(asctime)s %(message)s\", datefmt=\"%H:%M:%S\")\nlogging.getLogger(\"httpx\").setLevel(logging.WARNING)\n\n# Per-size config. I swept the learning rates with these global (effective) batch sizes,\n# also by incorporating accum_steps\nCONFIGS: dict[str, dict] = {\n    \"17m\":  {\"base_model_name\": \"jhu-clsp/ettin-encoder-17m\",  \"learning_rate\": 2.4e-4, \"global_batch_size\": 1024},\n    \"32m\":  {\"base_model_name\": \"jhu-clsp/ettin-encoder-32m\",  \"learning_rate\": 1.2e-4, \"global_batch_size\": 512},\n    \"68m\":  {\"base_model_name\": \"jhu-clsp/ettin-encoder-68m\",  \"learning_rate\": 3e-5,   \"global_batch_size\": 256},\n    \"150m\": {\"base_model_name\": \"jhu-clsp/ettin-encoder-150m\", \"learning_rate\": 1.5e-5, \"global_batch_size\": 192},\n    \"400m\": {\"base_model_name\": \"jhu-clsp/ettin-encoder-400m\", \"learning_rate\": 7e-6,   \"global_batch_size\": 256},\n    \"1b\":   {\"base_model_name\": \"jhu-clsp/ettin-encoder-1b\",   \"learning_rate\": 3e-6,   \"global_batch_size\": 512},\n}\nENCODER_SIZE = \"17m\"\n\ndef main() -> None:\n    config = CONFIGS[ENCODER_SIZE]\n    encoder_id = config[\"base_model_name\"]\n    learning_rate = config[\"learning_rate\"]\n    global_batch_size = config[\"global_batch_size\"]\n\n    world_size = int(os.environ.get(\"WORLD_SIZE\", 1))\n    per_device_batch_size = global_batch_size // world_size\n    dataloader_workers = 0 if world_size > 8 else 4\n    run_name = f\"ettin-reranker-{ENCODER_SIZE}-lr{learning_rate:.0e}\"\n\n    # 1. Load a model to finetune with model card data\n    # The model mirrors ModernBertForSequenceClassification, but with a 'headless' Transformer that just loads\n    # AutoModel. This allows for unpadding with FA2, which isn't possible with AutoModelForSequenceClassification.\n    # This speeds up training considerably, while heavily reducing memory usage.\n    torch.manual_seed(12)\n    transformer = Transformer(encoder_id, model_kwargs={\"attn_implementation\": \"flash_attention_2\"})\n    transformer.model.config.num_labels = 1\n    embedding_dimension = transformer.get_embedding_dimension()\n    pooling = Pooling(embedding_dimension=embedding_dimension, pooling_mode=\"cls\")\n    dense_inner = Dense(\n        in_features=embedding_dimension, out_features=embedding_dimension, bias=False,\n        activation_function=nn.GELU(),\n        module_input_name=\"sentence_embedding\", module_output_name=\"sentence_embedding\",\n    )\n    norm = LayerNorm(dimension=embedding_dimension)\n    dense_score = Dense(\n        in_features=embedding_dimension, out_features=1, bias=True,\n        activation_function=nn.Identity(),\n        module_input_name=\"sentence_embedding\", module_output_name=\"scores\",\n    )\n    model = CrossEncoder(\n        modules=[transformer, pooling, dense_inner, norm, dense_score],\n        num_labels=1,\n        activation_fn=nn.Identity(),\n        model_card_data=CrossEncoderModelCardData(\n            model_name=f\"Ettin Reranker {ENCODER_SIZE} distilled from mxbai-rerank-large-v2\",\n            language=\"en\",\n            license=\"apache-2.0\",\n        ),\n    )\n    actual_attn = getattr(model[0].model.config, \"_attn_implementation\", None)\n    if not (actual_attn and \"flash\" in actual_attn.lower()):\n        logging.warning(f\"FA2 may not be active (attn_impl={actual_attn!r}); training will be slower.\")\n\n    # 2. Load the dataset. Each config is one source subset (32 lighton + 7 rerank retrieval\n    # domains). The held-out eval rows live as the 'validation' split of the 'quora' config.\n    dataset_repo = \"cross-encoder/ettin-reranker-v1-data\"\n    train_pieces = []\n    eval_dataset = None\n    for config_name in get_dataset_config_names(dataset_repo):\n        dataset = load_dataset(dataset_repo, config_name)\n        train_pieces.append(dataset[\"train\"])\n        if \"validation\" in dataset:\n            eval_dataset = dataset[\"validation\"]\n    train_dataset = concatenate_datasets(train_pieces)\n    print(train_dataset)\n\n    # 3. Define a loss function\n    loss = MSELoss(model)\n\n    # 4. Specify training arguments\n    args = CrossEncoderTrainingArguments(\n        output_dir=f\"models/{run_name}\",\n        num_train_epochs=1,\n        per_device_train_batch_size=per_device_batch_size,\n        per_device_eval_batch_size=per_device_batch_size,\n        gradient_accumulation_steps=1,\n        learning_rate=learning_rate,\n        warmup_ratio=0.03,\n        bf16=True,\n        eval_strategy=\"steps\",\n        eval_steps=0.05,\n        save_strategy=\"steps\",\n        save_steps=0.05,\n        save_total_limit=5,\n        logging_steps=0.025,\n        logging_first_step=True,\n        load_best_model_at_end=True,\n        metric_for_best_model=\"eval_NanoBEIR_R100_mean_ndcg@10\",\n        dataloader_num_workers=dataloader_workers,\n        run_name=run_name,\n        seed=12,\n    )\n\n    # 5. Create an evaluator\n    evaluator = CrossEncoderNanoBEIREvaluator(\n        dataset_names=[\"msmarco\", \"nfcorpus\", \"nq\", \"fiqa2018\", \"touche2020\", \"scifact\",\n                       \"hotpotqa\", \"arguana\", \"fever\", \"dbpedia\", \"climatefever\", \"scidocs\",\n                       \"quoraretrieval\"],\n        batch_size=per_device_batch_size,\n        always_rerank_positives=False,\n        show_progress_bar=False,\n    )\n\n    # 6. Create a trainer\n    trainer = CrossEncoderTrainer(\n        model=model,\n        args=args,\n        train_dataset=train_dataset,\n        eval_dataset=eval_dataset,\n        loss=loss,\n        evaluator=evaluator,\n    )\n\n    # 7. Evaluate before training\n    if trainer.is_world_process_zero():\n        with torch.autocast(device_type=\"cuda\", dtype=torch.bfloat16):\n            evaluator(model)\n\n    # 8. Train\n    trainer.train()\n\n    # 9. Evaluate the final model\n    if trainer.is_world_process_zero():\n        with torch.autocast(device_type=\"cuda\", dtype=torch.bfloat16):\n            evaluator(model)\n\n    # 10. Save the final model\n    final_dir = f\"models/{run_name}/final\"\n    model.save_pretrained(final_dir)\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\nFor multi-node training (anything past 17m/32m), launch the same script with `torchrun`:\n\n```bash\n# Single-node (17m, 32m): defaults work\npython train.py\n\n# Multi-node 4n setup for 150m, preserves global_batch_size=192:\ntorchrun --nproc_per_node=8 --nnodes=4 ... train.py\n```\n\n## Conclusion\n\nThe ettin-reranker-v1 family, trained with a single simple recipe, is state-of-the-art at every released size up to 1B parameters. Pointwise MSE distillation from a strong teacher onto a broad-domain and retrieval-specific mix scales cleanly from 17M to 1B parameters, with only the learning rate and per-device batch size changing between sizes.\n\nEvery ettin-reranker-v1 model beats the `ms-marco-MiniLM-L*-v2` family by a comfortable margin on MTEB and NanoBEIR. `cross-encoder/ettin-reranker-150m-v1` is the strongest mid-tier reranker I tested in the under-600M range, `cross-encoder/ettin-reranker-400m-v1` lands within 0.0024 of the 1.54B teacher's MTEB score, and `cross-encoder/ettin-reranker-1b-v1` matches that teacher within 0.0001.\n\nEverything in one place:\n\n- **Models**:\n  - [`cross-encoder/ettin-reranker-17m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-17m-v1)\n  - [`cross-encoder/ettin-reranker-32m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-32m-v1)\n  - [`cross-encoder/ettin-reranker-68m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-68m-v1)\n  - [`cross-encoder/ettin-reranker-150m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1)\n  - [`cross-encoder/ettin-reranker-400m-v1`](https://huggingface.co/cross-encoder/ettin-reranker-400m-v1)\n  - [`cross-encoder/ettin-reranker-1b-v1`](https://huggingface.co/cross-encoder/ettin-reranker-1b-v1)\n- **Dataset**: [`cross-encoder/ettin-reranker-v1-data`](https://huggingface.co/datasets/cross-encoder/ettin-reranker-v1-data) with ~143M `(query, document, label)` triples, kept as 39 named splits so the provenance of every row is visible.\n- **Training script**: the ~150 lines in [Overall Training Script](https://huggingface.co/blog/ettin-reranker#overall-training-script) above, which is the same script used for all six models.\n\nIf you build something on top of these, please let me know! I'd genuinely love to see what people do with them, and if you manage to train better rerankers using the released data, even better. The recipe is intentionally simple, partly so that there's plenty of headroom for someone else to improve it. Train a stronger teacher and the same script can keep producing better students.\n\n## Acknowledgements\n\nI'd like to thank the Ettin team (Orion Weller, Kathryn Ricci, Marc Marone, Antoine Chaffin, Dawn Lawrie, and Benjamin Van Durme) for [building the base encoders](https://huggingface.co/blog/ettin) that these rerankers are built on, the LightOn team (Antoine Chaffin, Raphael Sourty, Paulo Moura, and Amélie Chatelain) for [their work on the training data collection](https://huggingface.co/blog/lightonai/denseon-lateon), and the Mixedbread AI team (Xianming Li, Aamir Shakir, Rui Huang, Tsz-fung Andrew Lee, Julius Lipp, Benjamin Clavié, and Jing Li) for [their work on the teacher model](https://arxiv.org/abs/2506.03487).\n\n## Citation\n\nIf you use the ettin-reranker-v1 family or any of the released artifacts, please cite this blogpost:\n\n```bibtex\n@misc{aarsen2026ettin-reranker,\n    title = \"Introducing the Ettin Reranker Family\",\n    author = \"Aarsen, Tom\",\n    year = \"2026\",\n    publisher = \"Hugging Face\",\n    url = \"https://huggingface.co/blog/ettin-reranker\",\n}\n```\n",
  "dateCreated": "2026-10-19T01:26:53.998049939+00:00",
  "date_created": "2026-05-19T00:00:00+00:00",
  "date_modified": "2026-05-19T00:00:00+00:00",
  "date_published": "2026-05-19T00:00:00+00:00",
  "description": "TL;DR Today I'm releasing six new Sentence Transformers CrossEncoder rerankers, state-of-the-art at their respective sizes, built on top of the Ettin ModernBERT encoders, together with the data and full training recipe that produced them:…",
  "external_url": "https://huggingface.co/blog/ettin-reranker",
  "git": {
    "commit": "ebb0941c5c06a2ab2377342d607535262a3e969e",
    "path": "items/huggingface-co/2026/05/2026-05-19-introducing-the-ettin-reranker-family.md",
    "permalink": "https://github.com/aymericbeaumet/aggr-instance/blob/ebb0941c5c06a2ab2377342d607535262a3e969e/items/huggingface-co/2026/05/2026-05-19-introducing-the-ettin-reranker-family.md"
  },
  "id": "urn:aggr:item:c464bd1f41424e2d2b7206a243a27543f487c5ca",
  "isBasedOn": {
    "@id": "https://huggingface.co/blog/ettin-reranker"
  },
  "mainEntity": {
    "@id": "https://huggingface.co/blog/ettin-reranker",
    "@type": "CreativeWork",
    "archivedAt": {
      "@id": "https://aggr.aymericbeaumet.com/items/huggingface-co/2026-05-19-introducing-the-ettin-reranker-family/#webpage"
    },
    "dateModified": "2026-05-19T00:00:00+00:00",
    "datePublished": "2026-05-19T00:00:00+00:00",
    "headline": "Introducing the Ettin Reranker Family",
    "timeRequired": "PT28M",
    "url": "https://huggingface.co/blog/ettin-reranker",
    "wordCount": 6217
  },
  "name": "Archived snapshot: Introducing the Ettin Reranker Family",
  "preview": null,
  "reading_minutes": 28,
  "replicated_at": null,
  "source": "huggingface-co",
  "source_name": "Hugging Face - Blog",
  "summary": null,
  "tags": [],
  "temporalCoverage": "2026-10-19T01:26:53.998049939+00:00",
  "title": "Introducing the Ettin Reranker Family",
  "url": "https://aggr.aymericbeaumet.com/items/huggingface-co/2026-05-19-introducing-the-ettin-reranker-family/",
  "word_count": 6217
}