Zum Inhalt sprangen
Streaming

Streaming

Setzt stream op true, an d'Äntwert kënnt als Server-sent Events un, wärend de Modell se schreift: fir d'éischt d'Reasoning, dann d'Äntwert, dann e leschte Chunk mam Grond fir d'Enn an der Usage. Benotzt et ëmmer, wann e Mënsch op den Text waart, a bei laangen Äntwerten.

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

D'OpenAI-SDKs ginn Iech d'Chunken een nom aneren. Liest all Chunk dorno, wat en enthält: e Stéck Reasoning, e Stéck vun der Äntwert, en Tool-Ruff, oder d'Enn vun der Äntwert.

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}")

Wéi e Stream opgebaut ass

  • D'Äntwert huet de Status 200 an d'Header content-type: text/event-stream an cache-control: no-cache.
  • All Event ass eng Zeil, déi mat data: ufänkt a vun enger eidel Zeil gefollegt gëtt. Den Text no data: ass ee JSON-Chunk. Et gëtt keng event:- oder id:-Zeilen.
  • Eng Zeil, déi mat engem Doppelpunkt ufänkt, wéi : ping, ass e Kommentar, deen d'Verbindung oppen hält. Iwwersprang se.
  • De Stream hält mat data: [DONE] op. E Stream, dee ouni et stoppt, ass onkomplett.

Chunke vun der Reiefolleg no

All Chunk ass e chat.completion.chunk-Objet:

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

All Chunke vun engem Stream hunn déiselwecht id, created an model. choices enthält ëmmer een Eintrag. Säin delta enthält dat, wat nei ass, an finish_reason ass null bis zum leschte Chunk.

Schlëssel am Delta Typ Beschreiwung Geschéckt vun
role string Ëmmer assistant. Et kënnt eemol, um Ufank vum Stream. Hosted Open-Weight-Modeller, shannon-2-lite, shannon-2-pro
reasoning_content string E Stéck vun der Reasoning vum Modell. Setzt d'Stécker der Reiefolleg no zesummen. Hosted Open-Weight-Modeller, Shannon-3-Famill, shannon-1.6-pro, shannon-coder-1
content string E Stéck vun der Äntwert. Setzt d'Stécker der Reiefolleg no zesummen. All Modeller
tool_calls array Een komplette Tool-Ruff. Kuckt Tool-Ruff-Deltaen. All Modeller

D'Reasoning kënnt als éischt, dann d'Äntwert, dann all Tool-Ruffer. Liest e Chunk no de Schlësselen a sengem delta, net no senger Plaz am Stream: e delta ka role zesumme mam éischte Stéck Text enthalen, an dee leschte ass eidel.

E ganze Stream, wéi en ënnerwee ass. Fir d'Zeilen kuerz ze halen, sinn id, object, created an model hei aus all Chunk erausgelooss.

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]

Reasoning-Deltaen

E Modell, dee reasonéiert, schéckt seng Reasoning an delta.reasoning_content virun der Äntwert. Haalt déi zwee Texter getrennt: weist d'Reasoning als separaten, zouklappbaren Deel, oder looss se eraus.

D'Hosted Open-Weight-Modeller schécken keng Reasoning, wann reasoning_effort off ass, a keng, wann d'Ufro e response_format huet.

shannon-2-lite an shannon-2-pro reasonéieren och, ier si äntweren. Op dësem Endpoint schécken si : thinking-Kommentar-Zeilen, wärend si dat maachen, an dann d'Äntwert.

reasoning_content ass net an den typiséierte Modeller vun den OpenAI-SDKs. Liest et a Python mat getattr(delta, "reasoning_content", None); a JavaScript funktionéiert delta.reasoning_content esou, wéi et ass.

Tool-Ruff-Deltaen

E Tool-Ruff kënnt ganz un: ee Chunk pro Ruff, deem säin delta de Ruff mam kompletten arguments-String enthält. index nummeréiert d'Ruffer vun der Äntwert vun 0 un. Code, dee arguments Stéck fir Stéck zesummesetzt, funktionéiert onverännert, well en een Stéck zesummesetzt.

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

No de Ruffer huet de leschte Chunk finish_reason tool_calls.

Wann d'Ufro tools huet, schécken shannon-1.6-lite, shannon-1.6-pro a shannon-coder-1 den Äntwert-Text als een Delta um Enn vun der Äntwert.

De leschte Chunk

De leschte Chunk virun data: [DONE] huet en eidelt delta, de finish_reason an den usage vun der Ufro, alles am selwechte Chunk. All Stream huet en; Dir braucht stream_options net.

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
  }
}

Bei den Hosted Open-Weight-Modeller huet usage och prompt_tokens_details.cached_tokens an completion_tokens_details.reasoning_tokens.

No enger Ufro mat web_search: true, där hir Sich eppes fonnt huet, dréit de leschte Chunk och sources, an ee Chunk virdrun dréit d'Zitatmarkéierungen als delta.annotations. Integréiert Websich

finish_reason Beschreiwung Geschéckt vun
stop De Modell huet seng Äntwert fäerdeg gemaach, oder e stop-String ass opgetaucht. All Modeller
tool_calls D'Äntwert enthält een oder méi Tool-Ruffer. All Modeller
length D'Äntwert gouf bei der Output-Limit ofgeschnidden. Shannon-3-Famill, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1

D'Felder vun usage si beim Endpoint beschriwwen. Chat Completions

Keep-alive-Zeilen

Wärend de Modell schafft an nach näischt ze schécken huet, enthält de Stream Kommentar-Zeilen. Si enthalen keng Daten. E SSE-Parser iwwersprengt se vu selwer; Code, deen rau Zeilen liest, muss all Zeil iwwerspréngen, déi mat engem Doppelpunkt ufänkt.

Zeil Geschéckt vun Wéini
: ping Shannon-3-Famill, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 All 15 Sekonnen.
: keepalive Hosted Open-Weight-Modeller All 15 Sekonne, wärend de Modell schafft.
: thinking shannon-2-lite, shannon-2-pro Wärend de Modell reasonéiert.

Feeler an engem Stream

Wann e Stream ugefaang huet, ass säi Status 200, dofir kënnt e Feeler am Stream: e Chunk mat engem error-Member do, wou choices wier.

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]

No dem Feeler-Chunk folgen nach de leschte Chunk, mat finish_reason an usage, an data: [DONE]. Kontrolléiert all Chunk op error. Ouni dës Kontroll gesäit eng Äntwert, déi hallef feelgeschloen ass, komplett aus.

Typ Code Message Wéini
api_error The model backend failed to answer. Please retry. De Modell ass gescheitert, oder huet näischt geschriwwen. Schéckt d'Ufro nach eng Kéier.
rate_limit_error Shannon routes are temporarily busy. Please retry. De Modell ass an dësem Moment beschäftegt. Waart e puer Sekonnen a schéckt d'Ufro nach eng Kéier.
invalid_request_error context_length_exceeded D'Konversatioun ass méi laang wéi d'Kontextfënster vum Modell. Kierzt se, ier Dir se nach eng Kéier schéckt. Den Text vun der Message variéiert.

D'Hosted Open-Weight-Modeller schécken den error-Member just mat type a message.

D'OpenAI-SDKs fir Python a JavaScript werfen e Feeler-Chunk als API-Feeler, wärend Dir iteréiert, sou datt Dir d'Loop an Är gewinnten Feelerbehandlung packt.

Status-Coden, de Feeler-Body a wat nach eng Kéier probéiert gëtt, hunn eng eege Säit. Feelerbehandlung

D'Verbindung zoumaachen

D'Verbindung zoumaachen stoppt d'Liwwerung, net d'Ufro. De Modell schreift d'Äntwert bis zum Enn, an d'Ufro gëtt berechent, wéi wann Dir se ganz gelies hätt. Fir manner ze bezuelen, freet manner: setzt e méi niddrege max_tokens bei engem Modell, dee en benotzt.

E Stream kann och op sengem Wee zu Iech fréi ophalen, zum Beispill bei engem Netzwierk-Ofbroch oder wärend e Server aktualiséiert gëtt. Hie stoppt dann ouni de leschte Chunk an ouni data: [DONE]. Behandelt dës Äntwert als onkomplett a schéckt d'Ufro nach eng Kéier.

E Stream ouni SDK liesen

E korrekte Reader mécht fënnef Saachen: hie schéckt Feeler, déi virum Stream ukommen, un seng Feelerbehandlung, deelt de Body a Zeilen, iwwersprengt Kommentar-Zeilen, hält bei data: [DONE] op a kontrolléiert all Chunk op error.

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))

D'Python-Beispill benotzt de Package requests. D'JavaScript-Beispill leeft op Node.js 18 oder méi spéit.

Streams vun deenen anere Formater

D'Responses- an d'Messages-Endpoints streamen och. Hir Frames enthalen eng event:-Zeil mam Numm vum Event an eng data:-Zeil mat sengem JSON. All Säit lëscht hir Events der Reiefolleg no op.

Am Stream Chat CompletionsResponsesMessages
Frames data:-Zeilenevent:- an data:-Zeilenevent:- an data:-Zeilen
D'Reasoning kënnt an delta.reasoning_contentresponse.reasoning_summary_text.deltathinking_delta
Den Äntwert-Text kënnt an delta.contentresponse.output_text.deltatext_delta
Usage kënnt an De leschte Chunkresponse.completedmessage_delta
De Stream hält op mat De leschte Chunk, dann data: [DONE]response.completedmessage_stop