Le renommage est la partie facile. Ce qui piège les utilisateurs est ce que compte le nouveau champ : max_completion_tokens couvre le raisonnement et la sortie visible. Un budget dimensionné uniquement pour la réponse peut donc revenir vide avec finish_reason "length", tout en étant facturé.
L’erreur
{
"error": {
"message": "Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.",
"type": "invalid_request_error",
"param": "max_tokens",
"code": "unsupported_parameter"
}
}Causes et solutions en bref
| Cause | Solution |
|---|---|
| Les familles de modèles de raisonnement ont remplacé ce champ | Envoyez max_completion_tokens au lieu de max_tokens pour ces modèles. |
| SDK ou wrapper limité à l’ancien champ | Mettez-le à niveau ou définissez explicitement le champ au lieu de passer par l’assistant. |
| Un même chemin de code distribue les requêtes à plusieurs fournisseurs | Normalisez une seule fois à la périphérie au lieu de créer une branche par modèle. |
| Réponse vide après la correction | Le budget inclut les tokens de raisonnement : augmentez-le largement au-dessus de la sortie attendue. |
Renommez le champ
Au point d’appel, il s’agit d’un remplacement direct. Tout le reste de la requête reste inchangé.
# Before
resp = client.chat.completions.create(
model="gpt-5-6-sol", max_tokens=1024, messages=msgs)
# After
resp = client.chat.completions.create(
model="gpt-5-6-sol", max_completion_tokens=1024, messages=msgs)Prévoyez un budget pour le raisonnement invisible
max_completion_tokens plafonne ensemble les tokens de raisonnement et la sortie visible. Si un modèle consomme 900 tokens pour réfléchir sur un plafond de 1 024, il ne vous reste que 124 tokens de réponse — ou un message vide avec finish_reason "length", tout en étant facturé pour l’ensemble. Dimensionnez le budget pour les deux et vérifiez finish_reason avant de faire confiance à une réponse vide.
Normalisez une seule fois au lieu de créer une branche par modèle
Un assistant unique à la périphérie de votre code maintient le reste indépendant du fournisseur et évite que la prochaine famille de modèles nécessite une nouvelle série de modifications.
def token_budget(model: str, n: int) -> dict:
"""One place that knows which spelling a model wants."""
if model.startswith("claude-"):
return {"max_tokens": n}
return {"max_completion_tokens": n}
resp = client.chat.completions.create(
model=model, messages=msgs, **token_budget(model, 4096))Attendez-vous aux rejets des paramètres voisins
Les mêmes familles de modèles qui ont abandonné max_tokens rejettent souvent aussi temperature et top_p. Corriger ce problème fait généralement apparaître le suivant ; supprimez les paramètres d’échantillonnage non pris en charge au lieu de leur attribuer leurs valeurs par défaut.
Si vous appelez via Kunavo
L’API /v1/chat/completions de Kunavo accepte max_tokens sur la famille de modèles de raisonnement GPT-5.x : le traducteur lit l’une ou l’autre des deux écritures que vous envoyez et la mappe vers le champ en amont, tandis que /v1/responses fait l’inverse. Avec ces modèles, vous n’avez donc rien à renommer. Une asymétrie, énoncée clairement : pour les modèles claude-*, le traducteur de chat ne lit actuellement que max_tokens ; utilisez donc cette écriture pour Claude — c’est ce que fait l’aide ci-dessus.
Questions fréquentes
max_completion_tokens est-il simplement un renommage ?
Au niveau de l’appel, oui ; en termes de signification, non : il plafonne ensemble les tokens de raisonnement et la sortie, tandis que max_tokens plafonnait uniquement la sortie visible.
Pourquoi ma réponse est-elle vide après cette correction ?
Le budget a été entièrement consacré au raisonnement. Vérifiez finish_reason : "length" avec un contenu vide signifie qu’il faut augmenter la limite.
Dois-je prévoir une branche par modèle ?
Pas sur Kunavo pour la famille GPT : les deux écritures sont acceptées. Prévoyez une branche uniquement pour les modèles claude-*, ou utilisez partout un utilitaire de normalisation.
Guides associés
- context_length_exceeded / prompt is too long — des correctifs qui n’abrutissent pas votre application
- API compatible OpenAI renvoyant 401/403 — pièges de base_url et des en-têtes
- « Streaming interrupted. Waiting for the complete message » — signification et solution
La sémantique détaillée des erreurs est disponible dans référence des erreurs ; obtenir une clé prend une minute via inscription et la guide d’authentification.