جریان
stream په true وټاکئ او ځواب د server-sent events په توګه رارسیږي پداسې حال کې چې ماډل یې لیکي: لومړی reasoning، بیا ځواب، بیا وروستی chunk د پای دلیل او usage سره. دا هر کله وکاروئ چې کس د متن انتظار کوي، او د اوږدو ځوابونو لپاره.
POST https://api.shannon-ai.com/v1/chat/completions
OpenAI SDKs chunks یو یو تاسو ته ورکوي. هر chunk د هغه څه له مخې ولولئ چې لیږدوي: د reasoning یوه ټوټه، د ځواب یوه ټوټه، tool call، یا د ځواب پای.
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}") import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
const stream = await client.chat.completions.create({
model: "shannon-3",
messages: [{ role: "user", content: "Explain server-sent events in three sentences." }],
stream: true,
});
let answer = "";
let reasoning = "";
const toolCalls = [];
let finishReason = null;
let usage = null;
try {
for await (const chunk of stream) {
if (chunk.usage) usage = chunk.usage;
const choice = chunk.choices?.[0];
if (!choice) continue;
const delta = choice.delta;
if (delta.reasoning_content) reasoning += delta.reasoning_content;
if (delta.content) {
answer += delta.content;
process.stdout.write(delta.content);
}
for (const call of delta.tool_calls ?? []) {
toolCalls.push({ id: call.id, name: call.function.name, arguments: call.function.arguments });
}
if (choice.finish_reason) finishReason = choice.finish_reason;
}
} catch (error) {
// A failure after the stream started arrives as an error chunk.
console.error("\nstream failed:", error.message);
}
console.log("\n", finishReason, usage); curl -N https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "shannon-3",
"messages": [{"role": "user", "content": "Explain server-sent events in three sentences."}],
"stream": true
}' Stream څنګه frame کیږي
- ځواب حالت
200او headerscontent-type: text/event-streamاوcache-control: no-cacheلري. - هر رخداد یوه کرښه ده چې په
data:پیلیږي او ورپسې خالي کرښه راځي. لهdata:وروسته متن یو JSON chunk دی. هیڅevent:یاid:کرښې نشته. - کرښه چې په کولن پیلیږي، لکه
: ping، تبصره ده چې اړیکه پرانیستې ساتي. پریږدئ یې. - Stream په
data: [DONE]پای ته رسیږي. Stream چې پرته له هغه ودریږي نیمګړی دی.
Chunks په ترتیب
هر chunk د chat.completion.chunk څیز دی:
{
"id": "chatcmpl-5f0c1e7a9b3d4c62a8e1f07d2b46c9a3",
"object": "chat.completion.chunk",
"created": 1791625200,
"model": "shannon-3",
"choices": [
{
"index": 0,
"delta": {
"content": "Server-sent"
},
"finish_reason": null
}
]
} د یوه stream ټول chunks همدا id، created او model لري. choices تل یوه داخله لري. د هغه delta هغه لري چې نوی دی، او finish_reason تر وروستي chunk پورې null دی.
| په delta کې کیلي | ډول | تشریح | لیږل شوی د |
|---|---|---|---|
role | string | تل assistant. دا یو ځل، د stream په پیل کې رارسیږي. | کوربه شوي open-weight ماډلونه، shannon-2-lite، shannon-2-pro |
reasoning_content | string | د ماډل د reasoning یوه ټوټه. ټوټې په ترتیب یوځای کړئ. | کوربه شوي open-weight ماډلونه، د Shannon 3 کورنۍ، shannon-1.6-pro، shannon-coder-1 |
content | string | د ځواب یوه ټوټه. ټوټې په ترتیب یوځای کړئ. | ټول ماډلونه |
tool_calls | array | یو بشپړ tool call. د Tool call deltas وګورئ. | ټول ماډلونه |
Reasoning لومړی راځي، بیا ځواب، بیا هر tool calls. chunk د خپل delta د کلیدونو له مخې ولولئ، نه د stream کې د ځای له مخې: delta کولی شي role د متن له لومړۍ ټوټې سره ولري، او وروستی خالي وي.
بشپړ stream هماغسې لکه چې سفر کوي. د کرښو د لنډ ساتلو لپاره، id، object، created او model دلته له هر chunk څخه وتل شوي.
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 deltas
ماډل چې reasoning کوي خپل reasoning مخکې له ځواب په delta.reasoning_content کې لیږي. دواړه متنونه جلا وساتئ: reasoning د جلا، پټیدونکې برخې په توګه وښایاست، یا یې پریږدئ.
کوربه شوي open-weight ماډلونه کله چې reasoning_effort off وي هیڅ reasoning نه لیږي، او کله چې غوښتنه response_format ولري هم نه.
shannon-2-lite او shannon-2-pro هم مخکې له ځواب reasoning کوي. پدې endpoint کې دوی پداسې حال کې چې reasoning کوي : thinking تبصرې کرښې لیږي، او بیا ځواب.
reasoning_content د OpenAI SDKs په ډول شوو ماډلونو کې نشته. په Python کې یې د getattr(delta, "reasoning_content", None) سره ولولئ؛ په JavaScript کې delta.reasoning_content هماغسې کار کوي.
Tool call deltas
Tool call بشپړ رارسیږي: د هر call لپاره یو chunk، چې delta یې call د بشپړ arguments string سره لري. index د ځواب calls له 0 څخه شمیري. کوډ چې arguments ټوټه ټوټه یوځای کوي بې بدلون کار کوي، ځکه چې یوه ټوټه یوځای کوي.
{
"tool_calls": [
{
"index": 0,
"id": "call_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
}
}
]
} د calls وروسته، وروستی 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 یې لري؛ تاسو stream_options ته اړتیا نه لرئ.
{
"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
}
} په کوربه شوو 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 string ښکاره شو. | ټول ماډلونه |
tool_calls | ځواب یو یا ډیر tool calls لري. | ټول ماډلونه |
length | ځواب د output په حد کې پرې شو. | د Shannon 3 کورنۍ، shannon-1.6-lite، shannon-1.6-pro، shannon-coder-1 |
د usage ساحې د endpoint سره بیان شوي. Chat Completions
Keep-alive کرښې
پداسې حال کې چې ماډل کار کوي او لا هیڅ نه لري چې ولیږي، stream تبصرې کرښې لیږدوي. دوی هیڅ data نه لري. SSE parser یې پخپله پریږدي؛ کوډ چې خام کرښې لولي باید هره کرښه پریږدي چې په کولن پیلیږي.
| کرښه | لیږل شوی د | کله |
|---|---|---|
: ping | د Shannon 3 کورنۍ، shannon-1.6-lite، shannon-1.6-pro، shannon-coder-1 | هر 15 ثانیې وروسته. |
: keepalive | کوربه شوي open-weight ماډلونه | هر 15 ثانیې وروسته پداسې حال کې چې ماډل کار کوي. |
: thinking | shannon-2-lite، shannon-2-pro | پداسې حال کې چې ماډل reasoning کوي. |
د stream دننه تېروتنې
کله چې stream پیل شي حالت یې 200 دی، نو ناکامي د stream دننه رارسیږي: chunk د error غړي سره هلته چې choices به وای.
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 | ګفتګه د ماډل له context window څخه اوږده ده. مخکې له بیا لیږلو یې لنډه کړئ. د پیغام متن توپیر لري. |
کوربه شوي open-weight ماډلونه error غړی یوازې د type او message سره لیږي.
د OpenAI Python او JavaScript SDKs د تېروتنې chunk د API تېروتنې په توګه راپورته کوي پداسې حال کې چې تاسو iterate کوئ، نو loop د خپل معمول د تېروتنې اداره کولو دننه ږدئ.
د حالت کوډونه، د تېروتنې بدنه او څه بیا هڅه کول خپله جلا پاڼه لري. د تېروتنې اداره کول
د اړیکې بندول
د اړیکې بندول تحویل ودروي، نه غوښتنه. ماډل ځواب تر پایه لیکي او غوښتنه داسې بیل کیږي لکه تاسو چې ټول لوستی وي. د لږ تادیې لپاره، لږ وغواړئ: په هغه ماډل کې ټیټ max_tokens وټاکئ چې دا پلي کوي.
Stream کولی شي ستاسو په لاره کې ژر هم پای ته ورسیږي، د مثال په توګه د شبکې ماتیدو سره یا کله چې server تازه کیږي. بیا دا پرته له وروستي chunk او پرته له data: [DONE] ودریږي. داسې ځواب نیمګړی وګڼئ او غوښتنه بیا ولیږئ.
پرته له SDK د stream لوستل
سم لوستونکی پنځه کارونه کوي: هغه تېروتنې چې مخکې له stream رارسیږي خپل تېروتنې اداره کولو ته لیږي، بدنه په کرښو ویشي، تبصرې کرښې پریږدي، په 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)) const response = await fetch("https://api.shannon-ai.com/v1/chat/completions", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "shannon-3",
messages: [{ role: "user", content: "Explain server-sent events in three sentences." }],
stream: true,
}),
});
// 1. Errors before the stream are plain JSON with their own status.
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const decoder = new TextDecoder();
let buffer = "";
let answer = "";
let done = false;
read: for await (const bytes of response.body) {
buffer += decoder.decode(bytes, { stream: true });
const lines = buffer.split("\n"); // 2. one line at a time
buffer = lines.pop(); // keep the unfinished line
for (const line of lines) {
if (!line.startsWith("data: ")) continue; // 3. empty lines and ": ping" comments
const data = line.slice(6);
if (data === "[DONE]") { // 4. the end of the stream
done = true;
break read;
}
const chunk = JSON.parse(data);
if (chunk.error) throw new Error(chunk.error.message); // 5. a failure inside the stream
const choice = chunk.choices[0];
if (choice.delta.content) answer += choice.delta.content;
if (chunk.usage) console.log(choice.finish_reason, chunk.usage);
}
}
if (!done) throw new Error("the stream ended before [DONE]");
console.log(answer); د Python نمونه requests کڅوړه کاروي. د JavaScript نمونه په Node.js 18 یا نوې نسخه کې چلیږي.
د نورو بڼو stream ګانې
Responses او Messages endpoints هم stream کوي. د دوی frames د رخداد نوم سره event: کرښه او د هغه JSON سره data: کرښه لري. هره پاڼه خپل رخدادونه په ترتیب لیست کوي.
| په stream کې | Chat Completions | Responses | Messages |
|---|---|---|---|
| Frames | data: کرښې | event: او data: کرښې | event: او data: کرښې |
| Reasoning رارسیږي په | delta.reasoning_content | response.reasoning_summary_text.delta | thinking_delta |
| د ځواب متن رارسیږي په | delta.content | response.output_text.delta | text_delta |
| Usage رارسیږي په | وروستی chunk | response.completed | message_delta |
| Stream پای ته رسیږي په | وروستی chunk، بیا data: [DONE] | response.completed | message_stop |