Training and Finetuning Multi-Vector Embedding Models with Sentence Transformers
A detailed Hugging Face blogpost on training and finetuning multi-vector (ColBERT-style late-interaction) embedding models using the new MultiVectorEncoder class in Sentence Transformers. It walks through model selection (finding that "-unsupervised" pre-supervised checkpoints adapt better to new domains than finished ones), dataset formatting, loss functions (CachedMultiVectorMultipleNegativesRankingLoss, MultiVectorDistillKLDivLoss), training arguments, and evaluators, then presents a full worked example finetuning mLateOn-medical on 1M MIRIAD medical question-passage pairs in 14.5 hours on a single RTX 3090, beating over 50 dense/sparse/lexical/multi-vector baselines by +0.062 NDCG@10. It closes with index optimization via HierarchicalTokenPooling and PLAID-style quantization (with Omar Khattab) showing a 13x storage reduction with minimal quality loss.
What it claims
Sentence Transformers now has a MultiVectorEncoder class and trainer for ColBERT-style late-interaction models. The author's main recipe is a pre-supervised checkpoint (lightonai/mLateOn-unsupervised), 1M in-domain query–passage pairs, in-batch negatives, full document length and LR 1e-4. It produced multi-vector-encoder/mLateOn-medical. On MIRIAD retrieval (1,000 queries over 200k passages), that model raised rank-1 hit rate from 75.8% (best zero-shot model) to 84.9%. It used no teacher model and no mined negatives. Most of the post is ablation-backed advice that changes how you would configure such a run.
Evidence
Starting point. Six starting points were trained on 25k MIRIAD pairs and tested against a 50k-passage corpus.
- The
-unsupervisedcheckpoints overtook their finished siblings in two model families, despite starting lower. - Finished checkpoints barely moved or regressed at every learning rate tried.
- A fresh random projection on
Alibaba-NLP/gte-modernbert-basecame within 0.03 of the checkpoint starting points.
Document truncation costs more than architecture choice. Passages average 941 tokens. Many released models cap documents at 180–512 tokens.
- Lifting the cap was worth +0.08 to +0.24 NDCG@10 for every multi-vector baseline.
- It was worth +0.03 for DenseOn.
Late interaction vs dense. At matched data and backbone:
- LateOn beats DenseOn by +0.12; mLateOn beats mDenseOn by +0.13.
- Qwen3-Embedding-4B, with about 33x the active parameters, is still 0.13 short of the finetuned model.
- Qwen3-Embedding-8B scores below the 4B version.
Ablations from the training run:
- Training at
max_length=512lost about 0.015 NDCG@10 for about 2x speed. The gap did not close with more data. - An LR sweep from 5e-6 to 2e-4 favoured 1e-4.
- Batch sizes above 128 gave no further gain.
[MASK]query expansion made no measurable difference in any of 4 configurations.- A punctuation skiplist modestly won a 4-way skiplist ablation and cut index size by 9.6%.
Training cost and data scaling:
- The full run took 14.5 h on one RTX 3090 with 17.5 GB peak VRAM.
- 100k pairs (75 min of training) came within 0.012 NDCG@10 of the 1M-pair run.
Index size. The raw index is about 878 vectors per passage, roughly 45 GB at fp16 for 200k passages.
- HierarchicalTokenPooling, applied post-hoc:
- Halving the vector count costs 0.0033 and leaves rank-1 accuracy unchanged.
- Keeping 1/4 of the vectors (11.2 GB) scores 0.8991.
- Keeping 1/10 scores 0.8765.
- Omar Khattab's fast-plaid runs used 1-bit residual quantization, packed ids and document pruning:
- The first configuration was 13x smaller than raw for a 0.0155 loss.
- The most aggressive was 1.45 GB, smaller than Qwen3-Embedding-8B's fp16 index (1.64 GB), and scored 0.0895 higher.
How to use it
pip install -U "sentence-transformers[train]"Configuration traps the page flags:
- Contrastive loss scale. Contrastive losses default to
scale=1.0. Do not copyscale=20.0from dense scripts: MaxSim scores already span roughly [0, query_length], so 20.0 saturates the softmax and kills gradients. - Prompts. Training does not apply the model's stored prompts. Map them explicitly, e.g.
prompts={"question": "[Q] ", "passage_text": "[D] "}. - Length caps. Lift per-task caps with
model[0].query_length = Noneandmodel[0].document_length = None. Then setprocessor_kwargs={"model_max_length": 8192}at load time, because that becomes the effective limit. - Skiplist. After changing
model[2].skiplist_words, callmodel[2].resolve_with_tokenizer(model.tokenizer). Token ids are cached. - Loss memory. With
CachedMultiVectorMultipleNegativesRankingLoss,mini_batch_sizebounds memory without changing results.mini_batch_num_tokenspacks chunks by token budget instead, which suits variable-length documents (16 docs × ~940 tokens ≈ 15,000). - Column order. Column 1 is encoded as the query and the remaining columns as documents. Override with
router_mapping. - Distillation data. KD data uses
(query, doc_1..doc_N, scores).resolve_idshandles id-based datasets.
The full training script is on the page. Its model card declares apache-2.0.
Limits
- Single domain. Results cover one domain. The author says mLateOn-medical is not claimed to be strongest elsewhere.
- MIRIAD favours lexical matching. Its questions are generated from their own passages, so lexical overlap is unusually high:
- BM25 beat every sparse model and all but three dense models. Do not expect that to transfer.
- Against only the 10k gold passages, nearly every model scored above 0.97. Add distractors until your own eval spreads out.
- Score scales differ. The starting-point (50k corpus) and final (200k corpus) scores are not comparable.
- Long passages are the worst case. Index sizes reflect ~900-token passages. Natural Questions–style passages (~125 vectors each) start about 7x smaller.
- Pruning is a floor. The pruning used was naive, so the bottom rows of the quantization table are a floor, not the frontier.
- No pooling-aware training. Pooling was measured without pooling-aware training.
Organisations named here
- LightOn
- Hugging Face
- Answer.AI
- Alibaba-NLP
- Alibaba-NLP/gte-modernbert-base
- BM25
- MIRIAD
- mLateOn-medical
- MS MARCO
- Natural Questions
- Omar Khattab
- Qdrant
- Weaviate
Technologies named here
- Sentence Transformers
- multi-vector-encoder/mLateOn-medical
- MultiVectorEncoder
- mLateOn-unsupervised
- MultiVectorEncoderTrainer
- LateOn-Code
- MultiVectorEncoderTrainingArguments
- GTE-ModernColBERT-v1
- MultiVectorMultipleNegativesRankingLoss
- ModernBERT-base
- CachedMultiVectorMultipleNegativesRankingLoss
- gte-modernbert-base
- MultiVectorDistillKLDivLoss
- mLateOn
- mDenseOn
- MultiVectorInformationRetrievalEvaluator
- DenseOn
- HierarchicalTokenPooling
- MultiVectorMask
- LateOn
- Qwen3-Embedding-4B
- fast-plaid
- Qwen3-Embedding-8B
- Qdrant
- voyage-4-nano
- Weaviate
- Vespa
- BM25
- Hugging Face datasets
- WandbCallback
- TensorBoardCallback
- CodeCarbonCallback
- Hugging Face
- PyTorch
- ModernBERT
- Qwen3
- LoRA
- ColBERT
- ColPali
- Python
- Transformer
Techniques named here
- Multi-vector retrieval
- MaxSim operator
- In-batch negatives training
- GradCache
- Knowledge distillation dataset format
- Hierarchical token pooling
- PLAID-style residual compression / 1-bit quantization
- Punctuation/stopword skiplist
- [MASK] query expansion
- Query/document marker tokens
- Multi-dataset training with batch samplers
Related in training



