İçeriğe Atla
Mustafa Erbay
Teknoloji İnsan tarafından yazıldı · 9 dk okuma · görüntülenme Read in English
100%

AI İçerik Pipeline'ımda Gözden Kaçan Hatalar: Idempotency'nin Önemi

AI ile içerik üretim süreçlerinde karşılaşılan mükerrer kayıt ve token israfı sorunlarını, idempotency prensipleriyle nasıl çözdüğümü anlatıyorum.

AI içerik üretim hattı ve veritabanı bağlantılarını temsil eden teknik illüstrasyon

Kendi siteme içerik üreten AI pipeline’ını ilk kurduğumda, her şeyin lineer bir akışta kusursuz çalışacağını varsaymıştım. Bir gün sabah uyandığımda, backend loglarında aynı başlık için üretilmiş üç farklı taslak ve her biri için ayrı ayrı harcanmış Gemini Flash token’ları gördüm. Sorun basitti ama çözümü sistem mimarisinin temel taşlarından birine dokunuyordu: Idempotency.

Yazılım dünyasında “bir işlemin birden fazla kez uygulanmasının, ilk uygulamadan sonra sonucu değiştirmemesi” olarak tanımlanan bu kavram, özellikle maliyetli ve uzun süren AI işlemlerinde hayati önem taşıyor. Eğer bir API isteği network hatası yüzünden yarıda kalırsa ve sisteminiz bunu “hiç yapılmadı” sayıp tekrar denerse, hem cüzdanınızdan hem de veri bütünlüğünüzden oluyorsunuz.

Sorun: Neden İki Kere Ödüyoruz?

AI içerik üretim süreci, tipik bir CRUD işleminden çok daha farklı bir doğaya sahip. Bir LLM’e (Large Language Model) prompt gönderdiğinizde, yanıtın gelmesi 10 saniye ile 2 dakika arasında sürebiliyor. Bu süre zarfında HTTP bağlantısı kopabilir, gunicorn worker’ı timeout yiyebilir veya kullandığınız provider (OpenRouter, Groq vs.) yanıtı gönderse bile sizin tarafınızda bir ConnectionResetError oluşabilir.

Geçen ay başıma gelen tam olarak buydu. Bir içerik üretimi başlattım, sistem Gemini Flash’a isteği gönderdi, model içeriği üretti ama yanıt bana dönerken network katmanında bir paket kaybı yaşandı. Benim retry (tekrar deneme) mekanizmam devreye girdi ve aynı içerik için tekrar istek attı. Sonuç? Veritabanında mükerrer kayıtlar ve boşuna giden işlemci gücü.

Idempotency Key Stratejisi

Bu sorunu çözmek için ilk yaptığım iş, her bir içerik üretim talebine benzersiz bir idempotency_key atamak oldu. Bu key’i genellikle içeriğin temel parametrelerinden (başlık, hedef dil ve tarih gibi) bir hash oluşturarak elde ediyorum. Eğer sistem aynı hash ile yeni bir istek alırsa, yeni bir işlem başlatmak yerine mevcut işlemin durumunu kontrol ediyor.

Bu stratejiyi uygularken veritabanı seviyesinde UNIQUE constraint kullanmak en sağlam yol. PostgreSQL üzerinde çalışırken, sadece bir sütunu değil, belirli bir logic’i korumak için EXCLUSION constraint veya PARTIAL INDEX bile gerekebiliyor. Ama en basiti, işleme özel üretilen anahtarı veritabanına “önce ben geldim” diyerek yazmak.

Veritabanı Seviyesinde Koruma

PostgreSQL’de ON CONFLICT ifadesi hayat kurtarır. Bir içeriği üretmeye başlamadan önce bir “işlem kaydı” oluşturuyorum. Eğer bu kayıt zaten varsa, veritabanı bana hata döndürüyor ve ben de “bu zaten yapılıyor veya yapıldı” diyerek süreci sonlandırıyorum.

INSERT INTO content_tasks (idempotency_key, status, title)
VALUES ('hsh_827364812', 'processing', 'Sistem Mimarisi Üzerine')
ON CONFLICT (idempotency_key) 
DO NOTHING;

Bu basit SQL sorgusu, aynı anda tetiklenen iki worker’ın aynı işi yapmasını engelliyor. Eğer ilk satır eklendiyse, ikinci worker DO NOTHING sayesinde sessizce dağılıyor. Ancak burada dikkat edilmesi gereken bir nokta var: İşlem yarıda kalırsa ne olacak?

Durum Yönetimi ve “Zombi” Tasklar

İşlem başladı (processing), ancak sunucu restart attı veya kernel panic oldu. Bu durumda o idempotency_key veritabanında sonsuza kadar “işleniyor” olarak kalır. Ben buna “zombi task” diyorum. Bu sorunu aşmak için bir updated_at sütunu ve bir timeout mekanizması kullanıyorum.

Eğer bir task 10 dakikadan uzun süredir “processing” durumundaysa, sistem bunu “fail” kabul edip tekrar denenebilir hale getiriyor. Bunu yaparken Redis üzerinde dağıtık bir kilit (distributed lock) kullanmak, birden fazla sunucunun (node) olduğu senaryolarda çakışmaları önlemek için şart.

Multi-Provider Fallback ve State Karmaşası

Kendi pipeline’ımda sadece tek bir AI provider’a bağlı kalmıyorum. Gemini Flash yanıt vermezse OpenRouter üzerinden başka bir modele, o da olmazsa Groq’a fallback yapıyorum. Bu durum idempotency yönetimini daha da karmaşıklaştırıyor. Çünkü her provider’ın farklı timeout süreleri ve hata kodları var.

Bir üretim ERP’sinde çalışırken öğrendiğim en önemli ders şuydu: “Yazılım mimarisi çoğu zaman kod değil, organizasyonel akıştır.” AI tarafında da bu böyle. Hangi modelin hangi aşamada başarısız olduğunu takip etmezseniz, sisteminiz “idempotent” olsa bile tutarsız veri üretebilir. Bu yüzden her provider denemesini ayrı bir attempt olarak logluyorum.

AşamaProviderDurumSüre (sn)
Attempt 1Gemini FlashTimeout30
Attempt 2Groq (Llama 3)Success4.2
Attempt 3-Skipped-

Pratik Bir Uygulama: FastAPI ve SQLAlchemy Örneği

Python (FastAPI) tarafında bu işi nasıl yönettiğime dair bir kod parçası paylaşayım. Burada önemli olan, veritabanı işlemini bir transaction içinde yönetmek ve dış servise (AI API) gitmeden önce durumu “başladı” olarak işaretlemektir.

async def generate_ai_content(db: Session, request: ContentRequest):
    # Idempotency key oluştur
    id_key = generate_hash(request.title, request.context)
    
    # Mevcut taskı kontrol et
    task = db.query(ContentTask).filter_by(idempotency_key=id_key).first()
    
    if task:
        if task.status == "completed":
            return task.result
        if task.status == "processing" and not is_timed_out(task):
            raise HTTPException(status_code=409, detail="İşlem devam ediyor")
    
    # Yeni task oluştur veya eskini güncelle
    task = upsert_task(db, id_key, status="processing")
    
    try:
        # Asıl AI çağrısı burada yapılıyor
        content = await ai_provider.call(request.prompt)
        
        task.status = "completed"
        task.result = content
        db.commit()
        return content
    except Exception as e:
        task.status = "failed"
        task.error_log = str(e)
        db.commit()
        raise e

Buradaki upsert_task fonksiyonu, eğer task varsa ve timeout olmuşsa onu tekrar “processing”e çekmeli. Bu, “atleast-once” delivery garantisi sağlar. Yani içerik en az bir kere üretilecektir ama idempotency sayesinde asla mükerrer olmayacaktır.

Monitoring ve Observability

Sistemi kurup bırakmak yetmiyor. PostgreSQL WAL (Write-Ahead Logging) bloat’u gibi sorunlar bazen bu hızlı insert-update trafiğinden kaynaklanabiliyor. Özellikle yüksek hacimli bir içerik üretim hattınız varsa, vacuum operasyonlarını yakından izlemeniz gerekir. Ben kendi sistemimde auditd ile dosya bütünlüğünü izlerken, uygulama seviyesinde de her başarısız idempotency kontrolünü bir metrik olarak Prometheus’a basıyorum.

Eğer “Conflict” hataları (HTTP 409) bir anda artıyorsa, bu genellikle bir yerlerde retry mekanizmasının çok agresif çalıştığını veya bir worker’ın “deadlock” durumuna düştüğünü gösterir. 20 yıllık saha tecrübemde gördüğüm en büyük hata, bu tip metrikleri “zaten çalışıyor” diyerek görmezden gelmektir.

Sonuç

AI içerik pipeline’ı kurmak sadece bir prompt gönderip yanıtı kaydetmek değildir. Gerçek dünya şartlarında; ağ kopar, API çöker, disk dolar. Idempotency, bu kaosun içinde verilerinizin temiz kalmasını sağlayan emniyet kemeridir. Kendi yan ürünlerimde ve kurumsal projelerimde bu prensibi ne zaman es geçsem, mutlaka bir gece yarısı operasyonuyla veritabanı temizlemek zorunda kaldım.

Bir sonraki yazıda, bu pipeline’ın üzerine inşa ettiğim RAG mimarisinde vektör veritabanı seçimlerimi ve neden bazı popüler çözümlerden kaçındığımı anlatacağım.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

✉️ Ücretsiz · Spam yok · İstediğin an çık

Haftalık özet — AI değil, bizzat ben seçiyorum

Haftada bir mail: o haftanın en önemli yazısı, perde arkası notları, ve "bu hafta gerçekten kullandığım araç" bölümü. Az gürültü, çok sinyal.

  • 📌
    Haftanın en iyisi Sadece okumaya değer tek yazı
  • 🔧
    Alet çantası Bu hafta kullandığım araçlar
  • 🧠
    Perde arkası Blog'a girmeyen notlar

Spam yapmıyoruz. İstediğiniz zaman ayrılabilirsiniz. · Sadece Umami (self-hosted, Google yok) ile takip.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar