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ü
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 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"])
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.
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}")
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ı)
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
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 |
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.
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.
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")
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 |
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
# 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,
}
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ı
# 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
# ── 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:
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.