Risposta AI troncata? Correggi finish_reason "length" e max_tokens
La tua risposta API si interrompe a metà frase o restituisce JSON rotto? Controlla finish_reason, aumenta max_tokens entro il limite e aggiungi un passo di continuazione.

In questa pagina
Il tuo script è stato eseguito, il modello ha risposto e la funzione termina a metà riga. Oppure il parser JSON va in errore su una risposta dall'aspetto del tutto normale. Il più delle volte il modello non ha fallito: ha raggiunto il limite max_tokens che hai impostato (o un default che non hai mai visto) e l'API lo ha interrotto a metà parola.
La soluzione rapida: leggi finish_reason nella risposta. Se è "length" (API compatibile OpenAI) o stop_reason è "max_tokens" (Anthropic Messages), la risposta è stata troncata. Aumenta max_tokens fino al limite di output del modello, oppure chiedi al modello di continuare. Il resto di questa pagina mostra entrambe le cose in codice che puoi incollare.
Se vuoi la versione in linguaggio semplice del perché accade, inizia da perché una risposta AI si interrompe a metà frase. Questa pagina è la versione per il debug.
Come appare a schermo una risposta troncata#
I sintomi variano in base a cosa hai chiesto, ma la causa è la stessa. Prova ad associare questi casi a ciò che hai visto:
Abbina le coppie
Associa il sintomo alla sua probabile causa
Tocca un elemento a sinistra, poi il suo abbinamento
- Una funzione termina con
return resuLa risposta di codice ha raggiunto max_tokens a metà riga json.loadsfallisce con "Unterminated string" o "Expecting ',' delimiter"Il JSON è stato troncato a metà- Una traduzione si ferma dopo la prima metà del testoIl limite di output è inferiore alla traduzione
- La risposta è completa e il campo indica
stopIl modello ha terminato da solo; cerca altrove
L'ultima riga è importante. Se finish_reason è stop, il limite non è il tuo problema, e aumentare max_tokens non cambierà nulla.
Passo 1: leggi il campo che te lo dice#
Ogni risposta indica perché la generazione è terminata. In una risposta compatibile OpenAI è choices[0].: "stop" quando il modello ha finito, "length" quando ha esaurito i token. Nell'API Anthropic Messages il campo è stop_reason, e il valore di troncamento è "max_tokens". La guida agli stop reason di Anthropic (verificata il 28 ottobre 2026) consiglia esattamente le due correzioni seguenti: aumentare max_tokens o continuare la risposta.
Ecco lo stesso controllo in tre forme. La base URL è https:/ per l'SDK OpenAI e https:/ (senza /v1) per l'SDK Anthropic. Il valore max_tokens=200 è volutamente piccolo, così puoi vedere il troncamento con i tuoi occhi.
Un controllo, tre modi
Python (SDK OpenAI)
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
resp = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
max_tokens=200,
messages=[{"role": "user", "content": "Write a Python class for a todo list with tests."}],
)
choice = resp.choices[0]
if choice.finish_reason == "length":
print("Cut off at the token limit")
print(choice.message.content)
print(resp.usage.completion_tokens)Python (SDK Anthropic)
import os
import anthropic
client = anthropic.Anthropic(
base_url="https://api.cheaptokens.dev",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
msg = client.messages.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
max_tokens=200,
messages=[{"role": "user", "content": "Write a Python class for a todo list with tests."}],
)
if msg.stop_reason == "max_tokens":
print("Cut off at the token limit")
print(msg.content[0].text)curl
curl https://api.cheaptokens.dev/v1/chat/completions \
-H "Authorization: Bearer $CHEAPTOKENS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-ai/DeepSeek-V4-Flash-0731",
"max_tokens": 200,
"messages": [{"role": "user", "content": "Write a Python class for a todo list with tests."}]
}'Cerca "finish_ nel JSON che ritorna.
Quando funziona come diagnosi, vedrai questa coppia: un limite basso dà length, un limite ampio dà stop.

Passo 2: aumenta max_tokens, ma non oltre il tetto#
La correzione ovvia è un numero più grande. Il problema: ogni modello ha il proprio limite sulla risposta. Non impostare un valore superiore: il limite è per modello, quindi controlla prima la tabella qui sotto. Questi sono i limiti per risposta su CheapTokens (dati verificati il 28 ottobre 2026):
Scorri la tabella verso destra →
| Modello | Output massimo per risposta | Contesto |
|---|---|---|
| DeepSeek-V4-Flash | 32.768 token | 380K |
| GLM-5.3-Flash | 8.192 token | 390K |
| MiniMax-M2.7 | 8.192 token | 180K |
Una traduzione da 9.000 token richiede un modello con un limite per risposta più ampio — DeepSeek-V4-Flash arriva fino a 32.768 token per risposta. Per codice lungo, JSON lungo o un intero documento, deepseek- ha più spazio: fino a 32.768 token per risposta, un unico prezzo a qualsiasi ora del giorno. Prendi gli id esatti dei modelli dalla documentazione CheapTokens e dalla pagina dei modelli, dato che i provider li denominano in modo diverso.
Una regola pratica: imposta max_tokens alla risposta più lunga che accetteresti, non al massimo. Paghi i token che il modello scrive davvero, quindi un tetto alto non costa nulla quando le risposte sono brevi.
Passo 3: JSON che si interrompe a metà#
Una risposta JSON troncata è il caso peggiore, perché il testo sembra corretto finché il parser non arriva alla fine. Supponi di estrarre campi da 40 fatture in un'unica chiamata e di chiedere un array. Il modello scrive 31 oggetti, raggiunge il limite e l'array non si chiude mai.

Non provare a riparare la stringa aggiungendo ]}. Otterrai JSON valido con record mancanti, che è peggio di un errore. Controlla prima finish_reason; se è length, aumenta il limite e riesegui la chiamata, oppure suddividi l'input in batch più piccoli. Per forzare il formato stesso, vedi JSON valido da un'API LLM.
Passo 4: lascia che il modello continui#
A volte la risposta è davvero più lunga di qualsiasi limite: un capitolo di un libro, un grande refactoring. Allora rimanda al modello ciò che hai e chiedigli di proseguire. Il ciclo qui sotto conserva il testo ottenuto finora, chiede il resto e si ferma dopo qualche giro, così un bug non può girare all'infinito.
def complete(base_messages, model, max_tokens=4096, rounds=4):
text = ""
for _ in range(rounds):
messages = list(base_messages)
if text:
messages += [
{"role": "assistant", "content": text},
{"role": "user", "content": "Continue exactly where you stopped. Do not repeat anything."},
]
r = client.chat.completions.create(model=model, max_tokens=max_tokens, messages=messages)
choice = r.choices[0]
text += choice.message.content or ""
if choice.finish_reason != "length":
return text, True # finished on its own
return text, False # still cut after all roundsDue abitudini mantengono tutto onesto. Restituisci il flag True/False e mostra all'utente un avviso su False, invece di presentare mezzo documento come finito. E ricorda che ogni giro rimanda il testo precedente come input, quindi una risposta continuata costa più di una risposta unica e grande. Per i dati strutturati, preferisci un limite più alto o batch più piccoli rispetto alla continuazione.
Quanto costa una risposta lunga#
Supponi che una risposta lunga sia 2.000 token in input e 8.000 token in output. Su DeepSeek-V4-Flash quella richiesta costa $0.00083 al prezzo odierno, e in totale, contando insieme input e output, è più economica di OpenRouter. Cambia i numeri con il tuo carico:
Calcolatore di costi
Una giornata di 50 risposte lunghe
Token di input per richiesta: 2000 · Token di output per richiesta: 8000 · Richieste al giorno: 50
| Modello | Al giorno | Al mese |
|---|---|---|
| GLM-5.3-Flash$0.02$0.04 | $0.018 | $0.54 |
| DeepSeek-V4-Flash$0.015$0.10 | $0.0415 | $1.25 |
| MiniMax-M2.7$0.05$0.15 | $0.065 | $1.95 |
La conclusione: in questo scenario domina il lato output, quindi un margine in max_tokens è un'assicurazione economica contro una nuova esecuzione. Una risposta troncata che devi rigenerare la paghi due volte. Il contesto sui due lati del conto è in token di input vs output, e l'elenco completo dei modelli con i prezzi è nella pagina dei prezzi.
Prima di rilasciare: una breve checklist#
Lista di controllo
Checklist sul troncamento per il tuo codice



