Accueil → Aide

Le modèle renvoie une chaîne vide, mais vous êtes quand même facturé

Sur un modèle de raisonnement, max_tokens plafonne ensemble les tokens de raisonnement et la sortie visible. Si la chaîne de pensée consomme tout le budget, vous obtenez un 200 valide avec un champ content vide, et vous payez chaque token de raisonnement.

Ce que vous voyez

Pourquoi cela arrive

Les modèles de raisonnement émettent deux sortes de tokens de sortie : la chaîne interne et la réponse que vous voyez. La facturation compte les deux. max_tokens limite les deux. Une valeur généreuse pour un modèle sans raisonnement peut être entièrement consommée avant le premier caractère visible.

L'échec est silencieux par conception. L'API a fait ce qu'on lui demandait : générer jusqu'à la limite, puis s'arrêter. finish_reason: "length" est le seul indice, et il passe facilement inaperçu quand votre code lit choices[0].message.content et trouve une chaîne vide anodine.

Nous avons rencontré ce cas sur un outil interne de notation de documents. max_tokens était réglé à 2500 : suffisant pour le modèle précédent, bien trop peu dès que le modèle s'est mis à raisonner d'abord. Pendant un temps, le symptôme ressemblait à un proxy cassé, car les requêtes réussissaient, la latence était normale et le coût bien réel. C'est la facture qui l'a trahi : des débits sans aucun texte correspondant.

Vérifiez si c'est bien la cause

Regardez finish_reason et le décompte des tokens, pas seulement le contenu :

curl -s 'YOUR_BASE_URL/chat/completions' \
  -H 'Authorization: Bearer YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"model":"YOUR_MODEL","max_tokens":64,
       "messages":[{"role":"user","content":"What is 17 * 23? Answer with the number only."}]}' \
  | python3 -m json.tool

"finish_reason": "length" avec un content vide et un nombre de tokens de sortie non nul, c'est la signature. Relancez avec max_tokens à 4000 et le même prompt obtiendra une réponse.

Comment le corriger

  1. Budgétez le raisonnement, pas seulement la réponseUn modèle de raisonnement a besoin de place pour les deux. Si vous voulez une réponse de 200 tokens, laisser 2000 tokens de marge n'est pas excessif — la chaîne est souvent plusieurs fois plus longue que la réponse.
  2. Traitez finish_reason: length comme une erreur dans votre codeNe laissez pas passer une chaîne vide en silence. Faites une branche : relancez avec un budget plus grand ou échouez bruyamment. Cette seule vérification transforme un mystère en une ligne de journal.
  3. Vérifiez si le modèle propose un budget de raisonnement séparéCertains exposent un paramètre dédié pour que la réponse visible ait sa propre allocation. Là où il existe, utilisez-le plutôt que de deviner un seul chiffre combiné.
  4. Comparez avec un modèle sans raisonnement avant d'accuser le réseauSi la même requête renvoie du texte avec un modèle sans raisonnement, le transport fonctionne et c'est le budget qui pose problème.
Chaque requête sur APICLAN affiche dans le journal d'utilisation ses tokens d'entrée, de sortie et de raisonnement, de sorte qu'une réponse vide avec une vraie facture est visible plutôt que mystérieuse. Le comportement de chaque modèle est documenté sur les pages de tarifs.

Voir aussi

Unexpected token '<' lors d'un appel à une API compatible OpenAI401 invalid API key : quand la clé semble correcte mais échoue quand même

Dernière vérification le 2026-10-01. Rédigé à partir de problèmes diagnostiqués sur une passerelle compatible OpenAI en production, pas compilé à partir d'autres sites.