Phase 05 - Lesson 22

Modelos de Embedding — La Inmersión Profunda de 2026

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

Word2Vec te daba un vector por palabra. Los modelos de embedding modernos te dan un vector por pasaje, cross-lingual, con vistas dispersas, densas y multivectoriales, dimensionados para caber en tu índice. Elige mal y tu RAG recupera lo que no debe.

Tipo: Aprender Lenguajes: Python Prerrequisitos: Fase 5 · 03 (Word2Vec), Fase 5 · 14 (Recuperación de Información) Tiempo: ~60 minutos

El Problema

Tu sistema RAG recupera el pasaje equivocado el 40% de las veces. El culpable rara vez es la base de datos vectorial o el prompt. Es el modelo de embedding.

Elegir un embedding en 2026 significa decidir entre cinco ejes:

  1. Denso vs disperso vs multivectorial. Un vector por pasaje, o uno por token, o una bolsa dispersa y ponderada de palabras.
  2. Cobertura de idiomas. Los modelos monolingües en inglés siguen ganando en tareas solo en inglés. Los modelos multilingües ganan cuando los corpus son mixtos.
  3. Longitud de contexto. 512 tokens vs 8.192 vs 32.768 — y la capacidad efectiva real suele ser el 60-70% del máximo anunciado.
  4. Presupuesto de dimensión. 3.072 floats en precisión completa = 12 KB por vector. Con 100M de vectores, el almacenamiento cuesta US$ 1.300/mes. El truncamiento Matryoshka reduce esto en 4×.
  5. Abierto vs alojado. Pesos abiertos significan que controlas el stack y los datos. Alojado significa cambiar control por estar siempre en la última versión.

Esta lección nombra los tradeoffs para que elijas con base en evidencia, no en lo que estuvo de moda el trimestre pasado.

El Concepto

Embeddings densos, dispersos y multivectoriales

Embeddings densos. Un vector por pasaje (normalmente 384-3.072 dimensiones). La similitud de coseno clasifica los pasajes por proximidad semántica. OpenAI text-embedding-3-large, modo denso de BGE-M3, Voyage-3. Opción por defecto.

Embeddings dispersos. Estilo SPLADE. Un transformer predice un peso para cada token del vocabulario y luego pone en cero la mayoría de ellos. El resultado es un vector disperso de tamaño |vocab|. Captura coincidencia léxica (como BM25) pero con pesos de términos aprendidos. Fuerte en consultas con muchas palabras clave.

Multivectorial (interacción tardía). ColBERTv2, Jina-ColBERT. Un vector por token. Puntuación con MaxSim: para cada token de la consulta, encuentra el token del documento más similar y suma las puntuaciones. Más costoso de almacenar y puntuar, pero gana en consultas largas y corpus específicos de dominio.

BGE-M3: los tres a la vez. Un solo modelo produce representaciones densas, dispersas y multivectoriales simultáneamente. Cada una puede consultarse de forma independiente; las puntuaciones se fusionan mediante suma ponderada. El estándar de 2026 cuando quieres flexibilidad a partir de un único checkpoint.

Matryoshka Representation Learning. Entrenado para que las primeras N dimensiones del vector formen un embedding autónomo útil. Trunca un vector de 1.536 dimensiones a 256 y paga ~1% de precisión por un ahorro de 6× en almacenamiento. Soportado por OpenAI text-3, Cohere v4, Voyage-4, Jina v5, Gemini Embedding 2, Nomic v1.5+.

El leaderboard MTEB cuenta una historia parcial

Massive Text Embedding Benchmark — 56 tareas en 8 tipos de tarea al lanzamiento (2022), expandido a más de 100 tareas en MTEB v2. A inicios de 2026, Gemini Embedding 2 lidera en recuperación (67,71 MTEB-R). Cohere embed-v4 lidera en general (65,2 MTEB). BGE-M3 lidera entre los multilingües de pesos abiertos (63,0). El leaderboard es necesario pero no suficiente — siempre haz benchmark en tu dominio.

El patrón de tres niveles

Caso de uso Patrón
Primera pasada rápida Bi-encoder denso (BGE-M3, text-3-small)
Aumento de recall Disperso (SPLADE, BGE-M3 disperso) + fusión RRF
Precisión en el top-50 Multivectorial (ColBERTv2) o reranker cross-encoder

La mayoría de los stacks de producción usan los tres.

Constrúyelo

Paso 1: baseline — embeddings densos con Sentence-BERT

from sentence_transformers import SentenceTransformer
import numpy as np

encoder = SentenceTransformer("BAAI/bge-small-en-v1.5")
corpus = [
    "The first iPhone launched in 2007.",
    "Apple released the iPod in 2001.",
    "Android is an operating system from Google.",
]
emb = encoder.encode(corpus, normalize_embeddings=True)

query = "When was the iPhone released?"
q_emb = encoder.encode([query], normalize_embeddings=True)[0]
scores = emb @ q_emb
print(sorted(enumerate(scores), key=lambda x: -x[1]))

normalize_embeddings=True hace que el producto punto sea igual a la similitud de coseno. Siempre actívalo.

Paso 2: truncamiento Matryoshka

def truncate(vectors, dim):
    out = vectors[:, :dim]
    return out / np.linalg.norm(out, axis=1, keepdims=True)

emb_256 = truncate(emb, 256)
emb_128 = truncate(emb, 128)

Renormaliza después del truncamiento. Nomic v1.5, OpenAI text-3 y Voyage-4 están entrenados de modo que esto sea sin pérdidas en los primeros niveles. Los modelos no Matryoshka (Sentence-BERT original) se degradan bruscamente al truncarse.

Paso 3: multifuncionalidad de BGE-M3

from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel("BAAI/bge-m3", use_fp16=True)

output = model.encode(
    corpus,
    return_dense=True,
    return_sparse=True,
    return_colbert_vecs=True,
)
# output["dense_vecs"]:    (n_docs, 1024)
# output["lexical_weights"]: list of dict {token_id: weight}
# output["colbert_vecs"]:  list of (n_tokens, 1024) arrays

Tres índices, una llamada de inferencia. Fusión de puntuaciones:

dense_score = ... # cosine over dense_vecs
sparse_score = model.compute_lexical_matching_score(q_lex, d_lex)
colbert_score = model.colbert_score(q_col, d_col)
final = 0.4 * dense_score + 0.2 * sparse_score + 0.4 * colbert_score

Ajusta los pesos en tu dominio.

Paso 4: evaluación MTEB en una tarea personalizada

from mteb import MTEB

tasks = ["ArguAna", "SciFact", "NFCorpus"]
evaluation = MTEB(tasks=tasks)
results = evaluation.run(encoder, output_folder="./mteb-results")

Ejecuta tus modelos candidatos en un subconjunto representativo. No confíes solo en la posición del leaderboard — tu dominio importa.

Paso 5: coseno hecho a mano desde cero

Ve code/main.py. Embeddings de Averaged Hashing Trick (solo stdlib). No competitivos con los embeddings de transformers, pero muestran la forma: tokenizar → vector → normalizar → producto punto.

Errores Comunes

  • Mismo modelo para consulta y documento. Algunos modelos (Voyage, Jina-ColBERT) usan codificación asimétrica — la consulta y el documento pasan por caminos diferentes. Siempre revisa la model card.
  • Prefijo ausente. Los modelos bge-* necesitan "Represent this sentence for searching relevant passages: " antepuesto a las consultas. Brecha de 3-5 puntos de recall si lo olvidas.
  • Truncamiento excesivo de Matryoshka. 1.536 → 256 suele ser seguro. 1.536 → 64 no lo es. Valida en tu conjunto de evaluación.
  • Truncamiento de contexto. La mayoría de los modelos trunca silenciosamente las entradas que superan su longitud máxima. Los documentos largos necesitan chunking (ve la lección 23).
  • Ignorar la cola de latencia. Las puntuaciones MTEB ocultan la latencia p99. Un modelo de 600M podría superar a uno de 335M por 2 puntos, pero costar 3× más por consulta.

Úsalo

El stack de 2026:

Situación Elección
Solo inglés, rápido, API text-embedding-3-large o voyage-3-large
Pesos abiertos, inglés BAAI/bge-large-en-v1.5
Pesos abiertos, multilingüe BAAI/bge-m3 o Qwen3-Embedding-8B
Contexto largo (32k+) Voyage-3-large, Cohere embed-v4, Qwen3-Embedding-8B
Despliegue solo en CPU Nomic Embed v2 (137M params, MoE)
Restringido por almacenamiento Truncado con Matryoshka + cuantización int8
Consultas con muchas palabras clave Agrega SPLADE disperso, fusión RRF con denso

Patrón de 2026: empieza con BGE-M3 o text-3-large, evalúa en tu dominio con MTEB, cambia si un modelo específico de dominio gana por más de 3 puntos.

Entrégalo

Guarda como outputs/skill-embedding-picker.md:

---
name: embedding-picker
description: Pick embedding model, dimension, and retrieval mode for a given corpus and deployment.
version: 1.0.0
phase: 5
lesson: 22
tags: [nlp, embeddings, retrieval]
---

Given a corpus (size, languages, domain, avg length), deployment target (cloud / edge / on-prem), latency budget, and storage budget, output:

1. Model. Named checkpoint or API. One-sentence reason.
2. Dimension. Full / Matryoshka-truncated / int8-quantized. Reason tied to storage budget.
3. Mode. Dense / sparse / multi-vector / hybrid. Reason.
4. Query prefix / template if required by the model card.
5. Evaluation plan. MTEB tasks relevant to domain + held-out domain eval with nDCG@10.

Refuse recommendations that truncate Matryoshka to <64 dims without domain validation. Refuse ColBERTv2 for corpora under 10k passages (overhead not justified). Flag long-document corpora (>8k tokens) routed to models with 512-token windows.

Ejercicios

  1. Fácil. Codifica 100 oraciones con bge-small-en-v1.5 en dimensión completa (384) y luego en Matryoshka 128. Mide la caída de MRR en 10 consultas.
  2. Medio. Compara denso, disperso y colbert de BGE-M3 en 500 pasajes de tu dominio. ¿Cuál gana en recall@10? ¿La fusión RRF supera al mejor modo individual?
  3. Difícil. Ejecuta MTEB en tres modelos candidatos sobre tus top-2 tareas de dominio. Reporta la puntuación MTEB, la latencia p99 en un lote de 100 consultas y el US$/1M de consultas. Elige el Pareto-óptimo.

Términos Clave

Término Lo que la gente dice Lo que realmente significa
Embedding denso El vector Un vector de tamaño fijo por texto. Similitud de coseno para clasificar.
Embedding disperso BM25 aprendido Un peso por token del vocabulario; mayormente ceros; entrenado de extremo a extremo.
Multivectorial Estilo ColBERT Un vector por token; puntuación MaxSim; índice más grande, mejor recall.
Matryoshka Truco de la muñeca rusa Las primeras N dimensiones son, por sí solas, un embedding más pequeño válido.
MTEB El benchmark Massive Text Embedding Benchmark — 56 tareas al lanzamiento, más de 100 en v2.
BEIR El benchmark de recuperación 18 tareas de recuperación zero-shot; citado a menudo por su robustez entre dominios.
Codificación asimétrica Consulta ≠ camino del doc El modelo usa proyecciones diferentes para consultas y documentos.

Lecturas Adicionales

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).