Sorun gidermeKılavuz
AI yanıtı kesildi mi? finish_reason "length" ve max_tokens sorununu düzeltin
API yanıtınız cümle ortasında mı duruyor ya da bozuk JSON mu döndürüyor? finish_reason alanını kontrol edin, max_tokens değerini sınır içinde yükseltin ve bir devam adımı ekleyin.

Bu sayfada
Betiğiniz çalıştı, model yanıt verdi ve fonksiyon bir satırın ortasında bitiyor. Ya da JSON ayrıştırıcısı tamamen normal görünen bir yanıtta hata fırlatıyor. Çoğu zaman model başarısız olmadı: sizin belirlediğiniz (ya da hiç görmediğiniz bir varsayılan) max_tokens sınırına takıldı ve API onu kelimenin ortasında durdurdu.
Hızlı çözüm: yanıttaki finish_reason alanını okuyun. "length" ise (OpenAI uyumlu API) ya da stop_reason değeri "max_tokens" ise (Anthropic Messages), yanıt kesilmiştir. max_tokens değerini modelin çıktı sınırına kadar yükseltin ya da modelden devam etmesini isteyin. Bu sayfanın geri kalanı her ikisini de kopyalayıp yapıştırabileceğiniz kodla gösteriyor.
Bunun neden olduğunun sade bir dille anlatımını istiyorsanız, bir AI yanıtı neden cümle ortasında durur yazısıyla başlayın. Bu sayfa hata ayıklama sürümüdür.
Kesilmiş bir yanıt ekranda nasıl görünür#
Belirtiler ne istediğinize göre değişir, ama neden aynıdır. Bunları gördüklerinizle eşleştirmeyi deneyin:
Eşleştir
Belirtiyi olası nedeniyle eşleştirin
Soldaki bir öğeye, ardından eşine dokun
- Bir fonksiyon
return resuile bitiyorKod yanıtı satır ortasında max_tokens sınırına takıldı json.loads"Unterminated string" veya "Expecting ',' delimiter" hatasıyla başarısız oluyorJSON yarıda kesildi- Bir çeviri metnin ilk yarısından sonra duruyorÇıktı sınırı çeviriden küçük
- Yanıt tam ve alan
stopdiyorModel kendi kendine bitirdi; başka yere bakın
Son satır önemli. finish_reason değeri stop ise sorununuz sınır değildir ve max_tokens değerini yükseltmek hiçbir şeyi değiştirmez.
Adım 1: size söyleyen alanı okuyun#
Her yanıt üretimin neden sona erdiğini söyler. OpenAI uyumlu bir yanıtta bu alan choices[0].: model bitirdiğinde "stop", tokenları tükendiğinde "length". Anthropic Messages API'sinde alan stop_reason ve kesilme değeri "max_tokens". Anthropic'in stop-reason kılavuzu (28 Ekim 2026'da kontrol edildi) tam olarak aşağıdaki iki düzeltmeyi öneriyor: max_tokens değerini yükseltin ya da yanıta devam edin.
Aynı kontrol üç biçimde. Temel URL, OpenAI SDK için https:/ ve Anthropic SDK için https:/ (/v1 olmadan). max_tokens=200 kasıtlı olarak küçük, böylece kesilmeyi kendiniz görebilirsiniz.
Tek kontrol, üç yol
Python (OpenAI SDK)
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 (Anthropic SDK)
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."}]
}'Geri gelen JSON'da "finish_ alanına bakın.
Bir teşhis olarak çalıştığında şu çifti görürsünüz: düşük bir sınır length verir, geniş bir sınır stop verir.

Adım 2: max_tokens değerini yükseltin, ama tavanı aşmayın#
Bariz düzeltme daha büyük bir sayıdır. İşin püf noktası: her modelin yanıt için kendi üst sınırı vardır. Bunun üzerinde bir değer ayarlamayın: sınır modele özgüdür, bu yüzden önce aşağıdaki tabloya bakın. Bunlar CheapTokens'teki yanıt başına sınırlardır (bilgiler 28 Ekim 2026'da kontrol edildi):
Tabloyu sağa kaydırın →
| Model | Yanıt başına maksimum çıktı | Bağlam |
|---|---|---|
| DeepSeek-V4-Flash | 32.768 token | 380K |
| GLM-5.3-Flash | 8.192 token | 390K |
| MiniMax-M2.7 | 8.192 token | 180K |
9.000 token'lık bir çeviri, yanıt başına sınırı daha büyük bir model gerektirir — DeepSeek-V4-Flash yanıt başına 32.768 token'a kadar alır. Uzun kod, uzun JSON veya bütün bir belge için deepseek- en fazla alana sahiptir: yanıt başına 32.768 token'a kadar, günün her saatinde tek fiyat. Sağlayıcılar bunları farklı adlandırdığı için tam model kimliklerini CheapTokens belgelerinden ve modeller sayfasından alın.
Pratik bir kural: max_tokens değerini kabul edeceğiniz en uzun yanıta ayarlayın, maksimuma değil. Modelin gerçekte yazdığı tokenlar için ödeme yaparsınız, bu yüzden yanıtlar kısa olduğunda yüksek bir tavan hiçbir maliyet getirmez.
Adım 3: yarıda duran JSON#
Kesilmiş bir JSON yanıtı en kötü durumdur, çünkü metin ayrıştırıcı sona ulaşana kadar doğru görünür. Tek bir çağrıda 40 faturadan alan çıkardığınızı ve bir dizi istediğinizi varsayalım. Model 31 nesne yazar, sınıra ulaşır ve dizi hiç kapanmaz.

Dizeyi ]} ekleyerek onarmaya çalışmayın. Eksik kayıtlarla geçerli JSON elde edersiniz, bu da bir hatadan daha kötüdür. Önce finish_reason alanını kontrol edin; length ise ya sınırı yükseltip çağrıyı yeniden çalıştırın ya da girdiyi daha küçük gruplara bölün. Biçimi zorlamanın kendisi için bir LLM API'sinden geçerli JSON yazısına bakın.
Adım 4: modelin devam etmesine izin verin#
Bazen yanıt gerçekten herhangi bir sınırdan uzundur: bir kitap bölümü, büyük bir yeniden düzenleme. O zaman elinizdekini geri besleyin ve modelden devam etmesini isteyin. Aşağıdaki döngü şu ana kadarki metni tutar, geri kalanını ister ve bir hata sonsuza kadar dönmesin diye birkaç turdan sonra vazgeçer.
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İki alışkanlık bunu dürüst tutar. True/False bayrağını döndürün ve yarım bir belgeyi tamamlanmış gibi sunmak yerine False durumunda kullanıcıya bir uyarı gösterin. Ve her turun önceki metni girdi olarak yeniden gönderdiğini unutmayın, bu yüzden devam ettirilen bir yanıt tek büyük yanıttan daha pahalıdır. Yapılandırılmış veriler için devam ettirmek yerine daha büyük bir sınırı veya daha küçük grupları tercih edin.
Uzun bir yanıtın maliyeti#
Uzun bir yanıtın 2.000 token girdi ve 8.000 token çıktı olduğunu varsayalım. DeepSeek-V4-Flash'te bu istek bugünkü fiyatla $0.00083 tutar ve girdi ile çıktı birlikte sayıldığında toplamda OpenRouter'dan daha ucuzdur. Sayıları kendi yükünüze göre değiştirin:
Maliyet hesaplayıcı
Günde 50 uzun yanıt
İstek başına giriş token'ı: 2.000 · İstek başına çıkış token'ı: 8.000 · Günlük istek sayısı: 50
| Model | Günlük | Aylık |
|---|---|---|
| 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 |
Çıkarım: bu senaryoda çıktı tarafı baskındır, bu yüzden max_tokens içindeki pay, yeniden çalıştırmaya karşı ucuz bir sigortadır. Yeniden üretmeniz gereken kesilmiş bir yanıtın bedeli iki kez ödenir. Faturanın iki tarafı hakkında arka plan bilgisi girdi ve çıktı tokenları yazısında, fiyatlarıyla birlikte tam model listesi ise fiyatlandırma sayfasında.
Yayına almadan önce: kısa bir kontrol listesi#
Kontrol listesi
Kodunuz için kesilme kontrol listesi



