سه مرحله ساخت مدل — Pre-training، SFT، RLHF

قسمت ۲ ۱۸ دقیقه

سفر یه مدل زبانی از صفر تا قابل استفاده

وقتی با یه مدل مثل ChatGPT یا LLaMA حرف می‌زنی، داری با محصول نهایی یه فرآیند سه مرحله‌ای صحبت می‌کنی. هر مرحله کار خاصی انجام می‌ده و بدون هر کدوم، مدل اونی نیست که الان می‌شناسیش.

فکر کن مثل تربیت یه نیرو توی یه سازمانه: اول دانشگاه می‌ره (Pre-training)، بعد کارآموزی می‌کنه (SFT)، و بعد بازخورد از مشتری‌ها می‌گیره تا رفتارش رو اصلاح کنه (RLHF).

مرحله ۱: Pre-training — همه چیز رو بخون

اینجا مدل از صفر شروع می‌کنه. تریلیون‌ها توکن متن از اینترنت، کتاب‌ها، مقالات و کد رو می‌خونه و یاد می‌گیره که “کلمه بعدی” رو پیش‌بینی کنه. همین — فقط پیش‌بینی کلمه بعدی.

# مفهوم Pre-training — ساده‌سازی شده
# مدل یاد می‌گیره: با توجه به کلمات قبلی، کلمه بعدی چیه؟

text = "هوش مصنوعی در سال‌های اخیر پیشرفت ___"
# مدل باید پیش‌بینی کنه: "چشمگیری" یا "زیادی"

# Loss function: Cross-entropy
# هدف: minimize کردن خطای پیش‌بینی کلمه بعدی
for batch in dataloader:
    input_ids = batch["input_ids"]      # کلمات ورودی
    labels = batch["labels"]            # کلمه بعدی واقعی
    
    outputs = model(input_ids)
    loss = cross_entropy(outputs, labels)
    loss.backward()
    optimizer.step()

مشخصات Pre-training

  • حجم داده: تریلیون‌ها توکن (مثلاً LLaMA 3 روی ۱۵ تریلیون توکن آموزش دیده)
  • هزینه: میلیون‌ها دلار (GPU‌های A100/H100 برای هفته‌ها)
  • نتیجه: یه مدل که زبان رو می‌فهمه ولی هنوز بلد نیست درست جواب بده
  • آیا تو انجامش می‌دی؟ نه! مگه اینکه بودجه چند میلیون دلاری داشته باشی
نکته مهم: مدل بعد از Pre-training هنوز مثل یه فرد باسواد ولی بی‌تجربه‌ست. اگه ازش سوال بپرسی، ممکنه به جای جواب دادن، ادامه متن بده. مثلاً بپرسی “پایتخت ایران کجاست؟” و اون بنویسه “پایتخت ایران کجاست و چه ویژگی‌هایی دارد؟ در این مقاله…”

مرحله ۲: SFT — یادش بده چطور جواب بده

Supervised Fine-Tuning یا SFT مرحله‌ایه که مدل یاد می‌گیره به سوال‌ها جواب بده. بهش هزاران جفت سوال-جواب نشون می‌دی و می‌گی “وقتی کسی اینو پرسید، اینطوری جواب بده.”

# فرمت داده SFT
sft_data = [
    {
        "instruction": "پایتخت ایران کجاست؟",
        "output": "پایتخت ایران تهران است."
    },
    {
        "instruction": "یه تابع پایتون بنویس که اعداد اول رو پیدا کنه.",
        "output": """def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False
    return True"""
    },
    {
        "instruction": "فرق لیست و تاپل در پایتون چیه؟",
        "output": "لیست تغییرپذیره (mutable) ولی تاپل تغییرناپذیره (immutable)..."
    }
]

فرمت رایج‌تر، فرمت مکالمه‌ایه:

# فرمت Chat/Conversation
chat_data = [
    {
        "messages": [
            {"role": "system", "content": "تو یه دستیار هوشمند فارسی‌زبان هستی."},
            {"role": "user", "content": "مرتب‌سازی حبابی رو توضیح بده."},
            {"role": "assistant", "content": "مرتب‌سازی حبابی یه الگوریتم ساده‌ست..."}
        ]
    }
]

مشخصات SFT

  • حجم داده: هزاران تا صدها هزار نمونه
  • هزینه: قابل مدیریت (با یه GPU خوب چند ساعت تا چند روز)
  • نتیجه: مدل بلد شده جواب بده، دستورالعمل اجرا کنه
  • آیا تو انجامش می‌دی؟ بله! این همون Fine-tuning معمولیه

وقتی می‌گیم "Fine-tuning"، معمولاً منظورمون همین مرحله SFT هست. یعنی داری یه مدل از پیش آموزش‌دیده رو روی داده‌های خودت Supervised Fine-tune می‌کنی.

مرحله ۳: RLHF — یاد بگیر چی خوبه چی بد

RLHF مخفف Reinforcement Learning from Human Feedback هست. توی این مرحله، انسان‌ها جواب‌های مدل رو ارزیابی می‌کنن و مدل یاد می‌گیره جواب‌هایی بده که انسان‌ها ترجیح می‌دن.

فرآیند RLHF

# مرحله ۱: جمع‌آوری ترجیحات انسانی
# مدل دو جواب تولید می‌کنه، انسان بهتره رو انتخاب می‌کنه

preferences = [
    {
        "prompt": "فرق TCP و UDP چیه؟",
        "chosen": "TCP یه پروتکل اتصال‌گراست که...",    # جواب بهتر
        "rejected": "TCP و UDP هر دو پروتکلن..."        # جواب بدتر
    }
]

# مرحله ۲: آموزش Reward Model
# یه مدل جداگانه که یاد می‌گیره به جواب‌ها امتیاز بده
reward_model = train_reward_model(preferences)

# مرحله ۳: بهینه‌سازی مدل اصلی با PPO
# مدل سعی می‌کنه جواب‌هایی بده که Reward Model بهشون امتیاز بالا بده
from trl import PPOTrainer

ppo_trainer = PPOTrainer(
    model=sft_model,
    reward_model=reward_model,
    ...
)
ppo_trainer.train()

چرا RLHF مهمه؟

بعد از SFT، مدل بلده جواب بده ولی ممکنه:

  • جواب‌های نامناسب یا خطرناک بده
  • هلوسینیشن داشته باشه (چیزی بسازه که واقعی نیست)
  • خیلی طولانی یا خیلی کوتاه جواب بده
  • لحن نامناسب داشته باشه

RLHF این مشکلات رو تا حد زیادی حل می‌کنه.

مشخصات RLHF

  • پیچیدگی: خیلی بالا — نیاز به Reward Model جداگانه و PPO
  • هزینه: بالا — هم محاسباتی هم نیروی انسانی برای ارزیابی
  • آیا تو انجامش می‌دی؟ احتمالاً نه مستقیم — ولی DPO (که بعداً بررسی می‌کنیم) یه جایگزین ساده‌تره

DPO: جایگزین ساده‌تر RLHF

DPO (Direct Preference Optimization) همون هدف RLHF رو داره ولی بدون نیاز به Reward Model جداگانه. مستقیم از داده‌های ترجیحی یاد می‌گیره. توی اپیزود ۸ مفصل بررسیش می‌کنیم.

# DPO خیلی ساده‌تره
from trl import DPOTrainer

# فقط داده ترجیحی لازمه — بدون Reward Model
trainer = DPOTrainer(
    model=sft_model,
    train_dataset=preference_data,  # chosen + rejected pairs
    ...
)
trainer.train()

خلاصه سه مرحله

  • Pre-training: مدل زبان رو یاد می‌گیره (تریلیون‌ها توکن، میلیون‌ها دلار) — تو انجام نمی‌دی
  • SFT: مدل یاد می‌گیره جواب بده (هزاران نمونه) — این همون Fine-tuning معمولیه
  • RLHF/DPO: مدل یاد می‌گیره بهتر جواب بده (داده ترجیحی) — اختیاری ولی مفید

تو کجای این فرآیند قرار می‌گیری؟

# مسیر عملی Fine-tuning
# ۱. یه مدل Pre-trained انتخاب کن
base_model = "meta-llama/Llama-3.1-8B"          # Pre-training شده

# ۲. یا بهتر: یه مدل Instruct (که SFT هم شده)
instruct_model = "meta-llama/Llama-3.1-8B-Instruct"  # SFT شده

# ۳. Fine-tune کن روی داده خودت (ادامه SFT)
my_model = fine_tune(instruct_model, my_data)

# ۴. اختیاری: DPO برای بهبود کیفیت
my_aligned_model = dpo_train(my_model, preference_data)
توصیه عملی: معمولاً از یه مدل Instruct شروع می‌کنی (مثل Llama-3.1-8B-Instruct) و روی داده‌های خودت SFT انجام می‌دی. اینطوری از مرحله ۱ و ۲ رد شدی و داری مرحله ۲ رو با داده خودت تکرار می‌کنی.

مقایسه مدل‌های Base و Instruct

وقتی توی Hugging Face یه مدل رو نگاه می‌کنی، معمولاً دو نسخه می‌بینی:

  • Base: فقط Pre-training شده (مثل Llama-3.1-8B)
  • Instruct: Pre-training + SFT + RLHF (مثل Llama-3.1-8B-Instruct)
# تفاوت عملی Base و Instruct
from transformers import pipeline

# مدل Base — فقط ادامه متن می‌ده
base = pipeline("text-generation", model="meta-llama/Llama-3.1-8B")
print(base("پایتخت ایران"))
# خروجی: "پایتخت ایران تهران است. تهران بزرگترین شهر ایران و مرکز..."

# مدل Instruct — سوال رو می‌فهمه و جواب می‌ده
instruct = pipeline("text-generation", model="meta-llama/Llama-3.1-8B-Instruct")
print(instruct("پایتخت ایران کجاست؟"))
# خروجی: "پایتخت ایران تهران است."

جمع‌بندی

حالا می‌دونی یه مدل زبانی چه مسیری رو طی می‌کنه تا به اون چیزی که الان استفاده می‌کنی تبدیل بشه. وقتی می‌گیم Fine-tuning، داریم از مرحله SFT حرف می‌زنیم — جایی که می‌تونی با هزینه معقول، مدل رو به سبک خودت در بیاری.

توی اپیزود بعدی، LoRA رو بررسی می‌کنیم — تکنیکی که اجازه می‌ده بدون تغییر کل مدل، فقط یه بخش کوچیک رو آموزش بدی. اینطوری مصرف حافظه به شدت کم می‌شه.

نظرات

هنوز نظری ثبت نشده. اولین نفر باشید!

نظر خود را بنویسید