مواد پر جائیں
اسٹریمنگ

اسٹریمنگ

stream کو true پر سیٹ کریں اور جواب ماڈل کے لکھنے کے ساتھ server-sent events کے طور پر آتا ہے: پہلے reasoning، پھر جواب، پھر اختتام کی وجہ اور usage کے ساتھ آخری chunk۔ جب کوئی شخص متن کا انتظار کر رہا ہو، اور لمبے جوابات کے لیے، اسے استعمال کریں۔

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

OpenAI SDKs آپ کو chunks ایک ایک کر کے دیتے ہیں۔ ہر 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 ہیں۔
  • ہر ایونٹ ایک لائن ہے جو data: سے شروع ہوتی ہے اور اس کے بعد ایک خالی لائن آتی ہے۔ data: کے بعد کا متن ایک JSON chunk ہے۔ event: یا id: لائنیں نہیں ہوتیں۔
  • جو لائن کولن سے شروع ہو، جیسے : ping، وہ تبصرہ ہے جو کنکشن کھلا رکھتا ہے۔ اسے چھوڑ دیں۔
  • سٹریم data: [DONE] پر ختم ہوتی ہے۔ جو سٹریم اس کے بغیر رک جائے وہ نامکمل ہے۔

chunks ترتیب سے

ہر 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
    }
  ]
}

ایک سٹریم کے تمام chunks میں وہی id، created اور model ہوتے ہیں۔ choices میں ہمیشہ ایک اندراج ہوتی ہے۔ اس کے delta میں جو نیا ہے وہ ہوتا ہے، اور finish_reason آخری chunk تک null رہتا ہے۔

delta میں کلید قسم تفصیل بھیجنے والا
role string ہمیشہ assistant۔ یہ سٹریم کے آغاز میں ایک بار آتا ہے۔ ہوسٹڈ اوپن ویٹ ماڈلز، shannon-2-lite، shannon-2-pro
reasoning_content string ماڈل کی reasoning کا ایک ٹکڑا۔ ٹکڑوں کو ترتیب سے جوڑیں۔ ہوسٹڈ اوپن ویٹ ماڈلز، Shannon 3 فیملی، shannon-1.6-pro، shannon-coder-1
content string جواب کا ایک ٹکڑا۔ ٹکڑوں کو ترتیب سے جوڑیں۔ تمام ماڈلز
tool_calls array ایک مکمل ٹول کال۔ ٹول کال ڈیلٹاز دیکھیں۔ تمام ماڈلز

پہلے reasoning آتی ہے، پھر جواب، پھر ٹول کالز۔ chunk کو اس کے delta کی کیز سے پڑھیں، سٹریم میں اس کی جگہ سے نہیں: delta میں role متن کے پہلے ٹکڑے کے ساتھ ہو سکتا ہے، اور آخری خالی ہوتا ہے۔

پوری سٹریم جیسی وہ سفر کرتی ہے۔ لائنیں مختصر رکھنے کے لیے یہاں ہر chunk سے id، object، created اور model نکال دیے گئے ہیں۔

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 ڈیلٹاز

reasoning کرنے والا ماڈل جواب سے پہلے اپنی reasoning delta.reasoning_content میں بھیجتا ہے۔ دونوں متن الگ رکھیں: reasoning کو الگ، سمٹنے والے حصے کے طور پر دکھائیں، یا اسے چھوڑ دیں۔

ہوسٹڈ اوپن ویٹ ماڈلز reasoning_effort کی قدر off ہونے پر کوئی reasoning نہیں بھیجتے، اور جب درخواست میں response_format ہو تب بھی نہیں۔

shannon-2-lite اور shannon-2-pro بھی جواب دینے سے پہلے reasoning کرتے ہیں۔ اس endpoint پر وہ اس دوران : thinking تبصرے کی لائنیں بھیجتے ہیں، اور پھر جواب۔

reasoning_content OpenAI SDKs کے ٹائپڈ ماڈلز میں نہیں ہے۔ Python میں اسے getattr(delta, "reasoning_content", None) سے پڑھیں؛ JavaScript میں delta.reasoning_content جوں کا توں کام کرتا ہے۔

ٹول کال ڈیلٹاز

ٹول کال پوری آتی ہے: ہر کال کے لیے ایک 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 جواب کا متن جواب کے آخر میں ایک ڈیلٹا کے طور پر بھیجتے ہیں۔

آخری 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
  }
}

ہوسٹڈ اوپن ویٹ ماڈلز پر usage میں prompt_tokens_details.cached_tokens اور completion_tokens_details.reasoning_tokens بھی ہوتے ہیں۔

اس درخواست کے بعد جس میں web_search: true ہو اور جس کی سرچ کو کچھ ملا ہو، آخری چنک میں sources بھی ہوتا ہے، اور اس سے پہلے والے ایک چنک میں حوالوں کے نشانات 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 پارسر انہیں خود چھوڑ دیتا ہے؛ جو کوڈ خام لائنیں پڑھتا ہے اسے کولن سے شروع ہونے والی ہر لائن چھوڑنی ہوگی۔

لائن بھیجنے والا کب
: ping Shannon 3 فیملی، shannon-1.6-lite، shannon-1.6-pro، shannon-coder-1 ہر 15 سیکنڈ بعد۔
: keepalive ہوسٹڈ اوپن ویٹ ماڈلز ماڈل کے کام کرنے کے دوران ہر 15 سیکنڈ بعد۔
: thinking shannon-2-lite، shannon-2-pro ماڈل کے reasoning کرنے کے دوران۔

سٹریم کے اندر ایررز

سٹریم شروع ہونے کے بعد اس کا اسٹیٹس 200 ہوتا ہے، اس لیے ناکامی سٹریم کے اندر آتی ہے: ایسا chunk جس میں choices کی جگہ error رکن ہو۔

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 گفتگو ماڈل کی کانٹیکسٹ ونڈو سے لمبی ہے۔ دوبارہ بھیجنے سے پہلے اسے مختصر کریں۔ پیغام کا متن مختلف ہو سکتا ہے۔

ہوسٹڈ اوپن ویٹ ماڈلز error رکن صرف type اور message کے ساتھ بھیجتے ہیں۔

OpenAI Python اور JavaScript SDKs آپ کے iterate کرتے وقت ایرر 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 endpoints بھی سٹریم کرتے ہیں۔ ان کے فریمز میں ایونٹ کے نام والی event: لائن اور اس کے JSON والی data: لائن ہوتی ہے۔ ہر صفحہ اپنے ایونٹس ترتیب سے درج کرتا ہے۔

سٹریم میں Chat CompletionsResponsesMessages
فریمز data: لائنیںevent: اور data: لائنیںevent: اور data: لائنیں
reasoning یہاں آتی ہے delta.reasoning_contentresponse.reasoning_summary_text.deltathinking_delta
جواب کا متن یہاں آتا ہے delta.contentresponse.output_text.deltatext_delta
usage یہاں آتا ہے آخری chunkresponse.completedmessage_delta
سٹریم اس پر ختم ہوتی ہے آخری chunk، پھر data: [DONE]response.completedmessage_stop