Phase 05 - Lesson 28
Evaluación de Contexto Largo — NIAH, RULER, LongBench, MRCR
Gemini 3 Pro anuncia 10M de tokens de contexto. En 1M de tokens, el MRCR de 8 agujas cae al 26,3%. Anunciado ≠ utilizable. La evaluación de contexto largo te dice la capacidad real del modelo sobre el que estás desplegando.
Tipo: Aprender Lenguajes: Python Requisitos previos: Fase 5 · 13 (Preguntas y Respuestas), Fase 5 · 23 (Estrategias de Chunking) Tiempo: ~60 minutos
El Problema
Tienes un contrato de 200 páginas. El modelo afirma tener un contexto de 1M de tokens. Pegas el contrato completo y preguntas: "¿Cuál es la cláusula de rescisión?" El modelo responde — pero responde desde la portada, porque la cláusula de rescisión está a 120k tokens de profundidad, más allá de donde el modelo realmente presta atención.
Esta es la brecha de capacidad de contexto de 2026. Las fichas técnicas dicen 1M o 10M. La realidad dice que el 60-70% de eso es utilizable, y "utilizable" depende de la tarea.
- Recuperación (una sola aguja en el pajar): casi perfecta hasta el máximo anunciado en modelos de frontera.
- Multi-salto / agregación: se degrada bruscamente por encima de ~128k en la mayoría de los modelos.
- Razonamiento sobre hechos dispersos: la primera tarea en fallar.
La evaluación de contexto largo mide estos ejes. Esta lección nombra los benchmarks, lo que cada uno realmente mide, y cómo construir una prueba de aguja personalizada para tu dominio.
El Concepto
Needle-in-a-Haystack (NIAH, 2023). Coloca un hecho ("la palabra mágica es piña") a una profundidad controlada dentro de un contexto largo. Pide al modelo que lo recupere. Barre profundidad × longitud. El benchmark original de contexto largo. Los modelos de frontera ahora saturan esta prueba; es una línea base necesaria pero no suficiente.
RULER (Nvidia, 2024). 13 tipos de tarea en 4 categorías: recuperación (clave única / múltiples claves / múltiples valores), rastreo multi-salto (seguimiento de variables), agregación (frecuencia de palabra común), QA. Longitud de contexto configurable (4k a 128k+). Revela modelos que saturan el NIAH pero fallan en multi-salto. En el lanzamiento de 2024, solo la mitad de los 17 modelos que afirmaban tener contexto de 32k+ mantuvo la calidad en 32k.
LongBench v2 (2024). 503 preguntas de opción múltiple, contextos de 8k a 2M palabras, seis categorías de tarea: QA de documento único, QA multi-documento, aprendizaje en contexto largo, diálogo largo, repositorio de código, datos estructurados largos. El benchmark de producción para el comportamiento de contexto largo en el mundo real.
MRCR (Multi-Round Coreference Resolution). Correferencia multi-turno a escala. Variantes de 8 agujas, 24 agujas, 100 agujas. Expone cuántos hechos puede manejar un modelo antes de que la atención se degrade.
NoLiMa. "Aguja no léxica." La aguja y la consulta no comparten ninguna superposición literal; la recuperación requiere un paso de razonamiento semántico. Más difícil que el NIAH.
HELMET. Concatena muchos documentos, hace una pregunta a partir de cualquiera de ellos. Prueba la atención selectiva.
BABILong. Inserta cadenas de razonamiento bAbI dentro de pajares irrelevantes. Prueba el razonamiento-en-el-pajar, no solo la recuperación.
Qué reportar realmente
- Ventana de contexto anunciada. El número de la ficha técnica.
- Longitud efectiva de recuperación. Aprobación en NIAH en algún umbral (por ejemplo, 90%).
- Longitud efectiva de razonamiento. Aprobación en multi-salto o agregación en ese umbral.
- Curva de degradación. Precisión vs longitud de contexto, graficada por tipo de tarea.
Dos números para tu ficha técnica: efectivo-para-recuperación y efectivo-para-razonamiento. Normalmente el efectivo-para-razonamiento es 25-50% de la ventana anunciada.
Constrúyelo
Paso 1: un NIAH personalizado para tu dominio
Ver code/main.py. El esqueleto:
def build_haystack(filler_text, needle, depth_ratio, total_tokens):
if not (0.0 <= depth_ratio <= 1.0):
raise ValueError(f"depth_ratio must be in [0, 1], got {depth_ratio}")
if total_tokens <= 0:
raise ValueError(f"total_tokens must be positive, got {total_tokens}")
filler_tokens = tokenize(filler_text)
needle_tokens = tokenize(needle)
if not filler_tokens:
raise ValueError("filler_text produced no tokens")
# Repeat filler until long enough to fill the haystack body.
body_len = max(total_tokens - len(needle_tokens), 0)
while len(filler_tokens) < body_len:
filler_tokens = filler_tokens + filler_tokens
filler_tokens = filler_tokens[:body_len]
insert_at = min(int(body_len * depth_ratio), body_len)
haystack = filler_tokens[:insert_at] + needle_tokens + filler_tokens[insert_at:]
return " ".join(haystack)
def score_niah(model, haystack, question, expected):
answer = model.complete(f"Context: {haystack}\nQ: {question}\nA:", max_tokens=50)
return 1 if expected.lower() in answer.lower() else 0
Barre depth_ratio ∈ {0, 0.25, 0.5, 0.75, 1.0} × total_tokens ∈ {1k, 4k, 16k, 64k}. Grafica el mapa de calor. Esa es la tarjeta NIAH de tu modelo objetivo.
Paso 2: una variante multi-aguja
def build_multi_needle(filler, needles, total_tokens):
depths = [0.1, 0.4, 0.7]
chunks = [filler[:int(total_tokens * 0.1)]]
for depth, needle in zip(depths, needles):
chunks.append(needle)
next_chunk = filler[int(total_tokens * depth): int(total_tokens * (depth + 0.3))]
chunks.append(next_chunk)
return " ".join(chunks)
Preguntas como "¿Cuáles son las tres palabras mágicas?" requieren recuperar las tres. El éxito con una sola aguja no predice el éxito con múltiples agujas.
Paso 3: rastreo de variables multi-salto (estilo RULER)
haystack = """X1 = 42. ... (filler) ... X2 = X1 + 10. ... (filler) ... X3 = X2 * 2."""
question = "What is X3?"
La respuesta requiere encadenar tres asignaciones. Los modelos de frontera en 128k a menudo caen al 50-70% de precisión aquí.
Paso 4: LongBench v2 en tu stack
from datasets import load_dataset
longbench = load_dataset("THUDM/LongBench-v2")
def eval_model_on_longbench(model, subset="single-doc-qa"):
tasks = [x for x in longbench["test"] if x["task"] == subset]
correct = 0
for x in tasks:
answer = model.complete(x["context"] + "\n\nQ: " + x["question"], max_tokens=20)
if normalize(answer) == normalize(x["answer"]):
correct += 1
return correct / len(tasks)
Reporta la precisión por categoría. Las puntuaciones agregadas ocultan grandes diferencias a nivel de tarea.
Trampas
- Evaluación solo con NIAH. Pasar el NIAH en 1M de tokens no dice nada sobre multi-salto. Ejecuta siempre RULER o una prueba multi-salto personalizada.
- Muestreo uniforme de profundidad. Muchas implementaciones solo prueban depth=0.5. Prueba depth=0, 0.25, 0.5, 0.75, 1.0 — el efecto "perdido en el medio" es real.
- Superposición léxica con el relleno. Si la aguja comparte palabras clave con el relleno, la recuperación se vuelve trivial. Usa agujas sin superposición al estilo NoLiMa.
- Ignorar la latencia. Los prompts de 1M de tokens tardan de 30 a 120 segundos en el prefill. Mide el tiempo hasta el primer token junto con la precisión.
- Números autorreportados por los proveedores. OpenAI, Google y Anthropic publican todos sus propias puntuaciones. Vuelve a ejecutar siempre de forma independiente en tu caso de uso.
Úsalo
El stack de 2026:
| Situación | Benchmark |
|---|---|
| Verificación rápida de cordura | NIAH personalizado en 3 profundidades × 3 longitudes |
| Selección de modelo para producción | RULER (13 tareas) en tu longitud objetivo |
| Calidad de QA en el mundo real | Subconjunto single-doc-QA de LongBench v2 |
| Razonamiento multi-salto | BABILong o rastreo de variables personalizado |
| Conversacional / diálogo | MRCR 8 agujas en tu longitud objetivo |
| Regresión en actualización de modelo | Harness NIAH + RULER interno fijo, ejecutado en cada nuevo modelo |
Regla práctica para producción: nunca confíes en una ventana de contexto hasta tener NIAH + 1 tarea de razonamiento en tu longitud prevista.
Despliégalo
Guarda como outputs/skill-long-context-eval.md:
---
name: long-context-eval
description: Design a long-context evaluation battery for a given model and use case.
version: 1.0.0
phase: 5
lesson: 28
tags: [nlp, long-context, evaluation]
---
Given a target model, target context length, and use case, output:
1. Tests. NIAH depth × length grid; RULER multi-hop; custom domain task.
2. Sampling. Depths 0, 0.25, 0.5, 0.75, 1.0 at each length.
3. Metrics. Retrieval pass rate; reasoning pass rate; time-to-first-token; cost-per-query.
4. Cutoff. Effective retrieval length (90% pass) and effective reasoning length (70% pass). Report both.
5. Regression. Fixed harness, rerun on every model upgrade, surface deltas.
Refuse to trust a context window from the model card alone. Refuse NIAH-only evaluation for any multi-hop workload. Refuse vendor self-reported long-context scores as independent evidence.
Ejercicios
- Fácil. Construye un NIAH con 3 profundidades (0.25, 0.5, 0.75) × 3 longitudes (1k, 4k, 16k). Ejecútalo en cualquier modelo. Grafica la tasa de aprobación como un mapa de calor 3×3.
- Medio. Añade una variante de 3 agujas. Mide la recuperación de las 3 en cada longitud. Compara con la tasa de aprobación de aguja única en la misma longitud.
- Difícil. Construye una tarea de rastreo de variables (X1 → X2 → X3, con 3 saltos) embebida en 64k de relleno. Mide la precisión en 3 modelos de frontera. Reporta la longitud efectiva de razonamiento por modelo.
Términos Clave
| Término | Lo que dice la gente | Lo que realmente significa |
|---|---|---|
| NIAH | Aguja en el pajar | Planta un hecho en el relleno y pide al modelo que lo recupere. |
| RULER | NIAH potenciado | 13 tipos de tarea en recuperación / multi-salto / agregación / QA. |
| Contexto efectivo | La capacidad real | Longitud en la que la precisión aún se mantiene por encima del umbral. |
| Perdido en el medio | Sesgo de profundidad | Los modelos prestan menos atención al contenido en el medio de entradas largas. |
| Multi-aguja | Muchos hechos a la vez | Múltiples plantas; prueba el manejo de la atención, no solo la recuperación. |
| MRCR | Correferencia multi-turno | Correferencia de 8, 24 o 100 agujas; expone la saturación de la atención. |
| NoLiMa | Aguja no léxica | La aguja y la consulta no comparten tokens literales; requiere razonamiento. |
Lectura Adicional
- Kamradt (2023). Needle in a Haystack analysis — el repositorio original del NIAH.
- Hsieh et al. (2024). RULER: What's the Real Context Size of Your Long-Context LMs? — el benchmark multi-tarea.
- Bai et al. (2024). LongBench v2 — evaluación de contexto largo en el mundo real.
- Modarressi et al. (2024). NoLiMa: Non-lexical needles — agujas más difíciles.
- Kuratov et al. (2024). BABILong — razonamiento-en-el-pajar.
- Liu et al. (2024). Lost in the Middle: How Language Models Use Long Contexts — el artículo sobre el sesgo de profundidad.