
Context Length Exceeded en llamadas a la API de LLM: soluciones, compromisos y selección de modelos

Tu llamada a la API de LLM acaba de devolver esto:
{
"error": {
"message": "This model's maximum context length is 128000 tokens. However, your messages resulted in 142837 tokens.",
"type": "invalid_request_error",
"code": "context_length_exceeded"
}
}Esto significa que tu entrada (system prompt + historial de conversación + mensaje del usuario) supera la ventana de contexto del modelo. La solicitud fue rechazada antes de que se generara un solo token.
A diferencia de los errores de rate limit (que tienen que ver con el volumen de solicitudes), los errores de context length tienen que ver con el tamaño de la solicitud. La solución no es ir más despacio, sino reducir la entrada, reestructurar la solicitud o cambiar a un modelo con una ventana de contexto más grande.
Resumen rápido
- Context length exceeded = tu entrada es demasiado grande para la ventana de tokens del modelo.
- Tienes cuatro opciones: truncar, resumir, dividir en chunks o cambiar de modelo.
- Cada opción tiene diferentes compromisos de costo, calidad y latencia.
- Usa la tabla de decisión que aparece a continuación para elegir el enfoque adecuado para tu caso de uso.
- En sistemas de producción, maneja esto antes de que el usuario lo vea, no después.
Lista de verificación rápida
Antes de elegir una estrategia, revisa primero estas causas comunes:
| Verificación | Qué buscar | Solución rápida |
|---|---|---|
| Historial de conversación demasiado largo | El array de mensajes crece sin límite en chats de varios turnos | Eliminar los mensajes más antiguos o implementar una ventana deslizante |
| System prompt demasiado grande | Instrucciones detalladas que consumen el presupuesto de contexto | Comprimir el system prompt o mover las instrucciones estáticas a una referencia |
| Contenido duplicado | El mismo contexto se inyecta múltiples veces (RAG, resultados de herramientas) | Deduplicar antes de enviar |
| Resultados de herramientas/funciones muy grandes | Una herramienta devolvió un bloque JSON o de texto enorme | Truncar o resumir la salida de la herramienta antes de agregarla al contexto |
| Metadatos innecesarios | Objetos completos cuando solo importan unos pocos campos | Extraer solo los campos relevantes |
Si ninguna de estas soluciones rápidas aplica, necesitas un enfoque estructural.
Tabla de decisión: truncar vs. resumir vs. dividir vs. cambiar modelo
| Estrategia | Cómo funciona | Impacto en calidad | Impacto en costo | Impacto en latencia | Ideal para |
|---|---|---|---|---|---|
| Truncar | Eliminar mensajes antiguos o recortar la entrada | Puede perder contexto importante | Reduce tokens de entrada = menor costo | Más rápido (menos entrada) | Apps de chat con historiales largos; casos donde el contexto reciente es lo más importante |
| Resumir | Usar un modelo más barato para comprimir el contexto previo en un resumen | Con pérdida — el resumen puede omitir detalles | Llamada API adicional para el resumen, pero la llamada principal es más pequeña | Agrega una llamada extra | Flujos de trabajo con agentes y estado acumulado; conversaciones con mucho conocimiento |
| Dividir + combinar | Dividir la entrada en chunks, procesar por separado, combinar resultados | Riesgo de perder contexto entre chunks | Múltiples llamadas = mayor costo total | Más lento (chunks secuenciales o paralelos) | Procesamiento de documentos, análisis de textos largos |
| Cambiar modelo | Usar un modelo con una ventana de contexto más grande | Generalmente neutral o mejor | Los modelos con mayor contexto suelen costar más por token | Puede variar | Cuando la entrada no se puede reducir sin perder información esencial |
Estrategia 1: Truncar — descartar lo menos importante
El truncamiento es el enfoque más simple. Elimina las partes más antiguas o menos relevantes de la entrada.
Ventana deslizante para chat
def sliding_window(messages: list, max_tokens: int, system_prompt: str) -> list:
"""Keep system prompt + most recent messages within token budget."""
# Always keep system prompt
result = [{"role": "system", "content": system_prompt}]
token_count = count_tokens(system_prompt)
# Add messages from newest to oldest
for msg in reversed(messages):
msg_tokens = count_tokens(msg["content"])
if token_count + msg_tokens > max_tokens:
break
result.insert(1, msg) # Insert after system prompt
token_count += msg_tokens
return resultCuándo funciona bien el truncamiento
- Chats de varios turnos donde el contexto reciente es lo más importante
- Pipelines de RAG donde puedes volver a recuperar información si es necesario
- Procesamiento por lotes donde puedes procesar en orden
Cuándo el truncamiento es peligroso
- Flujos de trabajo con agentes donde las instrucciones tempranas afectan el comportamiento posterior
- Contextos legales o de cumplimiento donde la completitud es importante
- Razonamiento de múltiples pasos donde omitir pasos cambia la respuesta
Estrategia 2: Resumir — comprimir sin perder significado
El resumen utiliza un modelo más barato y rápido para comprimir el contexto previo:
async def summarize_context(messages: list, client) -> str:
"""Compress older messages into a summary."""
context_text = "\n".join(
f"{m['role']}: {m['content']}" for m in messages
)
response = await client.chat.completions.create(
model="gpt-4o-mini", # Cheaper model for summarization
messages=[{
"role": "user",
"content": f"Summarize this conversation context in under 500 tokens. "
f"Preserve key decisions, facts, and pending actions:\n\n{context_text}"
}],
max_tokens=500
)
return response.choices[0].message.contentComparación de costos: resumir vs. truncar
| Enfoque | Tokens de entrada al modelo principal | Llamadas API adicionales | Costo total |
|---|---|---|---|
| Sin gestión (produce error) | N/A — solicitud rechazada | 0 | Latencia desperdiciada + costo de reintento |
| Truncar a 80K tokens | 80K | 0 | Costo base con 80K de entrada |
| Resumir contexto antiguo | ~10K (resumen) + 40K (reciente) = 50K | 1 llamada de resumen (~$0.01) | Menor costo en la llamada principal + pequeño costo de resumen |
El resumen agrega una llamada barata pero a menudo reduce significativamente los tokens de entrada de la llamada principal, lo que puede resultar en una reducción neta de costos para modelos costosos.
Estrategia 3: Dividir y combinar — para documentos largos
Cuando la entrada es un solo documento largo (no una conversación), dividir en chunks suele ser el enfoque correcto:
async def process_long_document(
document: str,
question: str,
client,
chunk_size: int = 50000
) -> str:
"""Process a long document by chunking."""
chunks = split_into_chunks(document, chunk_size)
chunk_results = []
for i, chunk in enumerate(chunks):
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": f"Analyze chunk {i+1}/{len(chunks)} of a document.\n"
f"Question: {question}\n\n"
f"Chunk content:\n{chunk}"
}]
)
chunk_results.append(response.choices[0].message.content)
# Merge chunk results
merge_response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": f"Merge these partial analyses into a final answer.\n"
f"Question: {question}\n\n"
f"Partial results:\n" + "\n---\n".join(chunk_results)
}]
)
return merge_response.choices[0].message.contentCompromisos del chunking
- Ventaja: Maneja entradas de cualquier longitud
- Desventaja: Se pierde el contexto entre chunks
- Desventaja: Múltiples llamadas API = mayor costo total y latencia
- Mitigación: Superponer los chunks en un 10-20% para preservar el contexto en los límites
Estrategia 4: Cambiar a un modelo con mayor contexto
Si tu entrada realmente necesita mantenerse grande, cambia a un modelo con una ventana de contexto más amplia:
| Familia de modelos | Contexto máximo típico | Cuándo usar |
|---|---|---|
| GPT-4o | 128K tokens | Opción predeterminada para la mayoría de cargas de trabajo |
| GPT-4o (long context) | 128K tokens | Ya es la opción predeterminada |
| Claude Sonnet/Opus | 200K tokens | Cuando necesitas más de 128K |
| Gemini Pro | 1M+ tokens | Documentos muy largos, codebases completas |
| Gemini Flash | 1M+ tokens | Tareas de contexto largo sensibles al costo |
Impacto en costos de modelos con mayor contexto
Las ventanas de contexto más grandes generalmente implican un mayor costo por token. Calcula si la mejora en calidad justifica el costo:
Option A: Truncar a 80K + GPT-4o = $X
Option B: 150K completos + Claude Sonnet = $Y
Option C: 150K completos + Gemini Flash = $Z
Comparar: diferencia de calidad vs. diferencia de costoUsar un gateway de enrutamiento para la selección de modelos
En lugar de codificar la selección de modelos de forma fija, puedes usar un gateway que enrute al modelo apropiado según el tamaño de la entrada:
from openai import OpenAI
client = OpenAI(
api_key="your-evolink-key",
base_url="https://api.evolink.ai/v1"
)
# Let the Smart Router choose based on your workload
response = client.chat.completions.create(
model="evolink/auto",
messages=your_messages
)Patrón de producción: verificar antes de enviar
No esperes a que la API rechace tu solicitud. Verifica el tamaño de la entrada antes de enviarla:
import tiktoken
def check_context_length(messages: list, model: str, max_tokens: int) -> dict:
"""Pre-check whether messages fit within the model's context window."""
encoder = tiktoken.encoding_for_model(model)
total_tokens = sum(
len(encoder.encode(m["content"])) for m in messages
)
if total_tokens > max_tokens:
return {
"fits": False,
"total_tokens": total_tokens,
"excess": total_tokens - max_tokens,
"suggestion": "truncate" if total_tokens < max_tokens * 1.5
else "summarize_or_switch"
}
return {"fits": True, "total_tokens": total_tokens}Esto evita latencia desperdiciada por solicitudes rechazadas y te permite aplicar la estrategia correcta antes de que el usuario vea un error.
Artículos relacionados
- Fix OpenRouter 429 "Provider Returned Error" — cuando el problema son los rate limits, no el tamaño de la entrada
- AI API Timeout: Causes, Retry Patterns, and Fallback Design — cuando entradas largas causan timeouts en lugar de rechazos
- How to Reduce 429 Errors in Agent Workloads — gestionar el volumen de solicitudes junto con el tamaño
- Best AI API Platform for Production Reliability — elegir una plataforma que maneje el enrutamiento de modelos
FAQ
¿Qué significa "context length exceeded"?
Significa que tu entrada (system prompt + mensajes + cualquier contexto inyectado) contiene más tokens de los que permite la ventana de contexto máxima del modelo. La solicitud se rechaza antes de que comience cualquier generación.
¿Es "context length exceeded" lo mismo que un error de rate limit?
No. Los errores de rate limit (429) tienen que ver con el volumen de solicitudes: demasiadas solicitudes en una ventana de tiempo. Los errores de context length tienen que ver con el tamaño de la solicitud: una sola solicitud que es demasiado grande. Requieren soluciones diferentes.
¿Qué es mejor: truncamiento o resumen?
El truncamiento es más simple y barato pero pierde información. El resumen preserva el significado pero agrega una llamada API adicional e introduce artefactos de compresión. Usa truncamiento para historiales de chat donde la información reciente es lo más importante; usa resumen para flujos de trabajo con agentes donde el contexto acumulado es importante.
¿Puedo evitar errores de context length usando un modelo más grande?
Sí, pero tiene un costo. Los modelos con ventanas de contexto más grandes (Gemini 1M+, Claude 200K) pueden aceptar entradas más grandes, pero generalmente cuestan más por token. Calcula si la mejora en calidad justifica el gasto adicional.
¿Cómo cuento los tokens antes de enviar una solicitud?
tiktoken para modelos de OpenAI o el endpoint de conteo de tokens del proveedor. El conteo exacto de tokens depende del tokenizer del modelo, así que usa el encoder correcto para tu modelo objetivo.¿Debo manejar este error en el código de la aplicación o a nivel de gateway?
Ambos. El código de la aplicación debe verificar previamente el tamaño de la entrada y aplicar la estrategia apropiada (truncar, resumir, dividir o cambiar). Un gateway de enrutamiento puede adicionalmente seleccionar un modelo con una ventana de contexto lo suficientemente grande para tu solicitud.

