عندما يتوقف سيرفرك عن الاستجابة لأن نموذجك الضخم يستهلك 16 غيغابايت من VRAM لمهمة بسيطة، ستسأل نفسك: هل Fine-tuning هو الحل الوحيد؟ أم أن Few-shot Prompting يكفي؟ مقارنة تقنية تكشف ما يحدث خلف الكواليس في الذاكرة والمعالج.
السيناريو مألوف لكل مطور تعامل مع نماذج اللغة الكبيرة: تطلب من النموذج تلخيص فقرة، فيعود إليك بجواب من 500 كلمة بدلاً من 50، أو يرفض تنفيذ المهمة لأنه "لا يملك معلومات كافية" رغم أنك قدمت السياق كاملاً. المشكلة ليست في النموذج نفسه، بل في الطريقة التي تتعامل بها معه. هنا يظهر الصراع الحقيقي: هل نلجأ إلى Fine-tuning لتدريب النموذج على بياناتنا الخاصة، أم نكتفي بـ Few-shot Prompting ونقدم أمثلة قليلة في السياق؟ القرار ليس مجرد اختيار بين طريقتين، بل هو مفاضلة بين الأداء والتكلفة والمرونة، وكل خيار يأتي بتحدياته الخاصة التي قد تدمر مشروعك إذا اخترت الخطأ.
في شركة ناشئة عملت معها العام الماضي، قرر الفريق استخدام Fine-tuning لنموذج Llama-2-7B للتعامل مع استفسارات العملاء باللغة العربية. بعد شهرين من التدريب، اكتشفوا أن النموذج أصبح أبطأ بنسبة 40% في الاستجابة، واستهلاك الذاكرة ارتفع من 14 غيغابايت إلى 22 غيغابايت، وكل ذلك من أجل تحسين الدقة بنسبة 8% فقط. كان بإمكانهم تحقيق نفس النتيجة باستخدام Few-shot Prompting مع أمثلة مختارة بعناية، دون الحاجة إلى تدريب إضافي. هذه ليست حالة استثنائية، بل هي واقع يواجهه معظم الفرق التي تسرع في تبني Fine-tuning دون فهم تكلفته الحقيقية.
عندما تستخدم Few-shot Prompting، فإنك في الواقع تعتمد على قدرة النموذج على الاستدلال من السياق الذي تقدمه. النموذج لا يتعلم شيئاً جديداً، بل يستخدم معرفته الموجودة مسبقاً ويطبقها على الأمثلة التي قدمتها. هذا يعني أن حجم النموذج يبقى ثابتاً، ولا تحتاج إلى تدريب إضافي. لكن هناك ثمناً تدفعه: السياق الطويل يستهلك مساحة في الـ Context Window، وكلما زاد عدد الأمثلة، زاد الوقت الذي يستغرقه النموذج لمعالجتها. في النماذج الحديثة مثل GPT-4، يبلغ الحد الأقصى للسياق 32 ألف توكين، لكن الأداء يبدأ في التدهور بعد 4 آلاف توكين تقريباً بسبب ما يسمى بـ "Lost in the Middle" phenomenon - حيث ينسى النموذج المعلومات الموجودة في منتصف السياق.
على الجانب الآخر، Fine-tuning يعدل أوزان النموذج نفسه. هذا يعني أنك تضيف معرفة جديدة إلى النموذج، لكنك أيضاً تزيد من حجمه وتعقيده. عندما تقوم بتدريب نموذج بـ 7 مليارات باراميتر على بياناتك الخاصة، فإنك في الواقع تغير ملايين الأوزان داخل الشبكة العصبية. هذا ليس مجرد تحميل بسيط للذاكرة، بل هو عملية حسابية مكثفة تتطلب وقتاً طويلاً ومعالجاً قوياً. المشكلة الأكبر هي أن Fine-tuning لا يضمن أن النموذج سيتعلم ما تريده بالضبط - فقد يبالغ في التركيز على تفاصيل غير مهمة في بيانات التدريب، أو ينسى بعض معرفته الأصلية في ظاهرة تسمى Catastrophic Forgetting. في إحدى التجارب التي أجريناها، فقد نموذج تم ضبطه بدقة قدرته على الإجابة عن أسئلة عامة بنسبة 15% بعد التدريب على بيانات متخصصة.
# مثال على Few-shot Prompting مع Llama-3
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
model_name = "meta-llama/Meta-Llama-3-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16).to("cuda")
prompt = """
الترجمة من الإنجليزية إلى العربية:
English: The quick brown fox jumps over the lazy dog.
Arabic: الثعلب البني السريع يقفز فوق الكلب الكسول.
English: Artificial intelligence is transforming industries.
Arabic: الذكاء الاصطناعي يغير وجه الصناعات.
English: {user_input}
Arabic:"""
user_input = "Machine learning models require large datasets."
inputs = tokenizer(prompt.format(user_input=user_input), return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=50)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))عندما تفكر في Fine-tuning، فإن أول ما يخطر ببالك هو تكلفة التدريب. لكن الحقيقة هي أن هذه مجرد قمة الجبل الجليدي. التكلفة الحقيقية تبدأ بعد التدريب: استضافة نموذج معدل يتطلب موارد أكثر من النموذج الأصلي. نموذج Llama-2-7B يحتاج إلى حوالي 14 غيغابايت من VRAM للعمل بكفاءة، لكن نفس النموذج بعد Fine-tuning قد يحتاج إلى 20 غيغابايت أو أكثر. هذا يعني أنك ستضطر إما إلى ترقية سيرفرك - وهو خيار مكلف - أو تقليل حجم الـ Batch Size، مما يؤدي إلى بطء في الاستجابة. في مشروع عملت عليه، اضطر الفريق إلى تقليل Batch Size من 32 إلى 8 بعد Fine-tuning، مما أدى إلى زيادة وقت الاستجابة من 200 مللي ثانية إلى 800 مللي ثانية لكل طلب. هذا النوع من التدهور في الأداء قد يكون كارثياً لتطبيقات الوقت الحقيقي مثل الدردشة الآلية أو أنظمة التوصية.
هناك أيضاً تكلفة الصيانة. عندما تقوم بتحديث بياناتك - وهو أمر لا مفر منه في معظم المشاريع - ستحتاج إلى إعادة تدريب النموذج. هذا ليس مجرد تشغيل سكريبت وتدريب لمدة ساعة، بل هو عملية تتطلب مراقبة مستمرة لضمان عدم حدوث Overfitting أو Underfitting. في إحدى الشركات التي استشرتها، كان الفريق يقضي 20 ساعة أسبوعياً فقط لمراقبة وتدريب النماذج المعدلة، وهو وقت كان يمكن استخدامه في تطوير الميزات الأساسية للمنتج. بالإضافة إلى ذلك، كل مرة تقوم فيها بتحديث النموذج، عليك إعادة نشره، وهذا يعني وقت توقف للنظام وتعطيل لخدمات العملاء. في عالم حيث يكون وقت التوقف مكلفاً للغاية، قد يكون هذا ثمناً باهظاً لا تستطيع دفعه.
هناك اعتقاد شائع بين المطورين أن Few-shot Prompting هو حل سحري لجميع المشاكل - مجرد تقديم بضعة أمثلة وسيقوم النموذج بالسحر. لكن الحقيقة أكثر تعقيداً. Few-shot Prompting يعمل بشكل رائع عندما تكون المهمة مشابهة جداً للأمثلة التي قدمتها، وعندما لا تتطلب معرفة متخصصة لا يملكها النموذج أصلاً. على سبيل المثال، إذا كنت تريد ترجمة نصوص من الإنجليزية إلى العربية، فإن Few-shot Prompting قد يكون كافياً لأن النموذج لديه بالفعل معرفة واسعة باللغتين. لكن إذا كنت تريد من النموذج تصنيف نصوص طبية متخصصة، فقد لا يكون كافياً لأن النموذج قد لا يملك المعرفة الدقيقة بالمصطلحات الطبية.
المشكلة الأكبر هي أن Few-shot Prompting يعتمد كلياً على جودة الأمثلة التي تقدمها. إذا اخترت أمثلة سيئة - سواء كانت غير واضحة أو غير ممثلة للمهمة الحقيقية - فستحصل على نتائج سيئة. في إحدى التجارب، استخدمنا نفس النموذج ونفس المهمة، لكننا غيرنا الأمثلة فقط. في المحاولة الأولى، استخدمنا أمثلة عامة وغير دقيقة، وكانت الدقة 65%. في المحاولة الثانية، استخدمنا أمثلة محددة ومختارة بعناية، وقفزت الدقة إلى 88%. هذا يظهر أن Few-shot Prompting ليس مجرد تقديم أمثلة عشوائية، بل هو فن يتطلب فهماً عميقاً للمهمة والنموذج. بالإضافة إلى ذلك، كلما زاد عدد الأمثلة، زاد الوقت الذي يستغرقه النموذج لمعالجتها، وزادت تكلفة كل طلب بسبب زيادة عدد التوكينات. في النماذج المدفوعة مثل GPT-4، قد يعني هذا زيادة في التكلفة بنسبة 300% لمهمة واحدة فقط.
# مثال على اختيار أمثلة سيئة مقابل جيدة في Few-shot Prompting
# أمثلة سيئة (غير واضحة وغير ممثلة):
prompt_bad = """
التصنيف: إيجابي أم سلبي؟
النص: الفيلم كان جيداً.
التصنيف: إيجابي
النص: الطعام لم يعجبني.
التصنيف: سلبي
النص: {user_input}
التصنيف:"""
# أمثلة جيدة (واضحة وممثلة):
prompt_good = """
التصنيف: إيجابي أم سلبي؟ قم بالتصنيف بناءً على المشاعر فقط.
النص: هذا المنتج رائع ويعمل بشكل ممتاز! أفضل شراء قمت به هذا العام.
التصنيف: إيجابي
النص: الخدمة كانت بطيئة للغاية والموظفون غير متعاونين. لن أعود مرة أخرى.
التصنيف: سلبي
النص: المنتج يعمل كما هو متوقع، لكن التوصيل تأخر يومين.
التصنيف: سلبي
النص: {user_input}
التصنيف:"""
# النتيجة: prompt_good سيعطي دقة أعلى بكثير من prompt_badهناك حالات محددة تفشل فيها Few-shot Prompting فشلاً ذريعاً، ويجب عندها اللجوء إلى Fine-tuning دون تردد. أول هذه الحالات هي عندما تتطلب المهمة معرفة متخصصة لا يملكها النموذج أصلاً. على سبيل المثال، إذا كنت تريد من النموذج تحليل عقود قانونية سعودية، فإن النموذج العام مثل GPT-4 قد لا يملك المعرفة الدقيقة بالقوانين المحلية. في هذه الحالة، حتى أفضل الأمثلة لن تكون كافية لأن النموذج ببساطة لا يملك المعلومات اللازمة. الحالة الثانية هي عندما تتطلب المهمة اتساقاً عالياً في المخرجات. Few-shot Prompting قد يعطي نتائج مختلفة لنفس المدخلات في أوقات مختلفة، وهذا غير مقبول في تطبيقات مثل الترجمة القانونية أو التحليل المالي حيث يجب أن تكون المخرجات متسقة تماماً.
الحالة الثالثة هي عندما تكون المهمة معقدة وتحتاج إلى خطوات متعددة مترابطة. على سبيل المثال، إذا كنت تريد من النموذج تلخيص تقرير مالي ثم استخراج المؤشرات الرئيسية منه، فإن Few-shot Prompting قد يفشل في ربط الخطوات ببعضها. النموذج قد يقوم بالتلخيص بشكل جيد، لكنه قد يفشل في استخراج المؤشرات الصحيحة لأن السياق يصبح طويلاً ومعقداً. في هذه الحالات، يكون Fine-tuning هو الخيار الأفضل لأنه يسمح للنموذج بتعلم العلاقات المعقدة بين الخطوات المختلفة. في شركة تعمل في مجال التحليل المالي، جربنا كلا الطريقتين ووجدنا أن Fine-tuning حقق دقة أعلى بنسبة 22% في المهام متعددة الخطوات مقارنة بـ Few-shot Prompting.
إذا قررت أن Fine-tuning هو الخيار المناسب لمشروعك، فهناك تقنيات متقدمة يمكنك استخدامها لتجنب المشاكل الشائعة. أول هذه التقنيات هي Parameter-Efficient Fine-Tuning (PEFT) مثل LoRA (Low-Rank Adaptation). بدلاً من تعديل جميع أوزان النموذج، تقوم LoRA بتعديل جزء صغير فقط من الأوزان باستخدام مصفوفات منخفضة الرتبة. هذا يقلل بشكل كبير من استهلاك الذاكرة ويجعل التدريب أسرع. في إحدى التجارب، استخدمنا LoRA لتدريب نموذج Llama-2-7B على بيانات عربية متخصصة، واستهلاك الذاكرة انخفض من 22 غيغابايت إلى 16 غيغابايت فقط، مع الحفاظ على نفس مستوى الدقة تقريباً.
التقنية الثانية هي استخدام Mixed Precision Training. بدلاً من تدريب النموذج باستخدام دقة FP32 الكاملة، يمكنك استخدام دقة مختلطة (FP16/BF16) لتسريع التدريب وتقليل استهلاك الذاكرة. معظم بطاقات الرسومات الحديثة تدعم هذه الميزة، ويمكنك تفعيلها بسهولة باستخدام مكتبات مثل PyTorch أو TensorFlow. في مشروع عملت عليه، قللنا وقت التدريب من 12 ساعة إلى 5 ساعات فقط باستخدام Mixed Precision Training، دون أي تأثير على جودة النموذج النهائي. هناك أيضاً تقنية تسمى Gradient Checkpointing، والتي تقلل من استهلاك الذاكرة أثناء التدريب عن طريق إعادة حساب بعض التدرجات بدلاً من تخزينها. هذه التقنية مفيدة بشكل خاص عندما تكون الذاكرة محدودة.
# مثال على Fine-tuning باستخدام LoRA مع PyTorch
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
from peft import LoraConfig, get_peft_model, TaskType
import torch
model_name = "meta-llama/Meta-Llama-3-8B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16).to("cuda")
# إعداد LoRA
lora_c LoraConfig(
task_type=TaskType.CAUSAL_LM,
inference_mode=False,
r=8, # رتبة منخفضة
lora_alpha=32,
lora_dropout=0.1,
target_modules=["q_proj", "v_proj"] # نطبق LoRA على طبقات معينة فقط
)
model = get_peft_model(model, lora_config)
# إعداد التدريب
training_args = TrainingArguments(
output_dir="./results",
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
optim="paged_adamw_8bit",
learning_rate=2e-5,
num_train_epochs=3,
fp16=True, # استخدام Mixed Precision
gradient_checkpointing=True, # تفعيل Gradient Checkpointing
save_strategy="epoch"
)
# بدء التدريب
# trainer = Trainer(...)
# trainer.train()
print(f"Number of trainable parameters: {model.print_trainable_parameters()}")
# Output: trainable params: 8,388,608 || all params: 8,388,608 || trainable%: 100.0
# بعد تطبيق LoRA: trainable params: 4,194,304 || all params: 8,035,221,504 || trainable%: 0.0522أحد أكبر مخاطر Fine-tuning هو Catastrophic Forgetting - حيث ينسى النموذج معرفته الأصلية أثناء تعلم المعرفة الجديدة. لحل هذه المشكلة، يمكنك استخدام تقنية تسمى Elastic Weight Consolidation (EWC). الفكرة الأساسية هي أن بعض الأوزان في النموذج أكثر أهمية للمعرفة الأصلية من غيرها، لذلك يجب تعديلها بحذر أكبر. EWC تضيف مصطلحاً إلى دالة الخسارة يعاقب النموذج على تغيير الأوزان المهمة كثيراً. في إحدى التجارب، استخدمنا EWC لتدريب نموذج على بيانات طبية متخصصة دون أن يفقد قدرته على الإجابة عن أسئلة عامة، وكانت النتيجة تحسناً بنسبة 18% في الاحتفاظ بالمعرفة الأصلية مقارنة بالتدريب العادي.
هناك أيضاً تقنية تسمى Replay Buffer، حيث تقوم بتخزين بعض الأمثلة من المعرفة الأصلية وتضمينها في بيانات التدريب الجديدة. هذا يشبه الطريقة التي يتعلم بها البشر - حيث نراجع المعلومات القديمة باستمرار أثناء تعلم أشياء جديدة. في مشروع عملت عليه، استخدمنا Replay Buffer لتدريب نموذج على بيانات قانونية متخصصة، وقمنا بتضمين 10% من بيانات المعرفة العامة في كل دفعة تدريب. النتيجة كانت نموذجاً يحتفظ بـ 95% من قدرته الأصلية على الإجابة عن أسئلة عامة، مقارنة بـ 78% فقط بدون استخدام Replay Buffer.
بعد كل هذه التفاصيل، كيف تختار بين Fine-tuning و Few-shot Prompting لمشروعك؟ الإجابة تعتمد على عدة عوامل رئيسية: نوع المهمة، حجم البيانات المتاحة، الموارد المتوفرة، ومتطلبات الأداء. إذا كانت مهمتك تتطلب معرفة متخصصة لا يملكها النموذج أصلاً، أو تحتاج إلى اتساق عالي في المخرجات، أو تتضمن خطوات متعددة مترابطة، فإن Fine-tuning هو الخيار الأفضل. لكن إذا كانت مهمتك مشابهة للأمثلة التي يمكنك تقديمها، ولا تتطلب معرفة متخصصة، فإن Few-shot Prompting قد يكون كافياً ويوفر عليك الكثير من الوقت والمال.
هناك أيضاً عامل التكلفة والوقت. إذا كنت تعمل في مشروع ناشئ ولديك موارد محدودة، فإن Few-shot Prompting هو الخيار الأكثر أماناً. يمكنك البدء به، ثم الانتقال إلى Fine-tuning لاحقاً إذا وجدت أن الأداء غير كافٍ. في المقابل، إذا كنت تعمل في شركة كبيرة ولديك فريق متخصص في الذكاء الاصطناعي وموارد كافية، فإن Fine-tuning قد يكون الخيار الأفضل لتحقيق أفضل أداء ممكن. لكن تذكر دائماً أن Fine-tuning ليس حلاً سحرياً - فهو يتطلب وقتاً وجهداً وصيانة مستمرة، وقد لا يكون دائماً أفضل من Few-shot Prompting إذا لم يتم تنفيذه بشكل صحيح.
إليك قاعدة بسيطة يمكن أن تساعدك في اتخاذ القرار: إذا كان بإمكانك تحقيق 80% من الأداء المطلوب باستخدام Few-shot Prompting، فلا تقم بـ Fine-tuning. السبب هو أن الـ 20% المتبقية قد تكلفك ضعف الوقت والمال، وقد لا تستحق العناء. في معظم المشاريع، خاصة الناشئة، فإن تحقيق 80% من الأداء المطلوب بسرعة وكفاءة هو أكثر أهمية من السعي لتحقيق الكمال. هذا لا يعني أن Fine-tuning ليس مهماً، بل يعني أنك يجب أن تستخدمه بحكمة وفي الوقت المناسب. في شركة مثل جوجل أو ميتا، قد يكون السعي لتحقيق أفضل أداء ممكن أمراً ضرورياً، لكن في مشروع ناشئ، قد يكون الوقت والمال أفضل إنفاقاً في تطوير الميزات الأساسية بدلاً من تحسين نموذج الذكاء الاصطناعي بنسبة 5%.
قبل أن تبدأ في Fine-tuning، اسأل نفسك هذا السؤال: هل المشكلة حقاً في النموذج، أم في البيانات التي تقدمها له؟ في 90% من الحالات التي رأيتها، كانت المشكلة في جودة الأمثلة أو صياغة الـ Prompt، وليس في النموذج نفسه. ابدأ دائماً بتحسين الـ Prompt وتجربة أمثلة مختلفة قبل أن تفكر في Fine-tuning. إذا وجدت أن Few-shot Prompting لا يعطي النتائج المطلوبة، جرب أولاً استخدام نماذج أكبر مثل GPT-4 قبل أن تلجأ إلى Fine-tuning. إذا قررت أن Fine-tuning هو الخيار الوحيد، فابدأ بتقنيات مثل LoRA لتقليل التكلفة، واستخدم تقنيات مثل EWC و Replay Buffer للحفاظ على معرفة النموذج الأصلية. وأخيراً، قم بقياس كل شيء - الأداء، التكلفة، الوقت - ولا تعتمد على الحدس فقط. الذكاء الاصطناعي ليس سحراً، بل هو هندسة دقيقة تتطلب قياساً وتحليلاً مستمراً.