Batch API في Claude: نصف الفاتورة بدون أي تنازل عن الجودة
المستوى: محترف
لو فاتورة Anthropic عندك بتعدّي $1000 شهريًا وأكتر من 60% من شغلك تصنيف أو تلخيص أو ترجمة دفعات (مش رد فوري للمستخدم)، إنت بتدفع ضعف اللي مفروض. Batch API في Claude بيوفّر 50% من السعر مع قدرة على تشغيل لحد 100,000 request في job واحد، مقابل تأخير تيوريتيكي لحد 24 ساعة (الإنتاج الفعلي بيخلّص في 12-22 دقيقة).
المشكلة باختصار
الـ Synchronous API بيطلب من Claude يرد عليك في ثواني، وده محسوب في الفاتورة. لو شغلك مش بيستنّى عميل قاعد على الشاشة، الموديل يقدر ياخد طلباتك على دفعة ويرجّعك النتائج بعد دقايق، مقابل خصم 50% فوري على الـ input والـ output. اللي ناس كتير بتغفل عنه: حوالي 70% من شغل LLM في الإنتاج (تصنيف تذاكر، تلخيص محتوى، استخراج بيانات، ترجمة، evaluation) مش real-time أصلاً، فبتدفع premium سرعة بدون فايدة.
مثال بسيط للفكرة قبل ما ندخل التفاصيل
تخيّل إنك بتبعت 1000 طرد عبر شركة شحن. عندك خياران:
- شحن سريع: كل طرد يوصل في ساعتين بـ 10 جنيه. الإجمالي 10,000 جنيه.
- شحن دفعة: الـ 1000 طرد يوصلوا في يوم واحد بـ 5 جنيه للطرد. الإجمالي 5,000 جنيه.
لو الطرود هدايا عيد ميلاد بكرة، الشحن السريع لازم. لو الطرود بضاعة لمستودع، إنت بتدفع 100% زيادة بدون فايدة. Batch API بنفس المنطق بالظبط: نفس الموديل، نفس الجودة، نفس الـ output؛ فقط بتاجّل اللحظة اللي بتقفل فيها الطلب.
التعريف العلمي بدقة
Batch API في Anthropic بيستلم لحد 100,000 request في job واحد (حد إجمالي 256MB) ويرجّع النتائج خلال window زمني max 24 ساعة. الـ pricing هو 50% من السعر الـ standard لكل من input tokens و output tokens، بنفس الموديلات المتاحة في الـ Synchronous (Opus 4، Sonnet 4.6، Haiku 4.5)، وبنفس قدرات الـ tool use و prompt caching. الفرق التشغيلي الوحيد: بدل ما تستلم الرد عبر HTTP synchronous، بتعمل polling على batch_id لحد ما الـ processing_status يبقى ended.
كود Python شغّال (anthropic SDK 0.40+)
import anthropic
import time
client = anthropic.Anthropic()
requests_payload = [
{
"custom_id": f"ticket-{i}",
"params": {
"model": "claude-sonnet-4-6",
"max_tokens": 256,
"messages": [{
"role": "user",
"content": f"صنّف التذكرة دي في فئة واحدة بس: {ticket_text}"
}]
}
}
for i, ticket_text in enumerate(tickets)
]
batch = client.messages.batches.create(requests=requests_payload)
print(f"Job: {batch.id}, status: {batch.processing_status}")
while True:
job = client.messages.batches.retrieve(batch.id)
if job.processing_status == "ended":
break
time.sleep(60)
for result in client.messages.batches.results(batch.id):
print(result.custom_id, result.result.message.content[0].text)