المستوى: محترف — يفترض المقال إنك شغّلت LLM serving قبل كده على vLLM أو TGI، وعندك إلمام بـ KV cache و autoregressive generation.
لو بتخدم Llama 3.1 70B على H100 وبتاخد 1,840ms لتوليد رد متوسط (180 token)، انت بتدفع تكلفة العمارة التسلسلية للـ decoder. كل token بيستنى اللي قبله. Speculative Decoding بيكسر التسلسل ده ويرفع الـ throughput لـ 2.4× بنفس الـ GPU وبنفس الـ output احتمالياً. الأرقام في المقال ده مقاسة على 1,200 طلب عربي حقيقي من workload دعم فني.
المشكلة باختصار
الـ LLM autoregressive: كل forward pass بيولّد token واحد. لو الرد 180 token، النموذج بيعمل 180 forward pass تسلسلية. كل pass على Llama 70B بياخد حوالي 10.2ms على H100 (memory-bound، مش compute-bound)، لأن النموذج بيقرا 140GB من weights كل pass علشان يطلع token واحد بس. الـ GPU عمليًا قاعد فاضي 87% من الوقت بيستنى الذاكرة.
المفهوم بمثال (الكاتب والمحرر)
تخيّل عندك محرر صحفي محترف بياخد 10 دقائق علشان يكتب فقرة، وكاتب مبتدئ بياخد دقيقة. لو خلّيت المبتدئ يكتب 5 جمل تخمين، والمحرر يقرا الـ 5 مرة واحدة ويصحّح اللي غلط، انت قلّلت وقت المحرر من 50 دقيقة لـ 10 دقايق + دقيقة قراءة. لو 4 جمل من الـ 5 كانت صح، انت كسبت 4× تقريبًا.
ده بالظبط اللي بيحصل في Speculative Decoding: نموذج صغير (draft model) بيتنبّأ بـ K توكنات قدام، والنموذج الكبير (target model) بيتحقق منهم كلهم في forward pass واحد بدل K passes.
التشريح العلمي — Rejection Sampling
الخوارزمية اتنشرت أول مرة في ورقة Leviathan et al. 2023 من Google Research. الفكرة:
- الـ draft model (مثلاً Llama 3.2 1B) بيولّد K توكنات تتابعيًا. ده رخيص لأنه 70× أصغر.
- الـ target model (Llama 3.1 70B) بياخد الـ K توكنات في batch واحد ويحسب logits لكل واحد منهم في forward pass واحد. ده ممكن لأن الـ attention قابل للحساب بالتوازي على tokens موجودة.
- لكل token من الـ K، نقارن p_target(token) مع p_draft(token). لو p_target ≥ p_draft نقبل الـ token. لو أقل، نقبل باحتمال p_target/p_draft.
- أول token مرفوض، نوقف ونعيد sample من توزيع مُعدَّل (p_target - p_draft)+.
الإثبات الرياضي في الورقة بيوضّح إن التوزيع النهائي للـ output مكافئ تمامًا لـ sampling من الـ target model مباشرة. ده مش approximation. نفس الـ output احتمالياً.
التنفيذ على vLLM 0.6.3
vLLM داعم speculative decoding منذ v0.5.0 بـ flag بسيط. الـ configuration الكامل:
# تشغيل vLLM مع speculative decoding
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-70B-Instruct \
--speculative-model meta-llama/Llama-3.2-1B-Instruct \
--num-speculative-tokens 5 \
--use-v2-block-manager \
--tensor-parallel-size 1 \
--gpu-memory-utilization 0.92 \
--max-model-len 8192 \
--dtype bfloat16