Blog'a Dön

Buğra Şıkel

Otonom PR İncelemelerinde False-Positive Gürültüsünü Bastıran 5 Prompt Deseni

Otonom PR İncelemelerinde False-Positive Gürültüsünü Bastıran 5 Prompt Deseni

Giriş

Bir otonom code review (PR inceleme) ajanı devreye aldığınız ilk gün genellikle bir kutlamayla başlar. İkinci gün ise takımın kıdemli yazılımcılarının Slack üzerinden size gönderdiği öfkeli mesajlarla devam eder. 200 mühendisin aktif kod yazdığı, günde ortalama 140 PR açılan bir organizasyonda, GPT-4-turbo tabanlı bir inceleme ajanı ilk haftasında PR başına ortalama 4.2 yorum üretti. Bu yorumların %78’i geliştiriciler tarafından “Resolve” edilip geçildi (ignore rate). Sorun modelin kodu anlamaması değildi; sorun, modelin bağlamdan kopuk bir şekilde statik analiz araçlarının işini yapmaya çalışması ve en ufak bir stil farklılığını “mimari bir hata” gibi sunmasıydı.

Otonom sistemlerde “false-positive” (hatalı pozitif) gürültüsü, developer deneyimini (DX) doğrudan baltalar. Geliştirici, 3. kez boşluk karakteri uyarısı veya sistemde zaten tanımlı olan bir util fonksiyonunun “yokluğu” hakkında halüsinatif bir yorum gördüğünde, ajanın ürettiği tüm çıktıları körleme geçmeye başlar. Bu durum, güvenlik açıklarını veya gerçek mimari darboğazları yakalayan %22’lik değerli yorumların da çöpe gitmesine neden olur.

Aşağıda, false-positive oranını %78’den %12 seviyelerine çeken, token maliyetlerinde ortalama %35 düşüş sağlayan ve PR inceleme sürelerindeki p99 gecikmesini (latency) 8.4 saniyeden 3.1 saniyeye indiren 5 spesifik prompt mühendisliği desenini (pattern) inceleyeceğiz.

İçindekiler

  • Linter-Aware Bypassing (Statik Analiz Bariyeri Deseni)
  • The Two-Stage Triage (Çift Aşamalı Triage Deseni)
  • Contextual Dependency Injection (Bağlamsal Bağımlılık Enjeksiyonu Deseni)
  • The Severity Matrix (Önem Derecesi Matrisi Deseni)
  • Internal Convention Anchoring (Kurum İçi Standart Çapalama Deseni)
  • Pratik Öneriler / Production Notları
  • Sık Sorulan Sorular
  • Sonuç

Linter-Aware Bypassing (Statik Analiz Bariyeri Deseni)

LLM’lerin en büyük zaaflarından biri, kendilerini bir linter veya formatter zannetmeleridir. PEP8 veya ESLint kuralları hakkında yorum yapmak, model için “kolay” bir çıktıdır.

Problem

Ajan, CI hattında zaten çalışan SonarQube, ESLint veya Black gibi araçların yakalayacağı stil, tip (typing) veya syntax hatalarını tekrarlar. Bu durum hem token israfına yol açar hem de PR üzerinde gereksiz bir gürültü yaratır.

Çözüm

Modelin sistem prompt’una linter raporunu enjekte ederek (veya linter’ın çalıştığı bilgisini vererek) bu kategorilerdeki tüm yorumları kesin bir dille yasaklamak.


# Linter raporunu prompt'a dahil eden yapı
import subprocess

def get_eslint_report(file_path):
    # ESLint sonucunu JSON formatında al
    result = subprocess.run(
        ["eslint", file_path, "-f", "json"],
        capture_output=True,
        text=True
    )
    return result.stdout

system_prompt = """
Sen kıdemli bir yazılım mimarısın.
Görev: Aşağıdaki Git Diff'ini incelemek ve SADECE mantıksal, mimari veya güvenlik hatalarını raporlamak.

KURALLAR:
1. Bu kod zaten ESLint ve Prettier tarafından kontrol edildi.
2. Stil, boşluk, isimlendirme standartları (camelCase vs snake_case) veya eksik noktalı virgül gibi konularda YORUM YAPMA.
3. Aşağıdaki  etiketleri arasında yer alan hatalar CI tarafından yakalanmıştır. Bu hatalarla ilgili hiçbir şey söyleme.


{eslint_output}

"""

Ne Zaman Uygulanır?

  • Projede katı bir CI/CD pipeline’ı ve statik analiz araçları varsa.
  • Modelin stil düzeltmeleri için gereksiz token tüketimi %15’in üzerine çıktıysa.

Ne Zaman Uygulanmaz?

  • Legacy (eski) bir kod tabanında çalışıyorsanız ve linter kuralları henüz projeye entegre edilmemişse.

Trade-off Analizi

Linter raporunu prompt’a eklemek (context injection) prompt boyutunu artırır ve maliyeti PR başına $0.002 ile $0.012 arasında yükseltebilir. Ancak üretilen gereksiz tokenları azalttığı için genellikle başabaş (break-even) noktasını geçer.

The Two-Stage Triage (Çift Aşamalı Triage Deseni)

Tek bir prompt ile “Bu kodu oku ve hataları yaz” komutu verdiğinizde, LLM genellikle boş dönmekten korkar. Modelin eğitildiği RLHF (Reinforcement Learning from Human Feedback) yapısı, sorulan soruya kapsamlı bir cevap verme eğilimindedir.

Problem

Kodda hiçbir hata olmamasına rağmen, modelin yapay bir sorun uydurması (halüsinasyon) veya kodu överken bile 10 satırlık bir paragraf oluşturması.

Çözüm

Süreci iki API çağrısına bölmek. İlk aşamada model sadece ikili (binary) bir karar verir ve güven skoru üretir. İkinci aşama sadece ilk aşamadan geçilirse tetiklenir.


from pydantic import BaseModel, Field
from openai import OpenAI

client = OpenAI()

class TriageResult(BaseModel):
    needs_comment: bool = Field(description="Kodda kritik bir mantık hatası veya güvenlik açığı var mı?")
    confidence_score: float = Field(description="0.0 ile 1.0 arası güven skoru")
    reasoning: str = Field(description="Neden yorum yapılması gerektiğinin tek cümlelik özeti")

def stage_one_triage(diff_text):
    response = client.beta.chat.completions.parse(
        model="gpt-4o-2024-08-06",
        messages=[
            {"role": "system", "content": "Kodu incele. Sadece gerçekten yorum yapmaya değer bir blok varsa needs_comment=true dön. Mükemmel kodlar için false dön."},
            {"role": "user", "content": diff_text}
        ],
        response_format=TriageResult,
        temperature=0.1
    )
    return response.choices[0].message.parsed

# Kullanım:
triage = stage_one_triage(git_diff)
if triage.needs_comment and triage.confidence_score > 0.85:
    # İkinci aşamayı (yorum oluşturma) tetikle
    generate_pr_comment(git_diff, triage.reasoning)

Ne Zaman Uygulanır?

  • PR’ların %50’sinden fazlasının trivial (önemsiz) değişiklikler içerdiği repository’lerde.
  • Modelin ürettiği “Looks good to me ama şunu da yapsan fena olmaz” tarzı yorumları bitirmek için.

Ne Zaman Uygulanmaz?

  • Çok düşük gecikme (latency) bütçesi olan, anlık çalışan IDE eklentilerinde (ekstra API çağrısı p99 süresini 800ms’den 1600ms’ye çıkarır).

Contextual Dependency Injection (Bağlamsal Bağımlılık Enjeksiyonu Deseni)

Git Diff’leri genellikle 3-5 satır bağlam (context) içerir. Ajan bu dar pencereye baktığında, dosyanın tepesinde import edilmiş modülleri göremez.

Problem

Ajanın “Burada `processData` fonksiyonunu çağırmışsın ama tanımlanmamış” diyerek false-positive üretmesi. Halbuki o fonksiyon PR’ın bir başka dosyasında veya base branch’te mevcuttur.

Çözüm

Diff analizi sırasında AST (Abstract Syntax Tree) çıkarımı yapmak veya ilgili dosyaların iskeletlerini (skeleton) prompt’a dahil etmek. Tüm repository’yi bağlama sokmak (128k+ token) maliyetlidir; bunun yerine sadece değiştirilen sembollerin referansları enjekte edilmelidir.


// Diff ile birlikte dosya bağımlılıklarının iskeletini XML tag'leri ile prompt'a ekleme
const prompt = `
Sen bir kod inceleme uzmanısın.
Aşağıda değiştirilen kod parçası (diff) ve bu dosyanın bağımlı olduğu diğer modüllerin sadece imza (signature) tanımları verilmiştir.


${gitDiff}



${extractFunctionSignatures(relatedFiles)} 
// Örn: export function processData(input: string): boolean;


Kurallar:
1.  içinde tanımlı olan değişken veya fonksiyonlar için 'tanımsız' (undefined) hatası verme.
`;

Ne Zaman Uygulanır?

  • Çok dosyalı (multi-file) refactoring PR’larında.
  • Monorepo yapılarında veya iç bağımlılıkların yoğun olduğu modüler sistemlerde.

Ne Zaman Uygulanmaz?

  • Tek satırlık hotfix PR’larında (gereksiz I/O ve token tüketimi yaratır).

Trade-off Analizi

Tüm repoyu RAG (Retrieval-Augmented Generation) ile bağlama katmak yerine AST tabanlı imza (signature) çıkarmak, token tüketimini %90 oranında düşürür (örn: 45.000 token -> 4.500 token) ancak statik analiz aracı çalıştırmayı gerektirdiği için CPU overhead’i yaratır.

The Severity Matrix (Önem Derecesi Matrisi Deseni)

Ajanlar, O(N^2) kompleksitesindeki bir performans darboğazı ile bir değişkenin isminin yeterince açıklayıcı olmamasını aynı tonla, aynı uzunlukta eleştirebilir.

Problem

Kritik hataların, düzinelerce “nitpick” (önemsiz takıntı) yorumunun arasında kaybolup gitmesi. Geliştiricinin PR’ı onaylamak için tüm bu küçük yorumlarla uğraşmak zorunda kalması.

Çözüm

Modele zorunlu bir JSON şeması vererek her bulguyu puanlatmak ve backend tarafında sadece belirli bir eşiği geçenleri GitHub/GitLab’a göndermek.


# System prompt içindeki metin yönergesi
matrix_instruction = """
Bulduğun her hatayı aşağıdaki Önem Matrisi'ne (Severity Matrix) göre sınıflandır:

1 (NIT): Basit isimlendirme iyileştirmeleri, çok küçük okunabilirlik önerileri.
2 (MINOR): Performansa etkisi olmayan ancak best-practice'lere uymayan kodlar.
3 (MAJOR): Olası null pointer hataları, bellek sızıntısı riskleri, edge-case eksiklikleri.
4 (CRITICAL): Kesin güvenlik açıkları (SQLi, XSS), sistemin çökmesine neden olacak bariz hatalar, yanlış iş mantığı (business logic).

Çıktını JSON formatında ver. 'severity_score' alanını doldur.
"""

# Backend'de filtreleme (Python örneği)
def filter_findings(findings_json):
    # Sadece MAJOR ve CRITICAL hataları PR yorumu olarak at
    # Diğerlerini veritabanında analitik için tut, geliştiriciyi rahatsız etme
    actionable_comments = [f for f in findings_json if f['severity_score'] >= 3]
    return actionable_comments

Ne Zaman Uygulanır?

  • Geliştirici ekibinin velocity (hız) metrikleri düşmeye başladığında ve “nitpick” yorgunluğu gözlendiğinde.
  • CI/CD pipeline’ında ajanın incelemesi “blocking” (zorunlu onaylayıcı) durumundaysa (Sadece Critical hatalar bloke etmeli).

Ne Zaman Uygulanmaz?

  • Junior geliştiricilerin eğitim sürecinde, mentorluk amaçlı çalışan ajanlarda (Bu senaryoda NIT ve MINOR yorumlar eğitici olabilir).

Internal Convention Anchoring (Kurum İçi Standart Çapalama Deseni)

Genel verilerle eğitilmiş bir LLM, internetteki en yaygın çözümü sunar. Oysa şirketlerin kendi iç kütüphaneleri ve yaklaşımları vardır.

Problem

Modelin tarih formatlama için standart datetime kütüphanesini önermesi, oysa şirketin mimari standartlarında özel bir Core.Utils.TimeManager kullanılmasının zorunlu olması. Bu durum %100 oranında false-positive üretir.

Çözüm

Şirketin spesifik mimari kararlarını (ADR – Architecture Decision Records) veya STYLEGUIDE.md dosyasını özetleyip system prompt’a “çapalamak” (anchoring).


# Şirket standartlarının prompt'a enjeksiyonu
corporate_guidelines = """

1. VERİTABANI: Doğrudan SQL sorgusu yazmak YASAKTIR. Sadece SQLAlchemy ORM kullanılmalıdır.
2. ZAMAN: `datetime.now()` KULLANILAMAZ. Her zaman `InternalUtils.Time.get_utc_now()` kullanılmalıdır.
3. LOGLAMA: `print()` veya standart `logging` KULLANILAMAZ. `DatadogLogger` sınıfı kullanılmalıdır.

"""

system_prompt = f"""
Sen {COMPANY_NAME} şirketinde çalışan bir principal engineersin.
Aşağıdaki kurumsal kurallar bizim için mutlaktır. Bu kuralları ihlal eden bir kod görürsen bunu CRITICAL (4) olarak işaretle.
Eğer kod bu kurallara uyuyorsa, aksini belirten genel internet pratiklerini ÖNERME.
{corporate_guidelines}
"""

Ne Zaman Uygulanır?

  • Kurum içi custom framework’lerin veya sarmalayıcı (wrapper) sınıfların yoğun kullanıldığı projelerde.

Ne Zaman Uygulanmaz?

  • Açık kaynak (Open Source) projelere yapılan dış katkılarda, standart kütüphanelerin teşvik edilmesi gereken yerlerde.

Trade-off Analizi

Kuralları hardcode etmek, sistemin esnekliğini azaltır. Eğer InternalUtils.Time kütüphanesi güncellenir ve isim değiştirirse, prompt’u güncellemezseniz sistem anında %100 hatalı sonuç üretmeye başlar. Bu nedenle bu kuralların bir vektör veritabanından RAG ile dinamik getirilmesi, ölçeklenebilirlik için daha doğru bir adımdır.

Pratik Öneriler / Production Notları

Bu desenleri canlı (production) ortama alırken gözlemlediğimiz bazı kritik mühendislik notları şunlardır:

Bileşen Öneri / Kısıtlama Beklenen Metrik
Token Limitleri Diff boyutunu sınırlayın. 64k token üzerindeki PR’ları ajana göndermek yerine “PR çok büyük, inceleme reddedildi” mesajı döndürün. Max 15k input token / PR
Gecikme (Latency) GitHub Actions’ta webhook timeout genellikle 10 saniyedir. Asenkron (Event-Driven) bir mimari kullanın, sonuçları REST ile GitHub API’ye sonradan push’layın. Response < 5s p95
Telemetry & Loglama Geliştiricilerin ajanın yorumlarına verdiği “thumbs up” / “thumbs down” veya “Resolve” sürelerini mutlaka Prometheus/Grafana gibi araçlara gönderin. > %60 Acceptance Rate hedefi
Fallback Stratejisi OpenAI API’si 5xx hatası verirse, CI pipeline’ı ASLA fail olmamalıdır (soft fail). Ajanın çöktüğü durumlarda PR inceleme adımı atlanabilmelidir. %99.9 API Uptime toleransı

“AI ajanları production ortamına alındığında en büyük risk, hatalı kod üretmeleri değil; doğru kodu yanlış yorumlayarak geliştirici takımlarının flow (akış) durumunu baltalamalarıdır.”

Sık Sorulan Sorular

Prompt mühendisliği yerine modeli fine-tune etmeli miyim?

Fine-tuning, şirkete özel mimari kuralları öğretmek için cazip görünse de, kod incelemesi gibi bağlamın sürekli değiştiği görevlerde maliyetlidir. Bir LLM’i code-review verisiyle fine-tune etmek $3.000+ bir maliyet ve haftalar süren veri temizliği gerektirirken, Internal Convention Anchoring deseni ile 2 saat içinde aynı başarı oranını yakalayabilirsiniz. Fine-tuning’i sadece prompt boyutunuz sürekli limitleri zorluyorsa düşünün.

Geliştiriciler ajanın yorumlarını tamamen görmezden gelmeye başladıysa ne yapmalıyım?

Bu durum “AI Blindness” (Yapay Zeka Körlüğü) olarak adlandırılır. İlk adımda The Severity Matrix desenini devreye alarak ajan yorumlarını %90 oranında kısın. Sadece “CRITICAL” seviyedeki güvenlik açıklarını veya bariz mantık hatalarını (örneğin division by zero) göstermeye başlayın. Güven yeniden tesis edildikten sonra kademeli olarak MAJOR uyarıları açabilirsiniz.

Çok büyük Git Diff’lerini nasıl handle etmeliyiz?

Eğer bir PR 50’den fazla dosya içeriyorsa, hiçbir LLM veya insan bunu verimli bir şekilde inceleyemez. Ajanı çalıştırmadan önce git diff boyutunu tiktoken ile sayın. Örneğin eşiği 20.000 token olarak belirleyin. Eşik aşılırsa, ajan sadece “Bu PR inceleme standartları için çok geniş, lütfen daha küçük PR’lara bölün” şeklinde tek bir uyarı basıp çıkmalıdır.

Ajanın “Security Vulnerability” uyarısı verdiği ama aslında false-positive olan durumları nasıl engelleriz?

Güvenlik konusunda LLM’ler fazla temkinli (over-cautious) davranmaya programlanmıştır. Model, parametrik SQL kullanan bir kodda bile sırf “SQL” kelimesini gördüğü için Injection uyarısı verebilir. Çözüm, The Two-Stage Triage deseninde güvenlik için spesifik kısıtlamalar eklemektir: “Sadece user-input doğrudan çalıştırılabilir bir fonksiyona parametre geçiliyorsa Security alert üret, statik string’ler için uyarı verme.”

Sonuç

Otonom code review ajanları, manuel kod inceleme süreçlerindeki darboğazları çözmek için eşsiz bir potansiyele sahiptir. Ancak zero-shot (sıfır yapılandırma) ile bırakıldıklarında, 20 satırlık basit bir güncelleme için 5 farklı yorum üreten mikroyönetici bir robota dönüşürler. İncelediğimiz Statik Analiz Bariyeri, Çift Aşamalı Triage, Bağlamsal Enjeksiyon, Önem Matrisi ve Standart Çapalama desenlerini sisteminize entegre etmek; sadece token maliyetlerinizi düşürmekle kalmaz, aynı zamanda geliştirici ekibinizin araca olan güvenini yeniden inşa eder.

Aksiyon planı olarak: İlk işiniz, mevcut ajanınızın son 100 PR’da ürettiği yorumların kaçının geliştiriciler tarafından dikkate alındığını (acceptance rate) ölçmek olsun. Bu oran %50’nin altındaysa, öncelikle The Severity Matrix desenini devreye alarak sistemi susturun ve sadece kritik müdahalelere izin verin.

Bunları da beğenebilirsiniz

REST API Tasarımında Offset mi Cursor Pagination mı? Veri Büyüklüğüne Göre Karar Matrisi

Milyar satırlık tablolarda API p99 gecikmesini 1400ms’den 45ms’ye düşüren pagination stratejileri. DB execution planları ve production trade-off analizi.

Devamını Oku

Dağıtık Sistemlerde Context Propagation Hataları: İzlenebilirlik Kayıplarını Teşhis Etme

Heterojen mikroservis ağlarında context propagation hatalarını teşhis etme stratejilerini öğrenin ve üretim ortamındaki izlenebilirlik açıklarını kapatın.

Devamını Oku

Mutation Testing vs Branch Coverage: Birim Testlerdeki Kör Noktaları Tespit Karar Matrisi

SonarQube raporlarında %95 branch coverage oranına ulaşmanıza rağmen production’a sızan kritik hataların anatomisi. Test süitinizin gerçek kalitesini ölçmek için metrik karşılaştırması.

Devamını Oku