
Context Length Exceeded dans les appels API LLM : solutions, compromis et choix de modèle

Votre appel API LLM vient de renvoyer ceci :
{
"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"
}
}Cela signifie que votre entrée (system prompt + historique de conversation + message utilisateur) dépasse la fenêtre de contexte du modèle. La requête a été rejetée avant même qu'un seul token ne soit généré.
Contrairement aux erreurs de rate limit (qui concernent le volume de requêtes), les erreurs de context length concernent la taille de la requête. La solution n'est pas de ralentir, mais de réduire l'entrée, restructurer la requête ou passer à un modèle avec une fenêtre de contexte plus grande.
En bref
- Context length exceeded = votre entrée est trop volumineuse pour la fenêtre de tokens du modèle.
- Vous avez quatre options : tronquer, résumer, découper ou changer de modèle.
- Chaque option présente des compromis différents en termes de coût, qualité et latence.
- Utilisez le tableau de décision ci-dessous pour choisir la bonne approche selon votre cas d'usage.
- En production, traitez ce problème avant que l'utilisateur ne le voie, pas après.
Liste de vérification rapide
Avant de choisir une stratégie, vérifiez d'abord ces causes courantes :
| Vérification | Ce qu'il faut chercher | Solution rapide |
|---|---|---|
| Historique de conversation trop long | Le tableau de messages grandit sans limite dans les chats multi-tours | Supprimer les messages les plus anciens ou implémenter une fenêtre glissante |
| System prompt trop volumineux | Des instructions détaillées qui consomment le budget de contexte | Compresser le system prompt ou déplacer les instructions statiques vers une référence |
| Contenu dupliqué | Le même contexte injecté plusieurs fois (RAG, résultats d'outils) | Dédupliquer avant l'envoi |
| Résultats d'outils/fonctions volumineux | Un appel d'outil a renvoyé un énorme bloc JSON ou texte | Tronquer ou résumer la sortie de l'outil avant de l'ajouter au contexte |
| Métadonnées inutiles | Objets complets alors que seuls quelques champs comptent | Extraire uniquement les champs pertinents |
Si aucune de ces solutions rapides ne s'applique, vous avez besoin d'une approche structurelle.
Tableau de décision : tronquer vs résumer vs découper vs changer de modèle
| Stratégie | Fonctionnement | Impact qualité | Impact coût | Impact latence | Idéal pour |
|---|---|---|---|---|---|
| Tronquer | Supprimer les messages anciens ou réduire l'entrée | Risque de perdre du contexte important | Réduit les tokens d'entrée = coût moindre | Plus rapide (moins d'entrée) | Apps de chat avec de longs historiques ; cas où le contexte récent est le plus important |
| Résumer | Utiliser un modèle moins cher pour compresser le contexte antérieur en un résumé | Avec perte — le résumé peut omettre des détails | Appel API supplémentaire pour le résumé, mais l'appel principal est plus petit | Ajoute un appel supplémentaire | Workflows d'agents avec état accumulé ; conversations riches en connaissances |
| Découper + fusionner | Diviser l'entrée en chunks, traiter séparément, fusionner les résultats | Risque de perdre le contexte inter-chunks | Plusieurs appels = coût total plus élevé | Plus lent (chunks séquentiels ou parallèles) | Traitement de documents, analyse de textes longs |
| Changer de modèle | Utiliser un modèle avec une fenêtre de contexte plus grande | Généralement neutre ou meilleur | Les modèles avec un contexte plus grand coûtent souvent plus par token | Peut varier | Quand l'entrée ne peut pas être réduite sans perdre des informations essentielles |
Stratégie 1 : Tronquer — supprimer le moins important
La troncature est l'approche la plus simple. Supprimez les parties les plus anciennes ou les moins pertinentes de l'entrée.
Fenêtre glissante pour le 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 resultQuand la troncature fonctionne bien
- Chats multi-tours où le contexte récent est le plus important
- Pipelines RAG où vous pouvez récupérer à nouveau si nécessaire
- Traitement par lots où vous pouvez traiter dans l'ordre
Quand la troncature est risquée
- Workflows d'agents où les instructions initiales influencent le comportement ultérieur
- Contextes juridiques ou de conformité où l'exhaustivité est essentielle
- Raisonnement multi-étapes où la suppression d'étapes modifie la réponse
Stratégie 2 : Résumer — compresser sans perdre le sens
Le résumé utilise un modèle moins cher et plus rapide pour compresser le contexte antérieur :
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.contentComparaison des coûts : résumer vs tronquer
| Approche | Tokens d'entrée vers le modèle principal | Appels API supplémentaires | Coût total |
|---|---|---|---|
| Aucune gestion (erreur déclenchée) | N/A — requête rejetée | 0 | Latence gaspillée + coût de nouvelle tentative |
| Tronquer à 80K tokens | 80K | 0 | Coût de base à 80K d'entrée |
| Résumer le contexte ancien | ~10K (résumé) + 40K (récent) = 50K | 1 appel de résumé (~0,01 $) | Coût réduit de l'appel principal + faible coût de résumé |
Le résumé ajoute un appel peu coûteux mais réduit souvent considérablement les tokens d'entrée de l'appel principal, ce qui peut représenter une réduction nette des coûts pour les modèles onéreux.
Stratégie 3 : Découper et fusionner — pour les documents longs
Lorsque l'entrée est un seul document long (pas une conversation), le découpage est souvent la bonne approche :
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.contentCompromis du découpage
- Avantage : Gère des entrées de longueur arbitraire
- Inconvénient : Le contexte inter-chunks est perdu
- Inconvénient : Plusieurs appels API = coût total et latence plus élevés
- Atténuation : Chevaucher les chunks de 10-20 % pour préserver le contexte aux frontières
Stratégie 4 : Passer à un modèle avec un contexte plus grand
Si votre entrée doit réellement rester volumineuse, passez à un modèle avec une fenêtre de contexte plus grande :
| Famille de modèles | Contexte max typique | Quand l'utiliser |
|---|---|---|
| GPT-4o | 128K tokens | Par défaut pour la plupart des charges de travail |
| GPT-4o (long context) | 128K tokens | Déjà le choix par défaut |
| Claude Sonnet/Opus | 200K tokens | Quand vous avez besoin de plus de 128K |
| Gemini Pro | 1M+ tokens | Documents très longs, codebases entières |
| Gemini Flash | 1M+ tokens | Tâches de contexte long sensibles au coût |
Impact financier des modèles à contexte élargi
Des fenêtres de contexte plus grandes impliquent généralement un coût par token plus élevé. Calculez si l'amélioration de qualité justifie le surcoût :
Option A : Tronquer à 80K + GPT-4o = $X
Option B : 150K complets + Claude Sonnet = $Y
Option C : 150K complets + Gemini Flash = $Z
Comparer : différence de qualité vs différence de coûtUtiliser une passerelle de routage pour la sélection de modèle
Au lieu de coder en dur la sélection du modèle, vous pouvez utiliser une passerelle qui route vers le modèle approprié en fonction de la taille de l'entrée :
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
)Patron de production : vérifier avant d'envoyer
N'attendez pas que l'API rejette votre requête. Vérifiez la taille de l'entrée avant l'envoi :
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}Cela évite la latence gaspillée par des requêtes rejetées et vous permet d'appliquer la bonne stratégie avant que l'utilisateur ne voie une erreur.
Articles connexes
- Fix OpenRouter 429 "Provider Returned Error" — quand le problème est le rate limit, pas la taille de l'entrée
- AI API Timeout: Causes, Retry Patterns, and Fallback Design — quand des entrées longues causent des timeouts plutôt que des rejets
- How to Reduce 429 Errors in Agent Workloads — gérer le volume de requêtes en plus de leur taille
- Best AI API Platform for Production Reliability — choisir une plateforme qui gère le routage de modèles
FAQ
Que signifie "context length exceeded" ?
Cela signifie que votre entrée (system prompt + messages + tout contexte injecté) contient plus de tokens que la fenêtre de contexte maximale du modèle ne le permet. La requête est rejetée avant le début de toute génération.
"Context length exceeded" est-il la même chose qu'une erreur de rate limit ?
Non. Les erreurs de rate limit (429) concernent le volume de requêtes — trop de requêtes dans une fenêtre de temps. Les erreurs de context length concernent la taille de la requête — une seule requête trop volumineuse. Elles nécessitent des solutions différentes.
Quel est le meilleur choix : troncature ou résumé ?
La troncature est plus simple et moins coûteuse mais entraîne une perte d'information. Le résumé préserve le sens mais ajoute un appel API supplémentaire et introduit des artefacts de compression. Utilisez la troncature pour les historiques de chat où la fraîcheur de l'information est primordiale ; utilisez le résumé pour les workflows d'agents où le contexte accumulé est important.
Puis-je éviter les erreurs de context length en utilisant un modèle plus grand ?
Oui, mais à un coût. Les modèles avec des fenêtres de contexte plus grandes (Gemini 1M+, Claude 200K) peuvent accepter des entrées plus volumineuses, mais ils coûtent généralement plus cher par token. Évaluez si l'amélioration de qualité justifie la dépense supplémentaire.
Comment compter les tokens avant d'envoyer une requête ?
tiktoken pour les modèles OpenAI ou l'endpoint de comptage de tokens du fournisseur. Le nombre exact de tokens dépend du tokenizer du modèle, utilisez donc le bon encodeur pour votre modèle cible.Dois-je gérer cette erreur dans le code applicatif ou au niveau de la passerelle ?
Les deux. Le code applicatif doit vérifier en amont la taille de l'entrée et appliquer la stratégie appropriée (tronquer, résumer, découper ou changer). Une passerelle de routage peut en complément sélectionner un modèle dont la fenêtre de contexte est suffisamment grande pour votre requête.


