Módulo 3: Modelos de Embeddings Comparison

Domain-Specific y Multilingual Embeddings

Descripción de la cápsula

Los embeddings "generales" (OpenAI, SBERT) funcionan bien para textos estándar, pero dominios especializados (legal, medical, code) y multiidioma requieren modelos específicos. ¿Cuándo usar embeddings especializados? ¿Cuándo vale la pena fine-tuning?

En esta cápsula aprenderás sobre domain-specific embeddings (legal, medical, financial, code), multilingual embeddings (mBERT, XLM-R, BGE-M3), cuándo fine-tune vs zero-shot, y trade-offs. También verás código para evaluar embeddings en tu dominio.

Al final, podrás elegir embeddings especializados cuando sea necesario.


Domain-Specific Embeddings

Por qué dominio importa:

# Embedding general (SBERT):
query = "consideration"
doc_1 = "He showed consideration for others"  # Contexto social
doc_2 = "In consideration of $100, parties agree..."  # Contexto legal

# Problema: Embedding general puede no diferenciar bien
# "consideration" tiene significado MUY diferente en legal vs social

Solución: Embeddings entrenados en corpus legal.


Dominios principales:

1. Legal:

# Modelos:
# - Law-BERT
# - Legal-SBERT

# Entrenado en:
# - Case law
# - Contracts
# - Legal documents

# Mejora: +10-15% MTEB en tareas legales vs modelos generales

2. Medical:

# Modelos:
# - BioBERT
# - PubMedBERT
# - Clinical-BERT

# Entrenado en:
# - PubMed papers
# - Clinical notes
# - Medical terminology

# Mejora: +20% en tareas médicas

3. Financial:

# Modelos:
# - FinBERT

# Entrenado en:
# - Financial reports
# - News articles
# - SEC filings

# Mejora: +15% en sentiment analysis financiero

4. Code:

# Modelos:
# - CodeBERT
# - GraphCodeBERT

# Entrenado en:
# - GitHub repos
# - Stack Overflow

# Mejora: +30% en code search

Multilingual Embeddings

Por qué multiidioma:

# Problema: SBERT (all-MiniLM-L6-v2) es inglés-only
# Textos en español, chino, árabe tienen embeddings subóptimos

# Solución: Multilingual embeddings
# Entrenados en 100+ idiomas simultáneamente

Modelos multilingual:

1. mBERT (multilingual BERT):

Idiomas: 104
Dimensiones: 768
MTEB (avg 100+ idiomas): ~55
Uso: General purpose multiidioma

from sentence_transformers import SentenceTransformer

model = SentenceTransformer('distiluse-base-multilingual-cased-v2')

2. XLM-RoBERTa:

Idiomas: 100
Dimensiones: 768
MTEB: ~58
Uso: Mejor performance que mBERT

model = SentenceTransformer('xlm-r-100langs-bert-base-nli-stsb-mean-tokens')

3. BGE-M3 (BAAI Multilingual):

Idiomas: 100+
Dimensiones: 1024
MTEB: ~64 (en promedio)
Uso: Estado del arte multiidioma

model = SentenceTransformer('BAAI/bge-m3')

4. Cohere Multilingual (API):

Idiomas: 100+
Dimensiones: 1024
MTEB: ~62
Costo: $0.10/1M tokens

# Uso con Cohere API
import cohere
co = cohere.Client('YOUR_API_KEY')
response = co.embed(texts=["Hola mundo"], model="embed-multilingual-v3.0")

Zero-Shot vs Fine-Tuning

Zero-Shot (usar modelo pre-entrenado sin modificar):

# Ventajas:
✅ No requiere datos de entrenamiento
✅ Funciona "out-of-the-box"
✅ Zero effort

# Desventajas:
❌ Performance subóptima en dominio específico
❌ No captura vocabulario único de tu dominio

Cuándo usar:

  • Prototipado
  • Dominio general (e-commerce, FAQ)
  • No tienes datos de entrenamiento

Fine-Tuning (re-entrenar embeddings en tu dominio):

# Ventajas:
✅ Performance +10-30% en tu dominio
✅ Captura vocabulario específico
✅ Aprende relaciones de tu data

# Desventajas:
❌ Requiere datos de entrenamiento (1K-10K pares)
❌ Tiempo de entrenamiento (horas-días)
❌ ML expertise requerido

Cuándo usar:

  • Dominio muy específico (legal, medical)
  • Tienes datos de entrenamiento
  • Performance crítica (vale el effort)

Comparison table:

CriterioZero-ShotFine-Tuning
EffortBajoAlto
Data required01K-10K pares
TimeMinutosHoras-días
Performance (general)BuenoN/A
Performance (domain)AceptableExcelente
Cost$0$50-$500 (GPU)

Ejemplos prácticos

1. Multilingual embeddings:

from sentence_transformers import SentenceTransformer
import numpy as np

# Cargar modelo multilingual
model = SentenceTransformer('distiluse-base-multilingual-cased-v2')

# Textos en diferentes idiomas (mismo significado)
texts = [
    "The cat is sleeping",  # English
    "El gato está durmiendo",  # Español
    "Le chat dort",  # Français
    "猫在睡觉",  # 中文
    "القط نائم"  # العربية
]

# Generar embeddings
embeddings = model.encode(texts)

# Calcular similarities
def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# Comparar inglés con otros idiomas
en_emb = embeddings[0]

for i, lang in enumerate(["Español", "Français", "中文", "العربية"]):
    sim = cosine_similarity(en_emb, embeddings[i+1])
    print(f"English vs {lang}: {sim:.4f}")

Output esperado:

English vs Español: 0.87
English vs Français: 0.85
English vs 中文: 0.82
English vs العربية: 0.80

Embeddings capturan significado cross-lingual.


2. Domain-specific (code search):

from sentence_transformers import SentenceTransformer

# Modelo general
model_general = SentenceTransformer('all-MiniLM-L6-v2')

# Modelo code-specific (si existe)
# model_code = SentenceTransformer('microsoft/codebert-base')

query = "function to sort array"
docs = [
    "def sort_array(arr): return sorted(arr)",
    "function sortArray(arr) { return arr.sort(); }",
    "The weather is nice today"
]

# Generar embeddings
query_emb = model_general.encode([query])[0]
docs_embs = model_general.encode(docs)

# Similarities
sims = [cosine_similarity(query_emb, doc_emb) for doc_emb in docs_embs]

for doc, sim in zip(docs, sims):
    print(f"{sim:.4f} | {doc[:50]}...")

Output (modelo general):

0.65 | def sort_array(arr): return sorted(arr)...
0.63 | function sortArray(arr) { return arr.sort(); }...
0.35 | The weather is nice today...

Con modelo code-specific (CodeBERT), scores serían más altos (~0.85).


Evaluar embeddings en tu dominio

Crear dataset de evaluación:

# Formato:
evaluation_pairs = [
    {
        "query": "How to install Python?",
        "doc_relevant": "Download Python from python.org",
        "doc_irrelevant": "JavaScript is a web language"
    },
    # ... más pares
]

# Mínimo: 100 pares (cuanto más, mejor)

Evaluar modelo:

from sentence_transformers import SentenceTransformer
import numpy as np

def evaluate_model(model_name, eval_pairs):
    """
    Evaluar modelo en dataset custom
    
    Returns:
        Accuracy (% de veces que doc_relevant > doc_irrelevant)
    """
    model = SentenceTransformer(model_name)
    
    correct = 0
    
    for pair in eval_pairs:
        query_emb = model.encode([pair['query']])[0]
        rel_emb = model.encode([pair['doc_relevant']])[0]
        irrel_emb = model.encode([pair['doc_irrelevant']])[0]
        
        sim_rel = np.dot(query_emb, rel_emb)
        sim_irrel = np.dot(query_emb, irrel_emb)
        
        if sim_rel > sim_irrel:
            correct += 1
    
    accuracy = correct / len(eval_pairs)
    return accuracy

# Test
evaluation_pairs = [
    {
        "query": "Python installation",
        "doc_relevant": "Download from python.org",
        "doc_irrelevant": "JavaScript is popular"
    },
    # ... más pares
]

accuracy = evaluate_model("all-MiniLM-L6-v2", evaluation_pairs)
print(f"Accuracy: {accuracy:.2%}")

Cuándo NO fine-tune

Casos donde zero-shot es suficiente:

✅ Dominio general (e-commerce, FAQ)
✅ No tienes datos de entrenamiento
✅ Presupuesto/tiempo limitado
✅ Modelo general ya tiene >85% accuracy en tu eval

Casos donde fine-tune vale la pena:

✅ Dominio muy específico (legal, medical, code)
✅ Tienes 1K+ pares de entrenamiento
✅ Performance crítica (cada % de accuracy importa)
✅ Modelo general tiene <80% accuracy
✅ Presupuesto para ML Engineering

Ejercicios

Ejercicio 1: Multilingual embeddings

Usa distiluse-base-multilingual-cased-v2 para comparar:

# Textos:
# - "Hello world" (English)
# - "Hola mundo" (Español)
# - "Bonjour le monde" (Français)

# ¿Cuál es más similar entre sí?
Ver solución
from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer('distiluse-base-multilingual-cased-v2')

texts = [
    "Hello world",
    "Hola mundo",
    "Bonjour le monde"
]

embeddings = model.encode(texts)

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

print("Similarities:")
print(f"EN vs ES: {cosine_similarity(embeddings[0], embeddings[1]):.4f}")
print(f"EN vs FR: {cosine_similarity(embeddings[0], embeddings[2]):.4f}")
print(f"ES vs FR: {cosine_similarity(embeddings[1], embeddings[2]):.4f}")

Output esperado:

Similarities:
EN vs ES: 0.88
EN vs FR: 0.86
ES vs FR: 0.89  ← Más similar (ambos idiomas latinos)

Ejercicio 2: Evaluar en dominio

Crea 5 pares de evaluación para tu dominio y evalúa all-MiniLM-L6-v2:

# Implementa función evaluate_model()
# Crea evaluation_pairs (mínimo 5)
# Calcula accuracy
Ver solución
evaluation_pairs = [
    {
        "query": "Python installation",
        "doc_relevant": "Download Python from python.org",
        "doc_irrelevant": "JavaScript is a web language"
    },
    {
        "query": "List comprehension syntax",
        "doc_relevant": "[x for x in range(10)]",
        "doc_irrelevant": "Java uses for loops"
    },
    {
        "query": "Django tutorial",
        "doc_relevant": "Django is a Python web framework",
        "doc_irrelevant": "React is a JavaScript library"
    },
    {
        "query": "NumPy array",
        "doc_relevant": "np.array([1, 2, 3])",
        "doc_irrelevant": "Arrays in C are different"
    },
    {
        "query": "Virtual environment",
        "doc_relevant": "Use venv or virtualenv in Python",
        "doc_irrelevant": "Docker containers isolate apps"
    }
]

accuracy = evaluate_model("all-MiniLM-L6-v2", evaluation_pairs)
print(f"Accuracy en dominio Python: {accuracy:.2%}")

Resumen

Qué aprendiste:

  • Domain-specific: Legal, medical, code (mejora +10-30%)
  • Multilingual: mBERT, XLM-R, BGE-M3 (100+ idiomas)
  • Zero-shot: Usar pre-entrenado (fácil, suficiente si >85% accuracy)
  • Fine-tuning: Re-entrenar (effort alto, mejora +10-30%)
  • Evaluación custom: Crear dataset de tu dominio

Conceptos clave:

  1. Dominio específico mejora performance significativamente
  2. Multilingual crítico para non-English
  3. Fine-tune solo si vale el effort (>$500, semanas)

Recursos adicionales

  1. BioBERT - Medical embeddings
  2. Legal-BERT - Legal embeddings
  3. CodeBERT - Code embeddings
  4. BGE-M3 - Multilingual SOTA

En la siguiente cápsula

Cápsula 08: Mini-Proyecto - Benchmark Framework

Construirás:

  • Comparar 3+ modelos
  • Métricas: MTEB, latencia, costo
  • Reportes automáticos
  • Recomendación final

De teoría a proyecto completo.


Módulo 3 - Embeddings Deep Dive Guide Domain-specific y multilingual: cuando generalista no es suficiente