الضبط الدقيق باستخدام LoRA وHugging Face PEFT
اضبطوا رتبة LoRA وقيمة alpha والوحدات المستهدفة، ونفذوا ضبطًا دقيقًا خاضعًا للإشراف باستخدام TRL SFTTrainer، وراقبوا خسارة التدريب، واحفظوا نقاط التحقق المدمجة ونقاط المحولات فقط.
الضبط الدقيق باستخدام LoRA وHugging Face PEFT درس مجاني في AI Engineering Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Engineering Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.
لماذا نستخدم LoRA بدلًا من الضبط الدقيق الكامل؟
يحدّث الضبط الدقيق الكامل كل مَعلمة في النموذج. وبالنسبة إلى نموذج يحتوي على 7 مليارات مَعلمة بدقة float32، يتطلب ذلك نحو 28GB من ذاكرة GPU للأوزان وحدها، إضافةً إلى حالات المُحسِّن والتدرجات والتنشيطات، ليصل الإجمالي بسهولة إلى 80-120GB. أما LoRA (Low-Rank Adaptation) فيضيف عددًا ضئيلًا من المَعلمات القابلة للتدريب (عادةً ما يتراوح بين 0.1% و1% من الإجمالي) على هيئة أزواج من المصفوفات منخفضة الرتبة تُطبَّق على طبقات محددة، مما يقلل متطلبات GPU بمقدار يتراوح بين 10 و50 مرة مع تحقيق نتائج مماثلة.
# LoRA math intuition:
# Full fine-tuning: update W (large matrix, e.g., 4096 x 4096 = 16.7M parameters)
# LoRA: instead train W = W_0 + A @ B where:
# A has shape (4096, r) - only r*4096 params
# B has shape (r, 4096) - only r*4096 params
# r (rank) is typically 4, 8, or 16 - much smaller than 4096
# Memory comparison for 7B model:
# Full fine-tuning: ~80GB GPU RAM
# LoRA (rank=8): ~12GB GPU RAM - fits on a single A100 or 3090
print('LoRA makes fine-tuning accessible without massive GPU clusters')تثبيت المكتبات المطلوبة
يتطلب الضبط الدقيق باستخدام LoRA مع Hugging Face ثلاث مكتبات: transformers (لتحميل النماذج وتجزئة الرموز)، وpeft (للضبط الدقيق الفعّال من حيث عدد المَعلمات، والذي يطبّق LoRA)، وtrl (للتعلّم التعزيزي باستخدام Transformer، والذي يوفر SFTTrainer للضبط الدقيق الخاضع للإشراف). وتوفر هذه المكتبات مجتمعةً سير عمل عالي المستوى وجاهزًا للإنتاج للضبط الدقيق.
# pip install transformers peft trl accelerate bitsandbytes datasets
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, TaskType
from trl import SFTTrainer, SFTConfig
from datasets import Dataset
import torch
print('Libraries imported successfully')
print(f'GPU available: {torch.cuda.is_available()}')
if torch.cuda.is_available():
print(f'GPU: {torch.cuda.get_device_name(0)}')
print(f'GPU memory: {torch.cuda.get_device_properties(0).total_memory / 1e9:.1f} GB')تحميل النموذج الأساسي مع التكميم
في معظم حالات الضبط الدقيق باستخدام LoRA، حمّلوا النموذج الأساسي باستخدام التكميم إلى 4 بت عبر bitsandbytes. فهذا يقلل البصمة الذاكرية للنموذج الأساسي بنسبة 75% (إذ ينخفض نموذج 7B من نحو 14GB إلى نحو 4GB) مع الحفاظ على معظم قدرات النموذج. ولا تُدرَّب إلا طبقات محوّل LoRA بدقة كاملة. ويُسمّى الجمع بين التكميم إلى 4 بت وLoRA باسم QLoRA، وهو ما يجعل الضبط الدقيق لنماذج 7B متاحًا على وحدات GPU المخصصة للمستهلكين.
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
MODEL_NAME = 'mistralai/Mistral-7B-Instruct-v0.2' # or 'meta-llama/Llama-3.2-3B-Instruct'
# 4-bit quantization config (QLoRA)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True, # quantize base model to 4-bit
bnb_4bit_quant_type='nf4', # NF4 quantization type
bnb_4bit_compute_dtype=torch.float16, # compute in float16
bnb_4bit_use_double_quant=True # double quantization for extra savings
)
# Load quantized model
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
quantization_config=bnb_config,
device_map='auto', # automatically distribute across GPUs
trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
tokenizer.pad_token = tokenizer.eos_token # required for training batches
print(f'Model loaded. Parameters: {model.num_parameters():,}')ضبط المعلمات الفائقة لـ LoRA
أهم ثلاث معلمات فائقة في LoRA هي: r (الرتبة) — بُعد المصفوفات منخفضة الرتبة؛ فكلما ارتفعت الرتبة زاد عدد المَعلمات القابلة للتدريب وزادت قدرة التكيّف التعبيرية، لكن زادت معها الذاكرة وخطر فرط التكيّف. وlora_alpha — معامل تحجيم يُضبط عادةً على ضعف الرتبة. وtarget_modules — مصفوفات الأوزان التي سيُطبَّق عليها LoRA؛ وتُعد طبقات الانتباه (q_proj, v_proj) الخيار الأكثر شيوعًا. ابدؤوا بالقيمة r=8 ثم اضبطوها وفقًا لذلك.
from peft import LoraConfig, TaskType
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM, # causal language modeling
r=8, # rank: 4, 8, 16, 32 — higher = more params
lora_alpha=16, # scaling: usually 2*r
lora_dropout=0.1, # dropout on LoRA layers for regularization
target_modules=['q_proj', 'v_proj', # which weight matrices to adapt
'k_proj', 'o_proj', # common to target all attention projections
'gate_proj', 'up_proj', 'down_proj'], # and FFN layers
bias='none', # do not adapt bias parameters
)
# Wrap the model with LoRA adapters
from peft import get_peft_model, prepare_model_for_kbit_training
model = prepare_model_for_kbit_training(model) # prepares quantized model for training
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Output: trainable params: 4,194,304 || all params: 3,752,071,168 || trainable%: 0.11%إعداد مجموعة البيانات
يتوقع SFTTrainer مجموعات بيانات بتنسيق محدد. وأبسط تنسيق هو مجموعة بيانات تحتوي على عمود واحد باسم text يتضمن سلسلة المطالبة + الاستجابة المنسقة بالكامل. استخدموا قالب المحادثة الخاص بـ tokenizer لتنسيق أمثلة المحادثات بصورة متسقة. ويتولى SFTTrainer تجزئة الرموز وتجميعها وإخفاء الخسارة (بحساب الخسارة على استجابات المساعد فقط، وليس على مطالبة الإدخال).
from datasets import Dataset
import json
def load_and_format_dataset(jsonl_path: str, tokenizer) -> Dataset:
examples = []
with open(jsonl_path) as f:
for line in f:
ex = json.loads(line.strip())
# Apply chat template to format as expected by the model
formatted = tokenizer.apply_chat_template(
ex['messages'],
tokenize=False,
add_generation_prompt=False
)
examples.append({'text': formatted})
return Dataset.from_list(examples)
# Load training and validation datasets
train_dataset = load_and_format_dataset('train.jsonl', tokenizer)
val_dataset = load_and_format_dataset('validation.jsonl', tokenizer)
print(f'Train examples: {len(train_dataset)}')
print(f'Validation examples: {len(val_dataset)}')
print('Sample formatted text:')
print(train_dataset[0]['text'][:300])التدريب باستخدام SFTTrainer
يغلّف SFTTrainer من TRL أداة Hugging Face Trainer مع إعدادات افتراضية للضبط الدقيق الخاضع للإشراف. اضبطوه باستخدام معلمات التدريب الفائقة: عدد العصور (تكون 1-3 كافية عادةً للضبط الدقيق للتعليمات)، وحجم الدفعة، وخطوات تراكم التدرج (لمحاكاة دفعات أكبر مع ذاكرة محدودة)، ومعدل التعلم (تُعد القيمة 2e-4 نقطة بداية شائعة)، ومجلد الإخراج لنقاط التحقق.
from trl import SFTTrainer, SFTConfig
training_args = SFTConfig(
output_dir='./fine-tuned-model',
num_train_epochs=2, # 2-3 epochs for instruction fine-tuning
per_device_train_batch_size=4, # increase if GPU memory allows
gradient_accumulation_steps=4, # effective batch size = 4*4 = 16
learning_rate=2e-4, # typical LoRA learning rate
warmup_ratio=0.05, # warmup for 5% of steps
lr_scheduler_type='cosine', # cosine decay learning rate schedule
logging_steps=10,
eval_strategy='steps',
eval_steps=50, # evaluate on validation set every 50 steps
save_steps=100,
max_seq_length=2048, # max token length per example
fp16=True, # mixed precision training
report_to='none' # or 'wandb' for experiment tracking
)
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=val_dataset,
)
print('Starting LoRA fine-tuning...')
trainer.train()مراقبة تقدم التدريب
راقبوا أثناء التدريب مقياسين أساسيين: يجب أن تنخفض خسارة التدريب باطراد. وينبغي أن تنخفض خسارة التحقق في البداية، ثم تستقر أو ترتفع قليلًا (بسبب فرط التكيّف). إذا ارتفعت خسارة التحقق ارتفاعًا ملحوظًا بينما واصلت خسارة التدريب الانخفاض، فأوقفوا التدريب مبكرًا؛ فهذا يعني أن النموذج يحفظ أمثلة التدريب بدلًا من التعميم. وتكون نقطة التوقف المثلى قبل بدء ارتفاع خسارة التحقق مباشرةً.
# Reading training logs
# Training step logs look like:
# {'loss': 1.4523, 'grad_norm': 0.85, 'learning_rate': 0.0002, 'epoch': 0.2, 'step': 20}
# {'loss': 1.2341, 'grad_norm': 0.72, 'learning_rate': 0.00018, 'epoch': 0.4, 'step': 40}
# Validation results look like:
# {'eval_loss': 1.1823, 'eval_runtime': 12.3, 'eval_samples_per_second': 8.1, 'step': 50}
# {'eval_loss': 1.0923, 'eval_runtime': 12.1, 'eval_samples_per_second': 8.3, 'step': 100}
# {'eval_loss': 1.1234, 'eval_runtime': 12.4, 'eval_samples_per_second': 8.2, 'step': 150}
# ^ validation loss went UP at step 150 - overfitting starting
# Load the best checkpoint (lowest validation loss)
from transformers import TrainerCallback
print('Best model checkpoint is saved automatically by SFTTrainer (load_best_model_at_end=True)')حفظ محوّلات LoRA ودمجها
بعد التدريب، احفظوا أوزان محوّل LoRA منفصلةً عن النموذج الأساسي. فالمحوّل صغير الحجم (من بضعة MB إلى بضع مئات من MB) ويمكن تطبيقه على النموذج الأساسي وقت الاستدلال. وللنشر في بيئة الإنتاج، يمكنكم أيضًا دمج أوزان LoRA في النموذج الأساسي، لإنشاء ملف نموذج واحد لا يتطلب مكتبة PEFT وقت الاستدلال، مما يقلل العبء الإضافي للاستدلال.
# Save only the LoRA adapter (tiny - typically 10-100MB)
model.save_pretrained('./lora-adapter-only')
tokenizer.save_pretrained('./lora-adapter-only')
# Load the adapter for inference (requires base model + peft)
from peft import PeftModel
base_model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, torch_dtype=torch.float16, device_map='auto')
model_with_adapter = PeftModel.from_pretrained(base_model, './lora-adapter-only')
# Alternative: Merge adapter into base model (no PEFT needed at inference)
print('Merging LoRA weights into base model...')
merged_model = model_with_adapter.merge_and_unload() # creates a regular model
merged_model.save_pretrained('./merged-model')
print('Merged model saved - can be used with standard transformers, no PEFT needed')تشغيل الاستدلال على النموذج المُحسَّن
اختبروا نموذجكم المُحسَّن على مجموعة من المطالبات المحجوزة قبل إعلان نجاحه. قارنوا المخرجات جنبًا إلى جنب مع النموذج الأساسي باستخدام المطالبات نفسها، للتحقق من أن الضبط الدقيق حقق أهدافه. وافحصوا الحالات التي يُفترض أن يتعامل معها بصورة أفضل (المهمة المستهدفة)، وكذلك الحالات التي ينبغي أن يظل قادرًا على التعامل معها جيدًا (المهام العامة التي لا تريدون أن يتدهور أداؤه فيها).
def generate(model, tokenizer, prompt: str, max_new_tokens=512) -> str:
inputs = tokenizer(prompt, return_tensors='pt').to(model.device)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=max_new_tokens,
temperature=0.1,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
# Decode only the new tokens (not the input prompt)
new_tokens = outputs[0][inputs['input_ids'].shape[1]:]
return tokenizer.decode(new_tokens, skip_special_tokens=True)
# Compare base vs fine-tuned
test_prompt = 'Extract JSON from: "Alice Johnson, 28, software engineer in NYC since 2021"'
print('=== BASE MODEL ===')
print(generate(base_model, tokenizer, test_prompt))
print('\n=== FINE-TUNED MODEL ===')
print(generate(merged_model, tokenizer, test_prompt))ملخص المعلمات الفائقة الأساسية لـ LoRA
لضبط LoRA وفق حالة استخدامكم، ابدؤوا بهذه القيم الافتراضية وعدّلوا معلمة واحدة في كل مرة. تُعد r=8 نقطة بداية آمنة؛ فارفعوها إلى 16 أو 32 إذا احتاج النموذج إلى قدرة تعبيرية أكبر. ويُعد lora_alpha = 2*r خيارًا مستقرًا. ويناسب معدل التعلم 2e-4 معظم حالات الضبط الدقيق للتعليمات؛ فاخفضوه إلى 1e-4 إذا لاحظتم عدم استقرار خسارة التدريب. أما العصور 1-3، فأوقفوا التدريب عندما تتوقف خسارة التحقق عن الانخفاض.
متى تستخدمون الضبط الدقيق من OpenAI بدلًا من ذلك؟
يتطلب Hugging Face PEFT LoRA وحدة GPU. وإذا لم تتوفر لديكم بنية تحتية لوحدات GPU، فإن واجهة الضبط الدقيق البرمجية من OpenAI تمثل بديلًا مُدارًا يتولى بنية التدريب التحتية نيابةً عنكم. ارفعوا ملف JSONL الخاص بكم، واستدعوا الواجهة البرمجية لبدء عملية تدريب، وستتلقون معرّف نموذج مُحسَّن يمكنكم استخدامه في استدعاءات الواجهة البرمجية. ويدعم الضبط الدقيق من OpenAI النموذجين GPT-4o-mini وGPT-3.5-turbo. وتكلفته أعلى لكل رمز، لكنه يلغي إدارة البنية التحتية بالكامل.
from openai import OpenAI
client = OpenAI()
# Upload training file
train_file = client.files.create(
file=open('train.jsonl', 'rb'),
purpose='fine-tune'
)
val_file = client.files.create(
file=open('validation.jsonl', 'rb'),
purpose='fine-tune'
)
# Create fine-tuning job
job = client.fine_tuning.jobs.create(
training_file=train_file.id,
validation_file=val_file.id,
model='gpt-4o-mini', # base model to fine-tune
hyperparameters={
'n_epochs': 3,
'batch_size': 'auto',
'learning_rate_multiplier': 'auto'
}
)
print(f'Fine-tuning job created: {job.id}')
# Monitor: client.fine_tuning.jobs.retrieve(job.id)
# Use: client.chat.completions.create(model=job.fine_tuned_model, ...)تحقق سريع
اختبروا مدى فهمكم للضبط الدقيق باستخدام LoRA من خلال هذا الدرس.
مراجعة الدرس
تعلمتم في هذا الدرس أن LoRA يقلل متطلبات GPU للضبط الدقيق بمقدار يتراوح بين 10 و50 مرة، من خلال تدريب مصفوفات محوّلات صغيرة منخفضة الرتبة بدلًا من جميع مَعلمات النموذج، وأن QLoRA (التكميم إلى 4 بت + LoRA) يجعل ضبط نماذج 7B الدقيق متاحًا على وحدات GPU للمستهلكين بذاكرة VRAM تبلغ نحو 12GB، وأن SFTTrainer من TRL يوفر واجهة API عالية المستوى تتولى تجزئة الرموز وتجميعها وإخفاء الخسارة وحفظ نقاط التحقق. بعد ذلك سنقيّم النموذج المُحسَّن وننشره.
الأسئلة الشائعة
هل درس «الضبط الدقيق باستخدام LoRA وHugging Face PEFT» مجاني؟
نعم — نص درس «الضبط الدقيق باستخدام LoRA وHugging Face PEFT» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Engineering Academy، انتقل إلى CoddyKit PRO. تتضمن دورة AI Engineering Academy 4 دروس في المجموع.
ماذا ستتعلم في «الضبط الدقيق باستخدام LoRA وHugging Face PEFT»؟
اضبطوا رتبة LoRA وقيمة alpha والوحدات المستهدفة، ونفذوا ضبطًا دقيقًا خاضعًا للإشراف باستخدام TRL SFTTrainer، وراقبوا خسارة التدريب، واحفظوا نقاط التحقق المدمجة ونقاط المحولات فقط. تتمرن على AI Engineering Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Engineering Academy؟
لا تُشترط خبرة سابقة. AI Engineering Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «الضبط الدقيق باستخدام LoRA وHugging Face PEFT»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Engineering Academy هذا؟
نعم. كل درس في AI Engineering Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- متى يتفوق الضبط الدقيق على هندسة المطالبات
- إعداد مجموعة بيانات تدريب عالية الجودة
- الضبط الدقيق باستخدام LoRA وHugging Face PEFT
- تقييم النموذج المضبوط بدقة ونشره