المستوى المطلوب: محترف. هذا الشرح يفترض إلمامك بأساسيات تشغيل نماذج اللغة والـ GPU ومصطلح الـ inference. لو انت مبتدئ، ابدأ بمقال أبسط عن كيفية عمل النماذج ثم ارجع هنا.
التكميم: إزاي تنزّل حجم نموذج اللغة 4 أضعاف من غير ما تعيد تدريبه
تقدر تشغّل نموذج بـ 70 مليار باراميتر على كارت شاشة واحد بـ 48GB بدل ما تحتاج كارتين A100 بـ 80GB لكل واحد. المفتاح مش سيرفر أقوى، المفتاح إنك تخزّن كل وزن في 4 بت بدل 16 بت. ده اسمه التكميم (Quantization)، وهو أرخص رافعة عندك لتشغيل النماذج الكبيرة محليًا.
المشكلة باختصار
نموذج بـ 70B مخزّن بدقة FP16 بياخد 140GB للأوزان لوحدها (70 مليار وزن × 2 بايت). ده قبل الـ KV cache وقبل أي overhead. النتيجة: مفيش كارت مستهلك يشغّله، وبتضطر تأجّر كذا GPU بتكلفة عالية. التكميم بيهاجم المشكلة دي مباشرة: يقلّل عدد البتات لكل وزن، فتقل الذاكرة والباندويدث المطلوبة.
الفكرة ببساطة قبل الدقة
تخيّل إنك بتسجّل درجات حرارة كل يوم. لو خزّنت 23.847 درجة بكل الكسور هتاخد مساحة كبيرة. لو قرّبت لأقرب نص درجة (23.5) هتوفّر مساحة كتير وتخسر تفصيلة بسيطة مش مهمة عمليًا. التكميم بيعمل نفس الحكاية مع أوزان النموذج بالظبط: بدل ما يخزّن كل وزن برقم عشري دقيق، بيقرّبه لأقرب قيمة من مجموعة صغيرة من القيم.
علميًا: كل وزن في FP16 له 65,536 مستوى ممكن. في INT4 عندك 16 مستوى بس (2 أُس 4). بنحسب لكل مجموعة أوزان (group) عامل قياس scale ونقطة صفر zero-point، وبنحوّل كل وزن لأقرب مستوى من الـ 16 عبر: q = round(w / scale) + zero_point. وقت الحساب بنفكّ التكميم مؤقتًا: w ≈ scale × (q - zero_point). الفكرة إن أوزان الشبكة موزّعة حوالين الصفر، فـ 16 مستوى موضوعة بذكاء بتكفي لتقريب كويس.
الأنواع اللي هتقابلك فعلاً
- LLM.int8(): تكميم 8 بت مع معالجة القيم الشاذة بدقة عالية. الأأمن على الدقة، بيوفّر ~2x ذاكرة.
- NF4 (QLoRA): نوع 4 بت (NormalFloat) مصمّم للأوزان الموزّعة طبيعيًا، مع "تكميم مزدوج" بيوفّر حوالي 0.4 بت إضافية لكل وزن.
- GPTQ / AWQ: تكميم 4 بت بعد التدريب (post-training) بيعاير الأوزان على عيّنة بيانات، فيقلّل خسارة الدقة أكتر من التقريب المباشر.
- GGUF (llama.cpp): صيغة ملف + عائلة k-quants زي
Q4_K_M، الأشهر للتشغيل المحلي على CPU/GPU.
مثال تنفيذي: شغّلها بنفسك
الطريقة الأولى بـ bitsandbytes داخل Transformers، تحمّل النموذج مكمّمًا لـ 4 بت مباشرة:
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
import torch
bnb = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # NF4 من ورقة QLoRA
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True, # تكميم مزدوج: ~0.4 بت/وزن توفير
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Meta-Llama-3-8B-Instruct",
quantization_config=bnb,
device_map="auto",
)
# نموذج 8B نزل من ~16GB لأقل من 6GB VRAM
الطريقة التانية بـ llama.cpp لو عايز ملف GGUF تشغّله على أي جهاز:
# 1) حوّل أوزان الـ Hugging Face لـ GGUF بدقة كاملة
python convert_hf_to_gguf.py ./Meta-Llama-3-8B --outfile llama3-8b-f16.gguf
# 2) كمّم لـ 4 بت — Q4_K_M توازن جيد بين الحجم والدقة
./llama-quantize llama3-8b-f16.gguf llama3-8b-q4_k_m.gguf Q4_K_M
الأرقام: الذاكرة والدقة والسرعة
لنموذج 70B: FP16 ≈ 140GB، INT8 ≈ 70GB، INT4 ≈ 35–40GB بعد إضافة overhead عوامل القياس. يعني تقريبًا 4 أضعاف توفير عند 4 بت. النتيجة العملية: نموذج كان محتاج 2×80GB يقدر يقعد على كارت واحد بـ 48GB (زي A6000).
الدقة: في القياسات المنشورة، تكميم 4 بت بطرق زي GPTQ وAWQ بيبقّي فرق الحيرة (perplexity) صغيرًا على WikiText-2، غالبًا في حدود أجزاء بسيطة من الوحدة للنماذج الكبيرة. القاعدة المهمة: كل ما النموذج أكبر، خسارة الدقة من التكميم أقل. النماذج الصغيرة (≤ 3B) بتتأثر أوضح.
الـ trade-off هنا: بتكسب ~4x ذاكرة و في الغالب سرعة توليد أعلى لأن فك التوليد (decoding) محدود بباندويدث الذاكرة. بتخسر فرق دقة صغير + احتمال overhead بسيط في فك التكميم على بعض النوى القديمة. الافتراض إنك بتعمل inference مش تدريب كامل.
متى لا تستخدم التكميم
ماتكمّمش لـ 4 بت لو بتعمل تدريب كامل بدقة عالية للأوزان — استخدم QLoRA اللي بيدرّب طبقات LoRA فوق قاعدة مكمّمة بدل ما يكمّم التدريب نفسه. وماتنزلش لـ 4 بت لو نموذجك صغير جدًا وحساس، أو لو مهمتك محتاجة دقة رقمية عالية (حسابات دقيقة، كود حسّاس)، ابدأ بـ 8 بت وقيس. ولو الذاكرة مش مشكلة عندك أصلاً، التكميم بيضيف تعقيد بلا مكسب.
الخطوة التالية
خُد نموذج 8B، حمّله مرة بـ FP16 ومرة بـ load_in_4bit=True، وقِس حاجتين: الـ VRAM بـ nvidia-smi، والحيرة على 500 جملة من بياناتك. لو الفرق في الحيرة أقل من 1–2% والذاكرة نزلت للربع، انقل باقي نماذجك لـ 4 بت. لو الفرق كبير، اطلع لـ Q5 أو 8 بت.
المصادر
- Dettmers et al., 2022 — LLM.int8(): arxiv.org/abs/2208.07339
- Dettmers et al., 2023 — QLoRA (NF4 + Double Quantization): arxiv.org/abs/2305.14314
- Frantar et al., 2022 — GPTQ: arxiv.org/abs/2210.17323
- Lin et al., 2023 — AWQ: arxiv.org/abs/2306.00978
- توثيق Transformers لـ bitsandbytes: huggingface.co/docs/transformers/quantization/bitsandbytes
- llama.cpp (GGUF و k-quants): github.com/ggml-org/llama.cpp