Exploring Infinite Possibilities on FrontEnd 🚀
Burak Sağlık
Search...

Fri Aug 07 2026

AI Ajanları İçin Model Özelleştirme: QLoRA ve SFT Rehberi

AI Ajanları İçin Model Özelleştirme: QLoRA ve SFT Rehberi

🎯 Giriş: Neden AI Ajanları İçin Model Özelleştirme Gerekiyor?

Hadi dürüst olalım: temel bir LLM'i ajan olarak kullanmak, stagista "şirketin tüm stratejisini yönet" demek kadar naïftir 😅 Ben de başlangıçta "zaten model her şeyi biliyor, prompt yazayım halleder" diye düşündüm. Spoiler: halledemiyor.

Ne oluyor burada? ❓

Bir müşteri destek ajanı hayal edin. Müşteri: "Siparişim #12345 iptal edildi mi?" der. Temel model ne yapar? "Bilmiyorum, veritabanına bakmadım" der — çünkü bilmiyor, sadece tahmin ediyor. Oysa ajanınız:

  • Şirket politikasını bilmeli (örn. "14 gün içinde iade özgür")
  • Canlı veriye erişip gerçek cevap vermeli
  • Marka tonunda (empatik, profesyonel) yanıtlamalı

Kod asistanı örneğine geçelim. "Bu repo nasıl deploy edilir?" sorusuna temel model generic bir CI/CD şablonu yazar. Ama sizin repoda:

  • docker-compose.prod.yml var
  • Secret'lar GitHub Actions'ta saklı
  • Migration script'i make migrate ile çalışır

Model bunu bilemez — çünkü sizin özel bağlamınızı (context) görmemiş.

Veri analizi ajanı 📊

"Son çeyrekte churn rate nasıldı?" sorusuna temel model SQL yazar. Ama:

  • Tablo isimleriniz usr_churn_events_v2 (model users bekler)
  • churn tanımınız: "30 gün login yok + abonelik iptal" (model bilmez)
  • Veri gizliliği kuralları: PII kolonları maskelenmeli

Model yanıltıcı ama güvenli görünen bir sorgu üretir. Production'da bu felakettir 💥


Benim "acı deneyim" paylaşımlarım 🤕

Senaryo Ne Oldu? Çözüm
İlk ajanım Prompt engineering ile "çözmeye" çalıştım → 3 gün sonra prompt 2000 satır oldu, yine hallolmadı Fine-tune + RAG kombinasyonu
Kod asistanı Model sürekli npm install yazıyordu, biz pnpm kullanıyorduk Domain-specific data ile SFT
Destek botu "Para iadesi politikası?" → model Amazon politikasını anlattı 😂 Şirket belgeleri üzerinde QLoRA

Ortak nokta: Temel model genel bilgi üretir. Ajanınıza özel bilgi + davranış + format lazım.


Peki ne zaman "yeter artık prompt yetmiyor, modele müdahale edelim" diyeceksiniz? 🤔

Ne zaman SFT/QLoRA'ya yönelmeliyiz? 🎯


❗️ Sorun: RAG ve Prompt Engineering Ne Zaman Yetersiz Kalır?

RAG ve prompt engineering güçlü araçlar ✨ — özellikle:

  • Bilgi getirme: İlgili belgeleri hızlıca yüzeye çıkarır 📄
  • Kontrol: Prompt’larla modelin tonunu, formatı ve kısıtlamalarını yönetebiliriz 🎛
  • Hızlı prototip: Kod yazmadan “proof‑of‑concept” aşamasında büyük kazanç sağlar ⚡️

Ama günlük iş akışlarında bu yöntemler sık sık kısır döngüye girer 🔁. İşte nedenler:

1️⃣ Çok adımlı planlama (multi‑step reasoning)

  • Model tek seferde “plan → eylem → doğrulama” zincirini kuramaz.
  • Her adım için ayrı prompt yazmak hata birikimine yol açar.

2️⃣ Alan özel terminoloji & bağlam

  • RAG’in getirdiği belgeler genel; alan‑içinde kullanılan kısaltmalar, kural setleri, “şirket dili” eksik kalır.
  • Prompt’a “bu terimleri kullan” demek yetmez; model yanlış eşleştirme yapar 🤷‍♂️

3️⃣ Uzun bağlam (long‑context) sınırları

  • Token limiti dolduğunda önemli detatlar kaybolur.
  • “Son 10.000 token” stratejisi, kritik karar noktalarını atlar ⛔

🎭 Gerçek hayattan bir “başarısız ajan” hikayesi

Senaryo: Bir finans şirketinde otomatik rapor hazırlama ajanı kurduk.

  • RAG: Geçen yılın bilançoları, mevzuat PDF’leri, iç politikalar yüklendi.
  • Prompt: “Şirket terminolojisini kullan, 5 sayfalık özet yaz, riskleri vurgula.”

Ne oldu?

  1. Ajan “nakit akışı” terimini “cash flow” olarak çevirdi → iç denetim ekibi anlamadı 😕
  2. Çok adımlı hesaplama (özet → tablo → yorum) tek prompt’ta istendi → model hesaplama hatası yaptı 📉
  3. 12 k token’lık bağlamda kritik mevzuat maddesi atlandı → rapor yasaya aykırı çıktı ⚖️

💸 Maliyet / Performans etkisi

Etki Açıklama
Token maliyeti 3‑4 kat daha fazla token tüketildi (yeniden deneme, düzeltme döngüleri) 💰
Gecikme Her iterasyon ~30 sn → toplam 5‑10 dk bekleme ⏱
İnsan müdahalesi 2 analist manuel düzeltme yapmak zorunda kaldı → ROI düştü 📉
Güven Ekip “ajanı güvenmiyor” diyerek yeni projelere direndi 🚫

🎯 Ne çıkarım yapmalıyız?

  • RAG + Prompt = Başlangıç noktası, tam çözüm değil.
  • Orkestrasyon, stateful planlama, domain‑specific fine‑tuning ve human‑in‑the‑loop mekanizmaları olmadan production’da hayal kırıklığı yaşarız.

Hadi bir sonraki bölümde bu eksikleri nasıl kapatabileceğimize (agentic workflows, tool use, evaluation loops) bakalım 🚀


🔁 Karar Matrisi: SFT vs QLoRA vs Tam Fine‑Tuning

Hangi yöntem sizin için en uygun? Aşağıdaki tablo ve karar ağacı ile kendi durumunuzu hızlıca eşleştirebilirsiniz 🎯

📊 Karşılaştırma Tablosu

Özellik SFT (Supervised Fine‑Tuning) QLoRA (4‑bit Quantized LoRA) Tam Fine‑Tuning
Veri miktarı 1 K – 10 K örnek 📄 500 – 5 K örnek 📄 10 K – 100 K+ örnek 📄
GPU bellek gereksinimi 1×A100 40 GB (fp16) 🎮 1×A100 24 GB (4‑bit) 🎮 4×A100 80 GB (fp16/bf16) 🎮
Eğitim süresi 2‑4 saat ⏱ 1‑2 saat ⏱ 12‑48 saat ⏱
Model kalitesi Orta‑yüksek (task‑specific) ⭐⭐⭐ Yüksek (LoRA + quant) ⭐⭐⭐⭐ En yüksek (full weights) ⭐⭐⭐⭐⭐
Bakım maliyeti Düşük (tek model, tek checkpoint) 💰 Çok düşük (adapter dosyası ~MB) 💰 Yüksek (büyük checkpoint, versiyonlama) 💰

Not: Sayılar tipik 7B‑13B parametreli modeller için; model boyutu büyüdükçe bellek ve süre lineer artar.


🌳 Karar Ağacı – Hangi Yolu Seçmelisiniz?

  1. Veri setiniz < 1 K mi?

    • EvetQLoRA (az veriyle de güçlü sonuç)
    • Hayır → 2️⃣
  2. GPU bütçeniz 1×A100 40 GB veya altı mı?

    • EvetSFT ya da QLoRA (her ikisi de sığar)
    • Hayır (çoklu GPU/80 GB varsa) → 3️⃣
  3. En yüksek kalite şart mı? (ör. üretimde kritik hata payı)

    • EvetTam Fine‑Tuning
    • HayırSFT (dengeli)
  4. Modeli sık güncellemeniz gerekiyor mu? (ör. haftalık yeni veri)

    • EvetQLoRA (adapter değiştirmek saniyeler)
    • HayırSFT ya da Tam Fine‑Tuning (tercihe göre)

🛠 Pratik İpucu

  • QLoRA ile başlayın, adapter dosyasını kaydedin.
  • Performans yeterli gelmezse SFT’ye geçin (aynı veri, daha fazla hesap).
  • Hala kalite açığı varsa ve donanımınız izin veriyorsa Tam Fine‑Tuning’e yatırım yapın.

Bu matris ve ağaç, kendi kısıtlarınızı (veri, GPU, zaman, kalite) göz önünde bulundurarak doğru yolu seçmenizi kolaylaştırır ✅.

Hadi şimdi kendi senaryonuzu tabloya yerleştirin ve yola çıkın! 🚀


🛠 QLoRA Temelleri: 4‑bit Quantization ve Low‑Rank Adaptation

Hazırsan QLoRA’nın iki ana bacağını — 4‑bit NF4 quantize ve LoRA adaptörleri — bir kahve molası süresinde kavrayalım ☕️

Neden 4‑bit yeterli? 🎯

  • NF4 (NormalFloat‑4), 4‑bit’lik bir veri tipidir ve normal dağılıma uygun olarak optimize edilmiştir.
  • Ağırlıkların %99+ bilgisi 4‑bit’te bile korunur; modelin perplexity kaybı genelde <0.5 % civarındadır.
  • Bu sayede GPU VRAM’i 4‑5× daha az harcıyoruz; 7B parametreli bir model ≈5 GB’a iner 🚀

LoRA rank (r) ve alpha (α) etkisi 🔁

Parametre Ne Yapar? Pratik İpucu
r (rank) Eğitilecek düşük‑boyutlu matrislerin boyutunu belirler. r=8 → her katmanda 8 × d_model boyutunda iki matris (A, B) eklenir. Küçük r → daha az parametre, daha hızlı eğitim; çok küçük olursa ifade yeteneği düşer.
α (alpha) LoRA güncellemesini ölçeklendirir: ΔW = (α / r) · B @ A. Genelde α = 2·r veya α = 16 gibi bir kural kullanılır; büyük α → daha güçlü adaptasyon ama overfit riski.

Küçük formül / pseudo‑kod ile matris boyutlarını görelim:

# d_model = 4096 (örnek)
r = 8
A ∈ ℝ^(r × d_model)      # (8, 4096)
B ∈ ℝ^(d_model × r)      # (4096, 8)
ΔW = (α / r) * (B @ A)   # (4096, 4096) → orijinal ağırlık boyutu

Bu sayede sadece 2 × r × d_model ≈ 65 K parametre eğitiyoruz; orijinal 16 M parametrenin %0.4’ü 🎉


Pratik: bitsandbytes ile 4‑bit yükleme + LoRA config (r=8, α=16) 🛠

# -------------------------------------------------
# 1️⃣ 4‑bit NF4 quantize ile modeli yükle
# -------------------------------------------------
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model

model_id = "meta-llama/Llama-2-7b-hf"          # örnek model
bnb_cfg = BitsAndBytesConfig(
    load_in_4bit=True,                         # 4‑bit modu
    bnb_4bit_quant_type="nf4",                 # NF4 quantizasyon
    bnb_4bit_use_double_quant=True,            # double quant için hafif artı
    bnb_4bit_compute_dtype=torch.bfloat16      # hesaplama dtype
)

model = AutoModelForCausalLM.from_pretrained(
    model_id,
    quantization_config=bnb_cfg,
    device_map="auto",
    torch_dtype=torch.bfloat16,
)

tokenizer = AutoTokenizer.from_pretrained(model_id)

# -------------------------------------------------
# 2️⃣ LoRA adaptörünü tanımla ve modele ekle
# -------------------------------------------------
lora_cfg = LoraConfig(
    r=8,                     # rank
    lora_alpha=16,           # alpha
    target_modules=["q_proj", "v_proj"],  # dikkat katmanları
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

model = get_peft_model(model, lora_cfg)
model.print_trainable_parameters()   # eğitilebilir parametre sayısını gör
# -------------------------------------------------
# Artık model 4‑bit quantize + LoRA (r=8, α=16) hazır 🎉
# -------------------------------------------------

Ne oldu?

  • BitsAndBytesConfig ile model NF4 4‑bit olarak yüklendi → VRAM ≈5 GB.
  • LoraConfig(r=8, lora_alpha=16) sayesinde sadece ~65 K parametre fine‑tune edilebilir.
  • get_peft_model adaptörleri orijinal ağırlıkların üzerine ekler; inference sırasında merge edip tek bir 4‑bit model olarak da kullanabilirsiniz.

Özetle: 4‑bit NF4 hafifletir, LoRA esnekleştirir. Birleşince “bu kadar hafif ama bu kadar güçlü” hissi verir 🎯.

Bir sonraki bölümde bu pipeline’ı bir instruction‑tuning veri seti üzerinde nasıl koşturacağımızı görelim 🚀


🛠 Ortam Kurulumu: GPU, Python, Hugging Face, bitsandbytes

Hazırsan başlayalım 🚀. Aşağıdaki adımları sırayla uygulayarak GPU destekli bir Python ortamı hazırlayabilirsin.

1️⃣ CUDA sürümünü kontrol et

nvcc --version          # CUDA toolkit sürümü
nvidia-smi              # Sürücü ve GPU bilgisi
  • CUDA 11.8 veya 12.1 (PyTorch’un resmi wheel’ları bu sürümlerle uyumludur).
  • Sürüm uyuşmazlığı olursa, ilgili CUDA toolkit’i NVIDIA indirme sayfasından kur.

2️⃣ Sanal ortam oluştur

python3 -m venv .venv          # .venv klasörü oluşur
source .venv/bin/activate      # Linux/macOS
# .venv\Scripts\activate       # Windows PowerShell

İpucu: pip install --upgrade pip ile pip’i güncellemeyi unutma.

3️⃣ requirements.txt dosyasını hazırla

# requirements.txt
torch==2.3.0+cu121          # CUDA 12.1 için; cu118 ise CUDA 11.8
transformers==4.41.0
accelerate==0.30.0
peft==0.11.0
bitsandbytes==0.43.0
datasets==2.19.0
  • torch sürümünde +cu121 / +cu118 etiketi, CUDA sürümüne göre değişir.
  • bitsandbytes 8‑bit/4‑bit quantizasyon için CUDA 11.8+ gerektirir.

4️⃣ Paketleri tek seferde kur

pip install -r requirements.txt

Kurulum bittikten sonra hızlı bir test:

import torch, transformers, bitsandbytes
print("CUDA available:", torch.cuda.is_available())
print("GPU:", torch.cuda.get_device_name(0))

5️⃣ Sık karşılaşılan hatalar ve çözümleri ❗️

Hata Neden Çözüm
CUDA out of memory Model / batch size GPU belleğini aşıyor torch.cuda.empty_cache()batch_size küçült • Gradient accumulation kullan • 8‑bit/4‑bit quantizasyon (bitsandbytes) etkinleştir
Version mismatch: torch CUDA 12.1 vs driver 11.8 PyTorch wheel CUDA sürümü sürücüyle uyuşmuyor nvidia-smi ile sürücü sürümünü kontrol et • Uygun torch wheel’ını seç (cu118 / cu121) • Gerekirse CUDA toolkit’i güncelle
ModuleNotFoundError: No module named 'bitsandbytes' Paket kurulamamış ya da CUDA yok pip install bitsandbytes==0.43.0 • CUDA 11.8+ olduğundan emin ol • `ldconfig -p
ImportError: libcusparse.so.11 CUDA kütüphaneleri PATH’te yok export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-12.1/lib64 (sürüme göre) • .bashrc / .zshrc ekleyip source et
pip install yavaş / timeout PyPI mirror sorunu pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt (Çin mirror) • Veya --timeout 120 ekle

6️⃣ Son kontrol ✅

python -c "import torch; print('Torch:', torch.__version__, '| CUDA:', torch.version.cuda)"
python -c "import transformers; print('Transformers:', transformers.__version__)"
python -c "import bitsandbytes; print('bitsandbytes ok')"

Her şey yolunda giderse “Ortam hazır 🎉” mesajını görürsün. Artık Hugging Face modellerini, LoRA/PEFT fine‑tuning’ini ve bitsandbytes quantizasyonunu sorunsuz çalıştırabilirsin.


Özet:

  1. CUDA sürümünü doğrula.
  2. Sanal ortam oluştur ve pip güncelle.
  3. requirements.txt ile tek komutta kur.
  4. Olası hataları tablo üzerinden hızla gider.

Şimdi model eğitimine / inference’e geçebilirsin. 🚀


🔁 Veri Hazırlama: Ajan Diyalogları İçin Instruction‑Response Formatı

Hazırsan başlayalım 🚀
Ajanlarımızın system / user / assistant diyaloglarını model eğitimi için uygun bir formata (JSONL veya Parquet) dönüştürmek, veri kalitesini garanti altına almak ve daha sonra datasets kütüphanesiyle hızlıca train/validation ayırmak için birkaç adım yeterli.

1️⃣ Diyalogları Temizleme & Standartlaştırma

  • Gereksiz boşluk / newline karakterlerini sil.
  • System mesajını her örnekte tek bir system alanında topla.
  • User‑Assistant çiftlerini instruction / response olarak yeniden adlandır.
  • Metadata (timestamp, model sürümü vb.) ayrı bir meta dict’inde sakla — eğitimde kullanmasak da debug için hayat kurtarıyor.
def normalize_dialog(raw: dict) -> dict:
    """Ham diyalog dict'ini instruction‑response formatına çevirir."""
    return {
        "instruction": raw["user"].strip(),
        "response": raw["assistant"].strip(),
        "system": raw.get("system", "").strip(),
        "meta": {k: v for k, v in raw.items() if k not in {"user", "assistant", "system"}}
    }

Bu sayede her satır tek bir eğitim örneği haline gelir ve downstream işlemler (tokenizasyon, batching) çok daha basit olur.


2️⃣ JSONL → Parquet & datasets ile Yükleme / Split

from datasets import load_dataset, DatasetDict

# 1️⃣ JSONL dosyasını oku
ds = load_dataset("json", data_files="data/dialogs.jsonl", split="train")

# 2️⃣ Normalizasyon fonksiyonunu uygula
ds = ds.map(lambda ex: normalize_dialog(ex))

# 3️⃣ Kalite kontrolleri (aşağıda tanımlı) – duplicate & kısa cevapları at
ds = ds.filter(is_clean)

# 4️⃣ Train / Validation ayır (ör. %90 / %10)
splits = ds.train_test_split(test_size=0.1, seed=42)
dataset_dict = DatasetDict({
    "train": splits["train"],
    "validation": splits["test"]
})

# 5️⃣ Parquet olarak kaydet (daha hızlı I/O)
dataset_dict.save_to_disk("data/processed_dialogs")

Nasıl çalışıyor?

  • load_dataset("json", ...) satırı JSONL’i Hugging Face Dataset objesine çevirir.
  • map ile her satırı normalize_dialog fonksiyonundan geçiririz.
  • filter(is_clean) ile kalite kontrolünü uygularız (aşağıya bak).
  • train_test_split rastgele ama reproducible (seed=42) bir bölme yapar.
  • save_to_disk Parquet tabanlı bir formatta diske yazar — eğitim script’lerinde load_from_disk ile saniyeler içinde yüklenir.

3️⃣ Veri Artırma (Augmentation) Teknikleri 🎨

Teknik Ne İşe Yarar? Nasıl Uygulanır?
Few‑shot örnekler Modelin bağlam öğrenmesini hızlandırır. Her instruction’ın başına 2‑3 örnek instruction‑response çifti ekle (prompt template içinde).
Negatif örnekler Yanlış cevapları tanıma yeteneği kazandırır. Aynı instruction için yanlış/hallucinated bir response üret, label: 0 etiketiyle ekle.
Çoklu görev karıştırması (multi‑task mixing) Genellemeyi artırır, overfitting’e engel olur. Farklı görev türlerini (QA, summarization, code) aynı dataset içinde shuffle ederek karıştır.

İpucu: Augmentation yaparken orijinal veri dağıtımını bozmamak için her teknikten %10‑%15 civarında ekleme yap — sonra train_test_split tekrar çalıştır.


4️⃣ Küçük Bir Kalite Kontrol Fonksiyonu 🔍

def is_clean(example: dict) -> bool:
    """
    - Duplicate instruction'ları atar (hash tabanlı).
    - Çok kısa (<5 token) response'ları eler.
    - Boş system mesajı olanları kabul eder (opsiyonel).
    """
    # 1️⃣ Duplicate kontrolü (global set kullanarak)
    instr_hash = hash(example["instruction"])
    if instr_hash in is_clean.seen:
        return False
    is_clean.seen.add(instr_hash)

    # 2️⃣ Çok kısa cevap filtresi
    if len(example["response"].split()) < 5:
        return False

    return True

# Static set init
is_clean.seen = set()

Ne oluyor burada?

  • is_clean.seen fonksiyon özelliği olarak global bir set tutar; map/filter sırasında aynı instruction hash’i ikinci kez görüldüğünde False döner → duplicate düşer.
  • response kelime sayısı <5 ise muhtemelen “Tamam” veya “Anladım” gibi bilgi taşımayan cevaplar → filtrelenir.

5️⃣ Özet & Sonraki Adım 📋

  1. Ham diyalogları normalize_dialog ile instruction‑response yapısına çevir.
  2. datasets ile JSONL yükle → mapfilter(is_clean)train_test_split.
  3. Parquet olarak kaydet, eğitimde load_from_disk ile hızlıca eriş.
  4. Augmentation (few‑shot, negatif, multi‑task) ekleyerek veri zenginliğini artır.

Artık elinizde temiz, dengeli ve model‑ready bir veri seti var 🎉
Bir sonraki bölümde bu veri setini tokenization & packing adımlarıyla nasıl optimize edeceğimize bakacağız. Hadi devam edelim!


🛠 SFT ve QLoRA ile Eğitim Scripti (PyTorch + PEFT)

Hazırsan tam bir eğitim betiği üzerinden gidelim.
Aşağıda train_qlora.py dosyasını parça parça anlatıyorum; her bloğu ne işe yaradığını kısaca özetleyeceğim 🎯

1️⃣ Gerekli kütüphaneleri içe aktar

import os
import torch
from datasets import load_dataset
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    TrainingArguments,
    Trainer,
    BitsAndBytesConfig,
    EarlyStoppingCallback,
)
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
import wandb   # 👉 WandB loglama için (istersen TensorBoard da kullanabilirsin)

Ne yaptık?

  • BitsAndBytesConfig → 4‑bit/8‑bit quantization ayarları
  • LoraConfig + get_peft_model → LoRA adapter ekleme
  • EarlyStoppingCallback → erken durdurma
  • wandb → deney takibi (opsiyonel)

2️⃣ Quantization (4‑bit) konfigürasyonu

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,                     # 4‑bit yükle
    bnb_4bit_quant_type="nf4",             # NormalFloat4
    bnb_4bit_compute_dtype=torch.bfloat16, # Hesaplama bf16
    bnb_4bit_use_double_quant=True,        # Double quantization
)

Neden?
GPU belleğini %70‑80 oranında tasarruf eder, büyük modelleri tek GPU’ya sığdırır 🎉


3️⃣ Model ve Tokenizer yükleme

model_id = "meta-llama/Llama-2-7b-hf"   # 👈 Kendi modelini buraya yaz

model = AutoModelForCausalLM.from_pretrained(
    model_id,
    quantization_config=bnb_config,
    device_map="auto",          # Otomatik GPU/CPU dağıtımı
    trust_remote_code=True,
)

tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token   # Pad token yoksa eos kullan
model.config.pad_token_id = tokenizer.pad_token_id

İpucu: device_map="auto" sayesinde model parçaları GPU’lara yayılır, manuel to("cuda") gerekmez.


4️⃣ Modeli LoRA için hazırla

# 4‑bit eğitim için gradient checkpointing ve kbit training hazırlığı
model = prepare_model_for_kbit_training(model, use_gradient_checkpointing=True)

lora_config = LoraConfig(
    r=16,                     # LoRA rank
    lora_alpha=32,            # Scaling
    target_modules=["q_proj", "v_proj"],  # Hangi linear layer’lara ekle
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

model = get_peft_model(model, lora_config)
model.print_trainable_parameters()   # ✅ Sadece LoRA parametreleri eğitilecek

Ne oluyor?
prepare_model_for_kbit_training → quantize edilmiş modelde gradient flow’unu düzeltir.
get_peft_model → sadece LoRA matrisleri requires_grad=True olur, geri kalan dondurulur ❄️


5️⃣ Veri seti hazırlığı (örnek: Alpaca formatı)

def format_example(example):
    # Basit instruction‑response birleştirme
    prompt = f"### Instruction:\n{example['instruction']}\n\n### Response:\n{example['output']}"
    return {"text": prompt}

dataset = load_dataset("tatsu-lab/alpaca", split="train")
dataset = dataset.map(format_example, remove_columns=dataset.column_names)

def tokenize(batch):
    return tokenizer(
        batch["text"],
        truncation=True,
        max_length=1024,
        padding="max_length",
    )

tokenized_ds = dataset.map(tokenize, batched=True, remove_columns=["text"])
tokenized_ds.set_format(type="torch", columns=["input_ids", "attention_mask", "labels"])

Özet:

  • format_example → modelin beklediği prompt şablonu
  • tokenizeinput_ids, attention_mask, labels (labels = input_ids kopyası)

6️⃣ TrainingArguments – hiperparametreler

training_args = TrainingArguments(
    output_dir="./qlora-llama2-7b",
    per_device_train_batch_size=2,          # 🎛 GPU belleğine göre ayarla
    gradient_accumulation_steps=8,          # Etkili batch = 2*8 = 16
    learning_rate=2e-4,
    num_train_epochs=3,
    fp16=False,                             # bf16 kullanıyorsak fp16=False
    bf16=True,                              # Ampere+ GPU’larda bf16 daha stabil
    logging_steps=10,
    evaluation_strategy="steps",
    eval_steps=200,
    save_steps=200,
    save_total_limit=2,
    load_best_model_at_end=True,
    metric_for_best_model="eval_loss",
    greater_is_better=False,
    report_to="wandb",                      # 👉 "tensorboard" da yazabilirsin
    run_name="qlora-llama2-7b-run",
    seed=42,
)

Neden bu değerler?

  • gradient_accumulation_steps → büyük batch simülasyonu
  • bf16=True → Ampere (RTX 30xx/40xx, A100) kartlarda hız + numerik stabilite
  • report_to="wandb" → deneyleri Weights & Biases’ta görselleştirir 📈

7️⃣ Trainer + EarlyStoppingCallback

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_ds,
    tokenizer=tokenizer,
    callbacks=[EarlyStoppingCallback(early_stopping_patience=3)],  # 3 eval’de iyileşme yoksa dur
)

# 👇 WandB init (opsiyonel ama önerilir)
wandb.init(project="qlora-llama2", name=training_args.run_name, config=training_args.to_dict())

Ne sağlıyor?

  • EarlyStoppingCallback → overfit önler, zaman kazandırır ⏱
  • wandb.init → hyperparameter’lar, loss grafikleri, model checkpoint’ları tek panelde 🎛

8️⃣ Eğitimi başlat ve modeli kaydet

trainer.train()                     # 🚀 Eğitim başlar
trainer.save_model("./qlora-llama2-7b-final")   # LoRA adapter + config
tokenizer.save_pretrained("./qlora-llama2-7b-final")
wandb.finish()

Sonuç:

  • ./qlora-llama2-7b-final/ klasöründe sadece LoRA ağırlıkları ve tokenizer bulunur.
  • İleride PeftModel.from_pretrained(base_model, "./qlora-llama2-7b-final") ile birleştirip inference yaparsın 🔁

📋 Kısaca özet

Adım Ne yaptık?
Quantization 4‑bit BitsAndBytesConfig ile modeli küçülttük
LoRA LoraConfig + get_peft_model → sadece adapter eğitildi
Data Alpaca → prompt → tokenize → labels kopyalama
TrainingArgs bf16, grad_accum, lr=2e-4, early_stop, wandb
Trainer Trainer + EarlyStoppingCallback
Kaydet LoRA adapter + tokenizer → inference için hazır

Artık elinde production‑ready bir QLoRA eğitim scripti var.
İstersen deepspeed config ekleyip multi‑GPU’ya ölçeklendirebilir, ya da bitsandbytes 8‑bit deneyerek hız/performans dengeyi test edebilirsin 🛠✨

Kolay gelsin, keyifli eğitimler! 🚀


🔁 Değerlendirme: Metrikler, Ajan Performansı ve İterasyon

Modeli eğittikten sonra nasıl performans gösterdiğini anlamak için birden fazla metrik ve insan geri bildirimi kombine ediyorum. İşte benim sık kullandığım stratejiler 🎯:

  • Perplexity – Dil modelinin ne kadar "şşkın" olduğunu gösterir; düşük değer daha iyi genelleme demek.
  • BLEU / ROUGE – Özellikle özetleme veya çeviri görevlerinde n-gram örtüşmesini ölçer.
  • Görev başarı oranı (tool use accuracy) – Ajan bir araç çağırdığında, doğru aracı doğru parametrelerle çağırma yüzdesi.
  • İnsan değerlendirme (A/B test) – İki model versiyonunu yan yana sunup, kullanıcıların hangisini tercih ettiğini izlerim.

Validation set üzerinde hata analizi 🔍

  1. Örnek çıktıları görselleştirvalidation kümesinden 20‑30 rastgele örnek al, modelin ürettiği metni ve hedefi yan yana koy.
  2. Hata kategorilerini etiketle
    • ❗️ Veri sorunu: Etiket hatası, eksik bağlam.
    • ❗️ Rank / LoRA boyutu: Model kapasitesi yetmiyor.
    • ❗️ Learning rate: Aşırı büyük/küçük → yakınsama sorunu.
  3. Kök nedeni tespiti – Hangi kategori en çok tekrar ediyorsa, o parametreye odaklan.

İpucu: Hata analizini bir tabloya döküp, her iterasyonda "bu kategori %X azaldı" diye takip et. Böylece ilerleme somutlaşır ✅.

Metrik hesaplama örneği (ROUGE) 🛠

Aşağıda evaluate kütüphanesiyle ROUGE skorlarını nasıl topladığımı gösteriyorum. Kodun hemen altında ne yaptığımı anlatıyorum.

from evaluate import load

# ROUGE metriğini yükle
rouge = load("rouge")

def compute_rouge(predictions, references):
    """
    predictions: modelin ürettiği metin listesi
    references : hedef (ground‑truth) metin listesi
    """
    # ROUGE‑1, ROUGE‑2, ROUGE‑L skorlarını hesapla
    results = rouge.compute(predictions=predictions, references=references, use_stemmer=True)
    return results

# Örnek kullanım
preds = ["model bu cümleyi özetledi", "ikinci tahmin örneği"]
refs  = ["bu cümle model tarafından özetlendi", "ikinci referans örneği"]

scores = compute_rouge(preds, refs)
print(scores)
# Çıktı örneği:
# {'rouge1': 0.78, 'rouge2': 0.55, 'rougeL': 0.73, 'rougeLsum': 0.73}

Ne oluyor burada?

  • load("rouge") ile HF’in hazır metrik nesnesini alırız.
  • compute_rouge fonksiyonu tahmin ve referans listelerini alır, use_stemmer=True ile kökleri eşleştirir.
  • Dönen sözlükte rouge1, rouge2, rougeL gibi alt metrikler hazır gelir; bunları TensorBoard / WandB’e loglayarak iterasyonlar arası trendi izleyebilirsin.

Bir sonraki iterasyonda ne düzeltilecek? 🔁

Kök Neden Aksiyon
Veri kalitesi Etiket temizliği, veri artırma (back‑translation) ekle.
Rank / LoRA boyutu Rank’ı 8 → 16 ya da 32’ye çıkar, GPU belleği uygun mu kontrol et.
Learning rate 1e‑4 → 5e‑5 dene; warmup step sayısını artır.
Araç çağırma başarısı Few‑shot örneklerle tool prompt’unu zenginleştir, tool_use_accuracy hedef %90 üstüne çek.

Bu döngüyü her eğitim çalışmasında tekrar ediyorum: metrik → hata analizi → kök neden → hiperparametre/veri güncelleme → yeniden eğitim. Böylece modelin her versiyonu bir öncekisinden ölçülebilir derecede iyileşir 🚀.


🎯 Bonus Tavsiye: Üretimde Ölçeklendirme ve Sürekli İyileştirme

Hazırsan bu son bölümü bir kadeh çayla beraber hızlıca geçelim ☕️. Modeli canlıya almak sadece “deploy et” demek değil; ölçeklenebilirlik, güvenilirlik ve sürekli öğrenme bir arada düşünülmeli.

1️⃣ Model Servisi Seçimi: vLLM / TGI

  • vLLM → PagedAttention sayesinde bellek verimliliği ↑, throughput ↑.
  • TGI (Text Generation Inference) → Hugging Face ekibi tarafından optimize edilmiş, container‑ready ve metrics (Prometheus) out‑of‑the‑box.
  • İpucu: Her ikisini de Docker Compose ile lokalde test et, sonra Kubernetes Deployment + HPA (Horizontal Pod Autoscaler) ile prod’a taşı.

2️⃣ A/B & Canary Deployment 🎯

Aşama Ne Yapılır? Neden?
Canary %5 Yeni modeli %5 trafiğe yönlendir Riski minimize et
Metrics İzle Latency, hata oranı, kullanıcı geri bildirimi Anında rollback kararı ver
Gradual Ramp %10 → %25 → %50 → %100 Güven artınca yaygınlaştır
Feature Flag model_version=v2 flag’i ile kontrol Kod değişikliği olmadan geçiş

Küçük başla, ölç, büyüt 🎯 — bu mottosunu canlıya almak için Argo Rollouts veya Flagger gibi araçları kullanabilirsin.

3️⃣ Veri Geri Besleme Döngüsü (Human‑in‑the‑Loop) 🔁

  1. Loglama → Her inference isteği + cevap + kullanıcı puanı (thumbs up/down) Kafka / PubSub’a push.
  2. Annotation UI → Etiketçiler hatalı cevapları düzeltir, ground‑truth seti oluşur.
  3. Dataset Versioning → DVC / LakeFS ile v1.0 → v1.1 takibi.
  4. Trigger → Yeni veri %10’u geçtiğinde CI/CD pipeline otomatik olarak fine‑tune job’ını tetikler.

4️⃣ Periyodik Yeniden Eğitim (Continual Learning) 🛠

  • Schedule: Haftalık / aylık (veri hacmine göre).
  • Strategy:
    • Replay Buffer → Eski veri %20’si karıştırılarak catastrophic forgetting önlenir.
    • LoRA / Adapters → Tam model yerine küçük adapter’lar eğitilir → GPU maliyeti ↓.
  • Validation: Önceki model ile A/B test yap, statistical significance (p < 0.05) kontrol et.
  • Promotion: Geçerse model_version tag’ini güncelle, canary’a sok.

📋 Pratik Checklist (Kopyala‑Yapıştır)

  • Servis: vLLM veya TGI + HPA ayarlandı mı?
  • Canary: Argo Rollouts / Flagger kuruldu mu?
  • Feedback: Kullanıcı puanlama UI’sı canlı mı?
  • Pipeline: Yeni veri → fine‑tune → test → promote otomatik mi?
  • Monitoring: Latency, error rate, drift metrics (Prometheus + Grafana) var mı?

Son söz: Prod’a çıkmak bir maraton, sprint değil. Küçük başla, ölç, büyüt prensibiyle her adımda veri topla, modelini iyileştir ve kullanıcıya değer kat.

İyi kodlamalar! 🚀


Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.

Burak Sağlık

Burak Saglik

©2024 Desing and Developed by @Burak Sağlık

All rights reserved