Joan edukira
Streaminga

Streaminga

Ezarri stream true gisa eta erantzuna server-sent events gisa iristen da modeloak idazten duen heinean: lehenengo arrazonamendua, gero erantzuna, gero azken chunk bat amaiera-arrazoiarekin eta erabilerarekin. Erabili pertsona bat testuaren zain dagoenean, eta erantzun luzeetarako.

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

OpenAI SDKek chunk-ak banan-banan ematen dizkizute. Irakurri chunk bakoitza daramanaren arabera: arrazonamendu zati bat, erantzunaren zati bat, tresna-dei bat, edo erantzunaren amaiera.

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

Stream bat nola dago markotuta

  • Erantzunak 200 egoera eta content-type: text/event-stream eta cache-control: no-cache goiburuak ditu.
  • Gertaera bakoitza data: -ekin hasten den lerro bat da, eta lerro huts bat dator ondoren. data: ondorengo testua JSON chunk bat da. Ez dago event: edo id: lerrorik.
  • Bi puntuekin hasten den lerro bat, adibidez : ping, konexioa irekita mantentzen duen iruzkin bat da. Saltatu.
  • Streama data: [DONE]-rekin amaitzen da. Hori gabe gelditzen den stream bat osatu gabea da.

Chunk-ak ordenan

Chunk bakoitza chat.completion.chunk objektu bat da:

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

Stream bateko chunk guztiek id, created eta model berak dituzte. choices-ek beti sarrera bakarra dauka. Bere delta-k berria dena dauka, eta finish_reason null da azken chunk-a arte.

Gakoa delta-n Mota Deskribapena Nork bidalia
role string Beti assistant. Behin iristen da, streamaren hasieran. Pisu irekiko modelo ostatatuak, shannon-2-lite, shannon-2-pro
reasoning_content string Modeloaren arrazonamenduaren zati bat. Elkartu zatiak ordenan. Pisu irekiko modelo ostatatuak, Shannon 3 familia, shannon-1.6-pro, shannon-coder-1
content string Erantzunaren zati bat. Elkartu zatiak ordenan. Modelo guztiak
tool_calls array Tresna-dei osatu bat. Ikusi Tool call deltas. Modelo guztiak

Arrazonamendua lehenengo dator, gero erantzuna, gero tresna-deiak. Irakurri chunk bat bere delta-ko gakoen arabera, ez streamean duen lekuaren arabera: delta batek role izan dezake testuaren lehen zatiarekin batera, eta azkena hutsik dago.

Stream oso bat bidean doan bezala. Lerroak laburrak izateko, id, object, created eta model chunk bakoitzetik kanpo utzi dira hemen.

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]

Arrazonamendu-deltak

Arrazoitzen duen modelo batek bere arrazonamendua delta.reasoning_content-en bidaltzen du erantzunaren aurretik. Mantendu bi testuak bereizita: erakutsi arrazonamendua zati bereizi eta tolesgarri gisa, edo utzi kanpoan.

Pisu irekiko modelo ostatatuek ez dute arrazonamendurik bidaltzen reasoning_effort off denean, ezta eskaerak response_format bat duenean ere.

shannon-2-lite eta shannon-2-pro ere arrazoitu egiten dute erantzun aurretik. Endpoint honetan : thinking iruzkin-lerroak bidaltzen dituzte hori egiten duten bitartean, eta gero erantzuna.

reasoning_content ez dago OpenAI SDKen modelo tipatuetan. Python-en irakurri getattr(delta, "reasoning_content", None) erabiliz; JavaScript-en delta.reasoning_content bere horretan funtzionatzen du.

Tool call deltas

Tresna-dei bat osorik iristen da: chunk bat dei bakoitzeko, eta bere delta-k deia dauka arguments kate osoarekin. index-ek erantzunaren deiak 0tik zenbatzen ditu. arguments zati-zati elkartzen duen kodeak aldatu gabe funtzionatzen du, zati bakarra elkartzen baitu.

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

Deien ondoren, azken chunk-ak finish_reason tool_calls du.

Eskaerak tools dituenean, shannon-1.6-lite, shannon-1.6-pro eta shannon-coder-1-ek erantzunaren testua delta bakar gisa bidaltzen dute erantzunaren amaieran.

Azken chunk-a

data: [DONE] baino lehenagoko azken chunk-ak delta hutsa, finish_reason eta eskaeraren usage ditu, guztiak chunk berean. Stream guztiek dute; ez duzu stream_options behar.

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

Pisu irekiko modelo ostatatuetan usage-k prompt_tokens_details.cached_tokens eta completion_tokens_details.reasoning_tokens ere baditu.

web_search: true duen eskaera baten ondoren, azken chunk-ak sources ere badauka, eta haren aurreko chunk batek aipu-markak darama delta.annotations gisa. Web bilaketa

finish_reason Deskribapena Nork bidalia
stop Modeloak erantzuna amaitu du, edo stop kate bat agertu da. Modelo guztiak
tool_calls Erantzunak tresna-dei bat edo gehiago ditu. Modelo guztiak
length Erantzuna irteera-mugan moztu zen. Shannon 3 familia, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1

usage-ren eremuak endpointarekin batera azaltzen dira. Chat Completions

Keep-alive lerroak

Modeloak lan egiten duen bitartean eta oraindik bidaltzeko ezer ez duenean, streamak iruzkin-lerroak darama. Ez dute daturik. SSE parser batek berez saltatzen ditu; lerro gordinak irakurtzen dituen kodeak bi puntuekin hasten den lerro guztiak saltatu behar ditu.

Lerroa Nork bidalia Noiz
: ping Shannon 3 familia, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 15 segundoz behin.
: keepalive Pisu irekiko modelo ostatatuak 15 segundoz behin modeloak lan egiten duen bitartean.
: thinking shannon-2-lite, shannon-2-pro Modeloak arrazoitzen duen bitartean.

Stream baten barruko erroreak

Stream bat hasi ondoren bere egoera 200 da, beraz hutsegitea streamaren barruan iristen da: choices egongo zen lekuan error kidea duen chunk bat.

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]

Errore-chunk-aren ondoren azken chunk-a, finish_reason eta usage dituena, eta data: [DONE] ere badatoz. Egiaztatu chunk bakoitzean error dagoen. Egiaztapen hori gabe, erdian huts egin duen erantzun bat osorik dagoela ematen du.

Mota Kodea Mezua Noiz
api_error The model backend failed to answer. Please retry. Modeloak huts egin du, edo ez du ezer idatzi. Bidali eskaera berriro.
rate_limit_error Shannon routes are temporarily busy. Please retry. Modeloa lanpetuta dago une honetan. Itxaron segundo batzuk eta bidali eskaera berriro.
invalid_request_error context_length_exceeded Elkarrizketa modeloaren context window-a baino luzeagoa da. Laburtu bidali aurretik. Mezuaren testua aldatu egiten da.

Pisu irekiko modelo ostatatuek error kidea type eta message soilik dituela bidaltzen dute.

OpenAI Python eta JavaScript SDKek errore-chunk bat API errore gisa jaurtitzen dute iteratzen ari zaren bitartean, beraz bildu begizta zure ohiko errore-kudeaketan.

Egoera-kodeek, errore-gorputzak eta zer berriz saiatu behar den beren orria dute. Errore‑kudeaketa

Konexioa ixtea

Konexioa ixteak entrega gelditzen du, ez eskaera. Modeloak erantzuna amaierara arte idazten du eta eskaera osorik irakurri bazenu bezala kobratzen da. Gutxiago ordaintzeko, eskatu gutxiago: ezarri max_tokens txikiago bat hura aplikatzen duen modelo batean.

Stream bat zuregana bidean ere amaitu daiteke goizegi, adibidez sare-etenaldi batean edo zerbitzari bat eguneratzen ari denean. Orduan azken chunk-a gabe eta data: [DONE] gabe gelditzen da. Hartu erantzun hori osatu gabetzat eta bidali eskaera berriro.

Stream bat SDKrik gabe irakurtzea

Irakurle zuzen batek bost gauza egiten ditu: streamaren aurretik iristen diren erroreak bere errore-kudeaketara bidaltzen ditu, gorputza lerrotan banatzen du, iruzkin-lerroak saltatzen ditu, data: [DONE]-n gelditzen da, eta chunk bakoitzean error dagoen egiaztatzen du.

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 adibideak requests paketea erabiltzen du. JavaScript adibidea Node.js 18 edo berriagoan exekutatzen da.

Beste formatuetako streamak

Responses eta Messages endpointek ere streaming egiten dute. Haien frame-ek gertaeraren izena duen event: lerro bat eta bere JSON duen data: lerro bat daramate. Orri bakoitzak bere gertaerak ordenan zerrendatzen ditu.

Streamean Chat CompletionsResponsesMessages
Frame-ak data: lerroakevent: eta data: lerroakevent: eta data: lerroak
Arrazonamendua hemen iristen da delta.reasoning_contentresponse.reasoning_summary_text.deltathinking_delta
Erantzunaren testua hemen iristen da delta.contentresponse.output_text.deltatext_delta
Erabilera hemen iristen da Azken chunk-aresponse.completedmessage_delta
Streama honekin amaitzen da Azken chunk-a, gero data: [DONE]response.completedmessage_stop