İçeriğe geç
Akış

Akış

stream değerini true yapın; yanıt, model yazarken server-sent events olarak gelir: önce akıl yürütme, sonra yanıt, sonra bitiş nedeni ve kullanım bilgisini içeren son bir chunk. Metni bir kişi beklerken ve uzun yanıtlarda kullanın.

POST https://api.shannon-ai.com/v1/chat/completions

OpenAI SDK'ları chunk'ları size tek tek verir. Her chunk'ı taşıdığına göre okuyun: bir akıl yürütme parçası, bir yanıt parçası, bir araç çağrısı ya da yanıtın sonu.

from openai import OpenAI, APIError

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.shannon-ai.com/v1",
)

stream = client.chat.completions.create(
    model="shannon-3",
    messages=[{"role": "user", "content": "Explain server-sent events in three sentences."}],
    stream=True,
)

answer, reasoning, tool_calls = [], [], []
finish_reason = usage = None

try:
    for chunk in stream:
        if chunk.usage:
            usage = chunk.usage
        if not chunk.choices:
            continue
        choice = chunk.choices[0]
        delta = choice.delta

        thought = getattr(delta, "reasoning_content", None)
        if thought:
            reasoning.append(thought)
        if delta.content:
            answer.append(delta.content)
            print(delta.content, end="", flush=True)
        for call in delta.tool_calls or []:
            tool_calls.append((call.id, call.function.name, call.function.arguments))
        if choice.finish_reason:
            finish_reason = choice.finish_reason
except APIError as error:
    # A failure after the stream started arrives as an error chunk.
    print(f"\nstream failed: {error}")

print(f"\n{finish_reason} {usage}")

Bir stream nasıl çerçevelenir

  • Yanıtın durumu 200 olur ve başlıkları content-type: text/event-stream ile cache-control: no-cache olur.
  • Her olay data: ile başlayan ve ardından boş bir satır gelen tek bir satırdır. data: sonrasındaki metin bir JSON chunk'tır. event: veya id: satırları yoktur.
  • : ping gibi iki nokta üst üste ile başlayan satır, bağlantıyı açık tutan bir yorumdur. Atlayın.
  • Stream data: [DONE] ile biter. Onsuz duran bir stream eksiktir.

Sırayla chunk'lar

Her chunk bir chat.completion.chunk nesnesidir:

JSON
{
  "id": "chatcmpl-5f0c1e7a9b3d4c62a8e1f07d2b46c9a3",
  "object": "chat.completion.chunk",
  "created": 1791625200,
  "model": "shannon-3",
  "choices": [
    {
      "index": 0,
      "delta": {
        "content": "Server-sent"
      },
      "finish_reason": null
    }
  ]
}

Bir stream'in tüm chunk'ları aynı id, created ve model değerlerini taşır. choices her zaman tek girdi içerir. delta yeni olanı içerir ve finish_reason son chunk'a kadar null olur.

Delta'daki anahtar Tür Açıklama Gönderen
role string Her zaman assistant. Stream'in başında bir kez gelir. Host edilen açık ağırlıklı modeller, shannon-2-lite, shannon-2-pro
reasoning_content string Modelin akıl yürütmesinden bir parça. Parçaları sırayla birleştirin. Host edilen açık ağırlıklı modeller, Shannon 3 ailesi, shannon-1.6-pro, shannon-coder-1
content string Yanıttan bir parça. Parçaları sırayla birleştirin. Tüm modeller
tool_calls array Eksiksiz bir araç çağrısı. Araç çağrısı delta'larına bakın. Tüm modeller

Önce akıl yürütme, sonra yanıt, sonra varsa araç çağrıları gelir. Bir chunk'ı stream içindeki yerine göre değil, delta içindeki anahtarlara göre okuyun: bir delta, ilk metin parçasıyla birlikte role içerebilir ve sonuncusu boştur.

Yolculuk ettiği haliyle bir stream'in tamamı. Satırları kısa tutmak için burada her chunk'tan id, object, created ve model çıkarılmıştır.

200 text/event-stream
data: {"choices":[{"index":0,"delta":{"reasoning_content":"Three sentences:"},"finish_reason":null}]}

data: {"choices":[{"index":0,"delta":{"reasoning_content":" what it is, how it is framed, why it is used."},"finish_reason":null}]}

: ping

data: {"choices":[{"index":0,"delta":{"content":"Server-sent"},"finish_reason":null}]}

data: {"choices":[{"index":0,"delta":{"content":" events let a server push text to a client over one HTTP reply."},"finish_reason":null}]}

data: {"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":1190,"completion_tokens":84,"total_tokens":1274}}

data: [DONE]

Akıl yürütme delta'ları

Akıl yürüten bir model, akıl yürütmesini yanıttan önce delta.reasoning_content içinde gönderir. İki metni ayrı tutun: akıl yürütmeyi ayrı, katlanabilir bir bölüm olarak gösterin ya da bırakın.

Host edilen açık ağırlıklı modeller, reasoning_effort değeri off olduğunda akıl yürütme göndermez; istekte bir response_format varsa da göndermez.

shannon-2-lite ve shannon-2-pro da yanıt vermeden önce akıl yürütür. Bu uç noktada akıl yürütürken : thinking yorum satırları, sonra yanıtı gönderirler.

reasoning_content, OpenAI SDK'larının tipli modellerinde yoktur. Python'da getattr(delta, "reasoning_content", None) ile okuyun; JavaScript'te delta.reasoning_content olduğu gibi çalışır.

Araç çağrısı delta'ları

Bir araç çağrısı bütün olarak gelir: çağrı başına bir chunk; delta alanı çağrıyı eksiksiz arguments dizesiyle içerir. index, yanıtın çağrılarını 0'dan başlayarak numaralandırır. arguments değerini parça parça birleştiren kod değişmeden çalışır, çünkü tek bir parçayı birleştirir.

delta
{
  "tool_calls": [
    {
      "index": 0,
      "id": "call_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
      "type": "function",
      "function": {
        "name": "get_weather",
        "arguments": "{\"city\":\"Paris\"}"
      }
    }
  ]
}

Çağrılardan sonra son chunk'ın finish_reason değeri tool_calls olur.

İstekte tools olduğunda shannon-1.6-lite, shannon-1.6-pro ve shannon-coder-1 yanıt metnini yanıtın sonunda tek bir delta olarak gönderir.

Son chunk

data: [DONE] öncesindeki son chunk'ta boş bir delta, finish_reason ve isteğin usage bilgisi aynı chunk içinde bulunur. Her stream'de vardır; stream_options gerekmez.

JSON
{
  "id": "chatcmpl-5f0c1e7a9b3d4c62a8e1f07d2b46c9a3",
  "object": "chat.completion.chunk",
  "created": 1791625200,
  "model": "shannon-3",
  "choices": [
    {
      "index": 0,
      "delta": {},
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 1190,
    "completion_tokens": 84,
    "total_tokens": 1274
  }
}

Host edilen açık ağırlıklı modellerde usage ayrıca prompt_tokens_details.cached_tokens ve completion_tokens_details.reasoning_tokens içerir.

Araması bir şey bulmuş, web_search: true içeren bir istekten sonra son chunk ayrıca sources taşır, ondan önceki bir chunk ise alıntı işaretlerini delta.annotations olarak taşır. Yerleşik Web Arama

finish_reason Açıklama Gönderen
stop Model yanıtını bitirdi ya da bir stop dizesi göründü. Tüm modeller
tool_calls Yanıt bir veya daha fazla araç çağrısı içeriyor. Tüm modeller
length Yanıt çıktı sınırında kesildi. Shannon 3 ailesi, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1

usage alanları uç nokta ile birlikte anlatılır. Chat Completions

Keep-alive satırları

Model çalışırken ve henüz gönderecek bir şeyi yokken stream yorum satırları taşır. Veri içermezler. Bir SSE ayrıştırıcısı onları kendiliğinden atlar; ham satırları okuyan kod, iki nokta üst üste ile başlayan her satırı atlamalıdır.

Satır Gönderen Ne zaman
: ping Shannon 3 ailesi, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 Her 15 saniyede bir.
: keepalive Host edilen açık ağırlıklı modeller Model çalışırken her 15 saniyede bir.
: thinking shannon-2-lite, shannon-2-pro Model akıl yürütürken.

Bir stream içindeki hatalar

Bir stream başladıktan sonra durumu 200'dür; bu yüzden bir başarısızlık stream'in içinde, choices olması gereken yerde bir error üyesi olan bir chunk olarak gelir.

200 text/event-stream
data: {"error":{"message":"The model backend failed to answer. Please retry.","type":"api_error","code":null,"param":null}}

data: {"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":1190,"completion_tokens":12,"total_tokens":1202}}

data: [DONE]

Hata chunk'ından sonra, finish_reason ve usage içeren son chunk ile data: [DONE] yine de gelir. Her chunk'ta error var mı diye bakın. Bu denetim olmadan yarıda başarısız olmuş bir yanıt tamamlanmış gibi görünür.

Tür Kod Mesaj Ne zaman
api_error The model backend failed to answer. Please retry. Model başarısız oldu ya da hiçbir şey yazmadı. İsteği yeniden gönderin.
rate_limit_error Shannon routes are temporarily busy. Please retry. Model şu anda meşgul. Birkaç saniye bekleyin ve isteği yeniden gönderin.
invalid_request_error context_length_exceeded Konuşma modelin bağlam penceresinden uzun. Yeniden göndermeden önce kısaltın. Mesaj metni değişir.

Host edilen açık ağırlıklı modeller error üyesini yalnızca type ve message ile gönderir.

OpenAI Python ve JavaScript SDK'ları, siz yineleme yaparken bir hata chunk'ını API hatası olarak fırlatır; bu yüzden döngüyü olağan hata yönetiminizle sarın.

Durum kodlarının, hata gövdesinin ve nelerin yeniden deneneceğinin kendi sayfası vardır. Hata yönetimi

Bağlantıyı kapatma

Bağlantıyı kapatmak teslimatı durdurur, isteği değil. Model yanıtı sonuna kadar yazar ve istek, hepsini okumuşsunuz gibi ücretlendirilir. Daha azını ödemek için daha azını isteyin: bunu uygulayan bir modelde daha düşük bir max_tokens ayarlayın.

Bir stream size gelirken de erken bitebilir, örneğin bir ağ kesintisinde ya da bir sunucu güncellenirken. O zaman son chunk'sız ve data: [DONE] olmadan durur. Bu yanıtı eksik sayın ve isteği yeniden gönderin.

Bir stream'i SDK olmadan okuma

Doğru bir okuyucu beş şey yapar: stream'den önce gelen hataları kendi hata yönetimine gönderir, gövdeyi satırlara böler, yorum satırlarını atlar, data: [DONE] satırında durur ve her chunk'ta error var mı diye bakar.

import json
import requests

response = requests.post(
    "https://api.shannon-ai.com/v1/chat/completions",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "model": "shannon-3",
        "messages": [{"role": "user", "content": "Explain server-sent events in three sentences."}],
        "stream": True,
    },
    stream=True,
)

# 1. Errors before the stream are plain JSON with their own status.
if response.status_code != 200:
    raise RuntimeError(f"{response.status_code}: {response.text}")

answer, done = [], False
for raw in response.iter_lines():          # 2. one line at a time
    line = raw.decode("utf-8")
    if not line.startswith("data: "):      # 3. empty lines and ": ping" comments
        continue
    data = line[len("data: "):]
    if data == "[DONE]":                   # 4. the end of the stream
        done = True
        break
    chunk = json.loads(data)
    if "error" in chunk:                   # 5. a failure inside the stream
        raise RuntimeError(chunk["error"]["message"])
    delta = chunk["choices"][0]["delta"]
    if delta.get("content"):
        answer.append(delta["content"])
    if chunk.get("usage"):
        print(chunk["choices"][0]["finish_reason"], chunk["usage"])

if not done:
    raise RuntimeError("the stream ended before [DONE]")
print("".join(answer))

Python örneği requests paketini kullanır. JavaScript örneği Node.js 18 veya üzerinde çalışır.

Diğer biçimlerin stream'leri

Responses ve Messages uç noktaları da stream eder. Frame'leri, olayın adını taşıyan bir event: satırı ve JSON'unu taşıyan bir data: satırı içerir. Her sayfa olaylarını sırayla listeler.

Stream'de Chat CompletionsResponsesMessages
Frame'ler data: satırlarıevent: ve data: satırlarıevent: ve data: satırları
Akıl yürütme şurada gelir delta.reasoning_contentresponse.reasoning_summary_text.deltathinking_delta
Yanıt metni şurada gelir delta.contentresponse.output_text.deltatext_delta
Kullanım bilgisi şurada gelir Son chunkresponse.completedmessage_delta
Stream şununla biter Son chunk, ardından data: [DONE]response.completedmessage_stop