Ffrydio
Gosodwch stream i true ac mae'r ateb yn cyrraedd fel digwyddiadau a anfonir gan y gweinydd tra bydd y model yn ei ysgrifennu: rhesymu yn gyntaf, yna'r ateb, yna darn olaf gyda'r rheswm gorffen a'r usage. Defnyddiwch ef pryd bynnag y mae person yn aros am y testun, ac ar gyfer atebion hir.
POST https://api.shannon-ai.com/v1/chat/completions
Mae SDKs OpenAI yn rhoi'r darnau i chi fesul un. Darllenwch bob darn yn ôl yr hyn y mae'n ei gario: darn o resymu, darn o'r ateb, galwad offeryn, neu ddiwedd yr ateb.
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
}' Sut mae ffrwd wedi'i fframio
- Mae gan yr ateb statws
200a'r penawdaucontent-type: text/event-streamacache-control: no-cache. - Un llinell sy'n dechrau gyda
data:ac a ddilynir gan linell wag yw pob digwyddiad. Y testun ar ôldata:yw un darn JSON. Nid oes llinellauevent:nacid:. - Sylw sy'n cadw'r cysylltiad ar agor yw llinell sy'n dechrau gyda cholon, fel
: ping. Hepgorwch hi. - Mae'r ffrwd yn dod i ben gyda
data: [DONE]. Mae ffrwd sy'n stopio hebddo yn anghyflawn.
Darnau yn y drefn
Gwrthrych chat.completion.chunk yw pob darn:
{
"id": "chatcmpl-5f0c1e7a9b3d4c62a8e1f07d2b46c9a3",
"object": "chat.completion.chunk",
"created": 1791625200,
"model": "shannon-3",
"choices": [
{
"index": 0,
"delta": {
"content": "Server-sent"
},
"finish_reason": null
}
]
} Mae holl ddarnau un ffrwd yn cario'r un id, created a model. Mae choices bob amser yn dal un cofnod. Mae ei delta yn dal yr hyn sy'n newydd, ac mae finish_reason yn null tan y darn olaf.
| Allwedd yn delta | Math | Disgrifiad | Anfonwyd gan |
|---|---|---|---|
role | string | Bob amser yn assistant. Mae'n cyrraedd unwaith, ar ddechrau'r ffrwd. | Modelau pwysau agored a gynhelir, shannon-2-lite, shannon-2-pro |
reasoning_content | string | Darn o resymu'r model. Unwch y darnau yn y drefn. | Modelau pwysau agored a gynhelir, teulu Shannon 3, shannon-1.6-pro, shannon-coder-1 |
content | string | Darn o'r ateb. Unwch y darnau yn y drefn. | Pob model |
tool_calls | array | Un alwad offeryn gyflawn. Gweler Deltâu galwadau offer. | Pob model |
Daw rhesymu yn gyntaf, yna'r ateb, yna unrhyw alwadau offer. Darllenwch ddarn yn ôl yr allweddi yn ei delta, nid yn ôl ei le yn y ffrwd: gall delta ddal role ynghyd â darn cyntaf y testun, ac mae'r un olaf yn wag.
Ffrwd gyfan fel y mae'n teithio. Er mwyn cadw'r llinellau'n fyr, gadewir id, object, created a model allan o bob darn yma.
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] Deltâu rhesymu
Mae model sy'n rhesymu yn anfon ei resymu yn delta.reasoning_content cyn yr ateb. Cadwch y ddau destun ar wahân: dangoswch y rhesymu fel rhan ar wahân y gellir ei phlygu, neu gadewch ef allan.
Nid yw'r modelau pwysau agored a gynhelir yn anfon rhesymu pan fo reasoning_effort yn off, nac pan fo gan y cais response_format.
Mae shannon-2-lite a shannon-2-pro yn rhesymu cyn iddynt ateb hefyd. Ar y pwynt terfyn hwn maent yn anfon llinellau sylw : thinking tra byddant yn gwneud hynny, ac yna'r ateb.
Nid yw reasoning_content yn modelau teipiedig SDKs OpenAI. Yn Python darllenwch ef gyda getattr(delta, "reasoning_content", None); yn JavaScript mae delta.reasoning_content yn gweithio fel y mae.
Deltâu galwadau offer
Mae galwad offeryn yn cyrraedd yn gyflawn: un darn am bob galwad, y mae ei delta yn dal yr alwad gyda'r llinyn arguments cyflawn. Mae index yn rhifo galwadau'r ateb o 0. Mae cod sy'n uno arguments fesul darn yn gweithio heb newid, oherwydd mae'n uno un darn.
{
"tool_calls": [
{
"index": 0,
"id": "call_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
}
}
]
} Ar ôl y galwadau, mae gan y darn olaf finish_reason tool_calls.
Pan fo gan y cais tools, mae shannon-1.6-lite, shannon-1.6-pro a shannon-coder-1 yn anfon testun yr ateb fel un delta ar ddiwedd yr ateb.
Y darn olaf
Mae gan y darn olaf cyn data: [DONE] delta gwag, y finish_reason a usage y cais, i gyd yn yr un darn. Mae gan bob ffrwd ef; nid oes angen stream_options arnoch.
{
"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
}
} Ar y modelau pwysau agored a gynhelir mae gan usage hefyd prompt_tokens_details.cached_tokens a completion_tokens_details.reasoning_tokens.
Ar ôl cais gyda web_search: true y daeth ei chwiliad o hyd i rywbeth, mae'r darn olaf hefyd yn cario sources, ac mae un darn cyn hynny yn cario'r marciau dyfynnu fel delta.annotations. Chwilio gwe
| finish_reason | Disgrifiad | Anfonwyd gan |
|---|---|---|
stop | Gorffennodd y model ei ateb, neu ymddangosodd llinyn stop. | Pob model |
tool_calls | Mae'r ateb yn dal un alwad offeryn neu fwy. | Pob model |
length | Torrwyd yr ateb wrth y terfyn allbwn. | Teulu Shannon 3, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 |
Disgrifir meysydd usage gyda'r pwynt terfyn. Chat Completions
Llinellau keep-alive
Tra bydd y model yn gweithio heb ddim i'w anfon eto, mae'r ffrwd yn cario llinellau sylw. Nid ydynt yn dal data. Mae dosbarthwr SSE yn eu hepgor ar ei ben ei hun; rhaid i god sy'n darllen llinellau crai hepgor pob llinell sy'n dechrau gyda cholon.
| Llinell | Anfonwyd gan | Pryd |
|---|---|---|
: ping | Teulu Shannon 3, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 | Bob 15 eiliad. |
: keepalive | Modelau pwysau agored a gynhelir | Bob 15 eiliad tra bydd y model yn gweithio. |
: thinking | shannon-2-lite, shannon-2-pro | Tra bydd y model yn rhesymu. |
Gwallau y tu mewn i ffrwd
Unwaith y bydd ffrwd wedi dechrau ei statws yw 200, felly mae methiant yn cyrraedd y tu mewn i'r ffrwd: darn ag aelod error lle byddai 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] Ar ôl y darn gwall mae'r darn olaf, gyda finish_reason ac usage, a data: [DONE] yn dal i ddilyn. Gwiriwch bob darn am error. Heb y gwiriad hwnnw mae ateb a fethodd hanner ffordd yn edrych yn gyflawn.
| Math | Cod | Neges | Pryd |
|---|---|---|---|
api_error | The model backend failed to answer. Please retry. | Methodd y model, neu ni ysgrifennodd ddim. Anfonwch y cais eto. | |
rate_limit_error | Shannon routes are temporarily busy. Please retry. | Mae'r model yn brysur ar hyn o bryd. Arhoswch ychydig eiliadau ac anfonwch y cais eto. | |
invalid_request_error | context_length_exceeded | Mae'r sgwrs yn hirach na ffenestr cyd-destun y model. Byrhewch hi cyn i chi ei hanfon eto. Mae testun y neges yn amrywio. |
Mae'r modelau pwysau agored a gynhelir yn anfon yr aelod error gyda type a message yn unig.
Mae SDKs Python a JavaScript OpenAI yn codi darn gwall fel gwall API tra byddwch yn ailadrodd, felly lapiwch y ddolen yn eich ymdrin â gwallau arferol.
Mae gan godau statws, corff y gwall a'r hyn i'w ailgeisio eu tudalen eu hunain. Rheoli gwallau
Cau'r cysylltiad
Mae cau'r cysylltiad yn atal y cyflenwi, nid y cais. Mae'r model yn ysgrifennu'r ateb hyd ei ddiwedd a chodir y cais fel pe baech wedi darllen y cyfan. I dalu am lai, gofynnwch am lai: gosodwch max_tokens is ar fodel sy'n ei gymhwyso.
Gall ffrwd hefyd ddod i ben yn gynnar ar ei ffordd atoch, er enghraifft ar doriad rhwydwaith neu tra bydd gweinydd yn cael ei ddiweddaru. Mae'n stopio wedyn heb y darn olaf a heb data: [DONE]. Trinnwch yr ateb hwnnw fel un anghyflawn ac anfonwch y cais eto.
Darllen ffrwd heb SDK
Mae darllenydd cywir yn gwneud pum peth: mae'n anfon gwallau sy'n cyrraedd cyn y ffrwd at ei ymdrin â gwallau, yn hollti'r corff yn llinellau, yn hepgor llinellau sylw, yn stopio wrth data: [DONE], ac yn gwirio pob darn am 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); Mae'r enghraifft Python yn defnyddio'r pecyn requests. Mae'r enghraifft JavaScript yn rhedeg ar Node.js 18 neu'n hwyrach.
Ffrydiau'r fformatau eraill
Mae'r pwyntiau terfyn Responses a Messages yn ffrydio hefyd. Mae eu fframiau'n cario llinell event: gydag enw'r digwyddiad a llinell data: gyda'i JSON. Mae pob tudalen yn rhestru ei digwyddiadau yn y drefn.
| Yn y ffrwd | Chat Completions | Responses | Messages |
|---|---|---|---|
| Fframiau | Llinellau data: | Llinellau event: a data: | Llinellau event: a data: |
| Mae rhesymu yn cyrraedd yn | delta.reasoning_content | response.reasoning_summary_text.delta | thinking_delta |
| Mae testun yr ateb yn cyrraedd yn | delta.content | response.output_text.delta | text_delta |
| Mae usage yn cyrraedd yn | Y darn olaf | response.completed | message_delta |
| Mae'r ffrwd yn dod i ben gyda | Y darn olaf, yna data: [DONE] | response.completed | message_stop |