Python & Data Science
LLMs y GenAI En revisión

Por qué los LLM olvidan el medio: Entendiendo las ventanas de contexto y el fenómeno Lost in the Middle

La última vez, Rae construyó su primer pipeline de RAG completo para su bot de soporte. Dividió en fragmentos el manual de producto de 500 páginas, generó los embeddings de cada fragmento con un modelo sentence-transformer, y recuperó los pasajes correctos con FAISS cuando un cliente hace una pregunta. Su bot comenzó a responder preguntas reales de los clientes a partir del manual. Pero pronto notó algo extraño. A veces, el bot omite un dato que ella puede ver justo ahí en los fragmentos recuperados: simplemente está enterrado en el medio de un pasaje largo. La recuperación funcionó, el fragmento era relevante, pero el LLM no lo utilizó.

1. El problema: tu LLM lee como un estudiante cansado

Rae notó algo extraño con su bot de soporte. Cuando un cliente preguntaba sobre una función mencionada al inicio o al final del contexto recuperado, el bot respondía correctamente. Pero cuando la misma respuesta estaba enterrada en medio de un pasaje largo—incluso uno que podía ver ahí mismo en los fragmentos recuperados—el bot alucinaba o decía “No sé”. Es como pasar horas leyendo un manual técnico, solo para darte cuenta de que recuerdas perfectamente la introducción y la conclusión, pero el medio es una niebla borrosa.

Los Modelos de Lenguaje Grande (LLMs) hacen lo mismo. A menudo hablamos de las “ventanas de contexto” como si fueran contenedores que retienen información con perfecta claridad hasta que se desbordan. La realidad es más compleja. Incluso cuando un modelo puede técnicamente ver un fragmento de información, a menudo lo ignora si esa información se encuentra en medio de un prompt largo.

Esto no es un bug. Es un comportamiento fundamental del mecanismo de atención. Los investigadores llaman a esto el fenómeno “Lost in the Middle”. Entonces, ¿qué pasa cuando ocultamos un hecho simple dentro de un documento largo?

import openai
import os

# Imagine we have a long document about a fictional company.
# We will place a specific fact (The CEO's favorite color) at different positions.
def test_retrieval_position(fact_position="middle"):
    fact = "The CEO's favorite color is Electric Purple."
    filler = "The company produces high-quality widgets for the global market. " * 100
    
    if fact_position == "start":
        prompt = f"{fact}\n{filler}"
    elif fact_position == "end":
        prompt = f"{filler}\n{fact}"
    else:
        prompt = f"{filler[:len(filler)//2]}\n{fact}\n{filler[len(filler)//2:]}"
    
    prompt += "\nQuestion: What is the CEO's favorite color? Answer in one word."
    
    # In a real test, you'd call an API here.
    # For this example, we simulate the common failure mode.
    print(f"Testing fact at: {fact_position.upper()}")
    # If position is middle, models often hallucinate or say 'I don't know'
    return "Electric Purple" if fact_position != "middle" else "Unknown/Blue"

print(test_retrieval_position("start"))
print(test_retrieval_position("middle"))
print(test_retrieval_position("end"))
Este bloque simula el problema de "Lost in the Middle" colocando un hecho objetivo ("El color favorito del CEO es el púrpura eléctrico.") en tres posiciones diferentes dentro de un documento largo. La variable `filler` crea una oración repetida 100× para simular un contexto largo. Cuando `fact_position` es `"start"`, el hecho va antes del filler (`f"{fact}\n{filler}"`); cuando es `"end"`, va después (`f"{filler}\n{fact}"`); cuando es `"middle"`, se inserta en el punto medio usando `filler[:len(filler)//2]` (primera mitad) y `filler[len(filler)//2:]` (segunda mitad) para dividir el filler alrededor del hecho. La función retorna `"Electric Purple"` para las posiciones de inicio y final, pero `"Unknown/Blue"` para la posición media—simulando el modo de falla del mundo real donde los modelos recuerdan con precisión los hechos en los extremos pero los pierden en el centro. En una prueba real, reemplazarías el return simulado con una llamada real a la API del LLM y medirías la diferencia.

El modelo suele acertar la respuesta cuando el hecho está al inicio o al final. Sin embargo, ponlo en el medio y la precisión cae—a veces en más de un 50%. Esta es la curva de rendimiento “en forma de U” que persigue a las aplicaciones de contexto largo.

2. Qué es realmente una ventana de contexto

La ventana de contexto es un límite estricto para la memoria a corto plazo del modelo. Se mide en tokens—las unidades básicas de texto que procesa el modelo.

Un token equivale a aproximadamente 0.75 palabras. Así que una ventana de 4,000 tokens parece amplia, pero eso es solo ~3,000 palabras—aproximadamente una entrada de blog larga. Si superas el límite, el modelo no puede ver el texto adicional. O bien lanza un error o, con mayor frecuencia, descarta las primeras partes de la conversación para hacer espacio para lo nuevo.

⚠️ Requiere: pip install tiktoken

import tiktoken

def count_tokens(text, model="gpt-4"):
    encoding = tiktoken.encoding_for_model(model)
    tokens = encoding.encode(text)
    return len(tokens)

text = "Data science is the study of data to extract meaningful insights for business."
num_tokens = count_tokens(text)
print(f"Token count: {num_tokens}")
# For this sentence, it's 15 tokens. 
# If your limit is 8192, you've used 0.18% of your budget.
Este bloque utiliza `tiktoken` para contar los tokens en una oración de ejemplo. `tiktoken.encoding_for_model("gpt-4")` carga el tokenizador específico para el vocabulario de GPT-4 (la misma codificación `cl100k_base` utilizada en el artículo sobre el pipeline RAG). `encoding.encode(text)` convierte la cadena en una lista de IDs de tokens—cada entero representa un token. `len(tokens)` da el recuento total. La oración de ejemplo produce 15 tokens, y el comentario señala que frente a un límite de 8,192 tokens, eso es solo el 0.18% del presupuesto—lo que ilustra qué tan pequeña es una sola oración en relación incluso con una ventana de contexto modesta. El punto más amplio: cuando Rae recupera 5–10 fragmentos de texto de un manual de producto y los apila en un prompt, podría estar usando 2,000–5,000 tokens—bien dentro del límite, pero lo suficientemente grande para que se active el efecto "Lost in the Middle".

Sin embargo, hay que tener en cuenta algo. Incluso cuando te mantienes dentro del límite, el modelo no le da el mismo peso a cada token. Tiene un presupuesto de atención suave, y gasta la mayor parte de ese presupuesto en los extremos.

3. Atención: por qué el modelo se enfoca en los extremos

¿Por qué ocurre esto? Es estructural. Los Transformers usan Position Embeddings para rastrear dónde se ubica una palabra en una oración.

  1. La ventaja del inicio: Los primeros tokens son el “ancla”. Cada token posterior se fija en ellos, por lo que establecen el tono y el tema.
  2. La ventaja del final: Los últimos tokens son los más recientes. Cuando el modelo está a punto de generar una respuesta, los tokens justo al lado del prompt “Question:” son los más frescos en su memoria matemática.
  3. El bache del medio: Los tokens del medio están lejos tanto del inicio como de la salida. En un mar de 30,000 tokens, una oración en el token 15,000 es solo “ruido” que el modelo tiene que filtrar.

4. La evidencia empírica: dónde miran realmente los modelos

El artículo Lost in the Middle de Liu et al. (2023) evaluó modelos como GPT-3.5 y Claude. Los resultados fueron contundentes. A medida que el contexto de entrada crece, la capacidad de un modelo para recuperar un dato específico del medio se desploma.

Por lo tanto, un modelo con una ventana de 32,000 tokens podría ser menos preciso al encontrar información que uno con una ventana de 8,000 tokens. Más espacio simplemente significa más “medio” en el que la información puede perderse.

5. Por qué esto importa: consecuencias en el mundo real

Esto no es solo una peculiaridad teórica. Rompe sistemas reales:

  • RAG (Generación Aumentada por Recuperación): Coloca el más relevante de 10 documentos recuperados en la mitad del prompt, y el LLM podría pasarlo por alto por completo.
  • Análisis legal: ¿Una cláusula crítica enterrada en la página 40 de un contrato de 100 páginas? El modelo podría resumir todo el documento como si esa cláusula no existiera.
  • Conversaciones largas: El modelo puede olvidar instrucciones específicas de hace diez minutos una vez que la conversación ha avanzado.

6. Soluciones alternativas: cómo lidiar con el ‘Lost in the Middle’

Dado que no podemos cambiar fácilmente cómo funcionan los Transformers, tenemos que cambiar la forma en que nos comunicamos con ellos. Algunas estrategias que ayudan:

  • Estrategia 1: Reordenamiento. Coloca los datos más importantes al principio o al final del prompt.
  • Estrategia 2: Fragmentación. En lugar de un solo prompt gigante, divide la tarea en 3 más pequeñas.
  • Estrategia 3: Reclasificación. Usa un modelo más pequeño y rápido para clasificar los documentos por relevancia, y luego coloca los 3 primeros al inicio de tu prompt.
def reorder_context(chunks, query_relevance_scores):
    # Sort chunks so the most relevant are at the 'edges'
    sorted_chunks = [x for _, x in sorted(zip(query_relevance_scores, chunks), reverse=True)]
    
    # Put best chunk first, second best last, third best second, etc.
    final_context = []
    for i, chunk in enumerate(sorted_chunks):
        if i % 2 == 0:
            final_context.insert(0, chunk)
        else:
            final_context.append(chunk)
    return "\n".join(final_context)

chunks = ["Chunk A (Low)", "Chunk B (High)", "Chunk C (Med)"]
scores = [0.1, 0.9, 0.5]
print(reorder_context(chunks, scores))
# Result puts 'Chunk B' at the start where attention is highest.
Este bloque reordena los fragmentos recuperados para colocar los más relevantes en los extremos del contexto, donde la atención es mayor. `sorted(zip(query_relevance_scores, chunks), reverse=True)` empareja cada puntuación con su fragmento y los ordena por puntuación de forma descendente; la comprensión de listas `[x for _, x in ...]` extrae solo los fragmentos ordenados, descartando las puntuaciones (el `_` es una variable desechable). El bucle `for` luego intercala: los fragmentos con índices pares (0, 2, 4…) se insertan en la posición 0 con `final_context.insert(0, chunk)` (empujándolos hacia el frente), mientras que los fragmentos con índices impares (1, 3, 5…) se agregan al final con `final_context.append(chunk)`. Este patrón de "cremallera" coloca el fragmento de mayor relevancia primero, el segundo de mayor relevancia al final, el tercero en segundo lugar, y así sucesivamente, reflejando la curva de atención en forma de U. Con los datos de ejemplo, "Chunk B" (puntuación 0.9) termina al inicio donde el modelo presta más atención, "Chunk C" (puntuación 0.5) va al final, y "Chunk A" (puntuación 0.1) se sitúa en el medio, donde menos importa.

7. Por qué los modelos más nuevos son mejores (pero no perfectos)

GPT-4o y Claude 3.5 Sonnet tienen ventanas de contexto mucho más grandes (128k a 200k+). Utilizan técnicas como “LongRoPE” o mejores datos de entrenamiento para ayudar al modelo a mantenerse enfocado. Son significativamente mejores que los modelos de hace dos años. Aún así, la curva en forma de U persiste. No puedes asumir que una ventana de 128k signifique 100% de recall en toda la ventana de 128k.

Lost in the Middle: ¿Mitigarlo o Cambiar a una Ventana Más Grande?

Rae tiene dos opciones generales cuando su bot de soporte pasa por alto hechos en el medio del contexto recuperado.

Opción A: Mitigar con reordenamiento, menos chunks y reranking. Mantén tu modelo y ventana de contexto actuales. En su lugar, reordena los chunks recuperados para que los más relevantes queden en los extremos (inicio y final) del prompt—la función reorder_context de la Sección 6 es una versión ligera. Recupera menos chunks pero de mayor calidad (top-3 en lugar de top-20) para reducir el “medio”. Añade un paso de reranking: recupera 10 chunks con un modelo de embeddings rápido, luego usa un cross-encoder más lento para seleccionar los mejores 3 y colocarlos en los extremos. Esto requiere esfuerzo de ingeniería pero sin gasto adicional de API por consulta. Es ideal cuando tu contexto recuperado ya es manejable (menos de ~10k tokens) y solo necesitas empujar al modelo hacia los pasajes correctos.

Opción B: Cambiar a una ventana de contexto más grande. Usa un modelo como GPT-4o o Claude 3.5 Sonnet con ventanas de 128k–200k tokens. Pega más—o todo—tu contexto recuperado de una sola vez. Menos esfuerzo de ingeniería, pero la curva en forma de U sigue aplicando: incluso con 128k tokens, los hechos en el medio de la ventana reciben menos atención que los hechos en los extremos. Procesar 128k tokens por consulta también es más lento y más costoso por llamada. Es ideal cuando tus documentos genuinamente necesitan la ventana completa y estás dispuesto a intercambiar costo por simplicidad.

Cuándo gana la Opción A: Estás con presupuesto de startup, tu contexto recuperado está por debajo de ~10k tokens, y te importan la latencia y el costo por consulta. El overhead de reordenamiento y reranking es pequeño comparado con el costo de alimentar 128k tokens a un modelo de vanguardia por cada pregunta del cliente—que es exactamente la situación de Rae con su manual de producto.

Cuándo gana la Opción B: Tus documentos son tan largos que RAG no puede recuperar bien (p. ej., la respuesta requiere sintetizar información de 20+ secciones distantes), y estás dispuesto a pagar por la ventana más grande. Pero recuerda: una ventana más grande reduce el techo de errores de lost-in-the-middle; no elimina la curva en forma de U.

La elección actual de Rae: Los top-5 chunks recuperados del manual de producto de Rae están bien por debajo de 10k tokens en total. El reordenamiento y reranking es la solución más económica por ahora. Pero la existencia de ventanas de 128k+ sigue rondando en su mente—si el modelo técnicamente puede leer todo el manual, ¿por qué molestarse con el retrieval en absoluto?

8. La parte difícil: por qué es genuinamente difícil de solucionar

La parte difícil: La atención es costosa.

La atención estándar tiene un costo “cuadrático”. Si duplicas la longitud del texto, el trabajo computacional se cuadruplica. Para manejar ventanas largas, los ingenieros usan “atención dispersa” — solo mirando algunos tokens. El modelo se ejecuta más rápido, pero también es más probable que “se salte” los tokens del medio. Cambiamos la memoria perfecta por la capacidad de siquiera leer documentos largos.

La auto-atención estándar calcula una relación entre cada par de tokens en la entrada. Para una secuencia de nn tokens, la matriz de atención es n×nn \times n, lo que significa que la computación escala cuadráticamente:

Attention costn2\text{Attention cost} \propto n^2

Si duplicas la longitud de la secuencia de nn a 2n2n, el costo pasa de n2n^2 a (2n)2=4n2(2n)^2 = 4n^2 — cuatro veces el trabajo por el doble de texto.

Lenguaje sencilloSímbolo estadísticoEquivalente en Python
Número de tokens en la entradannlen(tokens)
Costo de cómputo de la atención (cuadrático)O(n2)O(n^2)n ** 2
Duplicar la longitud de la secuencia cuadruplica el costo(2n)2=4n2(2n)^2 = 4n^2(2 * n) ** 2
La atención dispersa solo calcula kk vecinos por tokenO(nk)O(n \cdot k), donde knk \ll nn * k (donde k << n)

Esta es la razón por la que los ingenieros usan “atención dispersa” para hacer factibles las ventanas largas: cambian O(n2)O(n^2) por O(nk)O(n \cdot k) donde kk es un número fijo de vecinos por token. Pero esto es exactamente lo que facilita que el modelo “se salte” los tokens del medio: al no calcular la atención entre pares distantes, cierta información del medio nunca se amplifica. Estamos intercambiando memoria perfecta por la capacidad de siquiera leer documentos largos.

9. Qué hacer: guía práctica para tu caso de uso

Un árbol de decisión rápido para tu próximo proyecto:

  1. ¿Menos de 2,000 tokens? No te preocupes — es probable que el modelo vea todo el prompt.
  2. ¿De 2,000 a 10,000 tokens? Coloca tus instrucciones clave al final, justo antes de que el modelo comience a generar.
  3. ¿Más de 10,000 tokens? Usa un Reranker para que la información más relevante no quede enterrada en el medio, o divide el contenido con un enfoque de “Map-Reduce” (resumiendo las partes por separado primero).

10. Mirando al futuro: qué está cambiando

Los investigadores están desarrollando la “Atención Lineal” y los “Modelos de Espacio de Estados” (como Mamba) que eliminan este costo cuadrático. Algún día podríamos tener modelos que traten la parte media de un documento con el mismo respeto que al inicio. Por ahora, sin embargo, la posición importa.

11. Resumen y próximos pasos

  • Lost in the Middle significa que los LLMs tienen dificultades con la información en el centro de los prompts largos.
  • Attention favorece el inicio (contexto) y el final (recencia).
  • Solución alternativa: Mantén tus datos más importantes en los extremos de tu prompt.

Pero la alternativa de una ventana de contexto más grande sigue rondando en la mente de Rae. GPT-4o y Claude 3.5 Sonnet manejan 128k–200k tokens. Entonces, ¿por qué molestarse con chunking, embedding y recuperación en absoluto? ¿Por qué no pegar todo el manual del producto en el prompt y dejar que el modelo lo lea? En el próximo artículo, enfrentaremos a RAG contra los modelos de contexto largo directamente y veremos cuál gana realmente para el bot de soporte de Rae en 2026.

Comprueba tu comprensión

Las preguntas a continuación van desde el simple recuerdo hasta el diseño abierto, siguiendo aproximadamente la Taxonomía de Bloom.

Recordar ¿Cuál es el fenómeno de “Lost in the Middle”, y qué describe la curva de rendimiento en forma de U?

Comprender Explique con sus propias palabras por qué la atención crea una “ventaja al inicio” y una “ventaja al final”, y por qué los tokens en el medio de un prompt largo se tratan como ruido.

Aplicar Usando el árbol de decisión de la sección 9, tiene un prompt de 15,000 tokens donde la instrucción más importante se encuentra en el token 7,000. ¿Cuál de las soluciones alternativas del artículo debería aplicar y cómo la implementaría?

Analizar La sección 4 afirma que un modelo con una ventana de 32,000 tokens puede ser menos preciso al recuperar un hecho que un modelo de 8,000 tokens. Repase el razonamiento: ¿por qué una ventana de contexto más grande crea más “medio” en lugar de simplemente más espacio para la información?

Evaluar La función reorder_context del artículo coloca el fragmento de mayor relevancia al inicio y el de segunda mayor relevancia al final. Critique esa estrategia: describa un escenario real de RAG donde este ordenamiento de “poner lo mejor en los bordes” aún podría fallar al recuperar el hecho necesario.

Crear Diseñe una estrategia de resumen de “map-reduce” para un contrato legal de 100 páginas donde la cláusula crítica se encuentra en la página 40. Describa cómo dividiría en fragmentos, resumiría y recombinaría el documento para que el LLM muestre de manera confiable esa cláusula en lugar de enterrarla.

Artículos relacionados

Referencias y lecturas adicionales


Esta traducción fue generada automáticamente y puede contener errores. Si el idioma inglés es tu preferencia, puedes leer el artículo original en inglés .

«Aplica lo que aprendiste» es para suscriptores Supporter e Insider.

Suscríbete para desbloquear los ejercicios de este artículo.

Ver planes

¿Buscas otra cosa?

Busca en todos los artículos por título, resumen o tema.