مستوى المقال: مبتدئ
لو شات بوت بنيته على Claude API بياخد 12 ثانية يرد على المستخدم، ومفيش حاجة بتتحرك على الشاشة طول الفترة دي، 70% من الناس بيقفلوا التاب قبل ما الرد يوصل. Streaming بيخلّي أول كلمة تظهر بعد 400 مللي ثانية بدل 12 ثانية، وكل توكن يطبع وقت ما الموديل بيكتبه — بدون تغيير الموديل ولا الـ prompt ولا التكلفة.
Streaming في Claude API: مفهوم الرد التدفقي خطوة بخطوة
المشكلة باختصار
الافتراض الشائع إن الموديل بيرد دفعة واحدة. الحقيقة: الموديل بيولّد الرد توكن وراء توكن، لكن الـ SDK الافتراضي بيستنى الرد كله قبل ما يديك حاجة. النتيجة: المستخدم بيبص في شاشة فاضية لمدة 8 إلى 15 ثانية على ردود طويلة، ومعدل ترك الصفحة بيوصل لـ 70% على ردود أطول من 6 ثواني.
المفهوم بمثال بسيط
تخيّل إنك في كافيه وطلبت 4 سندوتشات. الكاشير قدامه طريقتين:
- بدون streaming: ياخد طلبك، يقفل الشباك، يستنى الـ 4 سندوتشات يجهزوا، وبعد 12 دقيقة يفتح الشباك ويسلّمك كل حاجة مرة واحدة.
- مع streaming: أول ما السندوتش الأول يجهز، يسلّمهولك. تاني واحد بعد دقيقتين، تالت، رابع. الوقت الكلي نفسه (12 دقيقة)، لكن إنت ابتديت تاكل من الدقيقة 3 بدل الدقيقة 12.
Claude API بيشتغل بنفس المنطق بالظبط. الموديل بياخد نفس الوقت يولّد الرد، لكن إنت بتبدأ تقرأ من أول توكن بدل ما تستنى الرد كله.
التعريف العلمي الدقيق
Streaming هنا بيستخدم بروتوكول Server-Sent Events (SSE) اللي معرّف في مواصفات WHATWG. الـ HTTP response بترجع بـ Content-Type: text/event-stream وبتفضل الـ connection مفتوحة. كل توكن (أو مجموعة توكنز صغيرة) بيتبعت كـ event مستقل من نوع content_block_delta، والـ SDK بيعمل parse فوري للـ event ويسلّمه للكود بتاعك.
الفرق العملي:
- غير streaming: طلب واحد ← استنى ← response كامل. الـ time-to-first-byte = total latency.
- Streaming: طلب واحد ← stream من events ← كل event بيحمل توكن أو أكتر. الـ time-to-first-byte ≈ 200 إلى 500ms على Claude Sonnet 4.6.
الكود: قبل وبعد على Anthropic SDK
الكود التقليدي اللي بيستنى الرد كله:
import anthropic, time
client = anthropic.Anthropic()
start = time.time()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "اشرحلي DevOps في 200 كلمة"}]
)
print(f"وقت الرد: {time.time() - start:.2f}s")
print(response.content[0].text)