Kılavuzlara dön
Sorun giderme·17 Temmuz 2026·6 dk okuma

LLM akış hataları — SSE kesilmeleri, takılan akışlar ve eksik kullanım bilgileri

Akış hatalarının nedeni nadiren modeldir — sorun sizinle model arasındaki bağlantı altyapısıdır. Boşta kalma zaman aşımı uygulayan proxy'ler sessiz bağlantıları sonlandırır, nginx arabelleğe alarak olayları yutar ve yarım tüketilmiş akışlar “API yanıt vermeyi kesti” gibi görünür. Önce bağlantı altyapısını kontrol edin.

Son inceleme tarihi: .

Akış hatalarının nedeni nadiren modeldir — sorun sizinle model arasındaki bağlantı altyapısıdır. Boşta kalma zaman aşımı uygulayan proxy'ler sessiz bağlantıları sonlandırır, nginx arabelleğe alarak olayları yutar ve yarım tüketilmiş akışlar “API yanıt vermeyi kesti” gibi görünür. Önce bağlantı altyapısını kontrol edin.

Hata

symptoms
- Stream stops mid-sentence, connection closed (no error event)
- Client hangs after the last token, never sees [DONE]
- usage is null on streamed responses
- Works in curl, dies behind nginx / a corporate proxy

Nedenler ve çözümler özeti

NedenÇözüm
Proxy/yük dengeleyici boşta kalma zaman aşımı (birçok kurulumda varsayılan 60 sn)API yolunun okuma zaman aşımlarını artırın; uzun düşünme duraklamaları proxy'ye boşta kalmış gibi görünür.
SSE'nin önünde arabelleğe alma (nginx proxy_buffering, bazı CDN'ler)Akış rotası için arabelleğe almayı devre dışı bırakın (X-Accel-Buffering: no / proxy_buffering off).
İstemci tüketmeyi durduruyor (await eksik, yineleyici bırakılmış)Sonuna kadar tüketin veya açıkça kapatın — akışın ortasında GC tarafından toplanan bir yineleyici, kesilmeyle ayırt edilemez.
İstemeden kullanım bilgisi beklemekOpenAI-wire: stream_options: {"include_usage": true} gönderin — kullanım bilgisi son parçada gelir.

curl -N ile doğrudan API'ye bağlanarak yeniden üretin

Her proxy'yi devre dışı bırakın. Ham SSE tüm üretim boyunca sorunsuz akıyorsa sorun uygulamanızın yolundadır — atlamaları tek tek yeniden ekleyin:

raw-stream.sh
curl -N https://api.kunavo.com/v1/chat/completions \
  -H "Authorization: Bearer $KUNAVO_API_KEY" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-5","stream":true,
       "stream_options":{"include_usage":true},
       "max_tokens":300,
       "messages":[{"role":"user","content":"Count slowly to 20 in words."}]}'

Soruna neden olan atlamayı düzeltin

nginx: rota için proxy_buffering off + proxy_read_timeout 300s. Sunucusuz ortam: platformun yanıt akışı sınırlarını kontrol edin. Kurumsal proxy'ler: bazıları SSE'yi hiç desteklemez — orada akışsız moda geçin.

Son kısmı doğru ele alın

Akışlı faturalandırma verileri en son gelir: son parça (istenmişse) [DONE] öncesinde kullanım bilgisini taşır. Farkları toplayın, kullanımı son parçadan okuyun ve erken kapanmayı (finish_reason yoksa) yeniden denenebilir kabul edin.

“SSE akışı [DONE] olmadan sona erdi” — yanıtın tamamı geldi mi?

Bu ileti, API'nin gönderdiği bir hata değil, istemcinizin kendi kontrolüdür: OpenAI uyumlu bir akışın sona erdiği data: [DONE] satırından önce bağlantı kapanmıştır. Buna üç şey neden olur: aradaki bir atlama bağlantıyı kapatmıştır (yukarıdaki proxy zaman aşımı ve arabelleğe alma nedenleri); sunucu yanıtın ortasında başarısız olmuş ve sonlandırıcı çerçeve olmadan kapanmıştır; ya da yanıt tamamlanmış, yalnızca işaretleyici kaybolmuştur. Hangisi olduğunu aldığınız son parça belirler: orada finish_reason varsa metin bütündür; finish_reason yoksa kesilmiştir ve yeniden denenmelidir. Bu kontrolü SDK'ye bırakmayın — OpenAI Python SDK, bağlantı [DONE] olmadan kapandığında döngüsünü sessizce bitirir ve yalnızca bir parça hata nesnesi taşıdığında istisna oluşturur. Kontrolü kendi kodunuza ekleyin:

stream_check.py
from openai import OpenAI

client = OpenAI(base_url="https://api.kunavo.com/v1", api_key="sk-kn-...")

finish_reason, parts = None, []
stream = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[{"role": "user", "content": "Count slowly to 20 in words."}],
    stream=True,
)
for chunk in stream:  # raises openai.APIError on a chunk that carries "error"
    for choice in chunk.choices:
        parts.append(choice.delta.content or "")
        finish_reason = choice.finish_reason or finish_reason

if finish_reason is None:
    raise RuntimeError("stream closed without a finish_reason: cut off, retry it")
print("".join(parts))

Boş bir akış: 200, sonra hiçbir şey yok

Bazen akış HTTP 200 ile açılır ve tek bir içerik parçası olmadan sona erer — metin yoktur, araç çağrısı yoktur, bazen rol parçası bile yoktur. Bu neredeyse her zaman başlıklar gönderildikten sonra başarısız olan bir üst akıştır: aşırı yüklenmiş bir sağlayıcı, kendi üst akışının isteği reddettiği bir ağ geçidi veya gövdeyi düşüren bir proxy. Bunu kesilmiş akış gibi ele alın ve geri çekilmeyle yeniden deneyin; ayrıca başarısız bir yanıtın ham gövdesini kaydedin, çünkü neden çoğu zaman SDK'nizin atladığı akış içindeki bir hata olayıdır. Claude Code aynı durumda isteği akış olmadan yeniden dener.

Kunavo üzerinden çağrı yapıyorsanız

Kunavo, /v1/messages üzerinde stream_options.include_usage desteğiyle standart OpenAI-wire SSE'sini ve Anthropic-wire olaylarını sunar; dolayısıyla yukarıdaki curl ile yeniden üretim aynı zamanda uyumluluk testidir. /v1/chat/completions üzerindeki Claude ve GPT modelleri için Kunavo akışı, yanıt tamamlanmış olsun ya da olmasın data: [DONE] ile sona erer: tamamlandıysa finish_reason parçasından sonra, üst akış yanıtın ortasında koptuysa type upstream_error, code upstream_disconnect veya upstream_timeout taşıyan bir hata parçasından sonra. Böylece OpenAI SDK'leri bir APIError oluşturur ve parçayı bütün yanıt olarak size teslim etmez. Üst akış, herhangi bir içerikten önce sona ererse veya ilk token'dan önce başarısız olursa size boş bir 200 olarak ulaşmaz: modelin birden fazla kanalı varsa deneme başka bir kanalda tekrarlanır; yoksa HTTP hatası olarak döndürülür. Çıktı oluşmadan önce başarısız olan akışlı istek faturalandırılmaz; yanıtın ortasında bozulan istek için bu garanti edilmez — ücretsiz olduğunu varsaymak yerine yeniden gönderin.

Sık sorulan sorular

Akışlı yanıtlarımda kullanım neden null?

OpenAI-wire API'lerinde stream_options: {"include_usage": true} göndermediğiniz sürece kullanım bilgisi akışlara dahil edilmez; gönderildiğinde son parçada gelir. Anthropic'in kendi akışı kullanımı message_start/message_delta olaylarında bildirir.

Kesilen bir akışla tamamlanan bir akışı nasıl ayırt ederim?

Tamamlanan akış finish_reason (veya Anthropic'te message_stop) ile sona erer ve ardından [DONE] gelir. Bu işaretler olmadan kapanan bağlantı kesilmiştir — kısa bir yanıt değil, yeniden denenebilir bir hata olarak ele alın.

“SSE akışı [DONE] olmadan sona erdi” ne anlama gelir?

İstemciniz bağlantının sonuna kadar akışı okudu ve OpenAI uyumlu akışı kapatan data: [DONE] satırını hiç görmedi. Bu iletiyi API göndermedi; istemciniz veya ajanınız yazdı. Son parça finish_reason taşıyorsa yanıt tamamdır ve yalnızca kapanış kaybolmuştur. Taşımıyorsa yanıt bir proxy, zaman aşımı veya sunucu tarafı hatası nedeniyle kesilmiştir ve istek yeniden denenmelidir.

“Akış finish_reason olmadan sona erdi” ne anlama gelir?

İstemci akışın sonuna kadar okudu ve hiçbir parça finish_reason taşımıyordu — bu, OpenAI uyumlu bir akışın yanıtın tamamlandığını belirtmek için kullandığı alandır (stop, length, tool_calls). Bu alan olmadan, son cümlesi ne kadar doğal görünürse görünsün elinizdeki metin bir parçadır. İsteği yeniden deneyin; tekrarlanırsa aranızdaki proxy'de zaman aşımı veya arabelleğe alma olup olmadığını kontrol edin.

Bir LLM API'si neden boş akış döndürür?

Çünkü hata HTTP başlıkları gönderildikten sonra meydana gelmiştir: sağlayıcı aşırı yüklenmiştir, bir ağ geçidinin üst akışı isteği reddetmiştir veya bir proxy gövdeyi düşürmüştür. Durum satırı hâlâ 200 dediği için yalnızca durum kontrolleri bunu yakalayamaz. İçerik parçası olmayan akışı başarısız istek olarak ele alın, geri çekilmeyle yeniden deneyin ve içindeki hata olayını bulmak için bir ham yanıtı kaydedin.

Metin aldıysam eksik [DONE] işaretini yok saymak güvenli mi?

Yalnızca son parça finish_reason taşıyorsa. Bu yoksa elinizdeki metin, cümlenin ortasında veya JSON bağımlı argümanları tamamlanmamış bir araç çağrısının ortasında bitebilecek bir parçadır. Yanıt olarak kaydetmek yerine yeniden deneyin.

İlgili kılavuzlar

Hata anlamlarına ilişkin daha fazla bilgi hata referansı bölümünde; anahtar almak kayıt ve kimlik doğrulama kılavuzu üzerinden bir dakika sürer.