Slaan oor na inhoud
Stroming

Stroming

Stel stream op true en die antwoord kom as bediener-gestuurde gebeure aan terwyl die model dit skryf: eers redenering, dan die antwoord, dan 'n laaste chunk met die voltooiingsrede en die gebruik. Gebruik dit wanneer 'n mens op die teks wag, en vir lang antwoorde.

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

Die OpenAI-SDK's gee jou die chunks een vir een. Lees elke chunk volgens wat dit dra: 'n stuk redenering, 'n stuk van die antwoord, 'n gereedskapoproep, of die einde van die antwoord.

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

Hoe 'n stroom geraam word

  • Die antwoord het status 200 en die headers content-type: text/event-stream en cache-control: no-cache.
  • Elke gebeurtenis is een reël wat met data: begin en deur 'n leë reël gevolg word. Die teks na data: is een JSON-chunk. Daar is geen event:- of id:-reëls nie.
  • 'n Reël wat met 'n dubbelpunt begin, soos : ping, is 'n kommentaar wat die verbinding oop hou. Slaan dit oor.
  • Die stroom eindig met data: [DONE]. 'n Stroom wat daarsonder stop, is onvolledig.

Chunks in volgorde

Elke chunk is 'n chat.completion.chunk-objek:

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

Alle chunks van een stroom dra dieselfde id, created en model. choices hou altyd een inskrywing. Sy delta hou wat nuut is, en finish_reason is null tot die laaste chunk.

Sleutel in delta Tipe Beskrywing Gestuur deur
role string Altyd assistant. Dit kom een keer aan, aan die begin van die stroom. Gehuisveste oopgewig-modelle, shannon-2-lite, shannon-2-pro
reasoning_content string 'n Stuk van die model se redenering. Voeg die stukke in volgorde saam. Gehuisveste oopgewig-modelle, Shannon 3-familie, shannon-1.6-pro, shannon-coder-1
content string 'n Stuk van die antwoord. Voeg die stukke in volgorde saam. Alle modelle
tool_calls array Een volledige gereedskapoproep. Sien Gereedskapoproep-deltas. Alle modelle

Redenering kom eerste, dan die antwoord, dan enige gereedskapoproepe. Lees 'n chunk volgens die sleutels in sy delta, nie volgens sy plek in die stroom nie: 'n delta kan role saam met die eerste stuk teks hou, en die laaste een is leeg.

'n Hele stroom soos dit reis. Om die reëls kort te hou, is id, object, created en model hier uit elke chunk gelaat.

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]

Redeneer-deltas

'n Model wat redeneer, stuur sy redenering in delta.reasoning_content voor die antwoord. Hou die twee tekste uitmekaar: wys die redenering as 'n afsonderlike, invoubare deel, of laat dit uit.

Die gehuisveste oopgewig-modelle stuur geen redenering wanneer reasoning_effort off is nie, en ook nie wanneer die versoek 'n response_format het nie.

shannon-2-lite en shannon-2-pro redeneer ook voordat hulle antwoord. Op hierdie eindpunt stuur hulle : thinking-kommentaarreëls terwyl hulle dit doen, en dan die antwoord.

reasoning_content is nie in die getipeerde modelle van die OpenAI-SDK's nie. In Python lees dit met getattr(delta, "reasoning_content", None); in JavaScript werk delta.reasoning_content soos dit is.

Gereedskapoproep-deltas

'n Gereedskapoproep kom heel aan: een chunk per oproep, waarvan die delta die oproep met die volledige arguments-string hou. index nommer die oproepe van die antwoord vanaf 0. Kode wat arguments stuk vir stuk saamvoeg, werk ongewysig, omdat dit een stuk saamvoeg.

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

Ná die oproepe het die laaste chunk finish_reason tool_calls.

Wanneer die versoek tools het, stuur shannon-1.6-lite, shannon-1.6-pro en shannon-coder-1 die antwoordteks as een delta aan die einde van die antwoord.

Die laaste chunk

Die laaste chunk voor data: [DONE] het 'n leë delta, die finish_reason en die usage van die versoek, almal in dieselfde chunk. Elke stroom het dit; jy het nie stream_options nodig nie.

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

Op die gehuisveste oopgewig-modelle het usage ook prompt_tokens_details.cached_tokens en completion_tokens_details.reasoning_tokens.

Ná 'n versoek met web_search: true waarvan die soektog iets gevind het, dra die laaste chunk ook sources, en een chunk daarvoor dra die aanhalingsmerke as delta.annotations. Websoektog

finish_reason Beskrywing Gestuur deur
stop Die model het sy antwoord voltooi, of 'n stop-string het verskyn. Alle modelle
tool_calls Die antwoord hou een of meer gereedskapoproepe. Alle modelle
length Die antwoord is by die uitvoerperk afgesny. Shannon 3-familie, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1

Die velde van usage word saam met die eindpunt beskryf. Chat Completions

Keep-alive-reëls

Terwyl die model werk en nog niks het om te stuur nie, dra die stroom kommentaarreëls. Hulle hou geen data nie. 'n SSE-ontleder slaan hulle self oor; kode wat rou reëls lees, moet elke reël wat met 'n dubbelpunt begin, oorslaan.

Reël Gestuur deur Wanneer
: ping Shannon 3-familie, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 Elke 15 sekondes.
: keepalive Gehuisveste oopgewig-modelle Elke 15 sekondes terwyl die model werk.
: thinking shannon-2-lite, shannon-2-pro Terwyl die model redeneer.

Foute binne 'n stroom

Sodra 'n stroom begin het, is sy status 200, so 'n mislukking kom binne die stroom aan: 'n chunk met 'n error-lid waar choices sou wees.

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]

Ná die fout-chunk volg die laaste chunk, met finish_reason en usage, en data: [DONE] steeds. Toets elke chunk vir error. Sonder daardie toets lyk 'n antwoord wat halfpad misluk het volledig.

Tipe Kode Boodskap Wanneer
api_error The model backend failed to answer. Please retry. Die model het misluk, of niks geskryf nie. Stuur die versoek weer.
rate_limit_error Shannon routes are temporarily busy. Please retry. Die model is op hierdie oomblik besig. Wag 'n paar sekondes en stuur die versoek weer.
invalid_request_error context_length_exceeded Die gesprek is langer as die model se konteksvenster. Verkort dit voordat jy dit weer stuur. Die boodskapteks wissel.

Die gehuisveste oopgewig-modelle stuur die error-lid met net type en message.

Die OpenAI Python- en JavaScript-SDK's gooi 'n fout-chunk as 'n API-fout terwyl jy herhaal, so draai die lus in jou gewone foutafhandeling toe.

Statuskodes, die foutliggaam en wat om weer te probeer, het hul eie bladsy. Fouthantering

Die verbinding toemaak

Om die verbinding toe te maak, stop die aflewering, nie die versoek nie. Die model skryf die antwoord tot by sy einde en die versoek word gehef asof jy dit alles gelees het. Om minder te betaal, vra vir minder: stel 'n laer max_tokens op 'n model wat dit toepas.

'n Stroom kan ook vroeg op pad na jou eindig, byvoorbeeld by 'n netwerkbreuk of terwyl 'n bediener opgedateer word. Dit stop dan sonder die laaste chunk en sonder data: [DONE]. Behandel daardie antwoord as onvolledig en stuur die versoek weer.

'n Stroom sonder 'n SDK lees

'n Korrekte leser doen vyf dinge: dit stuur foute wat voor die stroom aankom na sy foutafhandeling, verdeel die liggaam in reëls, slaan kommentaarreëls oor, stop by data: [DONE], en toets elke chunk vir 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))

Die Python-voorbeeld gebruik die requests-pakket. Die JavaScript-voorbeeld loop op Node.js 18 of nuuwer.

Strome van die ander formate

Die Responses- en Messages-eindpunte stroom ook. Hul rame dra 'n event:-reël met die naam van die gebeurtenis en 'n data:-reël met sy JSON. Elke bladsy lys sy gebeure in volgorde.

In die stroom Chat CompletionsResponsesMessages
Rame data:-reëlsevent:- en data:-reëlsevent:- en data:-reëls
Redenering kom aan in delta.reasoning_contentresponse.reasoning_summary_text.deltathinking_delta
Antwoordteks kom aan in delta.contentresponse.output_text.deltatext_delta
Gebruik kom aan in Die laaste chunkresponse.completedmessage_delta
Die stroom eindig met Die laaste chunk, dan data: [DONE]response.completedmessage_stop