نِت اَرز · مستندات API هوش مصنوعی
همهٔ مستندات
مدل‌ها و قیمت‌ها مرجع تعاملی دریافت کلید

استریم (SSE)

دریافت پاسخ توکن‌به‌توکن با stream: true، قالب رویدادها، usage پایانی، قطع ارتباط و مدیریت خطا در میانهٔ استریم.

base_url: https://netarz.ir/api/ai/v1 به‌روزرسانی: 1405/08/09

با stream: true پاسخ به‌صورت Server-Sent Events و توکن‌به‌توکن ارسال می‌شود — دقیقاً با همان قالب OpenAI (chat.completion.chunk). این برای همهٔ ارائه‌دهندگان کار می‌کند: رویدادهای Anthropic، Gemini و OpenRouter در سمت نِت اَرز به قالب OpenAI ترجمه می‌شوند.

نمونه

Python
stream = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "یک شعر کوتاه دربارهٔ پاییز بگویید."}],
    stream=True,
    max_tokens=200,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:                          # آخرین رویداد
        print("\n\ntokens:", chunk.usage.total_tokens)
Node.js
const stream = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "یک شعر کوتاه دربارهٔ پاییز بگویید." }],
  stream: true,
  max_tokens: 200,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
  if (chunk.usage) console.log("\n\ntokens:", chunk.usage.total_tokens); // آخرین رویداد
}
cURL
curl -N https://netarz.ir/api/ai/v1/chat/completions \
  -H "Authorization: Bearer $NETARZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "یک شعر کوتاه دربارهٔ پاییز بگویید."}],
    "stream": true,
    "max_tokens": 200
  }'

قالب رویدادها

هر رویداد یک خط data: {...} است که با یک خط خالی جدا می‌شود. آخرین رویداد پیش از [DONE] شامل usage است (نیازی به فرستادن stream_options.include_usage نیست؛ خودکار اضافه می‌شود):

پاسخ SSE
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Cache-Control: no-cache, no-transform
X-Request-Id: req_9f2c1e0b7a6d4c3f8e1a2b3c

data: {"id":"req_9f2c1e0b7a6d4c3f8e1a2b3c","object":"chat.completion.chunk","created":1756540800,"model":"gpt-4o-mini","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}

data: {"id":"req_9f2c1e0b7a6d4c3f8e1a2b3c","object":"chat.completion.chunk","created":1756540800,"model":"gpt-4o-mini","choices":[{"index":0,"delta":{"content":"برگ‌ها"},"finish_reason":null}]}

data: {"id":"req_9f2c1e0b7a6d4c3f8e1a2b3c","object":"chat.completion.chunk","created":1756540800,"model":"gpt-4o-mini","choices":[{"index":0,"delta":{"content":" می‌رقصند"},"finish_reason":null}]}

data: {"id":"req_9f2c1e0b7a6d4c3f8e1a2b3c","object":"chat.completion.chunk","created":1756540800,"model":"gpt-4o-mini","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"req_9f2c1e0b7a6d4c3f8e1a2b3c","object":"chat.completion.chunk","created":1756540800,"model":"gpt-4o-mini","choices":[],"usage":{"prompt_tokens":19,"completion_tokens":32,"total_tokens":51}}

data: [DONE]

خطا در میانهٔ استریم

اگر ارائه‌دهنده پیش از تولید هر توکنی خطا بدهد، پاسخ HTTP با کد خطای معمولی (مثلاً ۵۰۲) برمی‌گردد و هزینه‌ای ندارد. اگر ارتباط در میانهٔ استریم قطع شود، یک رویداد خطا ارسال و استریم بسته می‌شود:

رویداد خطا
data: {"error":{"message":"ارتباط با ارائه‌دهنده قطع شد.","type":"upstream_error","code":"stream_interrupted"}}

وقتی ارتباط از سمت ارائه‌دهنده قطع شود (کد stream_interrupted)، هزینه‌ای کسر نمی‌شود، حتی برای بخشی از پاسخ که به دستتان رسیده است. اگر خود ارائه‌دهنده پس از تولید بخشی از پاسخ رویداد خطا بفرستد (با type برابر upstream_error و کدی جز stream_interrupted)، فقط همان بخش تولیدشده محاسبه می‌شود. مبلغ نهایی هر درخواست را از GET /requests/{id} بخوانید؛ شناسه در هدر X-Request-Id پیش از اولین رویداد می‌رسد. SDK رسمی OpenAI این رویداد را به استثنا تبدیل می‌کند؛ اگر SSE را خودتان می‌خوانید، وجود کلید error را بررسی کنید.

قطع استریم توسط شما

اگر اتصال را ببندید (مثلاً کاربر دکمهٔ توقف را زد)، تولید متوقف می‌شود و هزینهٔ توکن‌های تولیدشده تا آن لحظه (طبق گزارش ارائه‌دهنده یا برآورد از طول خروجی) کسر می‌شود. این درخواست‌ها در گزارش با client_aborted مشخص می‌شوند.

خواندن SSE بدون SDK

Node.js / Edge
// مرورگر/Edge runtime: خواندن SSE بدون SDK — فقط از سرور خودتان (کلید را در مرورگر قرار ندهید)
const res = await fetch("https://netarz.ir/api/ai/v1/chat/completions", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.NETARZ_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ model: "gpt-4o-mini", stream: true, messages: [{ role: "user", content: "سلام" }] }),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split("\n\n");
  buffer = lines.pop();
  for (const line of lines) {
    const data = line.replace(/^data: /, "").trim();
    if (!data || data === "[DONE]") continue;
    const json = JSON.parse(data);
    if (json.error) throw new Error(json.error.message);
    process.stdout.write(json.choices?.[0]?.delta?.content ?? "");
  }
}

نکات فنی

  • پاسخ با هدرهای Content-Type: text/event-stream، Cache-Control: no-cache, no-transform و X-Accel-Buffering: no می‌آید؛ اگر پشت پراکسی خودتان هستید، بافر کردن پاسخ را غیرفعال کنید.
  • Responses API و Completions هم استریم را پشتیبانی می‌کنند (رویدادهای Responses به‌همان شکل OpenAI عبور می‌کنند).
  • در استریم، هر درخواست تا پایان پاسخ یکی از اسلات‌های همزمانی حساب شما را اشغال می‌کند (محدودیت‌ها).
  • اگر پشتیبانی موقتاً استریم را غیرفعال کند، خطای ۴۰۰ با کد streaming_disabled می‌گیرید؛ همان درخواست را با stream: false بفرستید.
  • برای اندازه‌گیری، زمان تا اولین توکن (TTFB) و کل تأخیر هر درخواست در پنل ثبت می‌شود.