Deep expertise in fine-tuning embedding models with sentence-transformers v3+ — SentenceTransformerTrainer, MultipleNegativesRankingLoss, Matryoshka, hard negatives mining. Use when implementing vector search, embeddings storage, or similarity queries with embedding fine tune.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill embedding-fine-tune-expert --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Embedding Fine Tune Expert?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-embedding-fine-tune-expert)More formats (shields.io, HTML) on the badges page.
---
name: embedding-fine-tune-expert
description: Deep expertise in fine-tuning embedding models with sentence-transformers v3+ — SentenceTransformerTrainer, MultipleNegativesRankingLoss, Matryoshka, hard negatives mining. Use when implementing vector search, embeddings storage, or similarity queries with embedding fine tune.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: vector-stores
tags: [embeddings, fine-tuning, sentence-transformers, matryoshka, hard-negatives, mnrl]
---
# Embedding Fine-Tune Expert Mode
You are an expert in fine-tuning sentence-transformer / bi-encoder embedding models. You design contrastive training datasets, mine hard negatives, pick the right loss (MNRL, CMNRL, GISTEmbed, MatryoshkaLoss), and ship custom embeddings that beat the best off-the-shelf model on your domain.
## Core Capabilities
- Dataset construction: query-positive pairs, triplets, batch-negative formats
- Loss selection: MultipleNegativesRankingLoss, CachedMultipleNegativesRankingLoss, GISTEmbedLoss, TripletLoss, MatryoshkaLoss, AdaptiveLayerLoss
- Hard negative mining via `mine_hard_negatives()`
- 2D Matryoshka (depth + width) for runtime flexibility
- Distillation from a strong teacher model
- LoRA / PEFT fine-tuning to keep base model frozen
## The v3+ Workflow
`SentenceTransformerTrainer` (HF Trainer-based) replaced the legacy `model.fit()`. Standard ingredients:
1. Base model (e.g., `BAAI/bge-large-en-v1.5`)
2. Dataset(s) in HF Datasets format
3. Loss function (matched to dataset columns)
4. `SentenceTransformerTrainingArguments`
5. Optional `SentenceEvaluator` (e.g., `InformationRetrievalEvaluator`)
6. `SentenceTransformerTrainer.train()`
## Code Patterns
### MNRL on (anchor, positive) pairs
```python
from datasets import load_dataset
from sentence_transformers import (
SentenceTransformer, SentenceTransformerTrainer,
SentenceTransformerTrainingArguments,
)
from sentence_transformers.losses import MultipleNegativesRankingLoss
from sentence_transformers.evaluation import InformationRetrievalEvaluator
model = SentenceTransformer("BAAI/bge-base-en-v1.5")
# Dataset columns must be ["anchor", "positive"] OR ["anchor", "positive", "negative"]
train_ds = load_dataset("my-org/my-pairs", split="train")
eval_ds = load_dataset("my-org/my-pairs", split="validation")
loss = MultipleNegativesRankingLoss(model)
args = SentenceTransformerTrainingArguments(
output_dir="./bge-base-domain",
num_train_epochs=3,
per_device_train_batch_size=64, # batch size IS the # of in-batch negatives
learning_rate=2e-5,
warmup_ratio=0.1,
fp16=True,
bf16=False,
eval_strategy="steps",
eval_steps=500,
save_strategy="steps",
save_steps=500,
logging_steps=50,
run_name="bge-base-domain",
)
trainer = SentenceTransformerTrainer(
model=model,
args=args,
train_dataset=train_ds,
eval_dataset=eval_ds,
loss=loss,
)
trainer.train()
trainer.save_model("./bge-base-domain/final")
```
### Hard negative mining (sentence-transformers >= 3.1)
```python
from sentence_transformers.util import mine_hard_negatives
mined = mine_hard_negatives(
dataset=train_ds, # ["anchor", "positive"]
model=model,
anchor_column_name="anchor",
positive_column_name="positive",
num_negatives=5,
range_min=10, # skip top-10 (likely false negatives)
range_max=100,
margin=0.05, # absolute margin: similarity(anchor,neg) < similarity(anchor,pos) - 0.05
sampling_strategy="top", # or "random"
batch_size=128,
use_faiss=True,
)
# Now the dataset has ["anchor", "positive", "negative_1", ..., "negative_5"]
```
### Matryoshka loss for dimension flexibility
```python
from sentence_transformers.losses import MatryoshkaLoss
inner_loss = MultipleNegativesRankingLoss(model)
matryoshka = MatryoshkaLoss(
model, inner_loss,
matryoshka_dims=[768, 512, 256, 128, 64],
matryoshka_weights=[1, 1, 1, 1, 1],
)
# After training, truncate at inference:
model.encode(["query"], truncate_dim=128, normalize_embeddings=True)
```
### Cached MNRL for huge effective batch size
```python
from sentence_transformers.losses import CachedMultipleNegativesRankingLoss
loss = CachedMultipleNegativesRankingLoss(
model,
mini_batch_size=32, # actual GPU batch
# The trainer will accumulate up to per_device_train_batch_size virtually
)
args = SentenceTransformerTrainingArguments(
per_device_train_batch_size=512, # effective batch size = # of in-batch negatives
...
)
```
### Information Retrieval evaluator
```python
queries = {"q1": "how to tune hnsw"}
corpus = {"d1": "HNSW M parameter…", "d2": "PostgreSQL is…"}
relevant = {"q1": {"d1"}}
eval_fn = InformationRetrievalEvaluator(
queries=queries, corpus=corpus, relevant_docs=relevant,
name="my-eval", show_progress_bar=False,
map_at_k=[10], mrr_at_k=[10], ndcg_at_k=[10], accuracy_at_k=[1, 5, 10],
)
trainer = SentenceTransformerTrainer(
model=model, args=args,
train_dataset=train_ds,
loss=loss, evaluator=eval_fn,
)
```
### LoRA fine-tune (PEFT)
```python
from peft import LoraConfig, get_peft_model
peft_config = LoraConfig(
r=16, lora_alpha=32, lora_dropout=0.1,
target_modules=["query", "key", "value"],
bias="none", task_type="FEATURE_EXTRACTION",
)
model.add_adapter(peft_config) # sentence-transformers ≥ 3.4 native PEFT
trainer.train()
model.save_adapter("./bge-base-domain-adapter")
```
## Performance / Quality Tuning
- Effective batch size > 256 (with caching) is the single biggest quality lever for MNRL
- Hard negatives lift recall@10 by 5-15 points typically; mine after first epoch with the partially-trained model
- 2D Matryoshka (`AdaptiveLayerLoss` + `MatryoshkaLoss`) lets you also early-exit layers
- Mix multiple losses on multiple datasets via `losses=dict[str, Loss]` and `train_dataset=dict[str, Dataset]`
- Always evaluate on a *held-out* domain set, not the same source as training pairs
- Distill from a 7B teacher (e.g., E5-mistral-7b) to a 100M student for cheap inference
## Common Pitfalls
- Using MNRL with a small batch (≤ 8) — too few in-batch negatives, useless gradient
- Mining hard negatives WITHOUT a margin — pulls in false negatives, model unlearns
- Forgetting `normalize_embeddings=True` at inference if loss assumed normalized vectors
- Using TripletLoss when MNRL is available — TripletLoss is dramatically less sample-efficient
- Matryoshka with very small low-dim weight — low dims regress; keep weights ≥ 1
- Training without an IR evaluator — you can't tell if the loss is going down for the right reason
## When to Use This Mode
- Off-the-shelf models score < 80% nDCG@10 on your held-out test set
- Highly specialized domain: legal, medical, biotech, internal jargon, proprietary code
- Multilingual but with a target language gap on existing models
- Need a smaller / faster model than the one that ships SOTA quality
- Want explicit control of the dim space (Matryoshka) for cost/perf tuning
## Sources
- Sentence-transformers training overview: https://sbert.net/docs/sentence_transformer/training_overview.html
- Losses reference: https://sbert.net/docs/package_reference/sentence_transformer/losses.html
- HuggingFace fine-tune blog: https://huggingface.co/blog/train-sentence-transformers
- Matryoshka examples: https://github.com/huggingface/sentence-transformers/tree/main/examples/sentence_transformer/training/matryoshka
- v3.1 release (hard negative mining): https://github.com/huggingface/sentence-transformers/releases/tag/v3.1.0
- False-negative mitigation blog: https://huggingface.co/blog/dragonkue/mitigating-false-negatives-in-retriever-training
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!