Sertaç Yıldırım saha notları

Ana sayfa → Teknik

Context: Uzun Pencere Değil, Doğru Özet

Aynı soruyu iki kez sordum: “bu müşterinin son çekimi neden reddedildi?” Birincisinde agent 40 dakikadır çalışıyordu, pencerede 118 bin token vardı; cevap yanlıştı ve üç ay önceki bir kaydı gösteriyordu. İkincisinde temiz bir oturum açtım, aynı tool’lar, aynı model, pencerede 9 bin token: cevap doğruydu. Model akıllanmadı. Sadece masası toplanmıştı.

Özet
  • Model hatırlamaz, yeniden okur. Her turda önüne konan yığının tamamı baştan işlenir. “Az önce söylemiştim” diye bir şey yok; ya yığında duruyordur ya da yok.
  • Uzun pencere, dağınık masayı büyütmektir. Doğru cümlenin yanına yüzlerce ilgisiz cümle girer. Bizde pencere %70 dolarken doğruluk 31/34 iken, %95’te 24/34’e düştü.
  • En büyük kazanç tool çıktısında. 2.300 satırlık listeyi modele hiç göndermedik; tool içinde 13 satıra indirdik. Tek değişiklikle koşu başına token 118 binden 31 bine düştü.
  • Koşu durumu pencerede durmaz. Hangi adımdayız, ne karar verildi, ne açık kaldı — bunlar diskte bir kayıtta durur, pencereye yalnızca özeti girer.
  • Özetleme son çaredir ve bir kayıptır. Kimlikler, kararlar ve açık sorular birebir korunur; ara akıl yürütme atılır. Özet sonrası ilk cevap mutlaka kontrol edilir.
  • Uzun pencere satın almak, çözüm satın almak değildir. Pencereyi iki katına çıkarmak, dolduğu ânı erteler; doldurma hızını değiştirmez.

Pencerede ne var?

Agent loop her turda modele bir yığın gönderir. Yığında sırayla şunlar birikir:

ParçaNe kadar yer kaplarÖmrü
System promptSabit, bizde ~900 tokenKoşu boyunca; her turda yeniden gönderilir
Tool tanımları (11 tool)~2.400 tokenKoşu boyunca
Kullanıcının sorusuKüçükKoşu boyunca
Tool cevaplarıSınırsız — asıl büyüyen yerGenelde bir–iki tur işe yarar, sonuna kadar kalır
Modelin ara cümleleriOrtaKararı verdikten sonra değersiz

Dikkat edilecek satır dördüncüsü. Bir tool 2.300 satır döndürdüğünde o 2.300 satır, koşunun sonuna kadar her turda yeniden gönderilir. 8 turluk bir koşuda aynı veriyi 8 kez ödersin ve 7 kezinde işe yaramaz.

Model hatırlamaz, yeniden okur. Pencereye koyduğun her satırı, kalan her turda tekrar ödersin.

Neden uzun pencere yetmiyor?

“Pencere 200 bin token, 2.300 satır sığar” doğru bir cümle ama yanlış bir sonuç çıkarır. Sığması, işe yaraması demek değil. Ölçtüğüm üç şey:

1. Doğruluk, doluluk arttıkça düşüyor

Önceki yazıdaki 34 çekimi etiketleme işini, pencereyi kasten doldurarak tekrarladım. Aynı model, aynı prompt, aynı veri; tek değişken pencerenin ne kadar dolu olduğu:

Pencere doluluğuDoğru etiket (34 üzerinden)Cevap süresi
%20 (sadece gerekli veri)319 sn
%503014 sn
%703119 sn
%852726 sn
%952434 sn

%70’e kadar ciddi bir kayıp yok; sonrasında düşüş sert. Kaybedilen kayıtlara baktığımda çoğunun yığının ortasında kalan veriye dayandığını gördüm. Baştaki talimat ve sondaki soru güçlü duruyor; arada kalan boğuluyor.

2. Maliyet tur sayısıyla kartopu oluyor

Pencere her turda yeniden gönderilir. 10 bin token’lık bir yığın 8 turluk koşuda 80 bin token eder. Yığın turlar boyunca büyüyorsa toplam, tur sayısının karesine yakın artar. O gece işinde 118 bin token’ın yaklaşık 71 bini, daha önce gönderilmiş verinin yeniden gönderilmesiydi.

3. Gecikme kullanıcıyı kaybettiriyor

Tablodaki son sütun: 9 saniye ile 34 saniye arasında dört katlık fark var ve aradaki tek şey pencerenin dolu olması. Chat ekranında 34 saniye, kullanıcının sekme değiştirmesi demek.

Nereden kesilir? Üç yer, bu sırayla

1. Tool çıktısı: en büyük kazanç

Ham veriyi modele hiç göndermemek, göndermiş olup sonra özetlemekten her zaman ucuz. islem_listesi tool’u önceden bütün satırları döndürüyordu. Şimdi döndürmüyor:

Tool cevabini sekillendirmek
# ONCE: 2.300 satir, ~46.000 token
return {"islemler": [satir for satir in sorgu()]}

# SONRA: ozet + sinirli ornek + devam anahtari, ~380 token
return {
  "toplam": 2300,
  "toplam_tutar": 1841250.40,
  "para_birimi": "USD",
  "ornek": ilk_n(sorgu(), 5),        # 5 satir, sadece sema gorunsun diye
  "eslesmeyen": eslesmeyenler(),     # 13 satir: isin gercekten ilgilendigi kisim
  "devam": "sayfa=2"                 # model isterse detay cagirir
}

Kural: tool, modelin karar vermek için ihtiyaç duyduğu kadarını döndürür; veri deposu değildir. Ayrıntı isteniyorsa ikinci bir çağrı vardır. Bu tek değişiklik gece işinde koşu başına token’ı 118 binden 31 bine indirdi. (Tool sözleşmesinin kendisi ayrı bir yazının konusu.)

2. Koşu durumu: pencerede değil, diskte

Agent’ın “nerede kaldım” bilgisi pencerede tutulursa, pencere temizlendiğinde kaybolur. Biz koşu durumunu ayrı bir kayıtta tutuyoruz:

Kosu durumu (diskte, pencerede degil)
{
  "kosu_id": "rec-2026-09-19-01",
  "adim": 3,
  "kararlar": ["tarih araligi: 18.09 00:00-23:59",
               "tolerans: 0.01 USD"],
  "acik_sorular": ["WD-24817 iki kayitta gorunuyor"],
  "tamamlanan": ["dosya_okundu", "eslestirildi"],
  "kimlikler": ["WD-24817", "WD-24902", "CUST-7741"]
}

Her tura bu kaydın kendisi değil, kısa bir çevirisi girer: 6–8 satır. Koşu yarıda kalırsa buradan devam edilir; pencere sıfırlansa bile iş kaybolmaz. Bu yapının güzel yanı, insanın da okuyabilmesi: sabah bakan kişi 8 satırdan nerede kalındığını görüyor.

3. Özetleme: son çare

Pencere yine de sınıra yaklaşırsa eski turlar tek bir nota indirilir. Burada iki kural var ve ikisi de acıyla öğrenildi:

  • Kimlikler, kararlar ve açık sorular birebir taşınır. Yeniden ifade edilmez. Özet yazdırdığım ilk denemede model WD-24817’yi WD-24871 diye yazdı ve agent yanlış kaydı inceledi. Numaralar özetin dışında, liste hâlinde taşınır.
  • Özet sonrası ilk cevap kontrol edilir. Özetleme, koşunun en kırılgan ânıdır. Bizde özet sonrası ilk cevabın doğruluğu, diğer cevaplardan belirgin biçimde düşük çıktı; bu yüzden özetten sonraki ilk adım daima doğrulanabilir bir adım (bir sayım, bir kimlik kontrolü) olacak şekilde sıralandı.
Özet bir kayıptır. Soru “kaybedeyim mi?” değil, “hangi kaybı seçiyorum?”

Sahadan: gece işinin 13. turu

Orchestrator yazısındaki 17 turluk gecenin 13–15. turlarında agent özet yazmaya başlayıp yarıda kesmiş, veriyi yeniden çekmişti. O turları context açısından tekrar okudum:

TurPencereNe oldu
1–312 bin tokenSorunsuz
4–758 bin2.300 satır metin olarak pencereye girdi
9–1296 binDört detay çağrısı daha eklendi
13112 binÖzet başladı: ilk turlardaki tarih aralığı kararı artık yığının ortasında
14118 binModel tarih aralığından emin olamayıp veriyi yeniden çekti
16–17118 bin (kırpıldı)Yarım eşleştirmeyle özet yazıldı: yanlış

Buradaki hata modelin değil, benim: karar bilgisini veriyle aynı yere koydum. “Tarih aralığı 18.09 00:00–23:59” bir karardır ve koşu boyunca geçerlidir; 2.300 satırlık liste ise bir kere kullanılıp bitmiştir. İkisini aynı yığına koyunca, veri kararı gömdü.

Pencerede dursun
  • Görev tanımı ve kısıtlar.
  • Verilen kararlar (tarih aralığı, eşik, seçilen etiket kümesi).
  • Kimlikler: kayıt no, müşteri no, dosya adı.
  • Açık kalan sorular.
  • Son adımın çıktısı, kırpılmış hâliyle.
Pencereye girmesin
  • Ham liste, tam dosya içeriği, uzun JSON.
  • Kullanılmış ve kararı verilmiş adımın ayrıntısı.
  • Modelin kendi ara akıl yürütmesi (karar kaldı, gerekçe gitti).
  • Hata mesajının stack trace’i; tek satırlık özeti yeter.
  • Değişmeyen referans metinler (onlar tool’un arkasında dursun).

“Pencereyi büyütelim” neden çözüm değil?

Daha büyük pencereli bir modele geçmek doldurma hızını değiştirmez; sadece dolmasını geciktirir. Üç şey de aynı kalır: kalite ortada düşer, maliyet her turda yeniden ödenir, gecikme büyür. Bizim 4 milyar parametrelik modelde pencere zaten küçüktü ve bu bizi erken disipline soktu. Sonradan büyük pencereli bir modelle denediğimde aynı hataların daha geç, ama aynı şekilde çıktığını gördüm. Pencere büyüklüğü bir bütçedir; bütçe büyüdü diye harcama disiplini gereksizleşmiyor.

Ne izlemeli?

  • Koşu başına token, tur kırılımıyla. Hangi turda sıçradığını görürsün; sıçrama daima bir tool cevabıdır.
  • Pencere doluluk oranı, p95. %70’i geçiyorsa kalite düşüşü başlamıştır.
  • Yeniden gönderilen token oranı. Toplam token ÷ benzersiz token. 3’ün üstündeyse yığın çok uzun taşınıyordur.
  • Özetleme sayısı ve özet sonrası hata oranı. Özetleme koşunun en kırılgan ânı; ölç.
  • Tool cevabı boyutu, tool başına p95. En şişkin tool’u bu sayı söyler.
  • İlk cevaba kadar geçen süre. Kullanıcının gördüğü tek sayı.

Kontrol listesi

Pencereyi büyütmeden önce
  • Koşu başına token’ın kaçı tool cevabı? En büyük üç tool hangisi?
  • Hangi tool ham veri döndürüyor? Özet + örnek + devam anahtarı ile küçültülebilir mi?
  • Aynı veri kaç turda yeniden gönderiliyor?
  • Koşu durumu nerede: pencerede mi, diskte mi?
  • Kararlar ile veri aynı yerde mi duruyor?
  • Kimlikler özetin içinde mi, ayrı listede mi?
  • Özetleme ne zaman tetikleniyor? Sonraki ilk adım doğrulanabilir mi?
  • Pencere %70’i geçince kalite ölçüldü mü, tahmin mi ediliyor?
  • İşi bölerek (alt agent) pencereyi küçültmek mümkün mü?
  • Kullanıcıya dönen ilk cevap kaç saniyede geliyor?

Sonuç

İki oturumda aynı soruya iki farklı cevap aldım. Aradaki fark model değildi, prompt değildi, veri değildi: pencereydi. Dolu pencerede doğru kayıt oradaydı, ama 2.300 satırın arasında duruyordu ve model onu seçemedi. Temiz pencerede aynı kayıt 13 satırın içindeydi.

Yaptığımız üç şey sırayla: tool’u kırptık, koşu durumunu pencereden çıkardık, özetlemeyi son çare hâline getirdik. Koşu başına token 118 binden 31 bine, ilk cevap süresi 34 saniyeden 11 saniyeye indi; etiket doğruluğu 24/34’ten 31/34’e çıktı. Hiçbiri model değişikliği değil.

Akılda kalacak cümle: context bir depo değil, bir masadır. Masaya ne koyduğuna dikkat et; büyük masa dağınıklığı çözmez, sadece daha fazlasını taşımana izin verir.