Bir ajanın ne yaptığını tahmin etme. Tekrar çalıştır.
Model çıktısı deterministik değil. Ama bir ajan koşusunun yeniden oynatılabilir olması, modelin aynı cevabı vermesini gerektirmiyor — kaydedilmesi gereken şey cevap değil, karar noktası.
This post is in Turkish.
Ajanla çalışırken en sık duyduğum itiraz şu: model deterministik olmadığı için ajanı yeniden oynatamazsın.
Bu doğru bir gözlem ama yanlış sonuca götürüyor. Yeniden oynatmanın amacı modelin aynı cümleyi kurması değil. Amacı, koşunun ne yaptığını tartışmak yerine görebilmek.
Ve bunun için kaydetmen gereken şey model çıktısı değil — karar noktaları.
Neyi kaydediyorsun
Bir ajan turu, dış dünyayla temas ettiği noktalardan oluşuyor. Hangi dosyayı okudu, ne gördü. Hangi komutu çalıştırdı, çıktısı ve çıkış kodu ne oldu. Modele hangi bağlamla gitti, ne döndü. Hangi aracı hangi argümanlarla çağırdı.
Bunların hepsi sıralı, değişmez bir kayıt. Turun kendisi bu kaydın üzerinde yürüyor.
Kritik ayrım şu: kayıt bir günlük değil. Günlük, olan bitenin insan için yazılmış özeti. Kayıt ise turu yeniden yürütmek için yeterli olan girdinin tamamı.
İki farklı oynatma
Bir kayıt iki şekilde çalıştırılabiliyor ve ikisi farklı soruları cevaplıyor.
Kapalı oynatma: model çağrıları da kayıttan besleniyor. Model hiç aranmıyor, kaydedilmiş cevap geri veriliyor. Bu, çevreleyen kodu test etmenin yolu — planlayıcı, araç yönlendirme, hata işleme, sandbox davranışı. Model dışındaki her şeyi deterministik hâle getiriyor, ve bir hata modelde değil senin kodundaysa bunu net gösteriyor.
Açık oynatma: aynı girdi, model gerçekten yeniden çağrılıyor. Bu deterministik değil ve olması da gerekmiyor. Bunun cevapladığı soru başka: aynı görev, aynı bağlam, kaç denemede kaç kez başarıyor.
İlki bir hata ayıklama aracı. İkincisi bir ölçüm aracı.
Model çıktısını sabitleyemezsin. Ama sorduğun soruyu sabitleyebilirsin — ve asıl karşılaştırılabilir olan o.
Determinizmin gerçek düşmanı model değil
Kapalı oynatmayı kurarken öğrendiğim şey ilginç: turu belirsiz yapan şeylerin çoğu modelden gelmiyor.
Zaman damgası, rastgele sayı üreteci, dosya sistemi sıralaması, geçici dizin adı, ortam değişkenleri, ağ gecikmesi. Bunların hepsi turun içine sızıyor ve iki koşuyu birbirinden farklı yapıyor.
Yani deterministik oynatma aslında bir disiplin: bu kaynakların hepsini açıkça enjekte edilen birer bağımlılık hâline getirmek. Kod içinde doğrudan saate bakan bir satır varsa, o tur tekrar oynatılamıyor.
Bunun yan faydası şu oldu — bu disiplin kodu zaten daha test edilebilir yaptı. Oynatmayı hiç kullanmasam bile kazanç orada.
Neden bu bir güvenlik özelliği
Sandbox yazısında değinmiştim, açayım.
Bir koşu tuhaf davrandığında elimde iki seçenek var: logları okuyup ne olduğunu tahmin etmek, veya turu tekrar çalıştırıp izlemek. İkincisi, izolasyonun gerçekten tuttuğunu iddia etmek ile göstermek arasındaki fark.
Hangi komut çalıştı, hangi dosyaya dokunuldu, hangi ağ isteği denendi — bunlar kayıtta duruyor. Bir güvenlik incelemesinde "bize güvenin" demek yerine kaydı açıp gösterebiliyorsun.
Hata taksonomisi buradan çıkıyor
Son parça: kayıt olmadan hata sınıflandırması yapamıyorsun.
"Bozuldu" bir kategori değil. Ama elinde başarısız koşuların kayıtları varsa, onları gruplayabiliyorsun — araç argümanı hatalı üretildi, test yanlış yorumlandı, plan gereksiz adım içerdi, sandbox limitine takıldı.
Her kategori kendi oranını taşıyor. Bir iyileştirme yaptığında, o oranın düşüp düşmediğine bakıyorsun. Düşmüyorsa yaptığın şey iyileştirme değil — sadece farklı.
Ölçülebilir otonomi yazısında söylediğim şeyin altyapısı tam olarak bu. Kayıt olmadan ölçüm yok; ölçüm olmadan da elinde bir demo var, ürün değil.