T1 · Intermediate · 7 دقيقةبيتحدّث · آخر مراجعة: 2026-08-19مسودة أولى — بنراجعها

الـ Streaming — الرد بيوصل كلمة كلمة

في سطر واحد · بدل ما تستنّى الرد كله يخلص، الـ streaming بيبعتهولك token ورا token وقت ما بيتولّدوا — نفس إحساس الشات بتاع ChatGPT.

القاموس:InferenceLLMSSEStreamingToken
ليه ده مهم؟

المستخدم بيحسّ إن المنتج أسرع بكتير لمّا يشوف الكلام بيطلع فورًا، حتى لو الوقت الكلّي واحد. ده بيفرّق جدًا في تجربة أي شات.

الفرق زي بث مباشر ضد تحميل فيديو كامل: بدل ما تقعد تبصّ على spinner لحد ما كل حاجة تجهز، بتبدأ تشوف أول جملة وإنت لسه بتستنّى الباقي.

خلينا نفهمها بمثال

زي المذيع اللي بيترجم فوري: مش بيستنّى المتكلّم يكمّل الخطبة كلها وبعدين يترجم، بيقولك كلمة بكلمة وهو ماشي — فإنت فاهم من أول ثانية.

تفتح الـ stream: true فبدل response واحد، بتوصلك أحداث SSE ورا بعض، كل واحد سطر data: فيه شويّة نص (delta) — بتلزقهم على بعض وتعرضهم أول بأول لحد ما ييجي سطر [DONE] يقولك خلص.

طيب بتحصل إزاي؟

بتضيف stream: true للـ request، فبدل JSON واحد الاتصال بيفضل مفتوح والسيرفر يبعت أحداث SSE: كل سطر data: فيه chunk صغير جوّاه delta من النص. إنت بتقرا الـ body كـ stream، تقسّمه سطور، تعمل parse لكل chunk، وتلزق الـ deltas على بعض في الـ UI أول بأول. لما يوصلك سطر [DONE] بتقفل وتعتبر الرد اكتمل — وأي انقطاع قبله معناه إن اللي عندك ناقص.

const res = await fetch(url, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ model: "model-name", stream: true, messages }),
});
const reader = res.body.getReader();
const decoder = new TextDecoder();
let text = "";
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  for (const line of decoder.decode(value).split("\n")) {
    if (!line.startsWith("data: ") || line.includes("[DONE]")) continue;
    const delta = JSON.parse(line.slice(6)).choices[0].delta.content ?? "";
    text += delta; // render incrementally here
  }
}
خلينا نبنيها

🧪 جرّب بنفسك: فعّل stream: true واعرض الرد كلمة كلمة في الترمينال أو صفحة بسيطة، لحد ما يوصل [DONE]. وبعدين اقطع الاتصال في النص (بـ AbortController) وشوف كودك هيتعامل مع الرد الناقص إزاي.

أشهر الأخطاء

(١) تجمع الـ stream كله في متغيّر وتعرضه في الآخر — دفعت تعقيد الـ streaming من غير أي فايدة للمستخدم. (٢) متتعاملش مع الانقطاع في النص: الاتصال ممكن يقع بعد نص الرد، ولو خزّنت الجزء ده كأنه رد كامل هتبوّظ الداتا. (٣) تعمل JSON.parse على الـ body كله — الـ stream سطور SSE منفصلة، مش JSON واحد.

إمتى تستخدمها؟

أي شات أو رد طويل بيتعرض لمستخدم بيستنّى قدّام الشاشة — أول كلمة بدري بتغيّر الإحساس بالمنتج كله.

وإمتى لأ؟

الشغل اللي في الخلفية (batch jobs) أو الردود اللي كودّك بيعمل لها parse كاملة زي الـ JSON المهيكل — هناك الـ non-streaming أبسط بكتير ومفيش حد بيتفرّج أصلًا.

خلينا نبنيهاالقراءة خلصت — دلوقتي ابنيها بإيدك.اعرض رد stream كلمة كلمة