embedding-fine-tuning
Fine-tuning sentence embedding models with sentence-transformers. Contrastive objectives (MultipleNegativesRankingLoss, TripletLoss, CoSENT), domain adaptation, synthetic query generation (GPL), hard negative mining, and downstream retrieval evaluation. USE WHEN: user mentions "fine-tune embeddings", "domain adaptation", "sentence-transformers training", "contrastive loss", "hard negatives", "GPL", "synthetic queries", "MNR loss", "triplet loss" DO NOT USE FOR: picking a pretrained model - use `embedding-models`; MRL truncation - use `matryoshka-embeddings`; reranker training - out of scope
What this skill does
# Embedding Fine-Tuning
## When to Fine-Tune
| Signal | Action |
|---|---|
| Domain vocabulary very different from web (legal, medical, code) | Fine-tune |
| Generic model recall@10 above 0.85 on eval | Do not fine-tune; tune retrieval |
| No labelled (query, doc) pairs available | Start with GPL synthetic queries |
| Fewer than 500 real pairs | Use synthetic + in-batch negatives |
| 10k+ labelled pairs with hard negatives | Expect 5-15% nDCG lift |
## Contrastive Loss Choices
| Loss | Inputs | When to use |
|---|---|---|
| MultipleNegativesRankingLoss (MNR) | (anchor, positive) | Default — uses in-batch negatives, no labels needed |
| MultipleNegativesSymmetricRankingLoss | (anchor, positive) | Symmetric tasks (STS-like) |
| TripletLoss | (anchor, positive, negative) | When hard negatives are curated |
| CachedMultipleNegativesRankingLoss | (anchor, positive) | Large batch sizes on small GPUs |
| CoSENT / AnglE | labelled similarity scores | STS regression tasks |
| Matryoshka2dLoss wrapper | any base loss | Train MRL-truncatable model |
## Minimal Training Loop (sentence-transformers v3+)
```python
from sentence_transformers import (
SentenceTransformer, SentenceTransformerTrainer,
SentenceTransformerTrainingArguments,
)
from sentence_transformers.losses import MultipleNegativesRankingLoss
from sentence_transformers.training_args import BatchSamplers
from sentence_transformers.evaluation import InformationRetrievalEvaluator
from datasets import Dataset
model = SentenceTransformer("BAAI/bge-base-en-v1.5")
# Dataset: two columns named exactly "anchor" and "positive"
train_ds = Dataset.from_dict({
"anchor": ["how do I reset my password?", "what is OAuth 2.0?"],
"positive": ["Go to Settings > Security > Reset Password.",
"OAuth 2.0 is an authorization framework for delegated access."],
})
loss = MultipleNegativesRankingLoss(model)
args = SentenceTransformerTrainingArguments(
output_dir="models/my-domain-embedder",
num_train_epochs=3,
per_device_train_batch_size=64,
learning_rate=2e-5,
warmup_ratio=0.1,
fp16=True,
batch_sampler=BatchSamplers.NO_DUPLICATES, # critical for MNR
eval_strategy="steps",
eval_steps=200,
save_strategy="steps",
save_steps=200,
logging_steps=50,
run_name="bge-domain-v1",
)
trainer = SentenceTransformerTrainer(
model=model,
args=args,
train_dataset=train_ds,
loss=loss,
)
trainer.train()
model.save_pretrained("models/my-domain-embedder/final")
```
## Triplet Loss with Hard Negatives
```python
from sentence_transformers.losses import TripletLoss, TripletDistanceMetric
from datasets import Dataset
triplet_ds = Dataset.from_dict({
"anchor": ["revoke OAuth token"],
"positive": ["Call POST /oauth/revoke with the token parameter."],
"negative": ["Register a new OAuth client in the developer console."], # topically similar but wrong
})
loss = TripletLoss(
model=model,
distance_metric=TripletDistanceMetric.COSINE,
triplet_margin=0.3,
)
```
## Hard Negative Mining
Random negatives are too easy; mine negatives that a pretrained model ranks highly
but are NOT the ground-truth positive.
```python
from sentence_transformers import SentenceTransformer, util
miner = SentenceTransformer("BAAI/bge-base-en-v1.5")
corpus = [...] # all candidate docs
corpus_emb = miner.encode(corpus, convert_to_tensor=True, normalize_embeddings=True)
def mine_hard_negatives(query: str, positive_idx: int, k: int = 3, top_n: int = 50):
q_emb = miner.encode(query, convert_to_tensor=True, normalize_embeddings=True)
hits = util.semantic_search(q_emb, corpus_emb, top_k=top_n)[0]
# Skip true positive; take next ranked items
negatives = [corpus[h["corpus_id"]] for h in hits if h["corpus_id"] != positive_idx][:k]
return negatives
# Filter out false negatives with a cross-encoder or teacher model before using.
```
False-negative filtering is critical — if a mined "negative" is actually relevant,
you teach the model the opposite of what you want. Use a strong cross-encoder
(`BAAI/bge-reranker-large`) to filter out candidates with rerank score above a
threshold.
## Synthetic Query Generation (GPL-style)
When you have documents but no queries:
```python
# Step 1: Generate queries per document using an LLM
from openai import OpenAI
client = OpenAI()
PROMPT = """Generate exactly 3 distinct search queries a user would type to find
this passage. Return one query per line, no numbering.
Passage:
{doc}"""
def generate_queries(doc: str) -> list[str]:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": PROMPT.format(doc=doc)}],
temperature=0.7,
)
return [q.strip() for q in resp.choices[0].message.content.splitlines() if q.strip()]
# Step 2: Mine hard negatives with a pretrained embedder
# Step 3: Score (query, pos, neg) triplets with a cross-encoder teacher to get
# soft margins (GPL uses margin-MSE loss on these scores).
from sentence_transformers.losses import MarginMSELoss
from sentence_transformers import CrossEncoder
teacher = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")
def margin(query, pos, neg):
s_pos = teacher.predict([(query, pos)])[0]
s_neg = teacher.predict([(query, neg)])[0]
return float(s_pos - s_neg)
# Build dataset of (query, pos, neg, margin) rows and train with MarginMSELoss.
```
## Matryoshka Training (MRL)
Train once, deploy at multiple dimensions. See also the `matryoshka-embeddings`
skill.
```python
from sentence_transformers.losses import MatryoshkaLoss, MultipleNegativesRankingLoss
base_loss = MultipleNegativesRankingLoss(model)
loss = MatryoshkaLoss(model, base_loss, matryoshka_dims=[768, 512, 256, 128, 64])
```
## Evaluation on Downstream Retrieval
Do not evaluate on loss curves. Score retrieval metrics on a held-out eval set.
```python
from sentence_transformers.evaluation import InformationRetrievalEvaluator
# queries: dict[qid, query]; corpus: dict[cid, doc]; relevant_docs: dict[qid, set[cid]]
ir_evaluator = InformationRetrievalEvaluator(
queries=queries,
corpus=corpus,
relevant_docs=relevant_docs,
name="domain-eval",
accuracy_at_k=[1, 5, 10],
precision_recall_at_k=[1, 5, 10],
mrr_at_k=[10],
ndcg_at_k=[10],
map_at_k=[10],
show_progress_bar=True,
)
metrics = ir_evaluator(model)
print(metrics)
# Pass ir_evaluator=... to SentenceTransformerTrainer to track during training.
```
## Domain Adaptation Pipeline (End-to-End)
```
1. Dump domain corpus (chunks of 200-400 tokens).
2. Generate 2-3 synthetic queries per chunk with an LLM (filter garbage).
3. Mine 3-5 hard negatives per (query, chunk) with a pretrained embedder.
4. Filter false negatives with a cross-encoder teacher.
5. Train with MNR or MarginMSE for 1-3 epochs.
6. Evaluate IR metrics on held-out real queries.
7. A/B test in production against pretrained baseline.
```
## Anti-Patterns
| Anti-Pattern | Fix |
|---|---|
| Training with random negatives only | Mine hard negatives + filter false negatives |
| BatchSampler keeps duplicates | Use `BatchSamplers.NO_DUPLICATES` with MNR |
| Evaluating only on training loss | Use `InformationRetrievalEvaluator` on held-out set |
| Too-high learning rate (1e-4+) on strong base | Use 1e-5 to 5e-5 for BGE/E5 base models |
| Tiny batch sizes with MNR | MNR benefits from batch 64-256; use `CachedMNRLoss` on small GPUs |
| Forgetting task prefixes on E5 / Nomic | Apply the same prefixes used at inference during training |
| Fine-tuning on <500 pairs with no synthetic data | Use GPL synthetic pipeline first |
## Production Checklist
- [ ] Held-out eval set with real user queries
- [ ] Baseline (pretrained) metrics recorded before training
- [ ] Hard negatives mined and filtered for false negatives
- [ ] Task prefixes applied consistently during training and inference
- [ ] MRL / Matryoshka loss used if tRelated in AI Agents
skill-development
IncludedComprehensive meta-skill for creating, managing, validating, auditing, and distributing Claude Code skills and slash commands (unified in v2.1.3+). Provides skill templates, creation workflows, validation patterns, audit checklists, naming conventions, YAML frontmatter guidance, progressive disclosure examples, and best practices lookup. Use when creating new skills, validating existing skills, auditing skill quality, understanding skill architecture, needing skill templates, learning about YAML frontmatter requirements, progressive disclosure patterns, tool restrictions (allowed-tools), skill composition, skill naming conventions, troubleshooting skill activation issues, creating custom slash commands, configuring command frontmatter, using command arguments ($ARGUMENTS, $1, $2), bash execution in commands, file references in commands, command namespacing, plugin commands, MCP slash commands, Skill tool configuration, or deciding between skills vs slash commands. Delegates to docs-management skill for official documentation.
reprompter
IncludedTransform messy prompts into well-structured, effective prompts — single or multi-agent. Use when: "reprompt", "reprompt this", "clean up this prompt", "structure my prompt", rough text needing XML tags and best practices, "reprompter teams", "repromptception", "run with quality", "smart run", "smart agents", multi-agent tasks, audits, parallel work, anything going to agent teams. Don't use when: simple Q&A, pure chat, immediate execution-only tasks. See "Don't Use When" section for details. Outputs: Structured XML/Markdown prompt, quality score (before/after), optional team brief + per-agent sub-prompts, agent team output files. Success criteria: Single mode quality score ≥ 7/10; Repromptception per-agent prompt quality score 8+/10; all required sections present, actionable and specific.
adaptive-compaction
IncludedAdaptive add-on policy and recovery layer that decides WHEN to compact, prune, snapshot, or fork -- replacing fixed-percent auto-compaction across Claude Code, Codex, and MCP-capable hosts. Trigger on auto-compact timing or damage: "when should I compact", "is it safe to compact now or start a fresh session", "auto-compact fires too early/mid-task", "switching to an unrelated task but the window still has space", "context rot", "answers get worse the longer the session runs", "the agent forgot the plan or my decisions after it summarized", "add a layer on top that manages context without changing the agent", raising autoCompactWindow to give the policy room, or installing/tuning a cross-tool compaction policy or PreCompact hook -- even when "compaction" is never said but the problem is context-window pressure or post-summarization memory loss. Do NOT use to summarize a conversation, build RAG, write a summarization prompt (decides WHEN not HOW), or answer max-context-length trivia.
agent-skill-creator
IncludedCreate cross-platform agent skills from workflow descriptions. Activates when users ask to create an agent, automate a repetitive workflow, create a custom skill, or need advanced agent creation. Triggers on phrases like create agent for, automate workflow, create skill for, every day I have to, daily I need to, turn process into agent, need to automate, create a cross-platform skill, validate this skill, export this skill, migrate this skill. Supports single skills, multi-agent suites, transcript processing, template-based creation, interactive configuration, cross-platform export, and spec validation.
llm-wiki
IncludedUse when building or maintaining a persistent personal knowledge base (second brain) in Obsidian where an LLM incrementally ingests sources, updates entity/concept pages, maintains cross-references, and keeps a synthesis current. Triggers include "second brain", "Obsidian wiki", "personal knowledge management", "ingest this paper/article/book", "build a research wiki", "compound knowledge", "Memex", or whenever the user wants knowledge to accumulate across sessions instead of being re-derived by RAG on every query.
skill-master
IncludedAgent Skills authoring, evaluation, and optimization. Create, edit, validate, benchmark, and improve skills following the agentskills.io specification. Use when designing SKILL.md files, structuring skill folders (references, scripts, assets), ingesting external documentation into skills, running trigger evals, benchmarking skill quality, optimizing descriptions, or performing blind A/B comparisons. Keywords: agentskills.io, SKILL.md, skill authoring, eval, benchmark, trigger optimization.