Անցնել բովանդակությանը
Ստրիմինգ

Ստրիմինգ

Սահմանեք stream-ը true, և պատասխանը կգա որպես server-sent events՝ մոդելի գրելու ընթացքում. սկզբում reasoning-ը, ապա պատասխանը, ապա վերջին chunk-ը՝ ավարտի պատճառով և usage-ով։ Օգտագործեք այն, երբ մարդը սպասում է տեքստին, և երկար պատասխանների համար։

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

OpenAI SDK-ները chunk-երը տալիս են մեկ-մեկ։ Յուրաքանչյուր chunk կարդացեք ըստ այն բանի, ինչ այն կրում է. reasoning-ի կտոր, պատասխանի կտոր, գործիքի կանչ կամ պատասխանի ավարտ։

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

Ինչպես է հոսքը շրջանակավորվում

  • Պատասխանն ունի 200 կարգավիճակ և content-type: text/event-stream ու cache-control: no-cache header-ները։
  • Յուրաքանչյուր իրադարձություն մեկ տող է, որը սկսվում է data: -ով, և հետևում է դատարկ տողը։ data: -ից հետո տեքստը մեկ JSON chunk է։ event: կամ id: տողեր չկան։
  • Երկու կետով սկսվող տողը, օրինակ՝ : ping, մեկնաբանություն է, որը բաց է պահում կապը։ Բաց թողեք այն։
  • Հոսքն ավարտվում է data: [DONE]-ով։ Առանց դրա կանգ առած հոսքը թերի է։

Chunk-երը՝ ըստ հերթականության

Յուրաքանչյուր chunk 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
    }
  ]
}

Մեկ հոսքի բոլոր chunk-երը կրում են նույն id-ն, created-ը և model-ը։ choices-ը միշտ պարունակում է մեկ գրառում։ Դրա delta-ն պարունակում է նորը, իսկ finish_reason-ը null է մինչև վերջին chunk-ը։

Բանալի delta-ում Տեսակ Նկարագրություն Ուղարկում է
role string Միշտ assistant։ Գալիս է մեկ անգամ՝ հոսքի սկզբում։ Hosted open-weight մոդելներ, shannon-2-lite, shannon-2-pro
reasoning_content string Մոդելի reasoning-ի մի կտոր։ Կտորները միացրեք ըստ հերթականության։ Hosted open-weight մոդելներ, Shannon 3 ընտանիք, shannon-1.6-pro, shannon-coder-1
content string Պատասխանի մի կտոր։ Կտորները միացրեք ըստ հերթականության։ Բոլոր մոդելները
tool_calls array Մեկ ամբողջական գործիքի կանչ։ Տե՛ս Գործիքի կանչի delta-ներ։ Բոլոր մոդելները

Սկզբում գալիս է reasoning-ը, ապա պատասխանը, ապա գործիքի կանչերը, եթե կան։ Chunk-ը կարդացեք ըստ իր delta-ի բանալիների, ոչ թե հոսքում ունեցած տեղով. delta-ն կարող է պարունակել role տեքստի առաջին կտորի հետ, իսկ վերջինը դատարկ է։

Ամբողջ հոսքն այնպես, ինչպես այն ճանապարհորդում է։ Տողերը կարճ պահելու համար id, object, created և model այստեղ բաց են թողնված յուրաքանչյուր chunk-ից։

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 delta-ներ

Տրամաբանող մոդելն իր reasoning-ը ուղարկում է delta.reasoning_content-ում՝ պատասխանից առաջ։ Երկու տեքստերը պահեք առանձին. reasoning-ը ցույց տվեք որպես առանձին, ծալվող մաս, կամ թողեք այն։

Hosted open-weight մոդելները reasoning չեն ուղարկում, երբ reasoning_effort-ը off է, և երբ հարցումն ունի response_format։

shannon-2-lite-ը և shannon-2-pro-ն նույնպես տրամաբանում են՝ պատասխանելուց առաջ։ Այս endpoint-ում դրանք տրամաբանելու ընթացքում ուղարկում են : thinking մեկնաբանության տողեր, ապա՝ պատասխանը։

reasoning_content-ը OpenAI SDK-ների տիպավորված մոդելներում չկա։ Python-ում կարդացեք այն getattr(delta, "reasoning_content", None)-ով. JavaScript-ում delta.reasoning_content-ն աշխատում է այնպես, ինչպես կա։

Գործիքի կանչի delta-ներ

Գործիքի կանչը գալիս է ամբողջությամբ. մեկ chunk յուրաքանչյուր կանչի համար, որի delta-ն պարունակում է կանչը՝ arguments ամբողջական տողով։ index-ը համարակալում է պատասխանի կանչերը 0-ից։ arguments-ը կտոր առ կտոր միացնող կոդն աշխատում է առանց փոփոխության, քանի որ միացնում է մեկ կտոր։

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

Կանչերից հետո վերջին chunk-ն ունի finish_reason tool_calls։

Երբ հարցումն ունի tools, shannon-1.6-lite-ը, shannon-1.6-pro-ն և shannon-coder-1-ը պատասխանի տեքստն ուղարկում են որպես մեկ delta՝ պատասխանի վերջում։

Վերջին chunk-ը

data: [DONE]-ից առաջ վերջին chunk-ն ունի դատարկ delta, finish_reason և հարցման usage՝ բոլորը նույն chunk-ում։ Յուրաքանչյուր հոսք ունի այն. 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
  }
}

Hosted open-weight մոդելների վրա usage-ն ունի նաև prompt_tokens_details.cached_tokens և completion_tokens_details.reasoning_tokens։

web_search: true ունեցող և որոնումով ինչ-որ բան գտած հարցումից հետո վերջին chunk-ը կրում է նաև sources, իսկ նրանից առաջ մեկ chunk-ը կրում է մեջբերման նշանները որպես delta.annotations։ Ներկառուցված վեբ որոնում

finish_reason Նկարագրություն Ուղարկում է
stop Մոդելը ավարտել է իր պատասխանը, կամ հայտնվել է stop տողը։ Բոլոր մոդելները
tool_calls Պատասխանը պարունակում է գործիքի մեկ կամ մի քանի կանչ։ Բոլոր մոդելները
length Պատասխանը կտրվել է ելքի սահմանում։ Shannon 3 ընտանիք, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1

usage-ի դաշտերը նկարագրված են endpoint-ի հետ։ Chat Completions

Keep-alive տողեր

Մինչ մոդելը աշխատում է և դեռ ուղարկելու բան չունի, հոսքը կրում է մեկնաբանության տողեր։ Դրանք տվյալ չեն պարունակում։ SSE parser-ն ինքը բաց է թողնում դրանք. հում տողեր կարդացող կոդը պետք է բաց թողնի երկու կետով սկսվող յուրաքանչյուր տող։

Տող Ուղարկում է Երբ
: ping Shannon 3 ընտանիք, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 Ամեն 15 վայրկյանը մեկ։
: keepalive Hosted open-weight մոդելներ Ամեն 15 վայրկյանը մեկ՝ մինչ մոդելը աշխատում է։
: thinking shannon-2-lite, shannon-2-pro Մինչ մոդելը տրամաբանում է։

Սխալներ հոսքի ներսում

Երբ հոսքը սկսվել է, դրա կարգավիճակը 200 է, ուստի ձախողումը գալիս է հոսքի ներսում. chunk՝ error անդամով այնտեղ, որտեղ կլիներ choices-ը։

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]

Սխալի chunk-ից հետո, այնուամենայնիվ, հաջորդում են վերջին chunk-ը՝ finish_reason-ով և usage-ով, և data: [DONE]-ը։ Յուրաքանչյուր chunk-ում ստուգեք error-ի առկայությունը։ Առանց այդ ստուգման կիսատ ձախողված պատասխանը թվում է ամբողջական։

Տեսակ Կոդ Հաղորդագրություն Երբ
api_error The model backend failed to answer. Please retry. Մոդելը ձախողվել է կամ ոչինչ չի գրել։ Ուղարկեք հարցումը կրկին։
rate_limit_error Shannon routes are temporarily busy. Please retry. Մոդելը այս պահին զբաղված է։ Սպասեք մի քանի վայրկյան և ուղարկեք հարցումը կրկին։
invalid_request_error context_length_exceeded Զրույցը մոդելի համատեքստի պատուհանից երկար է։ Կրճատեք այն՝ նախքան կրկին ուղարկելը։ Հաղորդագրության տեքստը տարբեր է լինում։

Hosted open-weight մոդելները ուղարկում են error անդամը միայն type-ով և message-ով։

OpenAI Python և JavaScript SDK-ները սխալի chunk-ը բարձրացնում են որպես API սխալ, մինչ դուք անցնում եք հոսքով, ուստի ցիկլը պատեք ձեր սովորական սխալների մշակմամբ։

Կարգավիճակի կոդերը, սխալի մարմինը և ինչը կրկնել՝ ունեն իրենց էջը։ Սխալների մշակում

Կապի փակում

Կապը փակելը դադարեցնում է առաքումը, ոչ թե հարցումը։ Մոդելը գրում է պատասխանն ամբողջությամբ, և հարցումը գանձվում է այնպես, կարծես կարդացել եք ամբողջը։ Քիչ վճարելու համար քիչ խնդրեք. սահմանեք ավելի ցածր max_tokens այն մոդելի վրա, որը կիրառում է այն։

Հոսքը կարող է նաև շուտ ավարտվել ձեզ հասնելու ճանապարհին, օրինակ՝ ցանցի խզման ժամանակ կամ երբ սերվերը թարմացվում է։ Այդ դեպքում այն կանգ է առնում առանց վերջին chunk-ի և առանց data: [DONE]-ի։ Այդ պատասխանը համարեք թերի և ուղարկեք հարցումը կրկին։

Հոսքի ընթերցում առանց SDK-ի

Ճիշտ ընթերցողը հինգ բան է անում. հոսքից առաջ եկած սխալները ուղարկում է իր սխալների մշակմանը, մարմինը բաժանում է տողերի, բաց է թողնում մեկնաբանության տողերը, կանգ է առնում data: [DONE]-ի մոտ և յուրաքանչյուր chunk-ում ստուգում է 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))

Python օրինակն օգտագործում է requests փաթեթը։ JavaScript օրինակն աշխատում է Node.js 18-ով կամ ավելի նոր տարբերակով։

Մյուս ձևաչափերի հոսքերը

Responses և Messages endpoint-ները նույնպես աշխատում են streaming-ով։ Դրանց շրջանակները կրում են event: տող՝ իրադարձության անունով, և data: տող՝ դրա JSON-ով։ Յուրաքանչյուր էջ թվարկում է իր իրադարձությունները ըստ հերթականության։

Հոսքում Chat CompletionsResponsesMessages
Շրջանակներ data: տողերevent: և data: տողերevent: և data: տողեր
Reasoning-ը գալիս է delta.reasoning_contentresponse.reasoning_summary_text.deltathinking_delta
Պատասխանի տեքստը գալիս է delta.contentresponse.output_text.deltatext_delta
Usage-ը գալիս է Վերջին chunk-ըresponse.completedmessage_delta
Հոսքն ավարտվում է Վերջին chunk-ը, ապա data: [DONE]response.completedmessage_stop