စตรีမင်း
stream ကို true ဟု သတ်မှတ်လျှင် model ရေးနေစဉ် ပြန်ကြားချက်သည် server-sent events အဖြစ် ရောက်လာသည်- reasoning ကို ပထမ၊ ထို့နောက် အဖြေ၊ ထို့နောက် finish reason နှင့် usage ပါသော နောက်ဆုံး chunk။ လူတစ်ဦးက စာသားကို စောင့်နေသည့်အခါနှင့် ရှည်လျားသော ပြန်ကြားချက်များအတွက် အသုံးပြုပါ။
POST https://api.shannon-ai.com/v1/chat/completions
OpenAI SDK များသည် chunk များကို တစ်ခုချင်း ပေးသည်။ 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 ခွဲသည်
- ပြန်ကြားချက်တွင် status
200နှင့် headercontent-type: text/event-streamနှင့်cache-control: no-cacheတို့ ပါသည်။ - event တစ်ခုစီသည်
data:ဖြင့်စပြီး စာကြောင်းလွတ်တစ်ကြောင်း နောက်လိုက်သော စာကြောင်းတစ်ကြောင်း ဖြစ်သည်။data:နောက်ရှိ စာသားသည် JSON chunk တစ်ခုဖြစ်သည်။event:သို့မဟုတ်id:စာကြောင်း မရှိပါ။ : pingကဲ့သို့ colon ဖြင့်စသော စာကြောင်းသည် ချိတ်ဆက်မှုကို ဖွင့်ထားစေသော comment ဖြစ်သည်။ ကျော်သွားပါ။- stream သည်
data: [DONE]ဖြင့် အဆုံးသတ်သည်။ ၎င်းမပါဘဲ ရပ်သွားသော stream သည် မပြည့်စုံပါ။
အစီအစဉ်အတိုင်း Chunks
chunk တိုင်းသည် chat.completion.chunk object တစ်ခု ဖြစ်သည်-
{
"id": "chatcmpl-5f0c1e7a9b3d4c62a8e1f07d2b46c9a3",
"object": "chat.completion.chunk",
"created": 1791625200,
"model": "shannon-3",
"choices": [
{
"index": 0,
"delta": {
"content": "Server-sent"
},
"finish_reason": null
}
]
} stream တစ်ခု၏ chunk အားလုံးတွင် တူညီသော id၊ created နှင့် model ပါသည်။ choices တွင် entry တစ်ခုသာ အမြဲရှိသည်။ ၎င်း၏ delta တွင် အသစ်ဖြစ်သည့်အရာ ပါပြီး နောက်ဆုံး chunk အထိ finish_reason သည် null ဖြစ်သည်။
| delta ထဲရှိ Key | Type | ဖော်ပြချက် | ပို့သူ |
|---|---|---|---|
role | string | အမြဲတမ်း assistant။ stream အစတွင် တစ်ကြိမ်သာ ရောက်လာသည်။ | Host လုပ်ထားသော open-weight မော်ဒယ်များ၊ shannon-2-lite၊ shannon-2-pro |
reasoning_content | string | model ၏ reasoning အပိုင်းတစ်ခု။ အပိုင်းများကို အစီအစဉ်အတိုင်း ပေါင်းပါ။ | Host လုပ်ထားသော open-weight မော်ဒယ်များ၊ Shannon 3 မိသားစု၊ shannon-1.6-pro၊ shannon-coder-1 |
content | string | အဖြေ၏ အပိုင်းတစ်ခု။ အပိုင်းများကို အစီအစဉ်အတိုင်း ပေါင်းပါ။ | Model အားလုံး |
tool_calls | array | ပြည့်စုံသော tool call တစ်ခု။ Tool call deltas ကို ကြည့်ပါ။ | Model အားလုံး |
reasoning ကို ပထမ၊ ထို့နောက် အဖြေ၊ ထို့နောက် tool calls များ လာသည်။ chunk ကို stream အတွင်း ၎င်း၏နေရာဖြင့် မဟုတ်ဘဲ ၎င်း၏ delta ထဲရှိ key များဖြင့် ဖတ်ပါ- delta တစ်ခုတွင် ပထမစာသားအပိုင်းနှင့်အတူ role ပါနိုင်ပြီး နောက်ဆုံးတစ်ခုသည် အလွတ်ဖြစ်သည်။
ကြိုးပေါ်တွင် သွားသည့်အတိုင်း stream တစ်ခုလုံး။ စာကြောင်းများ တိုစေရန် ဤနေရာတွင် chunk တစ်ခုစီမှ id၊ object၊ created နှင့် model ကို ချန်လှပ်ထားသည်။
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 လုပ်သော model သည် ၎င်း၏ reasoning ကို အဖြေမတိုင်မီ delta.reasoning_content တွင် ပို့သည်။ စာသားနှစ်ခုကို ခွဲထားပါ- reasoning ကို သီးခြား ခေါက်သိမ်းနိုင်သော အပိုင်းအဖြစ် ပြပါ၊ သို့မဟုတ် ချန်ထားပါ။
Host လုပ်ထားသော open-weight models များသည် reasoning_effort သည် off ဖြစ်လျှင် reasoning မပို့ပါ၊ request တွင် response_format ပါလျှင်လည်း မပို့ပါ။
shannon-2-lite နှင့် shannon-2-pro တို့သည်လည်း မဖြေမီ reasoning လုပ်သည်။ ဤ endpoint တွင် ၎င်းတို့ reasoning လုပ်နေစဉ် : thinking comment စာကြောင်းများကို ပို့ပြီး ထို့နောက် အဖြေကို ပို့သည်။
reasoning_content သည် OpenAI SDK များ၏ typed model များတွင် မပါပါ။ Python တွင် getattr(delta, "reasoning_content", None) ဖြင့် ဖတ်ပါ၊ JavaScript တွင် delta.reasoning_content သည် ရှိသည့်အတိုင်း အလုပ်လုပ်သည်။
Tool call deltas
tool call သည် တစ်ခုလုံး ရောက်လာသည်- call တစ်ခုလျှင် chunk တစ်ခု၊ ၎င်း၏ delta တွင် arguments string ပြည့်စုံစွာပါသော call ပါသည်။ index သည် ပြန်ကြားချက်၏ calls များကို 0 မှ နံပါတ်ပေးသည်။ arguments ကို အပိုင်းလိုက် ပေါင်းသော code သည် အပိုင်းတစ်ခုတည်းကို ပေါင်းသဖြင့် မပြောင်းလဲဘဲ အလုပ်လုပ်သည်။
{
"tool_calls": [
{
"index": 0,
"id": "call_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
}
}
]
} calls ပြီးနောက် နောက်ဆုံး chunk တွင် finish_reason tool_calls ပါသည်။
request တွင် tools ပါလျှင် shannon-1.6-lite၊ shannon-1.6-pro နှင့် shannon-coder-1 တို့သည် အဖြေစာသားကို ပြန်ကြားချက်အဆုံးတွင် delta တစ်ခုအဖြစ် ပို့သည်။
နောက်ဆုံး chunk
data: [DONE] မတိုင်မီ နောက်ဆုံး chunk တွင် အလွတ် delta၊ finish_reason နှင့် request ၏ 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
}
} Host လုပ်ထားသော open-weight models များတွင် usage တွင် prompt_tokens_details.cached_tokens နှင့် completion_tokens_details.reasoning_tokens လည်း ပါသည်။
ရှာဖွေမှုတွင် တစ်စုံတစ်ရာ တွေ့ခဲ့သော web_search: true request ပြီးနောက် နောက်ဆုံး chunk တွင် sources လည်း ပါပြီး ၎င်းမတိုင်မီ chunk တစ်ခုက ကိုးကားမှု အမှတ်အသားများကို delta.annotations အဖြစ် သယ်ဆောင်သည်။ ဝဘ်ရှာဖွေမှု
| finish_reason | ဖော်ပြချက် | ပို့သူ |
|---|---|---|
stop | model သည် ၎င်း၏ အဖြေကို ပြီးအောင်ရေးခဲ့သည်၊ သို့မဟုတ် stop string တစ်ခု ပေါ်လာခဲ့သည်။ | Model အားလုံး |
tool_calls | ပြန်ကြားချက်တွင် tool call တစ်ခု သို့မဟုတ် တစ်ခုထက်ပို၍ ပါသည်။ | Model အားလုံး |
length | ပြန်ကြားချက်ကို output limit တွင် ဖြတ်တောက်ခဲ့သည်။ | Shannon 3 မိသားစု၊ shannon-1.6-lite၊ shannon-1.6-pro၊ shannon-coder-1 |
usage ၏ field များကို endpoint နှင့်အတူ ဖော်ပြထားသည်။ Chat Completions
Keep-alive စာကြောင်းများ
model အလုပ်လုပ်နေပြီး ပို့စရာ မရှိသေးစဉ် stream တွင် comment စာကြောင်းများ ပါသည်။ ၎င်းတို့တွင် data မပါပါ။ SSE parser က ၎င်းတို့ကို ကိုယ်တိုင်ကျော်သွားသည်၊ raw စာကြောင်းများကို ဖတ်သော code သည် colon ဖြင့်စသော စာကြောင်းတိုင်းကို ကျော်ရမည်။
| စာကြောင်း | ပို့သူ | ဖြစ်ပေါ်ချိန် |
|---|---|---|
: ping | Shannon 3 မိသားစု၊ shannon-1.6-lite၊ shannon-1.6-pro၊ shannon-coder-1 | 15 စက္ကန့်တိုင်း။ |
: keepalive | Host လုပ်ထားသော open-weight မော်ဒယ်များ | model အလုပ်လုပ်နေစဉ် 15 စက္ကန့်တိုင်း။ |
: thinking | shannon-2-lite, shannon-2-pro | model သည် reasoning လုပ်နေစဉ်အတွင်း။ |
Stream အတွင်းရှိ အမှားများ
stream စတင်ပြီးသည်နှင့် ၎င်း၏ status သည် 200 ဖြစ်သဖြင့် ကျရှုံးမှုသည် stream အတွင်း ရောက်လာသည်- choices ရှိရာနေရာတွင် error member ပါသော chunk တစ်ခု။
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] error chunk ပြီးနောက် finish_reason နှင့် usage ပါသော နောက်ဆုံး chunk နှင့် data: [DONE] တို့ ဆက်လာသေးသည်။ chunk တိုင်းတွင် error ရှိမရှိ စစ်ဆေးပါ။ ထိုစစ်ဆေးမှုမရှိလျှင် တစ်ဝက်တွင် ကျရှုံးသော ပြန်ကြားချက်သည် ပြည့်စုံသကဲ့သို့ ထင်ရမည်။
| Type | Code | မက်ဆေ့ချ် | ဖြစ်ပေါ်ချိန် |
|---|---|---|---|
api_error | The model backend failed to answer. Please retry. | model ကျရှုံးခဲ့သည်၊ သို့မဟုတ် ဘာမျှ မရေးခဲ့ပါ။ request ကို ပြန်ပို့ပါ။ | |
rate_limit_error | Shannon routes are temporarily busy. Please retry. | ယခုအချိန်တွင် model အလုပ်များနေသည်။ စက္ကန့်အနည်းငယ်စောင့်ပြီး request ကို ပြန်ပို့ပါ။ | |
invalid_request_error | context_length_exceeded | စကားပြောဆိုမှုသည် model ၏ context window ထက် ပိုရှည်သည်။ ပြန်မပို့မီ တိုစေပါ။ မက်ဆေ့ချ်စာသား ကွဲပြားနိုင်သည်။ |
Host လုပ်ထားသော open-weight models များသည် type နှင့် message သာပါသော error member ကို ပို့သည်။
OpenAI Python နှင့် JavaScript SDK များသည် သင်ထပ်ခါထပ်ခါ ဖတ်နေစဉ် error chunk ကို API error အဖြစ် ပစ်ထုတ်သဖြင့် loop ကို သင့်ပုံမှန် error handling ဖြင့် ထုပ်ပိုးပါ။
Status code များ၊ error body နှင့် ပြန်ကြိုးစားရမည့်အရာများတွင် ကိုယ်ပိုင်စာမျက်နှာရှိသည်။ အမှားကိုင်တွယ်မှု
ချိတ်ဆက်မှုကို ပိတ်ခြင်း
ချိတ်ဆက်မှုကို ပိတ်ခြင်းသည် ပေးပို့မှုကို ရပ်စေသော်လည်း request ကို မရပ်စေပါ။ model သည် ပြန်ကြားချက်ကို အဆုံးထိ ရေးပြီး request ကို သင် အားလုံးဖတ်ခဲ့သကဲ့သို့ ကျသင့်ငွေတောင်းသည်။ ပိုနည်းနည်း ပေးချေလိုပါက ပိုနည်းနည်း တောင်းပါ- ၎င်းကို အသုံးပြုသော model တွင် max_tokens ကို နိမ့်နိမ့် သတ်မှတ်ပါ။
stream သည် သင့်ဆီသို့ လာစဉ် ကွန်ရက်ပြတ်တောက်ခြင်း သို့မဟုတ် server ကို update လုပ်နေစဉ်ကဲ့သို့ အကြောင်းများကြောင့် စောစီးစွာ ပြီးဆုံးနိုင်သည်။ ထိုအခါ နောက်ဆုံး chunk နှင့် data: [DONE] မပါဘဲ ရပ်သွားသည်။ ထိုပြန်ကြားချက်ကို မပြည့်စုံဟု သဘောထားပြီး request ကို ပြန်ပို့ပါ။
SDK မပါဘဲ stream ကို ဖတ်ခြင်း
မှန်ကန်သော reader သည် အရာငါးခု လုပ်ဆောင်သည်- stream မတိုင်မီ ရောက်လာသော အမှားများကို ၎င်း၏ error handling သို့ ပို့သည်၊ body ကို စာကြောင်းများခွဲသည်၊ comment စာကြောင်းများကို ကျော်သည်၊ 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 package ကို သုံးသည်။ JavaScript နမူနာသည် Node.js 18 သို့မဟုတ် ထို့ထက်နောက်ပိုင်းတွင် run သည်။
အခြား format များအတွက် stream များ
Responses နှင့် Messages endpoint များသည်လည်း stream လုပ်သည်။ ၎င်းတို့၏ frame များတွင် event အမည်ပါသော event: စာကြောင်းနှင့် ၎င်း၏ JSON ပါသော data: စာကြောင်း ပါသည်။ စာမျက်နှာတစ်ခုစီတွင် ၎င်း၏ events များကို အစီအစဉ်အတိုင်း စာရင်းပြထားသည်။
| 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 |