Fò lọ sí àkóónú
Sisanwọle

Sisanwọle

Ṣètò stream sí true, èsì sì ń dé bí server-sent events bí model ṣe ń kọ ọ́: ìrònú ní àkọ́kọ́, lẹ́yìn náà ìdáhùn, lẹ́yìn náà chunk tó gbẹ̀yìn pẹ̀lú ìdí ìparí àti usage. Lò ó nígbà gbogbo tí ènìyàn bá ń dúró de ọ̀rọ̀ náà, àti fún àwọn èsì gígùn.

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

Àwọn SDK OpenAI ń fún ọ ní àwọn chunk ọ̀kọ̀ọ̀kan. Ka chunk kọ̀ọ̀kan nípasẹ̀ ohun tó gbé: ègé ìrònú, ègé ìdáhùn, ìpè tool, tàbí òpin èsì.

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

Bí a ṣe ń ṣe frame stream

  • Èsì ní status 200 àti àwọn header content-type: text/event-stream àti cache-control: no-cache.
  • Event kọ̀ọ̀kan jẹ́ ìlà kan tó bẹ̀rẹ̀ pẹ̀lú data: tí ìlà òfo tẹ̀lé. Ọ̀rọ̀ lẹ́yìn data: jẹ́ chunk JSON kan. Kò sí àwọn ìlà event: tàbí id:.
  • Ìlà tó bẹ̀rẹ̀ pẹ̀lú àmì colon, bíi : ping, jẹ́ ọ̀rọ̀ ìṣàlàyé tó ń jẹ́ kí asopọ̀ ṣí. Fò ó.
  • Stream ń parí pẹ̀lú data: [DONE]. Stream tó dúró láìsí i jẹ́ aláìpé.

Àwọn chunk lẹ́sẹẹsẹ

Chunk kọ̀ọ̀kan jẹ́ object chat.completion.chunk:

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

Gbogbo chunk ti stream kan ń gbé id, created àti model kan náà. choices máa ń ní ìkọ̀sílẹ̀ kan. delta rẹ̀ ní ohun tuntun, finish_reason sì jẹ́ null títí di chunk tó gbẹ̀yìn.

Key nínú delta Irú Àpèjúwe Ẹni tó fi ránṣẹ́
role string Nígbà gbogbo assistant. Ó ń dé lẹ́ẹ̀kan, ní ìbẹ̀rẹ̀ stream. Àwọn model open-weight tí a gbàlejò, shannon-2-lite, shannon-2-pro
reasoning_content string Ègé ìrònú model. So àwọn ègé náà pọ̀ lẹ́sẹẹsẹ. Àwọn model open-weight tí a gbàlejò, ìdílé Shannon 3, shannon-1.6-pro, shannon-coder-1
content string Ègé ìdáhùn. So àwọn ègé náà pọ̀ lẹ́sẹẹsẹ. Gbogbo model
tool_calls array Ìpè tool pípé kan. Wo Àwọn delta ìpè tool. Gbogbo model

Ìrònú ló kọ́kọ́ dé, lẹ́yìn náà ìdáhùn, lẹ́yìn náà àwọn ìpè tool èyíkéyìí. Ka chunk nípasẹ̀ àwọn key inú delta rẹ̀, kì í ṣe nípasẹ̀ ipò rẹ̀ nínú stream: delta lè ní role pẹ̀lú ègé ọ̀rọ̀ àkọ́kọ́, èyí tó gbẹ̀yìn sì jẹ́ òfo.

Gbogbo stream bí ó ṣe ń rìn. Láti jẹ́ kí àwọn ìlà kúrú, a fi id, object, created àti model sílẹ̀ kúrò nínú chunk kọ̀ọ̀kan níbí.

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]

Àwọn delta ìrònú

Model tó ń ronú ń fi ìrònú rẹ̀ ránṣẹ́ nínú delta.reasoning_content ṣáájú ìdáhùn. Pa àwọn ọ̀rọ̀ méjèèjì mọ́ lọ́tọ̀ọ̀tọ̀: fi ìrònú hàn bí apá tó yàtọ̀ tí a lè pa dé, tàbí fi sílẹ̀.

Àwọn model open-weight tí a gbàlejò kì í fi ìrònú ránṣẹ́ nígbà tí reasoning_effort bá jẹ́ off, tàbí nígbà tí ìbéèrè bá ní response_format.

shannon-2-lite àti shannon-2-pro náà ń ronú kí wọ́n tó dáhùn. Lórí endpoint yìí, wọ́n ń fi àwọn ìlà ọ̀rọ̀ ìṣàlàyé : thinking ránṣẹ́ nígbà tí wọ́n bá ń ṣe bẹ́ẹ̀, lẹ́yìn náà ìdáhùn.

reasoning_content kò sí nínú àwọn typed model ti SDK OpenAI. Nínú Python, ka á pẹ̀lú getattr(delta, "reasoning_content", None); nínú JavaScript, delta.reasoning_content ń ṣiṣẹ́ bí ó ṣe wà.

Àwọn delta ìpè tool

Ìpè tool ń dé ní kíkún: chunk kan fún ìpè kọ̀ọ̀kan, tí delta rẹ̀ gbé ìpè náà pẹ̀lú string arguments pípé. index ń nọ́ńbà àwọn ìpè èsì láti 0. Code tó ń so arguments pọ̀ ègé-ègé ń ṣiṣẹ́ láìyípadà, nítorí ó ń so ègé kan.

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

Lẹ́yìn àwọn ìpè, chunk tó gbẹ̀yìn ní finish_reason tool_calls.

Nígbà tí ìbéèrè bá ní tools, shannon-1.6-lite, shannon-1.6-pro àti shannon-coder-1 ń fi ọ̀rọ̀ ìdáhùn ránṣẹ́ bí delta kan ní òpin èsì.

Chunk tó gbẹ̀yìn

Chunk tó gbẹ̀yìn ṣáájú data: [DONE] ní delta òfo, finish_reason àti usage ti ìbéèrè náà, gbogbo wọn nínú chunk kan náà. Gbogbo stream ní i; o kò nílò stream_options.

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

Lórí àwọn model open-weight tí a gbàlejò, usage tún ní prompt_tokens_details.cached_tokens àti completion_tokens_details.reasoning_tokens.

Lẹ́yìn ìbéèrè tó ní web_search: true tí ìwádìí rẹ̀ rí nǹkan, chunk ìkẹyìn tún ní sources, chunk kan ṣáájú rẹ̀ sì ní àwọn àmì ìtọ́kasí gẹ́gẹ́ bí delta.annotations. Iwadi Wẹẹbu ti a ṣe sinu

finish_reason Àpèjúwe Ẹni tó fi ránṣẹ́
stop Model parí ìdáhùn rẹ̀, tàbí string stop kan hàn. Gbogbo model
tool_calls Èsì ní ìpè tool kan tàbí jù bẹ́ẹ̀ lọ. Gbogbo model
length A gé èsì náà ní ààlà output. Ìdílé Shannon 3, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1

A ṣàpèjúwe àwọn field ti usage pẹ̀lú endpoint. Chat Completions

Àwọn ìlà keep-alive

Nígbà tí model ń ṣiṣẹ́ tí kò sì tíì ní nǹkan láti fi ránṣẹ́, stream ń gbé àwọn ìlà ọ̀rọ̀ ìṣàlàyé. Wọn kò ní data. Parser SSE ń fò wọ́n fúnra rẹ̀; code tó ń ka àwọn ìlà aláìṣàtúnṣe gbọdọ̀ fo gbogbo ìlà tó bá bẹ̀rẹ̀ pẹ̀lú colon.

Ìlà Ẹni tó fi ránṣẹ́ Nígbà wo
: ping Ìdílé Shannon 3, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 Ní ìṣẹ́jú-àáyá 15 kọ̀ọ̀kan.
: keepalive Àwọn model open-weight tí a gbàlejò Ní ìṣẹ́jú-àáyá 15 kọ̀ọ̀kan nígbà tí model ń ṣiṣẹ́.
: thinking shannon-2-lite, shannon-2-pro Nígbà tí model ń ronú.

Àwọn àṣìṣe inú stream

Nígbà tí stream bá ti bẹ̀rẹ̀, status rẹ̀ jẹ́ 200, nítorí náà ìkùnà ń dé nínú stream: chunk pẹ̀lú ẹ̀yà error níbi tí choices yóò wà.

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]

Lẹ́yìn chunk àṣìṣe, chunk tó gbẹ̀yìn, pẹ̀lú finish_reason àti usage, àti data: [DONE] ṣì tẹ̀lé e. Ṣàyẹ̀wò gbogbo chunk fún error. Láìsí ìṣàyẹ̀wò yẹn, èsì tó kùnà láàrín ọ̀nà dà bí èyí tó pé.

Irú Code Ìfiránṣẹ́ Nígbà wo
api_error The model backend failed to answer. Please retry. Model kùnà, tàbí kò kọ nǹkankan. Tún fi ìbéèrè náà ránṣẹ́.
rate_limit_error Shannon routes are temporarily busy. Please retry. Model kún lọ́wọ́ ní àkókò yìí. Dúró ìṣẹ́jú-àáyá díẹ̀ kí o sì tún fi ìbéèrè náà ránṣẹ́.
invalid_request_error context_length_exceeded Ìjíròrò gùn ju context window ti model. Dín in kù kí o tó tún fi ránṣẹ́. Ọ̀rọ̀ ìfiránṣẹ́ náà ń yàtọ̀.

Àwọn model open-weight tí a gbàlejò ń fi ẹ̀yà error ránṣẹ́ pẹ̀lú type àti message nìkan.

Àwọn SDK OpenAI Python àti JavaScript ń gbé chunk àṣìṣe sókè bí àṣìṣe API nígbà tí o bá ń yípo, nítorí náà fi ìtọ́jú àṣìṣe àtọwọ́dọ́wọ́ rẹ yí loop náà ká.

Àwọn status code, body àṣìṣe àti ohun tí a ó tún gbìyànjú ní ojú-ìwé tiwọn. Mimu Aṣiṣe

Pípa asopọ̀

Pípa asopọ̀ dé ń dá ìfijiṣẹ́ dúró, kì í ṣe ìbéèrè náà. Model ń kọ èsì dé òpin rẹ̀, a sì ń gba owó ìbéèrè náà bí ẹni pé o ti ka gbogbo rẹ̀. Láti sanwó díẹ̀, béèrè fún díẹ̀: ṣètò max_tokens tó kéré jù lórí model tó ń lò ó.

Stream tún lè parí ní kùtùkùtù lójú ọ̀nà rẹ̀ sí ọ, fún àpẹẹrẹ nígbà tí nẹ́tíwọ́ọ̀kì bá já tàbí nígbà tí a ń ṣàtúnṣe server. Ó máa dúró láìsí chunk tó gbẹ̀yìn àti láìsí data: [DONE]. Ka èsì yẹn sí aláìpé kí o sì tún fi ìbéèrè náà ránṣẹ́.

Kíka stream láìsí SDK

Olùkà tó tọ̀ ń ṣe nǹkan márùn-ún: ó ń fi àwọn àṣìṣe tó dé ṣáájú stream ránṣẹ́ sí ìtọ́jú àṣìṣe rẹ̀, ó ń pín body sí àwọn ìlà, ó ń fo àwọn ìlà ọ̀rọ̀ ìṣàlàyé, ó ń dúró ní data: [DONE], ó sì ń ṣàyẹ̀wò chunk kọ̀ọ̀kan fún 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))

Àpẹẹrẹ Python ń lo package requests. Àpẹẹrẹ JavaScript ń ṣiṣẹ́ lórí Node.js 18 tàbí tó ga jù.

Àwọn stream ti àwọn ọ̀nà mìíràn

Àwọn endpoint Responses àti Messages náà ń ṣe streaming. Àwọn frame wọn ń gbé ìlà event: pẹ̀lú orúkọ event àti ìlà data: pẹ̀lú JSON rẹ̀. Ojú-ìwé kọ̀ọ̀kan ń ṣàkójọ àwọn event rẹ̀ lẹ́sẹẹsẹ.

Nínú stream Chat CompletionsResponsesMessages
Àwọn frame Àwọn ìlà data:Àwọn ìlà event: àti data:Àwọn ìlà event: àti data:
Ìrònú ń dé nínú delta.reasoning_contentresponse.reasoning_summary_text.deltathinking_delta
Ọ̀rọ̀ ìdáhùn ń dé nínú delta.contentresponse.output_text.deltatext_delta
Usage ń dé nínú Chunk tó gbẹ̀yìnresponse.completedmessage_delta
Stream ń parí pẹ̀lú Chunk tó gbẹ̀yìn, lẹ́yìn náà data: [DONE]response.completedmessage_stop