Artfical AI / API
احصل على مفتاح API افتح tAI
البدء

البث

اضبط "stream": true لتُعيد نفس نقطة النهاية الاستجابة تدريجيًا عبر أحداث من جانب الخادم (server-sent events) بدلاً من الانتظار حتى ينتهي كل شيء.

لماذا البث

يحجب الطلب غير المتدفق حتى ينتهي النموذج من توليد الرد كاملاً، ثم يعيده دفعة واحدة. بالنسبة لإجابة قصيرة، نادرًا ما يُلاحَظ ذلك. أما بالنسبة لإجابة أطول، فهذا يعني انتظار عدة ثوانٍ (وأحيانًا أكثر) محدقًا في لا شيء قبل ظهور أي نص. يعالج البث ذلك بإرسال الرد قطعة قطعة، أثناء توليد النموذج له، بحيث يمكن للعميل البدء بعرض النص خلال جزء من الثانية من إرسال الطلب بدلاً من انتظار كل شيء. هذا هو الفرق بين واجهة دردشة تبدو فورية وأخرى تبدو وكأنها متوقفة عند كل رسالة. الميزة اختيارية ولا تكلف شيئًا إضافيًا عند استخدامها.

تفعيله

{
  "model": "tai-4.1",
  "messages": [{"role": "user", "content": "1'den 5'e kadar say"}],
  "stream": true
}

يصبح Content-Type الخاص بالاستجابة text/event-stream بدلاً من application/json. كل سطر حدث تُسبقه data: ، ويبقى الاتصال مفتوحًا، يرسل حدثًا واحدًا لكل قطعة محتوى جديد، إلى أن ينتهي البث بسطر حرفي data: [DONE].

شكل القطعة (chunk)

تحمل معظم القطع جزءًا صغيرًا من النص المولَّد حديثًا في choices[0].delta.content:

data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {"content": "1"}, "finish_reason": null}]}

data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {"content": ", 2"}, "finish_reason": null}]}

ضمّ كل قيمة delta.content بالترتيب، عبر كل القطع، يعيد بناء نص الرد كاملاً. بناء هذا الضم هو مهمة العميل؛ فالـ API لا يرسل النص المتراكم في أي لحظة، بل فقط القطعة الإضافية التي تضيفها كل قطعة.

قطعة الإنهاء

تحمل آخر قطعة تحتوي على محتوى قيمة delta فارغة وfinish_reason حقيقية ("stop"، أو "tool_calls" إذا كان النموذج يطلب استدعاء أداة، راجع استدعاء الأدوات):

data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}]}

قطعة الاستخدام

بعد قطعة الإنهاء، تُرسَل قطعة أخيرة إضافية بمصفوفة choices فارغة وكائن usage ممتلئ، بنفس شكل حقل usage في الاستجابة غير المتدفقة:

data: {"id": "chatcmpl-b94...", "object": "chat.completion.chunk", "created": 1788960276, "model": "tai-4.0.6P", "choices": [], "usage": {"prompt_tokens": 2, "completion_tokens": 3, "total_tokens": 5}}

data: [DONE]

العميل الذي يهتم فقط بالنص الظاهر يمكنه تجاهل أي قطعة بمصفوفة choices فارغة بأمان؛ أما العميل الذي يريد عرض استخدام الرموز أو التكلفة المقدّرة لاحقًا فعليه البحث تحديدًا عن هذه القطعة بدلاً من افتراض أن قطعة الإنهاء تحملها.

قراءة البث في الكود

# Python, using the official openai package
stream = client.chat.completions.create(
    model="tai-4.1",
    messages=[{"role": "user", "content": "Kısa bir şiir yaz"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

حزم OpenAI SDK الرسمية (بلغتي Python وNode) تعرف بالفعل كيفية تحليل شكل الأحداث هذا، لأنه نفس الشكل الذي تستخدمه واجهتها الخاصة؛ ولا يُطلب شيء خاص بـ tAI في العميل سوى توجيه base_url نحو https://api.artfical.com/v1، كما هو مشروح في صفحة المصادقة.

البث ينتهي دائمًا بشكل نظيف

حتى لو حدث خطأ ما في منتصف الطريق، فشل التوليد، انتهت مهلة طلب داخليًا، أيًا كان السبب، ينتهي البث دائمًا بإشارة مرئية بدلاً من انقطاع الاتصال ببساطة دون أي تفسير. في تلك الحالة سترى قطعة محتوى تحتوي على إشعار قصير بين قوسين، وقطعة إنهاء بـ "finish_reason": "stop"، ثم [DONE]، بنفس النهاية جيدة التكوين التي يمتلكها بث ناجح عادي. يجب على العميل أن يعامل دائمًا وصول [DONE] على أنه النهاية القطعية للدور، ولا ينبغي له أن يفترض أن بثًا انتهى دون ذلك قد نجح؛ فالاتصال المنقطع دون [DONE] يعني معاملة الطلب على أنه فشل وإعادة المحاولة، تمامًا كما تفعل مع طلب غير متدفق انتهت مهلته.