Kendi Verinle GPT Eğitme: Fine-tuning API Rehberi

Şirket içi dokümantasyonunuzu, destek ticket’larınızı ya da alan bazlı verilerinizi bir yapay zeka modeline öğretmek istiyorsunuz ama genel amaçlı GPT modellerinin yetersiz kaldığını fark ediyorsunuz. İşte tam bu noktada fine-tuning devreye giriyor. OpenAI’nin fine-tuning API’si, kendi verilerinizle özelleştirilmiş bir model oluşturmanıza olanak tanıyor. Bu yazıda sıfırdan başlayarak production’a hazır bir fine-tuned model oluşturma sürecini ele alacağız.

Fine-tuning Nedir ve Ne Zaman Kullanmalısınız?

Fine-tuning, önceden eğitilmiş bir modeli kendi veri kümenizle yeniden eğitme sürecidir. Model tamamen sıfırdan eğitilmez; mevcut ağırlıklar üzerine domain’e özgü bilgiler eklenir. Bu, hem maliyet hem de zaman açısından çok daha verimli bir yaklaşımdır.

Fine-tuning’i şu senaryolarda tercih etmelisiniz:

  • Tutarlı format: API’niz her zaman JSON döndürmeli, loglarınız belirli bir template’e uymalı
  • Alan bazlı terminoloji: Tıp, hukuk, yazılım gibi spesifik jargon gerektiren durumlar
  • Şirket kültürü: Marka sesi, iletişim tonu ve kurumsal standartlar
  • Maliyet optimizasyonu: Uzun system prompt’lar yerine modele bu bilgiyi öğretmek
  • Gizlilik: Hassas bilgileri her istekte göndermek yerine modele yerleştirmek

Öte yandan fine-tuning her derde deva değil. Eğer bilgi güncel tutulması gerekiyorsa ya da çok az örneğiniz varsa (50’nin altı), önce RAG (Retrieval-Augmented Generation) yaklaşımını değerlendirin.

Gereksinimler ve Ortam Kurulumu

Başlamadan önce şunlara ihtiyacınız var:

  • OpenAI API anahtarı (fine-tuning erişimi olan)
  • Python 3.8+
  • En az 10-50 kaliteli eğitim örneği (ideal olarak 100+)

Ortamı kuralım:

# Virtual environment oluştur
python3 -m venv finetuning-env
source finetuning-env/bin/activate

# Gerekli paketleri yükle
pip install openai tiktoken pandas jsonlines

# API anahtarını ortam değişkenine ekle
export OPENAI_API_KEY="sk-..."

# .bashrc veya .zshrc'ye kalıcı olarak eklemek için
echo 'export OPENAI_API_KEY="sk-..."' >> ~/.bashrc
source ~/.bashrc

Eğitim Verisi Hazırlama

Fine-tuning için veri formatı çok kritik. OpenAI, JSONL (JSON Lines) formatı bekliyor. Her satır, bir conversation örneği içeren geçerli bir JSON nesnesi olmalı.

JSONL Format Yapısı

Temel format şu şekilde:

cat > training_data.jsonl << 'EOF'
{"messages": [{"role": "system", "content": "Sen bir Linux sistem yöneticisi asistanısın. Teknik sorulara kısa, net ve uygulanabilir cevaplar verirsin."}, {"role": "user", "content": "Nginx servisini nasıl yeniden başlatırım?"}, {"role": "assistant", "content": "sudo systemctl restart nginxnnDurumu kontrol etmek için: sudo systemctl status nginx"}]}
{"messages": [{"role": "system", "content": "Sen bir Linux sistem yöneticisi asistanısın. Teknik sorulara kısa, net ve uygulanabilir cevaplar verirsin."}, {"role": "user", "content": "Disk doluluk oranını nasıl kontrol ederim?"}, {"role": "assistant", "content": "df -hnnBelirli bir dizin için: du -sh /var/log/*nnEn çok yer kaplayan dosyaları bulmak: du -sh /* 2>/dev/null | sort -hr | head -10"}]}
EOF

Toplu Veri Üretimi için Python Script

Gerçek dünyada verileriniz muhtemelen farklı kaynaklardan geliyor. Destek ticket’larından, wiki sayfalarından ya da mevcut dokümantasyondan veri üretmek için bir script yazalım:

cat > prepare_training_data.py << 'PYTHON'
import json
import csv
import sys

def csv_to_jsonl(input_file, output_file, system_prompt):
    """
    CSV dosyasından JSONL eğitim verisi üretir.
    CSV formatı: soru,cevap
    """
    training_examples = []
    
    with open(input_file, 'r', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            example = {
                "messages": [
                    {
                        "role": "system",
                        "content": system_prompt
                    },
                    {
                        "role": "user", 
                        "content": row['soru'].strip()
                    },
                    {
                        "role": "assistant",
                        "content": row['cevap'].strip()
                    }
                ]
            }
            training_examples.append(example)
    
    with open(output_file, 'w', encoding='utf-8') as f:
        for example in training_examples:
            f.write(json.dumps(example, ensure_ascii=False) + 'n')
    
    print(f"{len(training_examples)} örnek {output_file} dosyasına yazıldı.")
    return len(training_examples)

system_prompt = """Sen XYZ Şirketinin IT destek asistanısın. 
Şirket içi sistemler, uygulamalar ve altyapı hakkında 
çalışanlara yardımcı olursun. Cevapların kısa ve 
adım adım olmalı."""

if __name__ == "__main__":
    count = csv_to_jsonl(
        'tickets.csv', 
        'training_data.jsonl',
        system_prompt
    )
    print(f"Toplam {count} eğitim örneği hazır.")
PYTHON

python3 prepare_training_data.py

Veri Kalite Kontrolü

Veriyi yüklemeden önce mutlaka doğrulama yapın. Bozuk JSON, token limiti aşımı ya da boş mesajlar eğitimi başarısız kılabilir:

cat > validate_data.py << 'PYTHON'
import json
import tiktoken

def validate_jsonl(file_path, max_tokens=4096):
    encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
    errors = []
    total_tokens = 0
    
    with open(file_path, 'r', encoding='utf-8') as f:
        for line_num, line in enumerate(f, 1):
            line = line.strip()
            if not line:
                continue
            
            try:
                data = json.loads(line)
            except json.JSONDecodeError as e:
                errors.append(f"Satır {line_num}: Geçersiz JSON - {e}")
                continue
            
            if 'messages' not in data:
                errors.append(f"Satır {line_num}: 'messages' alanı eksik")
                continue
            
            messages = data['messages']
            if len(messages) < 2:
                errors.append(f"Satır {line_num}: En az 2 mesaj gerekli")
                continue
            
            # Token sayısını hesapla
            text = ' '.join([m['content'] for m in messages])
            token_count = len(encoding.encode(text))
            total_tokens += token_count
            
            if token_count > max_tokens:
                errors.append(f"Satır {line_num}: Token limiti aşıldı ({token_count} > {max_tokens})")
            
            # Rol kontrolü
            roles = [m['role'] for m in messages]
            if 'assistant' not in roles:
                errors.append(f"Satır {line_num}: 'assistant' rolü eksik")
    
    if errors:
        print("HATALAR:")
        for err in errors:
            print(f"  - {err}")
    else:
        print("Veri doğrulama başarılı!")
        print(f"Toplam token: {total_tokens:,}")
        print(f"Tahmini maliyet (eğitim): ${total_tokens * 0.000008:.4f}")

validate_jsonl('training_data.jsonl')
PYTHON

python3 validate_data.py

Fine-tuning İşini Başlatma

Veri hazır ve doğrulandıktan sonra asıl işe geçebiliriz.

Dosya Yükleme

cat > upload_and_train.py << 'PYTHON'
import openai
import time
import json

client = openai.OpenAI()

# Eğitim dosyasını yükle
print("Dosya yükleniyor...")
with open("training_data.jsonl", "rb") as f:
    response = client.files.create(
        file=f,
        purpose="fine-tune"
    )

file_id = response.id
print(f"Dosya ID: {file_id}")
print(f"Dosya durumu: {response.status}")

# Dosyanın işlenmesini bekle
print("Dosya işleniyor...")
while True:
    file_status = client.files.retrieve(file_id)
    if file_status.status == "processed":
        print("Dosya hazır!")
        break
    elif file_status.status == "error":
        print(f"Dosya hatası: {file_status.status_details}")
        exit(1)
    time.sleep(5)
    print(".", end="", flush=True)

# Fine-tuning işini başlat
print("nFine-tuning başlatılıyor...")
job = client.fine_tuning.jobs.create(
    training_file=file_id,
    model="gpt-3.5-turbo",
    hyperparameters={
        "n_epochs": 3,
        "batch_size": "auto",
        "learning_rate_multiplier": "auto"
    },
    suffix="sysadmin-v1"  # Model adına eklenecek suffix
)

print(f"İş ID: {job.id}")
print(f"Durum: {job.status}")

# Job ID'yi kaydet
with open("job_info.json", "w") as f:
    json.dump({"job_id": job.id, "file_id": file_id}, f)

print("Job bilgileri job_info.json dosyasına kaydedildi.")
PYTHON

python3 upload_and_train.py

İş Durumunu Takip Etme

Fine-tuning işi genellikle birkaç dakika ile birkaç saat arasında sürebilir. Durumu izlemek için:

cat > monitor_job.py << 'PYTHON'
import openai
import json
import time
import sys

client = openai.OpenAI()

# Job ID'yi dosyadan oku
with open("job_info.json", "r") as f:
    info = json.load(f)

job_id = info["job_id"]

def check_status(job_id, verbose=True):
    job = client.fine_tuning.jobs.retrieve(job_id)
    
    if verbose:
        print(f"nİş ID: {job.id}")
        print(f"Durum: {job.status}")
        print(f"Model: {job.model}")
        
        if job.fine_tuned_model:
            print(f"Eğitilmiş model: {job.fine_tuned_model}")
        
        if job.trained_tokens:
            print(f"Eğitilen token: {job.trained_tokens:,}")
            
        # Son olayları listele
        events = client.fine_tuning.jobs.list_events(job_id, limit=5)
        print("nSon olaylar:")
        for event in events.data:
            print(f"  [{event.level}] {event.message}")
    
    return job

# Sürekli izleme modu
if "--watch" in sys.argv:
    print("İzleme modu aktif. Ctrl+C ile durdur.")
    while True:
        job = check_status(job_id)
        if job.status in ["succeeded", "failed", "cancelled"]:
            print(f"nİş tamamlandı: {job.status}")
            if job.fine_tuned_model:
                print(f"Kullanılabilir model: {job.fine_tuned_model}")
                # Model ID'yi kaydet
                info["model_id"] = job.fine_tuned_model
                with open("job_info.json", "w") as f:
                    json.dump(info, f)
            break
        time.sleep(30)
else:
    check_status(job_id)
PYTHON

# Tek seferlik kontrol
python3 monitor_job.py

# Sürekli izleme
python3 monitor_job.py --watch

Fine-tuned Modeli Kullanma

Model eğitimi tamamlandıktan sonra, tıpkı diğer OpenAI modelleri gibi kullanabilirsiniz.

cat > test_model.py << 'PYTHON'
import openai
import json

client = openai.OpenAI()

# Eğitilmiş model ID'sini yükle
with open("job_info.json", "r") as f:
    info = json.load(f)

model_id = info.get("model_id")

if not model_id:
    print("Model henüz hazır değil!")
    exit(1)

def ask_model(question, model=model_id):
    """Fine-tuned modele soru sor"""
    response = client.chat.completions.create(
        model=model,
        messages=[
            {
                "role": "system",
                "content": "Sen bir Linux sistem yöneticisi asistanısın."
            },
            {
                "role": "user",
                "content": question
            }
        ],
        temperature=0.3,
        max_tokens=500
    )
    return response.choices[0].message.content

# Test soruları
test_questions = [
    "Apache web sunucusunu nasıl yeniden başlatırım?",
    "Bir kullanıcının sudo yetkisini nasıl kaldırırım?",
    "Cron job nasıl oluştururum?"
]

print(f"Model: {model_id}n")
print("=" * 50)

for question in test_questions:
    print(f"nSoru: {question}")
    print(f"Cevap: {ask_model(question)}")
    print("-" * 50)
PYTHON

python3 test_model.py

Hiperparametre Optimizasyonu

Eğitim sonuçlarından memnun değilseniz hiperparametreleri ayarlamanız gerekebilir.

Önemli hiperparametreler şunlardır:

  • n_epochs: Kaç epoch eğitim yapılacağı. Az veriyle 3-5, çok veriyle 1-2 epoch önerilir
  • batch_size: Her adımda işlenen örnek sayısı. “auto” genellikle iyi sonuç verir
  • learning_rate_multiplier: Öğrenme hızı çarpanı. Düşük değer (0.1) kararlı ama yavaş, yüksek değer (2.0) hızlı ama dengesiz
cat > advanced_training.py << 'PYTHON'
import openai

client = openai.OpenAI()

# Az veri ile agresif eğitim
job_aggressive = client.fine_tuning.jobs.create(
    training_file="file-abc123",
    validation_file="file-def456",  # Opsiyonel validation seti
    model="gpt-3.5-turbo",
    hyperparameters={
        "n_epochs": 5,
        "batch_size": 4,
        "learning_rate_multiplier": 0.5
    },
    suffix="sysadmin-aggressive"
)

# Çok veri ile konservatif eğitim
job_conservative = client.fine_tuning.jobs.create(
    training_file="file-xyz789",
    model="gpt-3.5-turbo",
    hyperparameters={
        "n_epochs": 2,
        "batch_size": 16,
        "learning_rate_multiplier": 0.1
    },
    suffix="sysadmin-conservative"
)

print(f"Agresif iş ID: {job_aggressive.id}")
print(f"Konservatif iş ID: {job_conservative.id}")
PYTHON

Maliyet Yönetimi ve İzleme

Fine-tuning hem eğitim hem de inference için ücretlidir. Maliyetleri kontrol altında tutmak kritik:

  • Eğitim maliyeti: Kullanılan token başına hesaplanır. gpt-3.5-turbo için 1000 token başına 0.008$
  • Inference maliyeti: Fine-tuned model, base modelden daha pahalıdır. Input için 1000 token 0.012$, output için 0.016$
  • Gereksiz modelleri silin: Kullanılmayan fine-tuned modeller depolanır ama inference yapılmazsa ücret oluşmaz
cat > cost_estimator.py << 'PYTHON'
import json

def estimate_training_cost(jsonl_file, n_epochs=3):
    """Eğitim maliyetini tahmin et"""
    import tiktoken
    
    encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
    total_tokens = 0
    example_count = 0
    
    with open(jsonl_file, 'r') as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            data = json.loads(line)
            text = ' '.join([m['content'] for m in data['messages']])
            total_tokens += len(encoding.encode(text))
            example_count += 1
    
    training_tokens = total_tokens * n_epochs
    cost_per_1k = 0.008  # gpt-3.5-turbo fine-tuning fiyatı
    estimated_cost = (training_tokens / 1000) * cost_per_1k
    
    print(f"Örnek sayısı: {example_count}")
    print(f"Toplam token: {total_tokens:,}")
    print(f"Epoch sayısı: {n_epochs}")
    print(f"Eğitim token: {training_tokens:,}")
    print(f"Tahmini maliyet: ${estimated_cost:.4f}")
    
    return estimated_cost

estimate_training_cost('training_data.jsonl', n_epochs=3)
PYTHON

python3 cost_estimator.py

Gerçek Dünya Senaryosu: Şirket İçi Chatbot

Bir şirkette IT helpdesk asistanı oluşturma senaryosunu ele alalım. Elinizdeki veriler: 500 adet çözülmüş destek ticket’ı, şirket wiki’si ve SSS sayfaları.

Bu senaryoda izlenecek adımlar şunlardır:

  • Veri temizleme: Ticket’lardan kişisel bilgileri çıkarın, boş ya da alakasız ticket’ları filtreleyin
  • Veri zenginleştirme: Her ticket’ı conversation formatına dönüştürün, tek satırlık cevapları genişletin
  • Validation seti oluşturma: Verinin %10-20’sini validation için ayırın
  • İteratif eğitim: İlk model genellikle mükemmel olmaz, sonuçları değerlendirin ve veriyi iyileştirin
  • A/B testi: Fine-tuned modeli base modelle karşılaştırın, gerçek kullanıcı senaryolarında test edin
  • Monitoring: Production’da model cevaplarını loglayın, kalite düşüşlerini izleyin

En sık yapılan hatalar arasında yetersiz veri miktarı ile başlamak var. 10 örnekle fine-tuning yapılmaz, en az 50-100 kaliteli örnek gerekir. Bunun yanı sıra tutarsız veri de büyük sorun yaratır; bazı cevaplar detaylı, bazıları tek satır olursa model ne öğreneceğini bilemez. System prompt’u eğitim verisinde de kullanmak önemli, inference sırasında farklı bir system prompt kullanırsanız sonuçlar bozulur. Son olarak validation seti olmadan eğitim yaparsanız overfitting’i tespit etmek güçleşir.

Sonuç

Fine-tuning, doğru kullanıldığında gerçekten güçlü bir araç. Özellikle tutarlı format gereksinimleri, alan bazlı terminoloji ve şirket içi süreçler için mükemmel sonuçlar veriyor. Ama her yapay zeka sorusunun cevabı değil; önce RAG ve prompt engineering’i değerlendirin, bunlar yetersiz kaldığında fine-tuning’e geçin.

Dikkat etmeniz gereken en kritik nokta veri kalitesi. Miktardan çok kalite önemli; 50 mükemmel örnek, 500 kötü örnekten çok daha iyi sonuç verir. Bunun yanı sıra maliyetleri baştan hesaplayın, özellikle yüksek trafikli uygulamalarda fine-tuned model maliyeti hızla artabilir.

Başlangıç için pratik öneri: Küçük bir pilot proje seçin, 100-200 örnek hazırlayın, gpt-3.5-turbo ile başlayın ve sonuçları ölçün. Sonuçlar iyiyse production’a taşıyın, değilse veri kalitenizi artırın ya da hiperparametreleri ayarlayın. Fine-tuning bir kez yapıp bırakılan bir işlem değil, sürekli iyileştirme gerektiren iteratif bir süreç.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir