Kalo te përmbajtja
Transmetim

Transmetim

Vendosni stream në true dhe përgjigjja arrin si server-sent events ndërsa modeli e shkruan: fillimisht arsyetimi, pastaj përgjigjja, pastaj një pjesë e fundit me arsyen e mbarimit dhe përdorimin. Përdoreni sa herë që një person pret tekstin, dhe për përgjigje të gjata.

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

SDK-të OpenAI ju japin pjesët një nga një. Lexojeni çdo pjesë sipas asaj që mban: një copë arsyetimi, një copë përgjigjeje, një thirrje mjeti, ose fundin e përgjigjes.

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

Si kornizohet një stream

  • Përgjigjja ka statusin 200 dhe header-at content-type: text/event-stream dhe cache-control: no-cache.
  • Çdo ngjarje është një rresht që fillon me data: dhe ndiqet nga një rresht bosh. Teksti pas data: është një pjesë JSON. Nuk ka rreshta event: ose id:.
  • Një rresht që fillon me dy pika, si : ping, është koment që e mban lidhjen të hapur. Kapërcejeni.
  • Stream-i mbaron me data: [DONE]. Një stream që ndalon pa të është i paplotë.

Pjesët në radhë

Çdo pjesë është një objekt 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
    }
  ]
}

Të gjitha pjesët e një stream-i mbajnë të njëjtat id, created dhe model. choices mban gjithmonë një hyrje. delta i saj mban atë që është e re, dhe finish_reason është null deri te pjesa e fundit.

Çelësi në delta Lloji Përshkrimi Dërguar nga
role string Gjithmonë assistant. Arrin një herë, në fillim të stream-it. Modele open-weight të hostuara, shannon-2-lite, shannon-2-pro
reasoning_content string Një copë e arsyetimit të modelit. Bashkojini copat sipas radhës. Modele open-weight të hostuara, familja Shannon 3, shannon-1.6-pro, shannon-coder-1
content string Një copë e përgjigjes. Bashkojini copat sipas radhës. Të gjitha modelet
tool_calls array Një thirrje e plotë mjeti. Shihni Delta-t e thirrjeve të mjeteve. Të gjitha modelet

Arsyetimi vjen i pari, pastaj përgjigjja, pastaj çdo thirrje mjeti. Lexojeni një pjesë sipas çelësave në delta të saj, jo sipas vendit në stream: një delta mund të mbajë role së bashku me copën e parë të tekstit, dhe e fundit është bosh.

Një stream i plotë siç udhëton. Për t'i mbajtur rreshtat të shkurtër, id, object, created dhe model lihen jashtë çdo pjese këtu.

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]

Delta-t e arsyetimit

Një model që arsyeton e dërgon arsyetimin te delta.reasoning_content para përgjigjes. Mbajini dy tekstet të ndara: shfaqeni arsyetimin si pjesë të veçantë që mund të paloset, ose lëreni jashtë.

Modelet open-weight të hostuara nuk dërgojnë arsyetim kur reasoning_effort është off, dhe asnjë kur kërkesa ka një response_format.

shannon-2-lite dhe shannon-2-pro arsyetojnë gjithashtu para se të përgjigjen. Në këtë endpoint dërgojnë rreshta komenti : thinking ndërsa arsyetojnë, dhe pastaj përgjigjen.

reasoning_content nuk është te modelet e tipizuara të SDK-ve OpenAI. Në Python lexojeni me getattr(delta, "reasoning_content", None); në JavaScript delta.reasoning_content funksionon siç është.

Delta-t e thirrjeve të mjeteve

Një thirrje mjeti arrin e plotë: një pjesë për thirrje, delta i së cilës mban thirrjen me stringun e plotë arguments. index i numëron thirrjet e përgjigjes nga 0. Kodi që i bashkon arguments copë-copë funksionon pa ndryshime, sepse bashkon një copë.

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

Pas thirrjeve, pjesa e fundit ka finish_reason tool_calls.

Kur kërkesa ka tools, shannon-1.6-lite, shannon-1.6-pro dhe shannon-coder-1 e dërgojnë tekstin e përgjigjes si një delta në fund të përgjigjes.

Pjesa e fundit

Pjesa e fundit para data: [DONE] ka një delta bosh, finish_reason dhe usage të kërkesës, të gjitha në të njëjtën pjesë. Çdo stream e ka; nuk keni nevojë për 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
  }
}

Te modelet open-weight të hostuara usage ka edhe prompt_tokens_details.cached_tokens dhe completion_tokens_details.reasoning_tokens.

Pas një kërkese me web_search: true kërkimi i së cilës gjeti diçka, pjesa e fundit mban edhe sources, dhe një pjesë para saj mban shenjat e citimit si delta.annotations. Kërkim i integruar në ueb

finish_reason Përshkrimi Dërguar nga
stop Modeli e mbaroi përgjigjen, ose u shfaq një string stop. Të gjitha modelet
tool_calls Përgjigjja mban një ose më shumë thirrje mjetesh. Të gjitha modelet
length Përgjigjja u ndërpre te kufiri i daljes. Familja Shannon 3, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1

Fushat e usage përshkruhen me endpoint-in. Chat Completions

Rreshtat keep-alive

Ndërsa modeli punon dhe ende nuk ka çfarë të dërgojë, stream-i mban rreshta komenti. Ata nuk mbajnë të dhëna. Një parser SSE i kapërcen vetë; kodi që lexon rreshta të papërpunuar duhet të kapërcejë çdo rresht që fillon me dy pika.

Rreshti Dërguar nga Kur
: ping Familja Shannon 3, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 Çdo 15 sekonda.
: keepalive Modele open-weight të hostuara Çdo 15 sekonda ndërsa modeli punon.
: thinking shannon-2-lite, shannon-2-pro Ndërsa modeli arsyeton.

Gabimet brenda një stream-i

Pasi një stream ka nisur statusi i tij është 200, prandaj një dështim arrin brenda stream-it: një pjesë me anëtar error aty ku do të ishte 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]

Pas pjesës së gabimit vijnë prapë pjesa e fundit, me finish_reason dhe usage, dhe data: [DONE]. Kontrolloni çdo pjesë për error. Pa këtë kontroll një përgjigje që dështoi në mes duket e plotë.

Lloji Kodi Mesazhi Kur
api_error The model backend failed to answer. Please retry. Modeli dështoi, ose nuk shkroi asgjë. Dërgoni kërkesën përsëri.
rate_limit_error Shannon routes are temporarily busy. Please retry. Modeli është i zënë në këtë çast. Prisni disa sekonda dhe dërgoni kërkesën përsëri.
invalid_request_error context_length_exceeded Biseda është më e gjatë se dritarja e kontekstit të modelit. Shkurtojeni para se ta dërgoni përsëri. Teksti i mesazhit ndryshon.

Modelet open-weight të hostuara dërgojnë anëtarin error vetëm me type dhe message.

SDK-të OpenAI Python dhe JavaScript e ngrenë një pjesë gabimi si gabim API ndërsa iteroni, prandaj mbështjellni ciklin në trajtimin tuaj të zakonshëm të gabimeve.

Kodet e statusit, trupi i gabimit dhe çfarë të provohet përsëri kanë faqen e tyre. Trajtimi i gabimeve

Mbyllja e lidhjes

Mbyllja e lidhjes e ndalon dërgimin, jo kërkesën. Modeli e shkruan përgjigjen deri në fund dhe kërkesa faturohet sikur ta kishit lexuar të gjithën. Për të paguar më pak, kërkoni më pak: vendosni një max_tokens më të ulët te një model që e zbaton.

Një stream mund të mbarojë edhe herët gjatë rrugës drejt jush, për shembull në një ndërprerje rrjeti ose gjatë përditësimit të një serveri. Atëherë ndalon pa pjesën e fundit dhe pa data: [DONE]. Trajtojeni atë përgjigje si të paplotë dhe dërgoni kërkesën përsëri.

Leximi i një stream-i pa SDK

Një lexues i saktë bën pesë gjëra: i dërgon te trajtimi i gabimeve gabimet që arrijnë para stream-it, e ndan trupin në rreshta, kapërcen rreshtat e komenteve, ndalon te data: [DONE], dhe kontrollon çdo pjesë për 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))

Shembulli Python përdor paketën requests. Shembulli JavaScript ekzekutohet në Node.js 18 ose më të ri.

Stream-et e formateve të tjera

Endpoint-et Responses dhe Messages bëjnë gjithashtu streaming. Frame-et e tyre mbajnë një rresht event: me emrin e ngjarjes dhe një rresht data: me JSON-in e saj. Çdo faqe i liston ngjarjet e veta në radhë.

Në stream Chat CompletionsResponsesMessages
Frame-et Rreshta data:Rreshta event: dhe data:Rreshta event: dhe data:
Arsyetimi arrin në delta.reasoning_contentresponse.reasoning_summary_text.deltathinking_delta
Teksti i përgjigjes arrin në delta.contentresponse.output_text.deltatext_delta
Përdorimi arrin në Pjesa e funditresponse.completedmessage_delta
Stream-i mbaron me Pjesa e fundit, pastaj data: [DONE]response.completedmessage_stop