Son iki yıldır, sektör, Kodlama için Büyük Dil Modellerini (LLM) değerlendirmek için tek bir metrik üzerine takıntılı: Pass@1. Pass@1, bir modelin ilk denemede testleri geçen bir fonksiyon üretebileceğini söylese de, kurumsal geliştirme için daha kritik bir soruyu yanıtlamakta başarısız oluyor: Kod bakımlı mı?
Deneysel prototiplerden üretim düzeyinde sistemlere geçtikçe, kod sağlığını, okunabilirliğini ve evrim geçirme yeteneğini dikkate alan değerlendirme çerçevelerine ihtiyacımız var. Bu gönderi, LLM'leri yalnızca doğruluk açısından değil, ürettikleri kodun kalitesi açısından nasıl ölçebileceğimizi inceliyor.
Pass@1'in Sınırlılıkları
Pass@1 ikili bir metriktir. Üretilen bir fonksiyon gizli test paketini ya geçer ya da geçemez. Bu yaklaşımın birkaç kör noktası vardır:
- Stili Yoksayar: Bir LLM, insanlar tarafından gözden geçirilmesi zor olan obskür tek satırlık ifadeler veya agresif optimizasyon teknikleri kullanarak verimli ama okunması zor kod üretebilir.
- Bağlam Eksikliği: Kodun mevcut bir kod tabanına ne kadar iyi uyduğunu ölçmez. Projenin adlandırma kurallarına uyar mı? Standart kütüphaneyi mi kullanır yoksa gereksiz bağımlılıklar mı getirir?
- Yeniden Yapılandırma Sinyali Yok: Mevcut kodu anlama ve değiştirme yeteneğini test etmez; oysa bu, sıfırdan yazmaktan çok daha fazla geliştiricinin günlük iş akışının bir parçasıdır.
Bileşik Kalite Metriklerinin Tanıtımı
Bu boşlukları doldurmak için, işlevsel doğruluğu statik analiz metrikleriyle ağırlıklandıran bir bileşik puanlama sistemi öneriyoruz. Bileşenlerin dökümü şöyledir:
1. Kod Karmaşıklığı (Döngüsel Karmaşıklık)
Döngüsel karmaşıklığı ölçmek için radiate veya pylint gibi araçları kullanıyoruz. Yüksek karmaşıklık puanları, test edilmesi ve bakımı zor olan kodu gösterir. Bir ölçüm, derin iç içe geçme veya karmaşık koşullu mantık yoluyla doğru sonuçlara ulaşan çözümleri cezalandırmalıdır.
2. Diff Kararlılığı ve Minimal Değişiklikler
Yeniden yapılandırma görevlerinde, "diff kararlılığını" ölçeriz. Yüksek kaliteli bir model, mevcut koda minimal ve cerrahi müdahaleler yapmalıdır. Bir LLM'den bir fonksiyona parametre eklemesi istendiğinde ancak tüm sınıfı yeniden yazarsa, cezalandırılmalıdır. Bunu, diff üzerindeki Levenshtein mesafesini kullanarak veya değiştirilen satır sayısını gerekli satır sayısıyla karşılaştırarak nicelendirebiliriz.
3. Çözümün Test Kapsamı
Üretilen kod sağlam testlerle birlikte geliyor mu? Otomatik üretilen birim testlerinin kalitesini, kenar durumlarının kapsamını ölçerek değerlendirebiliriz. Kod üreten ancak yalnızca "mutlu yolu" (happy path) test eden bir LLM, olası arıza modlarını belirleyen bir modele göre daha düşük puan almalıdır.
Pratik Örnek: Bir Yeniden Yapılandırmayı Değerlendirme
İstemin şu olduğu bir görevi düşünün: "Aşağıdaki fonksiyonu okunabilirliği artırmak ve hata yönetimi eklemek için yeniden yapılandırın."
# Orijinal Kod
def process_data(data):
if data:
return [x for x in data if x > 0]
return []
Aşağıdaki gibi yanıt veren bir model, Pass@1'de yüksek puan alabilir (testler geçerse) ancak bakımlılıkta düşük puan alır:
# Yanıt A: Düşük Kalite
def process_data(d):
if d is not None:
try:
return [i for i in d if i > 0]
except Exception as e:
return []
return []
Yanıt A, obskür değişken adları (d, i) kullanır ve tüm istisnaları yakalar, bu da bir anti-desendir (anti-pattern). Yüksek kaliteli bir yanıt şu şekilde olmalıdır:
# Yanıt B: Yüksek Kalite
def process_data(data):
"""
Girdi verisinden pozitif olmayan değerleri filtreler.
Args:
data: Sayılar listesi.
Returns:
Pozitif sayılar listesi, girdi None ise boş liste.
"""
if not data:
return []
positive_values = []
for value in data:
if isinstance(value, (int, float)) and value > 0:
positive_values.append(value)
return positive_values
Yanıt B uzun, ancak kendini belgeleyen, tür denetimini açıkça ele alan ve PEP8 standartlarına uyan bir yapıdadır. Bakımlılığa odaklı bir ölçüm, her iki yanıtın da temel işlevsel testleri geçse bile, Yanıt B'ye Yanıt A'dan önemli ölçüde daha yüksek bir puan atamalıdır.
Ölçümün Uygulanması
Bunu uygulamak için, değerlendirme iskeletinin CI/CD akışına entegre olan bir boru hattı oluşturabiliriz:
- Kod Üret: LLM'ye görevi iletin.
- Statik Analiz: Çıktıda
flake8,banditvemypyçalıştırın. Uyarıları ayrıştırın. - İşlevsel Test: Üretilen kodu birim testleri paketiyle karşılaştırarak çalıştırın.
- Yeniden Yapılandırma Doğrulama: Görev mevcut kodu değiştirmeyi içeriyorsa, değişikliklerin yerel kaldığından emin olmak için bir "diff kontrolü" çalıştırın.
- Puan Toplama: Bu sinyalleri ağırlıklı bir nihai puana dönüştürün. Örneğin:
Puan = 0.5 * Islevsel_Dogruluk + 0.3 * Statik_Analiz_Puanı + 0.2 * YenidenYapilandiirma_Etkinligi
Sonuç
LLM'ler geliştirme iş akışlarımızın ayrılmaz bir parçası haline geldikçe, yalnızca Pass@1'e güvenmek, bir geliştiriciyi yalnızca tek bir kodlama mülakatını geçme yeteneğine göre işe almak ve uzun vadeli kültürel uyumunu ile kod kalitesini görmezden gelmek gibidir. Ölçümlerimize bakımlılık ve yeniden yapılandırma metriklerini dahil ederek, bu modellerin gerçek dünya yazılım mühendisliği bağlamlarında nasıl performans göstereceğini daha iyi tahmin edebiliriz. LLM değerlendirmesinin geleceği, yalnızca bugün neyin işe yaradığıyla değil, altı ay sonra hâlâ işe yarayacak olanla ilgilidir.