All skills
huggingface avatar

/train-sentence-transformers

@0201949 official
by Hugging Facehuggingface/skills11k stars
753

Train or fine-tune sentence-transformers models across `SentenceTransformer` (bi-encoder, dense or static embedding model for retrieval, similarity, clustering, classification, paraphrase mining, dedup, multimodal), `CrossEncoder` (reranker, pair scoring for two-stage retrieval / pair classification), `SparseEncoder` (SPLADE, sparse embedding model for learned-sparse retrieval), and `MultiVectorEncoder` (ColBERT / late-interaction, per-token embeddings scored with MaxSim). Covers loss selection, hard-negative mining, evaluators, distillation, LoRA, Matryoshka, and Hugging Face Hub publishing. Use for any sentence-transformers training task.

Use this Skill: https://skilld.dev/gh/huggingface/skills/train-sentence-transformers

This session only. Nothing lands on disk.

referencesevaluators_cross_encoder.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Evaluators (Cross-Encoder)

All cross-encoder evaluators live in sentence_transformers.cross_encoder.evaluation.

Choosing the right evaluator

Task Evaluator
Rerank retrieval results (nDCG@k on BM25 top-N), fast default CrossEncoderNanoBEIREvaluator
Rerank with custom candidates per query CrossEncoderRerankingEvaluator
Binary / multi-class pair classification CrossEncoderClassificationEvaluator
Continuous pair scoring (STS-style) CrossEncoderCorrelationEvaluator

Wrap multiple in SequentialEvaluator (from sentence_transformers.base.evaluation) to track them together:

from sentence_transformers.base.evaluation import SequentialEvaluator
evaluator = SequentialEvaluator([nano_beir_eval, custom_rerank_eval])

The default: CrossEncoderNanoBEIREvaluator

Analog of NanoBEIREvaluator for rerankers. Takes BM25 top-100 for each NanoBEIR query and measures how well the cross-encoder re-ranks them.

from sentence_transformers.cross_encoder.evaluation import CrossEncoderNanoBEIREvaluator

evaluator = CrossEncoderNanoBEIREvaluator(
    dataset_names=["msmarco", "nfcorpus", "nq"],   # default: 11 of 13 NanoBEIR datasets (excludes "arguana", "touche2020")
    batch_size=64,
    rerank_k=100,                                   # rerank the BM25 top-K
)

Output key for metric_for_best_model: eval_NanoBEIR_R100_mean_ndcg@10. The R100 signals "rerank top-100". If you change rerank_k, the prefix changes (e.g. R50).

Each individual dataset contributes eval_Nano{DatasetName}_R100_ndcg@10 (e.g. eval_NanoMSMARCO_R100_ndcg@10) too.

Custom reranking with your own candidates

Use when you have query + positive + distractor candidates that aren't part of NanoBEIR:

from sentence_transformers.cross_encoder.evaluation import CrossEncoderRerankingEvaluator

samples = [
    {"query": "...", "positive": ["the gold answer"], "documents": ["...", "...", ...]}
    for ...
]

evaluator = CrossEncoderRerankingEvaluator(
    samples=samples,
    batch_size=64,
    name="my-rerank",
    always_rerank_positives=False,   # default is True; override to False for realistic eval
)
  • always_rerank_positives=True (the library default) forces the positive into the candidate pool even when the retriever missed it. The reranker is graded only on candidates it can actually score, so the metric reflects pure reranker quality.
  • always_rerank_positives=False: the positive is only reranked if it's already in documents. If the retriever missed it, the rank counts as N+1. This reflects end-to-end retriever+reranker quality. A positive the retriever missed is lost, regardless of reranker skill.

Output key: eval_{name}_ndcg@10, eval_{name}_map, eval_{name}_mrr@10.

Classification-style cross-encoders

CrossEncoderClassificationEvaluator

Works for both binary (num_labels=1) and multi-class (num_labels>=2) cross-encoders. Branches internally:

  • num_labels=1: binary mode. Sweeps thresholds to report accuracy, F1, precision, recall, and average_precision (primary).
  • num_labels>=2: multi-class mode (e.g. NLI: entailment / neutral / contradiction). Reports f1_macro (primary), f1_micro, f1_weighted, and per-class precision / recall.
from sentence_transformers.cross_encoder.evaluation import CrossEncoderClassificationEvaluator

evaluator = CrossEncoderClassificationEvaluator(
    sentence_pairs=[(premise, hypothesis), ...],
    labels=[0, 1, 2, ...],
    batch_size=64,
    name="nli-dev",
)

Output keys (binary, num_labels=1): eval_{name}_accuracy, eval_{name}_f1, eval_{name}_average_precision (primary). Output keys (multi-class, num_labels>=2): eval_{name}_f1_macro (primary), eval_{name}_f1_micro, eval_{name}_f1_weighted.

CrossEncoderCorrelationEvaluator

For continuous-score cross-encoders (like an STS cross-encoder outputting a similarity score). Reports Pearson/Spearman vs. gold scores.

from sentence_transformers.cross_encoder.evaluation import CrossEncoderCorrelationEvaluator

evaluator = CrossEncoderCorrelationEvaluator(
    sentence_pairs=[(a, b), ...],
    scores=[0.4, 0.8, ...],
    name="stsb-dev",
)

Output keys: eval_{name}_spearman, eval_{name}_pearson.

Writing metric_for_best_model

Pattern: f"eval_{evaluator.primary_metric}". Inspect after construction: print(evaluator.primary_metric). Common values:

  • eval_NanoBEIR_R100_mean_ndcg@10: CrossEncoderNanoBEIREvaluator default
  • eval_{name}_ndcg@10: CrossEncoderRerankingEvaluator
  • eval_{name}_average_precision: CrossEncoderClassificationEvaluator (binary, num_labels=1)
  • eval_{name}_f1_macro: CrossEncoderClassificationEvaluator (multi-class, num_labels>=2)
  • eval_{name}_spearman: CrossEncoderCorrelationEvaluator

Gotchas

  • Always run evaluator(model) once before training: pre-training baseline. Tiny post-training delta means the loss/data/base is wrong.
  • CrossEncoderClassificationEvaluator accepts both num_labels=1 (binary, primary average_precision) and num_labels>=2 (multi-class, primary f1_macro). CrossEncoderCorrelationEvaluator requires num_labels=1.
  • The default dataset_names=None excludes arguana and touche2020 (Argument-Retrieval task differs from the rest). Pass dataset_names=list(DATASET_NAME_TO_HUMAN_READABLE) from sentence_transformers.cross_encoder.evaluation.nano_beir to actually run all 13.
  • Subset NanoBEIR datasets during training (3-4) to keep eval cheap. Run the broader set post-training.

Source: SKILL.md on GitHub

1 warning16d3 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides a comprehensive environment for training sentence-transformers models, including production-ready scripts and detailed documentation. It involves standard practices such as downloading packages from official registries and processing datasets from remote sources.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: MEDIUM · 1 issue

Signed by skilld at 0201949. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last week.

Activeupdated last month
  • sentence-transformers
  • training
  • fine-tuning
  • embeddings
  • retrieval
  • cross-encoder
  • sparse-encoder
  • ner
  • classification

README badge

README badge for huggingface/skills/train-sentence-transformers

Trains or fine-tunes sentence-transformers models across SentenceTransformer (bi-encoder for dense embeddings), CrossEncoder (reranker for pair scoring), and SparseEncoder (SPLADE for sparse vectors). Covers loss selection, hard-negative mining, evaluators, distillation, LoRA, and Hub publishing. Use this skill for any sentence-transformers training task.

Generated from the current SKILL.md.

Does this skill cover all three model types (SentenceTransformer, CrossEncoder, SparseEncoder)?
Yes. The skill routes you to type-specific references and production templates. Use section 1 to identify which model type matches your task, then load the corresponding references and example script.
Can I use this skill to fine-tune models with LoRA, distillation, or Matryoshka?
Yes. The skill includes variant scripts for `train_sentence_transformer_with_lora_example.py`, `train_sentence_transformer_distillation_example.py`, and `train_sentence_transformer_matryoshka_example.py`, plus distillation variants for CrossEncoder and SparseEncoder.
Do I need to write my own training script or can I copy from the templates?
Copy from the production templates (`scripts/train_<type>_example.py`). The skill explicitly states not to synthesize from the routing file alone; templates contain load-bearing scaffolding (autocast helpers, seed handling, version-compatible imports, required callbacks) that prior runs have missed when rolling their own.
What if my task involves hard-negative mining or training on multiple datasets?
The skill includes `scripts/mine_hard_negatives.py` for hard-negative mining and a `train_sentence_transformer_multi_dataset_example.py` variant. Check section 2 (Variant scripts) and `references/dataset_formats.md` for reshaping recipes.
Does this work with multimodal models or non-English languages?
For multimodal: install `sentence-transformers[train,image]` or add audio/video extras. For non-English: the skill references `references/base_model_selection.md` (non-English shortcuts) and `references/prompts_and_instructions.md` for prompt-tuned bases (E5, BGE, Qwen3-Embedding, etc.).

Generated from the current SKILL.md. These answers refresh after source changes.