Model upgrade'inde seni kurtaran 1 saatlik eval harness
Her model yükseltmesi, eski modele göre ince ayar yaptığın prompt'ları sessizce bozar. Çözüm daha iyi prompt değil — küçük ama gerçek bir eval harness. Üretimden çıkmış 5 adımlık bir playbook.
Bir AI ürününü üretimde tutuyorsan en sinsi hata anı, kod yazdığın an değil — sağlayıcının yeni bir model çıkardığı andır. Yeni model neredeyse her metrikte daha iyidir; ama aylarca eski modele göre tek tek ayarladığın prompt'ların, few-shot örneklerin ve kenar-durum yamaların bir kısmını sessizce bozar. Hiçbir şey patlamaz. Sadece birkaç gün sonra, downstream'de tuhaf bir semptomla karşılaşırsın.
Refleks çözüm 'prompt'u daha iyi yazayım' olur. Yanlış katman. Asıl ihtiyacın, modelin doğru davranıp davranmadığını sana 60 saniyede söyleyen küçük bir eval harness. Bir hafta sonu değil, bir saatte kurulur. İşte üretimden çıkmış hâli.
1 — Test setini kendi log'larından kur.
Sentetik test verisi üretme. Üretim log'larından 20-50 gerçek vaka topla. Sıradan olanları değil; özellikle tuhaf çıkanları, kullanıcının beklenmedik girdi verdiği, modelin daha önce kafayı yediği vakaları al. Bu set, ürününün gerçek dağılımıdır — sentetik veri o dağılımı asla yakalayamaz.
- ▸20-50 vaka yeter; binlerce değil. Amaç kapsama değil, sinyal.
- ▸Mutlaka geçmişte kırılan / şikayet gelen vakaları dahil et.
- ▸Her vakayı (input, beklenen invariant) olarak sakla — beklenen tam çıktıyı değil.
2 — Tam string değil, invariant assert et.
Yeni başlayanların en büyük hatası: çıktının birebir aynı stringe eşit olmasını beklemek. Model her zaman kelimesi kelimesine aynı yanıtı vermez, vermek zorunda da değil. Sen davranışın doğruluğunu test etmek istiyorsun, üslubun aynılığını değil. Doğru çıktının ihlal EDEMEYECEĞİ invariant'ları assert et.
// Kötü: kırılgan, üslup değişince patlar
expect(out).toBe("Tamam, randevunuz 14:00'e alındı.");
// İyi: davranışın doğruluğunu test eder
expect(out.toolCalls).toContainEqual({ name: "book_slot" });
expect(out.charges).toHaveLength(1); // çift tahsilat yok
expect(() => JSON.parse(out.payload)).not.toThrow();
expect(out.amount).toBeGreaterThan(0);Tipik invariant'lar: doğru tool çağrıldı mı? İki kez tahsilat yapılmadı mı? Çıktı geçerli JSON mı? Tutar pozitif mi? Bunlar üsluba bağımsız, gerçek hataları yakalar.
3 — Fail çıktısını okunur yap.
Bir assertion patladığında 'expected true, got false' görmek işine yaramaz. Fail mesajı tek başına teşhis koydurmalı: hangi input, model ne yaptı, hangi invariant kırıldı, ham tool argümanları neydi. İyi bir fail satırı, log'a bakmana gerek bırakmadan sorunu anlatır.
// Fail satırı bir log satırı gibi okunmalı:
// CASE #37 | input: {user_id: null, amount: "12.5"}
// → expected 1 tool call, got 0
// raw args: {"action":"clarify","reason":"missing user"}
// broken invariant: must call book_slot when amount present4 — İki modelde de koş, DIFF al.
Asıl güç burada. Aynı seti hem eski hem yeni modelde koştur ve sonuçları diff'le. Yeni modelin 50 vakanın 46'sında aynı, 4'ünde regresyon yaptığını görürsün. İşte o 4 vaka, tam olarak senin re-tuning listendir. Körlemesine 'yeni model geldi, prompt'ları gözden geçireyim' yerine, dokunman gereken tam noktayı bilirsin.
“Upgrade kararı artık his değil tablo: 46/50 sabit, 4 regresyon — ve o 4'ün ne olduğunu adıyla biliyorsun.”
5 — Her prod incident kalıcı olarak harness'a girer.
Üretimde yeni bir bug çıktığında, düzeltmeden ÖNCE o vakayı bir test olarak harness'a ekle. Zamanla harness, ürününün başına gelmiş her gerçek aksaklığın hafızası hâline gelir. Bu, kopyalanamayan bir moat'tır: rakibin senin prompt'unu çalabilir ama 6 aydır biriken incident kütüphaneni çalamaz.
Bütün bunların güzelliği: bir saatte kurulur, ama her model yükseltmesinde, her prompt değişikliğinde sana saatlerce hata ayıklama kazandırır. Prompt'u sertleştirmek tek seferlik; harness kalıcı.
“Model hiçbir zaman zayıf halka değildi. Zayıf halka, onu doğrulayan katmanın olmamasıydı.”