embedding-comparison
Compare and evaluate embedding models for semantic search
What this skill does
# Embedding Comparison Skill
> Evaluate and compare different embedding models on your actual data.
## Overview
The default `all-MiniLM-L6-v2` model is a good starting point, but may not be optimal for your specific content. This skill helps you:
- Benchmark different models on your data
- Compare retrieval quality
- Make informed model selection decisions
## Why Compare Models?
| Factor | Impact |
|--------|--------|
| Domain vocabulary | Technical jargon may need specialized models |
| Document length | Some models handle long text better |
| Query style | Conversational vs keyword queries |
| Speed requirements | Larger models = better quality but slower |
| Memory constraints | Some models need significant RAM |
## Candidate Models
### General Purpose
| Model | Dimensions | Speed | Quality | Size |
|-------|-----------|-------|---------|------|
| `all-MiniLM-L6-v2` | 384 | Fast | Good | 80MB |
| `all-MiniLM-L12-v2` | 384 | Medium | Better | 120MB |
| `all-mpnet-base-v2` | 768 | Slow | Best | 420MB |
### Specialized
| Model | Best For | Dimensions |
|-------|----------|-----------|
| `multi-qa-MiniLM-L6-cos-v1` | Question answering | 384 |
| `msmarco-MiniLM-L6-cos-v5` | Search/retrieval | 384 |
| `paraphrase-MiniLM-L6-v2` | Semantic similarity | 384 |
### Code-Focused
| Model | Best For | Source |
|-------|----------|--------|
| `krlvi/sentence-t5-base-nlpl-code_search_net` | Code search | HuggingFace |
| `flax-sentence-embeddings/st-codesearch-distilroberta-base` | Code + docs | HuggingFace |
## Benchmarking Framework
### Step 1: Create Test Dataset
```python
#!/usr/bin/env python3
"""Create a test dataset for embedding comparison."""
from typing import List, Dict
import json
def create_test_dataset(
documents: List[str],
queries: List[str],
relevance: Dict[str, List[int]]
) -> Dict:
"""
Create a test dataset.
Args:
documents: List of documents to search
queries: List of test queries
relevance: Dict mapping query index to relevant document indices
Returns:
Test dataset dict
"""
return {
"documents": documents,
"queries": queries,
"relevance": relevance
}
# Example: Create test dataset from your actual content
def create_from_qdrant(collection_name: str, sample_size: int = 50) -> Dict:
"""Create test dataset from existing Qdrant collection."""
from qdrant_client import QdrantClient
client = QdrantClient(url="http://localhost:6333")
# Scroll through collection to get samples
results = client.scroll(
collection_name=collection_name,
limit=sample_size,
with_payload=True
)
documents = [p.payload.get("content", "") for p in results[0]]
# You'll need to manually create queries and mark relevance
# This is the ground truth that benchmarks against
return {
"documents": documents,
"queries": [], # Fill in manually
"relevance": {} # Fill in manually
}
# Example test dataset
EXAMPLE_DATASET = {
"documents": [
"Python is a high-level programming language known for readability.",
"FastAPI is a modern web framework for building APIs with Python.",
"Qdrant is a vector database for AI applications.",
"Docker containers provide isolated runtime environments.",
"REST APIs use HTTP methods for client-server communication.",
],
"queries": [
"How do I build a web API?",
"What is a vector database?",
"How do I containerize my application?",
],
"relevance": {
"0": [1, 4], # Query 0 is relevant to docs 1 and 4
"1": [2], # Query 1 is relevant to doc 2
"2": [3], # Query 2 is relevant to doc 3
}
}
if __name__ == "__main__":
with open("test_dataset.json", "w") as f:
json.dump(EXAMPLE_DATASET, f, indent=2)
print("Created test_dataset.json")
```
### Step 2: Benchmark Script
```python
#!/usr/bin/env python3
"""Benchmark embedding models on test dataset."""
import json
import time
from typing import Dict, List
import numpy as np
from sentence_transformers import SentenceTransformer
# Models to compare
MODELS = [
"all-MiniLM-L6-v2",
"all-MiniLM-L12-v2",
"all-mpnet-base-v2",
"multi-qa-MiniLM-L6-cos-v1",
"msmarco-MiniLM-L6-cos-v5",
]
def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
"""Compute cosine similarity between two vectors."""
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
def compute_metrics(
model: SentenceTransformer,
documents: List[str],
queries: List[str],
relevance: Dict[str, List[int]],
k: int = 3
) -> Dict:
"""
Compute retrieval metrics for a model.
Metrics:
- Precision@k: Fraction of top-k results that are relevant
- Recall@k: Fraction of relevant docs found in top-k
- MRR: Mean Reciprocal Rank
"""
# Encode documents
doc_embeddings = model.encode(documents)
precisions = []
recalls = []
reciprocal_ranks = []
for q_idx, query in enumerate(queries):
q_key = str(q_idx)
if q_key not in relevance:
continue
relevant_docs = set(relevance[q_key])
# Encode query and compute similarities
q_embedding = model.encode([query])[0]
similarities = [
cosine_similarity(q_embedding, doc_emb)
for doc_emb in doc_embeddings
]
# Get top-k results
top_k_indices = np.argsort(similarities)[-k:][::-1]
# Precision@k
hits = len(set(top_k_indices) & relevant_docs)
precisions.append(hits / k)
# Recall@k
recalls.append(hits / len(relevant_docs))
# MRR (reciprocal rank of first relevant result)
for rank, idx in enumerate(top_k_indices, 1):
if idx in relevant_docs:
reciprocal_ranks.append(1 / rank)
break
else:
reciprocal_ranks.append(0)
return {
"precision_at_k": np.mean(precisions),
"recall_at_k": np.mean(recalls),
"mrr": np.mean(reciprocal_ranks)
}
def benchmark_model(model_name: str, dataset: Dict) -> Dict:
"""Benchmark a single model."""
print(f"\nBenchmarking: {model_name}")
# Load model (time it)
load_start = time.perf_counter()
model = SentenceTransformer(model_name)
load_time = time.perf_counter() - load_start
# Time encoding
encode_start = time.perf_counter()
_ = model.encode(dataset["documents"])
encode_time = time.perf_counter() - encode_start
# Compute retrieval metrics
metrics = compute_metrics(
model,
dataset["documents"],
dataset["queries"],
dataset["relevance"]
)
# Get model info
test_embedding = model.encode(["test"])[0]
return {
"model": model_name,
"dimensions": len(test_embedding),
"load_time_s": round(load_time, 2),
"encode_time_s": round(encode_time, 3),
"encode_per_doc_ms": round(encode_time / len(dataset["documents"]) * 1000, 2),
**{k: round(v, 3) for k, v in metrics.items()}
}
def run_benchmark(dataset_path: str = "test_dataset.json") -> List[Dict]:
"""Run full benchmark."""
with open(dataset_path) as f:
dataset = json.load(f)
print(f"Dataset: {len(dataset['documents'])} docs, {len(dataset['queries'])} queries")
results = []
for model_name in MODELS:
try:
result = benchmark_model(model_name, dataset)
results.append(result)
print(f" P@3: {result['precision_at_k']:.3f}, MRR: {result['mrr']:.3f}")
except Exception as e:
print(f" Error: {e}")
return results
def print_results_table(results: List[Dict]):
"""Print results as formatted table."""
print("\n" + "=" * 80)
print("BENCHMARK RESULTS")
print("=" * 80)
# Header
print(f"{'Model':<35} {'Dim':>5} {Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.