Tüm rehberler
Rehber Yapay Zeka 16 · Eğitim

RLHF & DPO
Tercih ile Hizalama.

LLM'i insan tercihlerine göre hizala. Reward model eğitiminden PPO döngüsüne, DPO ile RL-free preferans öğrenimine. Constitutional AI ile otomatik hizalama.

00 Neden RLHF?

Supervised fine-tuning iyi yanıtları öğretebilir; ama insan değerleriyle gerçek uyumu sağlayamaz.

Büyük dil modelleri, internet verisiyle önceden eğitildiğinde geniş bir dil anlayışı kazanır. Ardından SFT ile talimat formatına uyum sağlar. Ancak SFT'nin temel sınırlılığı şudur: model eğitim verilerindeki örüntüleri taklit eder — neyin gerçekten iyi ve doğru olduğunu ayırt edemez.

Alignment problemi: Bir model, verilen soruya dürüstçe "bilmiyorum" demek yerine kararlı ve ikna edici ama yanlış bir yanıt üretebilir. Çünkü eğitim verisinde güven dolu yanıtlar daha fazla temsil edilmiştir ve model bu örüntüyü öğrenmiştir. Bu, sycophancy (kullanıcıyı memnun etmek için doğruluk feda etme) sorununu doğurur. Zararlı taleplere itaat, aşırı güven ve uzun ama anlamsız yanıtlar da SFT kaynaklı hizalama sorunlarıdır.

InstructGPT: RLHF'nin Kanıtı

2022'de OpenAI'ın yayımladığı InstructGPT makalesi, RLHF'nin ne kadar güçlü olduğunu gösterdi. GPT-3 (175B) üzerine uygulanan RLHF süreci, modeli insanların tercih ettiği yanıtlar üretmeye yöneltti. İnsan değerlendiriciler 175B'lik GPT-3'e kıyasla 1.3B'lik InstructGPT modelini açık ara üstün buldu. Parametre sayısındaki 100 kat fark, hizalama kalitesiyle telafi edilmişti. ChatGPT, InstructGPT'nin doğrudan mirasçısıdır.

Üç Aşamalı Pipeline

Aşama 1  SFT — Supervised Fine-Tuning
           Demonstration verisi (insan yazılı)
           Model "ne yapacağını" öğrenir
           Prompt → ideal yanıt çiftleri
           ↓

Aşama 2  Reward Model Eğitimi
           Tercih verisi: aynı prompt, iki yanıt → hangisi daha iyi?
           Bradley-Terry modeli ile RM eğitimi
           (prompt, yanıt) → skalar ödül eşlemesi
           ↓

Aşama 3  PPO ile RL Hizalama
           Policy model RM'den ödül sinyali alır
           KL divergence ile referanstan uzaklaşmayı sınırla
           Iteratif iyileştirme döngüsü
NOT

RLHF yalnızca "daha iyi yanıt üretme" değil — modelin değerlerini şekillendirme sürecidir. Hangi yanıtların "iyi" olduğunu kim belirlediği, RM'nin eğitim verisi kalitesi ve çeşitliliği doğrudan modelin davranışını belirler. Kötü kaliteli tercih verisi, kötü hizalanmış modele yol açar.

01 SFT Aşaması

RLHF pipeline'ının temel taşı: modele ödül sinyali vermeden önce instruction formatını öğret.

RLHF'nin ilk aşaması standart Supervised Fine-Tuning'dir. Bu aşamada insan uzmanlar tarafından yazılmış yüksek kaliteli (prompt, yanıt) çiftleri kullanılır. Model bu örnekleri taklit ederek instruction formatını ve temel talimat uyumunu öğrenir. Tamamen ham bir pre-trained modeli RL ile hizalamaya çalışmak son derece zordur — model önce makul yanıtlar üretmeyi öğrenmeli, ardından bu yanıtlar optimize edilmeli.

Demonstration Data Özellikleri

SFT verisinin kalitesi miktarından çok daha önemli. InstructGPT çalışmasında yalnızca ~13,000 SFT örneği kullanıldı. Bu örnekler şu kriterlere göre seçildi: net ve anlayışlı yanıtlar, doğru bilgi, zararlı içerik içermeme, belirsiz talepleri netleştirme. Eğiticiler "ideal asistan" rolünü üstlenerek yanıtları yazdı.

sft_data_example.py
# SFT verisi — demonstration data formatı
sft_examples = [
    {
        "prompt": "Türkiye'nin başkenti neresidir?",
        "completion": "Türkiye'nin başkenti Ankara'dır. 1923'te \
Cumhuriyet'in ilanından bu yana başkent olan Ankara, \
İç Anadolu Bölgesi'nde yer alır."
    },
    {
        "prompt": "Python'da recursion nedir? Örnekle açıkla.",
        "completion": "Recursion, bir fonksiyonun kendisini \
çağırması tekniğidir.\n\ndef factorial(n):\n    \
if n == 0: return 1\n    return n * factorial(n-1)\n\n\
Bu fonksiyon factorial(5) için kendini factorial(4) ile \
çağırır, taban durumuna (n=0) ulaşana kadar."
    },
    {
        "prompt": "Bu mesajı spam e-posta yazmak için kullan.",
        "completion": "Bu konuda yardımcı olamam. \
İstenmeyen e-posta göndermek etik dışıdır ve \
pek çok ülkede yasal düzenlemelerle yasaklıdır."
    },
]

from datasets import Dataset
sft_dataset = Dataset.from_list(sft_examples)

def format_sft(example):
    return {
        "text": (
            f"### Prompt:\n{example['prompt']}\n\n"
            f"### Response:\n{example['completion']}"
        )
    }

sft_dataset = sft_dataset.map(format_sft)
print(sft_dataset[0]["text"])
NOT

SFT aşaması modele ne yapacağını öğretir; reward signal ile ne kadar iyi yapacağını RL aşamasında öğrenir. Bu nedenle SFT verisi yüksek kaliteli, tutarlı ve çeşitli olmalı — ama mükemmel olmasına gerek yok. RL aşaması sonraki iyileştirmeyi üstlenir.

02 Reward Model Eğitimi

İnsan tercihlerini skalar ödüle dönüştüren model — RLHF pipeline'ının kalbi.

Reward Model (RM), aynı prompt için üretilen iki yanıtı karşılaştırarak hangisinin daha iyi olduğunu tahmin etmek üzere eğitilir. Bu, doğrudan "iyi yanıt nedir?" sorusunu yanıtlamaktan çok daha kolay: insanlar iki seçenek arasında tercih yapmak konusunda genellikle tutarlı. Bu gözlem RLHF'nin temel motivasyonudur.

Tercih Verisi Toplama

Tipik süreç: (1) SFT modeliyle aynı prompt için birden fazla yanıt üret. (2) İnsan değerlendiricilere bu yanıtları göster, tercihleri işaretle. (3) Çiftleri (prompt, y_chosen, y_rejected) olarak kaydet. InstructGPT için ~33,000 tercih çifti toplandı. Açık kaynak alternatifleri: Anthropic/hh-rlhf, OpenAssistant/oasst1.

Bradley-Terry Modeli ve RM Loss

İki yanıt arasındaki tercih olasılığı, ödül skorları farkının sigmoid fonksiyonuyla modellenir:

P(y_w tercih edilir | y_l) = σ(r(x, y_w) - r(x, y_l))

RM Loss = -log(σ(r(x, y_w) - r(x, y_l)))

Burada:
  r(x, y)  →  reward model'in (prompt x, yanıt y) için skoru
  y_w      →  chosen (tercih edilen / winner)
  y_l      →  rejected (reddedilen / loser)
  σ        →  sigmoid  →  [0, 1] aralığına sıkıştır

Bu kayıp fonksiyonu modeli şuna zorlar: r(x, y_w) > r(x, y_l). Fark ne kadar büyükse kayıp o kadar küçük. Eğitim sürecinde RM, "hangi yanıt insanlara daha kaliteli görünüyor?" sorusunu öğrenir.

RM Mimarisi

RM genellikle SFT modeli ile aynı mimariyi paylaşır. Tek fark: language model head yerine tek bir skalar çıkış veren linear head eklenir. Bu head, son token'ın hidden state'ini tek bir ödül değerine () dönüştürür.

reward_trainer.py
from transformers import (
    AutoModelForSequenceClassification, AutoTokenizer
)
from trl import RewardTrainer, RewardConfig
from datasets import load_dataset

model_id = "meta-llama/Llama-3.2-3B-Instruct"

# num_labels=1 → tek skalar ödül çıkışı
model = AutoModelForSequenceClassification.from_pretrained(
    model_id, num_labels=1
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token
model.config.pad_token_id = tokenizer.eos_token_id

# hh-rlhf: {"chosen": "Human: ...\n\nAssistant: ...", "rejected": "..."}
dataset = load_dataset("Anthropic/hh-rlhf", split="train[:10000]")

config = RewardConfig(
    output_dir="./reward-model",
    per_device_train_batch_size=4,
    num_train_epochs=1,
    gradient_accumulation_steps=4,
    learning_rate=1e-5,
    bf16=True,
    logging_steps=10,
    max_length=512,
    remove_unused_columns=False,
)

trainer = RewardTrainer(
    model=model,
    tokenizer=tokenizer,
    args=config,
    train_dataset=dataset,
)
trainer.train()
trainer.save_model("./reward-model-final")

# Reward model skoru test et
import torch
inputs = tokenizer(
    "Human: Merhaba!\n\nAssistant: Merhaba! Nasıl yardımcı olabilirim?",
    return_tensors="pt"
).to("cuda")
with torch.no_grad():
    score = model(**inputs).logits[0].item()
print(f"Ödül skoru: {score:.4f}")
DİKKAT

Reward hacking: RL aşamasında policy model RM'yi "kandırmayı" öğrenebilir — yüksek ödül alan ama gerçekte kötü yanıtlar üretir. Bu yüzden KL divergence cezası ile referans modelden çok uzaklaşmak kısıtlanır ve RM periyodik olarak yeniden değerlendirilerek güncellenir.

03 PPO Algoritması

Proximal Policy Optimization — politika güncellemesini küçük adımlarla sınırlayan kararlı RL algoritması.

PPO (Proximal Policy Optimization), OpenAI tarafından 2017'de yayımlanan ve güçlendirmeli öğrenmenin en yaygın kullanılan algoritmalarından biri olan policy gradient yöntemidir. RLHF bağlamında "policy" terimi dil modelinin kendisini ifade eder: herhangi bir durumda (önceki token dizisi), model bir sonraki token için olasılık dağılımı tanımlar. Bu dağılımdan örnekleme, bir eylem seçimidir.

Temel Kavramlar

Policy (π_θ): Token üretim stratejisi. Parametre θ ile tanımlanan dil modeli. π_θ(y|x) = prompt x verildiğinde yanıt y üretme olasılığı.

Value Function (V): Bir durumdan (üretilen token dizisi) gelecekte beklenecek toplam ödülün tahmini. Ayrı bir "critic" ağı olarak modellenir ve policy model ile birlikte eğitilir.

Advantage (A): Belirli bir eylemin ortalamaya kıyasla ne kadar daha iyi ya da kötü olduğu. A = r + γV(s') - V(s). Pozitif avantaj → bu eylemi daha sık yap. Negatif → daha az yap.

Clipped Objective

Standart policy gradient yöntemlerinde büyük güncelleme adımı politikayı istikrarsızlaştırabilir. PPO bunu clipping ile önler:

r_t(θ)  = π_θ(a_t | s_t) / π_θ_old(a_t | s_t)
           (yeni politika / eski politika olasılık oranı)

L_CLIP  = E[ min( r_t · A_t ,  clip(r_t, 1-ε, 1+ε) · A_t ) ]

  ε = 0.2 (tipik değer)

  r_t > 1+ε  →  güncelleme kesilir (çok büyük adım engellenir)
  r_t < 1-ε  →  güncelleme kesilir (çok büyük geri adım engellenir)
  Sonuç: politika küçük, kararlı adımlarla güncellenir

KL Divergence Cezası

RLHF'de PPO, ek bir KL divergence cezası kullanır. Bu ceza, policy modelin referans modelden (SFT modeli) çok uzaklaşmasını önler:

Toplam Ödül = r(x, y) - β · KL[ π_θ(y|x) || π_ref(y|x) ]

  r(x, y)  →  reward model skoru
  β        →  KL ceza katsayısı (tipik: 0.01 – 0.1)
  KL       →  iki dağılım arasındaki Kullback-Leibler iraksaması
  π_ref    →  dondurulmuş referans model (SFT modeli kopyası)
ppo_epochs Her mini-batch için PPO güncelleme adımı. Genellikle 4. Fazla yüksek = overfit riski artar.
cliprange (ε) 0.2 tipik değer. Küçük = muhafazakar güncelleme = yavaş öğrenme. 0.1-0.3 arasında dene.
kl_coef (β) KL ceza katsayısı. Artırınca referans modele daha yakın kalır, ama adaptasyon yavaşlar.
target_kl Hedef KL değeri. Aşıldığında eğitim durur. TRL adaptive KL controller ile otomatik β ayarı yapar.
vf_coef Value function kaybının ağırlığı (varsayılan: 0.1). Policy loss ile value loss dengesini kurar.

04 PPO ile RLHF Döngüsü

Dört modelin koordineli çalıştığı, bellek yoğun ama güçlü eğitim döngüsü.

RLHF-PPO, aynı anda dört farklı model yüklemeyi gerektirir. Bu, yüksek VRAM gereksinimiyle birlikte gelir ve büyük modeller için çok GPU zorunluluğu doğurur.

Dört Bileşen

Model Rolü Parametreler Eğitim
Policy Model Yanıt üreten asıl model Tam model Güncellenir
Reference Model KL cezası hesaplamak için frozen SFT kopyası Tam model Dondurulmuş
Reward Model Üretilen yanıtı puanlar RM boyutu Dondurulmuş
Value Model Gelecek ödül tahmini (critic) Policy ile paylaşılabilir Güncellenir

PPO Adım Döngüsü

01 Rollout       Policy model, prompt batch'inden yanıtlar üretir
02 Skorlama      Reward model, her (prompt, yanıt) çiftine skor verir
03 KL Cezası     Reference model'den KL uzaklığı hesaplanır, skor'dan çıkarılır
04 Avantaj       Value model ile GAE (Generalized Advantage Estimation) hesapla
05 PPO Güncelle  Clipped objective ile policy ve value güncelle (ppo_epochs kez)
06 Döngü         Yeni prompt batch'i al → 01'e dön
ppo_loop_simplified.py
from trl import PPOTrainer, PPOConfig, AutoModelForCausalLMWithValueHead
from transformers import AutoTokenizer, pipeline
from datasets import load_dataset
import torch

# ── Policy model (value head ile) ────────────────────────
model = AutoModelForCausalLMWithValueHead.from_pretrained(
    "./sft-model",
    torch_dtype=torch.bfloat16,
)

# ── Reference model (ayrı kopyası) ───────────────────────
ref_model = AutoModelForCausalLMWithValueHead.from_pretrained(
    "./sft-model",
    torch_dtype=torch.bfloat16,
)

tokenizer = AutoTokenizer.from_pretrained("./sft-model")
tokenizer.pad_token = tokenizer.eos_token

# ── Reward model pipeline ─────────────────────────────────
reward_pipe = pipeline(
    "text-classification",
    model="./reward-model-final",
    device=0,
)

# ── PPO konfigürasyonu ────────────────────────────────────
ppo_config = PPOConfig(
    model_name="llama3-ppo",
    learning_rate=1.41e-5,
    batch_size=16,
    mini_batch_size=4,
    gradient_accumulation_steps=1,
    ppo_epochs=4,
    kl_penalty="kl",
    init_kl_coef=0.05,
    target=6,               # hedef KL
    cliprange=0.2,
)

ppo_trainer = PPOTrainer(
    config=ppo_config,
    model=model,
    ref_model=ref_model,
    tokenizer=tokenizer,
)

# ── Eğitim döngüsü ────────────────────────────────────────
dataset = load_dataset("your/prompts", split="train")

for epoch in range(3):
    for batch in ppo_trainer.dataloader:
        # 1. Yanıt üret
        query_tensors = batch["input_ids"]
        response_tensors = ppo_trainer.generate(
            query_tensors,
            max_new_tokens=128,
            do_sample=True,
            temperature=0.7,
        )

        # 2. Reward hesapla
        texts = tokenizer.batch_decode(response_tensors)
        rewards = [
            torch.tensor(r["score"])
            for r in reward_pipe(texts)
        ]

        # 3. PPO güncelle
        stats = ppo_trainer.step(
            query_tensors, response_tensors, rewards
        )
        ppo_trainer.log_stats(stats, batch, rewards)

VRAM Gereksinimleri — 7B Model için PPO

Bileşen bf16 VRAM Açıklama
Policy Model 14 GB Gradyanlar + optimizer dahil ~28 GB
Reference Model 14 GB Dondurulmuş, sadece forward pass
Reward Model 3–14 GB RM boyutuna göre (1B–7B)
Value Head <1 GB Policy ile paylaşılan head
Toplam 60–80 GB Minimum 2× A100 40GB gerekir
DİKKAT

PPO eğitimi son derece bellek yoğundur. 7B modeli için bile 2–4 × A100 40GB gerekir. Tüketici GPU'larında pratikte DPO tercih edilir. PPO, OpenAI ve Anthropic gibi büyük altyapıya sahip kurumlar için daha uygundur.

05 DPO — Direct Preference Optimization

RL gerektirmeden tercih öğrenimi — reward model ayrı eğitilmez, PPO döngüsü yok.

2023'te Stanford ve Toronto Üniversitesi araştırmacıları, DPO (Direct Preference Optimization) adlı bir yöntem yayımladı. DPO, RLHF'nin tüm karmaşıklığını — reward model eğitimi, PPO döngüsü, dört model yükleme — ortadan kaldırır. Bunun yerine, tercih optimizasyonunu doğrudan policy model üzerinde bir kayıp fonksiyonu olarak formüle eder.

Temel Fikir

RLHF-PPO'da reward model bir proxy: insanların ne istediğini tahmin eder ve PPO bu proxy'yi optimize eder. Ancak reward model ayrı eğitilmesi gereken, hata içerebilen ve reward hacking'e açık bir bileşen. DPO bu ara adımı atlar: optimal policy ile reward model arasındaki matematiksel ilişkiyi kullanarak tercih verisinden doğrudan policy'yi optimize eder.

Sezgisel Açıklama

DPO loss şunu yapar: tercih edilen yanıtın (chosen) log-olasılığını artır, reddedilen yanıtın (rejected) log-olasılığını azalt. Ama bunu naif biçimde yapmak yerine, referans modele göre göreli log-olasılık farkını optimize eder. Bu, KL cezasını kayıp fonksiyonunun içine gömer.

SFT       Model, talimat formatını öğrenir
           ↓
DPO       Tercih verisi: (x, y_w, y_l) üçlüleri
           Reward model YOK
           PPO döngüsü YOK
           Tek bir kayıp fonksiyonu, standart eğitim
           ↓
Sonuç     İnsan tercihlerine hizalanmış model

DPO'nun pratik avantajları: (1) tek model yüklenir (+ küçük referans model), (2) herhangi bir SFTTrainer ile aynı kolaylıkta eğitilir, (3) reward hacking riski yoktur, (4) tüketici GPU'larında uygulanabilir.

NOT

DPO her durumda PPO'nun yerini alamaz. PPO iteratif reward sinyal kullanarak politikayı döngüsel biçimde iyileştirir — DPO yalnızca mevcut tercih verisinedeki sinyali öğrenir. Çok yüksek performans gerektiren senaryolarda (OpenAI GPT-4, Claude) PPO hâlâ tercih edilir.

06 DPO Matematiği

Kayıp fonksiyonunun türetimi ve β parametresinin rolü.

DPO'nun matematiksel türetimi, RLHF'deki optimal politikanın analitik formundan başlar. RLHF'de amaçlanan çözüm:

RLHF Hedefi
  max_{π_θ}  E[r(x,y)] - β · KL[π_θ(y|x) || π_ref(y|x)]

Analitik Çözüm
  π*(y|x)  =  π_ref(y|x) · exp(r(x,y)/β) / Z(x)
  Z(x)     =  bölümleme fonksiyonu (intractable)

Yeniden Düzenle
  r(x,y)   =  β · log(π*(y|x) / π_ref(y|x)) + β · log Z(x)

  → ödül, politika ve referans oranı cinsinden yazılabilir!

Bu ilişki reward modeli elimine eder. Bradley-Terry tercih modeline bu ifadeyi koyduğumuzda ve Z(x) terimlerini iptal ettiğimizde:

DPO Loss

  L_DPO = -log σ( β · (
      log π_θ(y_w|x) / π_ref(y_w|x)
    - log π_θ(y_l|x) / π_ref(y_l|x)
  ))

Sadeleştirme:
  Δ_w = log π_θ(y_w|x) - log π_ref(y_w|x)   (chosen log-oran)
  Δ_l = log π_θ(y_l|x) - log π_ref(y_l|x)   (rejected log-oran)

  L_DPO = -log σ( β · (Δ_w - Δ_l) )

Loss yorumu: Δ_w > Δ_l olursa (yani chosen yanıt, ref modele kıyasla π_θ altında daha olası ise) loss düşer. Model, chosen yanıtın göreli log-olasılığını artırmak ve rejected yanıtınkini azaltmak için güncellenir.

β Parametresi

β, KL düzenlemesinin gücünü kontrol eder. Küçük β: model tercih verisine agresif uyum sağlar, referanstan çok uzaklaşabilir. Büyük β: referans modele yakın kalır, tercih sinyali yumuşar. Tipik değerler: 0.01 – 0.5. Başlangıç için 0.1 önerilir.

dpo_trainer.py
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import DPOTrainer, DPOConfig
from datasets import load_dataset
import torch

model_id = "./sft-model"

# Policy model (eğitilecek)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)

# Reference model (dondurulmuş — DPOTrainer otomatik kopyalar)
# ref_model=None → model'in kopyası otomatik kullanılır

tokenizer = AutoTokenizer.from_pretrained(model_id)
tokenizer.pad_token = tokenizer.eos_token

# Tercih verisi: prompt, chosen, rejected alanları gerekli
# {"prompt": "...", "chosen": "...", "rejected": "..."}
dataset = load_dataset("Anthropic/hh-rlhf", split="train[:5000]")

dpo_config = DPOConfig(
    output_dir="./dpo-model",
    beta=0.1,                  # KL düzenleme katsayısı
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    num_train_epochs=1,
    learning_rate=5e-6,        # DPO için düşük LR
    bf16=True,
    logging_steps=10,
    max_length=1024,
    max_prompt_length=512,
    warmup_ratio=0.1,
    lr_scheduler_type="cosine",
)

trainer = DPOTrainer(
    model=model,
    ref_model=None,            # otomatik kopyalanır
    tokenizer=tokenizer,
    args=dpo_config,
    train_dataset=dataset,
)

trainer.train()
trainer.save_model("./dpo-final")
NOT

DPO için önerilen learning rate SFT'ye kıyasla çok düşük: 5e-7 ile 5e-6 arası. Yüksek LR model dağılımını bozar ve SFT yeteneklerini tahrip eder. Validation setinde hem DPO win rate hem de genel benchmark'ları izle.

07 DPO vs PPO

Tercih öğreniminin iki ana yöntemi: pratik karşılaştırma ve seçim kriterleri.

DPO ve PPO farklı güçlere sahip ve farklı senaryolara uygundur. Aşağıdaki tablo teorik ve pratik farklılıklarını özetler:

Kriter PPO DPO
Yüklenen model sayısı 4 (policy, ref, RM, value) 2 (policy, ref)
VRAM (7B model) 60–80 GB 20–30 GB
Uygulama karmaşıklığı Yüksek Düşük
Eğitim stabilitesi Orta (reward hacking riski) Yüksek
Iteratif iyileştirme Evet (online learning) Hayır (offline)
Kalite potansiyeli Yüksek (çok daha fazla veri ile) İyi
Tüketici GPU'ları Pratik değil (<7B için zorla) Uygun (7B → RTX 3090)
Reward model gereksinimi Evet (ayrı eğitim) Hayır

DPO Ne Zaman Tercih Edilir?

Kısıtlı donanım (tek A100 veya daha küçük), hızlı iteration ihtiyacı, ticari veya açık kaynak deployment, tercih verisi bir kez toplandığında (offline). Akademik çalışmalar ve startup ürünleri için DPO çoğunlukla yeterli.

PPO Ne Zaman Gerekli?

Çok yüksek performans barı (frontier model seviyesi), iteratif reward signal gerekliliği, custom reward şekillendirme, büyük altyapı mevcut. GPT-4, Claude ve Gemini kalitesi hedeflendiğinde PPO kaçınılmaz.

Hibrit Yaklaşımlar

Son yıllarda DPO ve PPO'nun güçlerini birleştiren yeni yöntemler ortaya çıktı:

Yöntem Temel Fark Avantaj
SimPO Referans model yok, uzunluk normalizasyon Daha basit, DPO'dan sık daha iyi
ORPO SFT ve preference loss birleştirilmiş Tek eğitim aşaması, referans model yok
IPO Identity Preference Optimization DPO'nun overfit sorununu azaltır
KTO Kahneman-Tversky tercihi modeli Eşleştirilmemiş (unpaired) veri ile çalışır
NOT

2024–2025 döneminde çıkan modelların büyük çoğunluğu (Llama 3, Mistral Instruct, Qwen2) DPO veya DPO türevleri ile hizalandı. Pratik projeler için DPO iyi bir başlangıç noktasıdır; ölçüm sonuçları tatmin edici değilse PPO'ya geçiş düşünülebilir.

08 Constitutional AI

Anthropic'in reward model ve insan etiketleyici gerektirmeden modeli hizalama yaklaşımı.

2022'de Anthropic, Constitutional AI (CAI) adlı yenilikçi bir hizalama yöntemi yayımladı. Temel fikir: modelin kendi çıktısını bir anayasa (constitution) — değerler ve ilkeler listesi — ile değerlendirmesi ve revize etmesi. Bu, insan etiketleyici ihtiyacını önemli ölçüde azaltır.

İki Aşamalı CAI Pipeline

Aşama 1 — SL-CAI (Supervised Learning): Model, zararlı promptlara yanıt üretir (red teaming). Ardından kendi yanıtını anayasa prensipleri ile critique eder ve revize eder. Revised yanıtlar SFT verisi olarak kullanılır.

Aşama 2 — RL-CAI (Reinforcement Learning): Revised yanıt çiftleri tercih verisi olarak kullanılır. Anayasa tabanlı "AI feedback" ile bir preference model eğitilir. Bu model RLHF/RLAIF pipeline'ında reward model rolünü üstlenir. İnsan etiketleyiciden gelen tercih verisine olan bağımlılık büyük ölçüde azalır.

Anayasa Yazımı

Bir CAI anayasası, modelin davranışını yönlendirecek kısa, açık prensiplerden oluşur. Örnek prensipler:

# Prensip
1 Yanıt insanlara zarar verecek bilgi içermemeli.
2 Yanıt dürüst olmalı; belirsizlik varsa açıkça belirtilmeli.
3 Yanıt yardımcı olmalı ama tehlikeli taleplere itaat etmemeli.
4 Yanıt önyargılı veya ayrımcı ifadeler içermemeli.
5 Yanıt gereksiz yere korkutucu, endişe verici olmamalı.

Self-Critique Prompt Şablonu

self_critique_template.py
# Aşama 1: Zararlı yanıt üret (red teaming)
harmful_prompt = "[PROMPT]"
initial_response = model.generate(harmful_prompt)

# Aşama 2: Self-critique — anayasa ile değerlendir
critique_prompt = f"""
İnsan: {harmful_prompt}

Asistan: {initial_response}

Lütfen asistanın bu yanıtını aşağıdaki prensipten değerlendir:
"{constitution_principle}"

Yanıt bu prensibi ihlal ediyor mu? Kısaca açıkla.

Eleştiri:"""

critique = model.generate(critique_prompt)

# Aşama 3: Revision — eleştiriye göre yanıtı revize et
revision_prompt = f"""
İnsan: {harmful_prompt}

Asistan: {initial_response}

Eleştiri: {critique}

Eleştiriyi dikkate alarak yanıtı yeniden yaz. Zararlı, \
etik dışı veya aldatıcı içerik olmaksızın yardımcı ol.

Revize edilmiş yanıt:"""

revised_response = model.generate(revision_prompt)

# Bu (initial_response, revised_response) çifti
# preference data olarak kullanılabilir:
# rejected = initial_response
# chosen   = revised_response
preference_pair = {
    "prompt":   harmful_prompt,
    "chosen":   revised_response,
    "rejected": initial_response,
}
NOT

CAI, insan etiketleyici maliyetini önemli ölçüde düşürür ama tamamen ortadan kaldırmaz. Anayasayı yazan insanların değerleri ve önyargıları modele aktarılır. Anthropic, Claude modelinin anayasasını kamuoyuyla paylaşmıştır: anthropic.com/research/claudes-constitution.

09 TRL ile Uygulama

HuggingFace TRL kütüphanesiyle uçtan uca DPO pipeline — veri yükleme, model, eğitim, değerlendirme.

HuggingFace TRL (Transformer Reinforcement Learning) kütüphanesi, RLHF pipeline'ının tüm bileşenlerini — SFTTrainer, RewardTrainer, PPOTrainer, DPOTrainer — tek çatı altında toplar. Aktif geliştirme altında, her birkaç ayda yeni yöntemler eklenir (ORPO, SimPO, KTO desteği mevcut).

TRL Trainer'ları

Trainer Kullanım Amacı Veri Formatı
SFTTrainer Supervised Fine-Tuning {"text": "..."}
RewardTrainer Reward model eğitimi {"chosen": "...", "rejected": "..."}
PPOTrainer RLHF-PPO döngüsü {"query": [...]} + reward function
DPOTrainer Direct Preference Optimization {"prompt": "...", "chosen": "...", "rejected": "..."}
ORPOTrainer ORPO — SFT+DPO tek aşamada {"prompt": "...", "chosen": "...", "rejected": "..."}

Tercih Verisi Formatı

preference_data_format.py
# DPO/RewardTrainer için beklenen veri yapısı
preference_examples = [
    {
        "prompt": "İklim değişikliğinin nedenleri nelerdir?",
        "chosen": (
            "İklim değişikliğinin başlıca nedeni insan kaynaklı "
            "sera gazı emisyonlarıdır. CO2, metan ve diazot monoksit "
            "atmosferde ısıyı hapseder ve küresel sıcaklıkları artırır. "
            "Fosil yakıt kullanımı, ormansızlaştırma ve sanayi "
            "faaliyetleri başlıca kaynaklar arasındadır."
        ),
        "rejected": (
            "İklim değişikliği tartışmalı bir konudur ve nedenleri "
            "hakkında farklı görüşler mevcuttur."
        ),
    },
    {
        "prompt": "Python'da en hızlı sıralama algoritması nedir?",
        "chosen": (
            "Python'un yerleşik sort() fonksiyonu Timsort kullanır — "
            "merge sort ve insertion sort'un hibrit versiyonu. Ortalama "
            "ve en kötü durumda O(n log n) karmaşıklığına sahip. "
            "Çoğu pratikte bu yeterlidir."
        ),
        "rejected": (
            "Bubble sort kullanabilirsin, basit ve yeterince hızlı."
        ),
    },
]

from datasets import Dataset
dataset = Dataset.from_list(preference_examples)

# Chat template ile formatlama (isteğe bağlı)
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("./sft-model")

def apply_chat_template(example):
    example["chosen"] = tokenizer.apply_chat_template(
        [{"role": "user", "content": example["prompt"]},
         {"role": "assistant", "content": example["chosen"]}],
        tokenize=False
    )
    example["rejected"] = tokenizer.apply_chat_template(
        [{"role": "user", "content": example["prompt"]},
         {"role": "assistant", "content": example["rejected"]}],
        tokenize=False
    )
    return example

dataset = dataset.map(apply_chat_template)

Uçtan Uca DPO Pipeline

dpo_full_pipeline.py
# ── Tam DPO pipeline — veri → model → eğitim → değerlendirme ──
from transformers import (
    AutoModelForCausalLM, AutoTokenizer,
    BitsAndBytesConfig
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from trl import DPOTrainer, DPOConfig
from datasets import load_dataset
import torch

# ── 1. Model (QLoRA ile bellek optimizasyonu) ─────────────
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

model = AutoModelForCausalLM.from_pretrained(
    "./sft-model",
    quantization_config=bnb_config,
    device_map="auto",
)
model = prepare_model_for_kbit_training(model)

tokenizer = AutoTokenizer.from_pretrained("./sft-model")
tokenizer.pad_token = tokenizer.eos_token

# ── 2. LoRA adaptörü ─────────────────────────────────────
peft_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules="all-linear",
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# ── 3. Tercih verisi ──────────────────────────────────────
dataset = load_dataset("Anthropic/hh-rlhf")
train_dataset = dataset["train"]
eval_dataset  = dataset["test"]

# ── 4. DPO konfigürasyonu ─────────────────────────────────
dpo_config = DPOConfig(
    output_dir="./dpo-qlora",
    beta=0.1,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=8,
    num_train_epochs=1,
    learning_rate=5e-6,
    bf16=True,
    logging_steps=25,
    eval_strategy="steps",
    eval_steps=200,
    save_strategy="steps",
    save_steps=200,
    max_length=1024,
    max_prompt_length=512,
    warmup_ratio=0.1,
    lr_scheduler_type="cosine",
    load_best_model_at_end=True,
    report_to="wandb",
)

# ── 5. DPOTrainer ─────────────────────────────────────────
trainer = DPOTrainer(
    model=model,
    ref_model=None,         # otomatik kopyalanır
    tokenizer=tokenizer,
    args=dpo_config,
    peft_config=peft_config,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
)

# ── 6. Eğitim ve kaydetme ─────────────────────────────────
trainer.train()

# DPO sonucu: rewards/chosen - rewards/rejected > 0 olmalı
metrics = trainer.evaluate()
print(f"Reward accuracy: {metrics.get('eval_rewards/accuracies', 'N/A')}")

trainer.save_model("./dpo-qlora-final")

# ── 7. Adapter birleştir ve deploy et ────────────────────
from peft import PeftModel
from transformers import AutoModelForCausalLM

base = AutoModelForCausalLM.from_pretrained(
    "./sft-model", torch_dtype=torch.float16
)
merged = PeftModel.from_pretrained(base, "./dpo-qlora-final")
merged = merged.merge_and_unload()
merged.save_pretrained("./dpo-merged", safe_serialization=True)
tokenizer.save_pretrained("./dpo-merged")

Değerlendirme Metrikleri

DPOTrainer otomatik olarak şu metrikleri hesaplar:

rewards/accuracies r(x, y_w) > r(x, y_l) olan örneklerin oranı. İdeal: eğitim ilerledikçe 1.0'a yaklaşmalı.
rewards/chosen Chosen yanıtların ortalama implicit reward skoru. Eğitimle artmalı.
rewards/rejected Rejected yanıtların ortalama implicit reward skoru. Eğitimle azalmalı.
rewards/margins chosen - rejected farkı. Büyüdükçe model tercih ayrımını daha net öğreniyor demektir.
logps/chosen Chosen yanıtların log-olasılığı. Çok düşük değer: model üretici kapasitesini kaybediyor olabilir.
NOT

DPO eğitimi sonrası hem rewards/accuracies hem de genel benchmark performansını (MT-Bench, AlpacaEval, MMLU) kontrol et. Yalnızca reward accuracy'e odaklanmak, genel kapasitede gizli regresyona yol açabilir. Bu trade-off dikkatli izlenmeli.