Voltar ao blog

Solução de problemasGuia

Resposta de IA cortada? Corrija finish_reason "length" e max_tokens

Sua resposta da API para no meio da frase ou retorna JSON quebrado? Verifique finish_reason, aumente max_tokens dentro do limite e adicione um passo de continuação.

Por CheapTokens TeamPublicado em 6 min de leitura

Capa em estilo terminal mostrando finish_reason length em uma resposta da API
Nesta página
  1. Como uma resposta cortada aparece na tela
  2. Passo 1: leia o campo que te informa
  3. Passo 2: aumente max_tokens, mas não além do teto
  4. Passo 3: JSON que para no meio
  5. Passo 4: deixe o modelo continuar
  6. Quanto custa uma resposta longa
  7. Antes de publicar: uma checklist curta

Seu script rodou, o modelo respondeu e a função termina no meio de uma linha. Ou o parser JSON lança erro em uma resposta que parece perfeitamente normal. Na maioria das vezes o modelo não falhou: ele atingiu o limite max_tokens que você definiu (ou um padrão que você nunca viu) e a API o interrompeu no meio da palavra.

A correção rápida: leia finish_reason na resposta. Se for "length" (API compatível com OpenAI) ou stop_reason for "max_tokens" (Anthropic Messages), a resposta foi cortada. Aumente max_tokens até o limite de saída do modelo, ou peça ao modelo para continuar. O restante desta página mostra os dois em código que você pode colar.

Se você quer a versão em linguagem simples de por que isso acontece, comece por por que uma resposta de IA para no meio da frase. Esta página é a versão de depuração.

Como uma resposta cortada aparece na tela#

Os sintomas variam conforme o que você pediu, mas a causa é a mesma. Tente associar estes aos que você já viu:

Emparelhar os pares

Associe o sintoma à sua causa provável

  • Uma função termina com return resuA resposta de código atingiu max_tokens no meio da linha
  • json.loads falha com "Unterminated string" ou "Expecting ',' delimiter"O JSON foi cortado no meio
  • Uma tradução para depois da primeira metade do textoO limite de saída é menor que a tradução
  • A resposta está completa e o campo diz stopO modelo terminou sozinho; procure em outro lugar

Essa última linha importa. Se finish_reason for stop, o limite não é o seu problema, e aumentar max_tokens não mudará nada.

Passo 1: leia o campo que te informa#

Toda resposta diz por que a geração terminou. Em uma resposta compatível com OpenAI é choices[0].finish_reason: "stop" quando o modelo terminou, "length" quando ficou sem tokens. Na API Anthropic Messages o campo é stop_reason, e o valor de corte é "max_tokens". O guia de stop-reason da Anthropic (verificado em 28 de outubro de 2026) recomenda exatamente as duas correções abaixo: aumentar max_tokens ou continuar a resposta.

Aqui está a mesma verificação em três formas. A URL base é https://api.cheaptokens.dev/v1 para o SDK da OpenAI e https://api.cheaptokens.dev (sem /v1) para o SDK da Anthropic. O max_tokens=200 é deliberadamente pequeno, para você ver o corte por conta própria.

Uma verificação, três formas

Python (SDK da OpenAI)

python
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 da Anthropic)

python
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

bash
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."}]
  }'

Procure "finish_reason": "length" no JSON que retorna.

Quando funciona como diagnóstico, você verá este par: um limite baixo dá length, um limite folgado dá stop.

Mesma requisição com max_tokens baixo e alto: finish_reason muda de length para stop
Os dois valores de finish_reason que você mais vai encontrar

Passo 2: aumente max_tokens, mas não além do teto#

A correção óbvia é um número maior. O detalhe: cada modelo tem seu próprio limite para a resposta. Não defina um valor acima dele: o limite é por modelo, então confira a tabela abaixo primeiro. Estes são os limites por resposta na CheapTokens (fatos verificados em 28 de outubro de 2026):

Modelo Saída máxima por resposta Contexto
DeepSeek-V4-Flash 32.768 tokens 380K
GLM-5.3-Flash 8.192 tokens 390K
MiniMax-M2.7 8.192 tokens 180K

Uma tradução de 9.000 tokens precisa de um modelo com limite por resposta maior — o DeepSeek-V4-Flash aceita até 32.768 tokens por resposta. Para código longo, JSON longo ou um documento inteiro, deepseek-ai/DeepSeek-V4-Flash-0731 tem mais espaço: até 32.768 tokens por resposta, um preço a qualquer hora do dia. Pegue os ids exatos dos modelos na documentação da CheapTokens e na página de modelos, já que os provedores os nomeiam de forma diferente.

Uma regra prática: defina max_tokens como a resposta mais longa que você aceitaria, não como o máximo. Você paga pelos tokens que o modelo realmente escreve, então um teto alto não custa nada quando as respostas são curtas.

Passo 3: JSON que para no meio#

Uma resposta JSON cortada é o caso mais chato, porque o texto parece certo até o parser chegar ao fim. Digamos que você extraia campos de 40 notas fiscais em uma chamada e peça um array. O modelo escreve 31 objetos, atinge o limite e o array nunca fecha.

Um erro de json.loads em um array cortado no limite de tokens
Como um array JSON truncado aparece em um parser

Não tente reparar a string adicionando ]}. Você obterá JSON válido com registros faltando, o que é pior que um erro. Verifique finish_reason primeiro; se for length, aumente o limite e execute a chamada de novo, ou divida a entrada em lotes menores. Para forçar o formato em si, veja JSON válido de uma API de LLM.

Passo 4: deixe o modelo continuar#

Às vezes a resposta é genuinamente maior que qualquer limite: um capítulo de livro, uma refatoração grande. Então devolva o que você tem e peça ao modelo para continuar. O loop abaixo mantém o texto obtido até agora, pede o restante e desiste após algumas rodadas para que um bug não gire para sempre.

python
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 rounds

Dois hábitos mantêm isso honesto. Retorne o flag True/False e mostre um aviso ao usuário em False, em vez de apresentar meio documento como concluído. E lembre-se de que cada rodada reenvia o texto anterior como entrada, então uma resposta continuada custa mais que uma resposta grande única. Para dados estruturados, prefira um limite maior ou lotes menores a continuar.

Quanto custa uma resposta longa#

Digamos que uma resposta longa tenha 2.000 tokens de entrada e 8.000 tokens de saída. No DeepSeek-V4-Flash essa requisição custa $0.00083 pelo preço de hoje, e no total, com entrada e saída contadas juntas, sai mais barato que na OpenRouter. Troque os números pela sua própria carga:

Calculadora de custos

Um dia de 50 respostas longas

Tokens de entrada por solicitação: 2.000 · Tokens de saída por solicitação: 8.000 · Solicitações por dia: 50

ModeloPor diaPor mês
GLM-5.3-Flash$0.018$0.54
DeepSeek-V4-Flash$0.0415$1.25
MiniMax-M2.7$0.065$1.95

A conclusão: o lado da saída domina neste cenário, então folga em max_tokens é um seguro barato contra uma nova execução. Uma resposta cortada que você precisa regenerar é paga duas vezes. Contexto sobre os dois lados da conta está em tokens de entrada vs saída, e a lista completa de modelos com preços está na página de preços.

Antes de publicar: uma checklist curta#

Lista de verificação

Checklist de truncamento para o seu código