Bir yapay zekâ asistanıyla saatlerce çalışırsınız. Ona nasıl kod yazmasını sevdiğinizi anlatırsınız, birlikte iki hata yaparsınız, üçüncüsünde doğrusunu bulursunuz. Sonra pencereyi kaparsınız.
Ertesi gün açtığınızda hiçbirini hatırlamaz. Aynı tercihi baştan anlatırsınız. Aynı hatayı birlikte tekrar yaparsınız.
Bunun sebebi modelin aptal olması değil. Sadece hatırlamıyor. Eksik olan zekâ değil, kalıcılık.
Yadigar tam olarak bunu ekliyor: asistanın hatırlama yeteneği. Adı zaten bunu anlatıyor — yadigar, hatırlanmak için bırakılan şey demek.
Nasıl bağlanıyor
Asistanın kendisine hiç dokunmuyorum. Bunun yerine ona bir alet veriyorum, o da gerektiğinde bu aleti kullanıyor. Bu bağlantı için MCP diye bir standart var (Model Context Protocol) — "yapay zekâ asistanına dışarıdan yetenek takmanın ortak yolu" diye düşünebilirsiniz. USB gibi: takıyorsunuz, çalışıyor.
Şu anda dört ayrı asistan aynı hafızayı paylaşıyor: Claude Code, Codex, Goose ve opencode. Birinde öğrenilen şey diğerinde de biliniyor.
Aradığını nasıl buluyor?
Bir şey hatırlamak demek, doğru anıyı bulmak demek. Bunun iki yolu var ve ikisi de tek başına yetmiyor.
Birincisi kelime araması. Ctrl+F gibi: yazdığınız kelime metinde geçiyor mu diye bakar. "pnpm" ararsanız içinde "pnpm" geçenleri bulur. Kusuru şu: "paket yöneticisi" diye ararsanız, cevap "pnpm kullanıyor" olsa bile bulamaz — çünkü o kelimeler birebir geçmiyor.
İkincisi anlam araması. Burada her cümle bir sayı dizisine çevriliyor. Bu işe "embedding" deniyor ve şöyle çalışıyor: anlamca yakın cümleler, birbirine yakın sayı dizilerine dönüşüyor. Yani "paket yöneticisi" ile "pnpm kullanıyor" farklı kelimeler olsa da sayı olarak komşu çıkıyorlar. Böylece kelime tutmasa bile anlam tutuyor.
Bunun da kusuru var: özel isimleri karıştırıyor. Anlamca benzer diye yanlış proje adını, yanlış kütüphaneyi getirebiliyor.
Ben ikisini birden çalıştırıyorum. Her biri kendi sıralamasını üretiyor, sonra ikisi tek listede birleştiriliyor. Mantığı basit: iki listede de üst sıralarda çıkan sonuç, muhtemelen gerçekten alakalıdır.
Bir de Türkçeye özel bir ayar var. Arama motorları normalde kelimelerin kökünü bulmaya çalışır ("kitapları" → "kitap"). Türkçede bu kök bulucu ekleri yanlış kesip anlamı bozuyordu, o yüzden kapattım. Eksiz eşleşme, yanlış kökten iyidir.
Hangi çeviriciyi seçtim, neden?
Cümleyi sayı dizisine çeviren modele geri dönelim. Piyasada bir sürü var ve hangisinin Türkçede iyi olduğu tahmin edilecek bir şey değil. Ölçtüm.
Kendi Türkçe test setimi hazırladım: 170 tane anı, 140 tane soru. Sonra altı modeli sırayla denedim. Baktığım şey şu: doğru cevabı ilk on sonucun içine koyabiliyor mu? Buna Recall@10 deniyor. 0,933 demek, yüz soruda doksan üçünde doğru cevap ilk onda çıkıyor demek.
| model | ilk 10'da bulma | zor sorular | karışık dilli sorular |
|---|---|---|---|
| multilingual-e5-large | 0,933 | 0,95 | 0,71 |
| nomic-embed-text-v2-moe | 0,921 | 0,90 | 0,67 |
| embeddinggemma | 0,919 | 0,95 | 0,64 |
| snowflake-arctic-embed2 | 0,912 | 0,85 | 0,64 |
| bge-m3 | 0,911 | 0,85 | 0,57 |
| qwen3-embedding:0.6b | 0,895 | 0,85 | 0,69 |
Soldaki sayılar birbirine çok yakın — hepsi 0,89 ile 0,93 arasında. Modelleri asıl ayıran sağdaki iki sütun: kasten zorlaştırdığım sorular, ve içinde hem Türkçe hem İngilizce geçen sorular. Orada fark açılıyor: kazanan model 0,71, sonuncu 0,57.
Hepsi kendi bilgisayarımda çalışıyor, hiçbiri internete bir şey göndermiyor. Bir hafıza katmanı her arama için dışarıya para ödeyen bir şey olmamalı.
Neden bilerek unutuyor?
Her şeyi sonsuza kadar saklayan bir hafıza, hiçbir şey saklamayan kadar işe yaramaz. Beş yıl önceki bir tercihi bugünkü kadar güçlü hatırlarsanız, sonuçlar çöple dolar.
O yüzden anılar zamanla soluyor. Bu, insan hafızası üzerine yapılmış eski bir çalışmadan (Ebbinghaus unutma eğrisi) alınma: bir şey tekrarlanmazsa hatırlanma ihtimali giderek düşer. Bende de öyle — bir anı kullanılmazsa iki haftada gücünün yarısını kaybediyor. Kullanıldığında güçleniyor.
Önemli ayrıntı: anı silinmiyor, sadece sıralamada geriye düşüyor.
Ama zaman tek başına yanıltıcı
Buradaki mantık hatası şu: bir anının eski olması onu değersiz yapmaz, yeni olması da değerli yapmaz. Zaman, faydanın gerçek ölçüsü değil — sadece kabaca yerini tutan bir şey.
Gerçek ölçü zaten elimin altındaydı ve ben onu yalnızca bir istatistik ekranında gösteriyordum. Şimdi her anı iki sayı taşıyor:
- Kaç kez asistanın önüne kondu? Yani arama sonucu olarak kaç kez sunuldu.
- Kaç kez işe yaradı? Yani asistan bunu kullandım diye kaç kez işaretledi.
Yirmi kez gösterilip bir kez bile işe yaramamış bir anı, kaç yaşında olursa olsun çöptür. Artık bu oran anının gücünü doğrudan etkiliyor.
İki tane ince ayrıntı var, ikisi de bilerek:
Bu oran sadece aşağı çekiyor, yukarı itmiyor. Çünkü yukarı iten şey zaten var: işe yaradığı söylenen anı hemen güçleniyor. İkinci bir yukarı kanal eklersem aynı olayı iki kez saymış olurum ve şöyle bir kısır döngü başlar — üstte çıkan anı puan kazanır, daha üstte çıkar, yine puan kazanır. Alakalı olduğu için değil, sırf üstte olduğu için.
Yeni anılar bu cezadan muaf. Henüz beş kez bile gösterilmemiş bir anının "hiç işe yaramadı" karnesi olmaz — daha fırsatı olmamıştır. Beş gösterimi dolduran anılar ölçülmeye başlıyor.
Bazı şeyler hiç unutulmamalı
Anıların tipleri var ama bu tipler konu anlatmıyor. Konuyu zaten anlam araması hallediyor. Tipin tek işi şunu söylemek: bu anı ne kadar dayanıklı olmalı?
- kimlik — hiç solmaz, hiç arşivlenmez, her oturumun başında otomatik olarak asistana verilir. "Ben kimim, ne iş yaparım" bilgisi burada.
- tercih — yavaş solar. "Şunu şöyle yapmayı severim."
- kötü deneyim — yavaş solar, önceliği yüksek. "Bunu denedik, patladı."
- bilgi — kullanılmazsa arşivlenir. Sıradan olgular.
Tek tek olaylar bu listeye hiç girmiyor; onların ayrı bir defteri var. Bir olayı kural gibi saklarsanız, aylar sonra o günün ayrıntıları alakasız yere karşınıza çıkar.
Peki fikriniz değişirse?
Bu, hafıza sistemlerinin en sinsi sorunu. Diyelim sistem "kullanıcı pnpm kullanıyor" diye kaydetti. Altı ay sonra başka bir araca geçtiniz. Şimdi hafızada iki anı var ve ikisi de doğru görünüyor.
Aynı anıyı iki kez kaydetmeyi engellemek kolay — metinleri karşılaştırırsınız, bitti. Ama bu iki cümle aynı değil ki, çelişkili. Otomatik kontrol bunu yakalayamaz.
Çözüm şu: yeni bilgiyi kaydeden asistan, aynı anda "bu şunun yerine geçiyor" diyebiliyor. Ayrı bir işlem yapmasını istemedim bilerek — yeni şeyi az önce öğrenen asistan neyin eskidiğini zaten biliyor, ayrı bir adım istersen genelde atlanır.
Eski anı silinmiyor, "artık geçerli değil" diye işaretleniyor ve arama sonuçlarından çıkıyor. Geçmiş duruyor, sadece yolunuza çıkmıyor.
Kendi kendine öğrenmesi
Asistan bir işin nasıl gittiğini kaydediyor — başarılı mı, başarısız mı, ne oldu. Bu kayıtlar düzenli olarak taranıp "bundan kalıcı bir ders çıkar mı?" diye süzülüyor. Çıkanlar hafızaya ekleniyor.
Ayrıca beceriler var: sistemin kendi çıkardığı küçük kural setleri. Yeni bir beceri önce deneme durumunda bekliyor. Üç kez işe yararsa terfi ediyor, bir kez batırırsa geri çekiliyor. Bir başarısızlık üç başarıyı siliyor — bilerek katı, çünkü yanlış bir kural hiç kural olmamasından kötü.
Bunların hiçbirinde bana sormuyor.
Sunucuda neden akıllı bir model yok?
"Bundan ders çıkar mı?" sorusunu bir süre sunucudaki küçük bir yapay zekâ modeline sordurdum. Sonra ölçtüm. Aynı beş olayı ikisine de verdim:
| kim özetledi | çıkardığı ders | çıkardığı beceri | süre |
|---|---|---|---|
| sunucudaki küçük model | 2 | 0 | 5 saniye |
| bilgisayarımdaki büyük model | 4 | 2 | 22 saniye |
Küçük model iki başarılı işi tamamen görmezden geldi — sadece hataları fark etti. Yani ucuz model, iyi modelin ucuz sürümü değil; başka ve daha kötü bir şey.
Sonra basit bir şey fark ettim: olayı yaşayan asistan zaten benim bilgisayarımda çalışıyor ve sunucuya sığabilecek her şeyden güçlü. Dersi o yazsın, sunucu sadece saklasın.
Artık sunucuda hiç sohbet modeli yok. Sunucu iki şey yapıyor: cümleleri sayıya çeviriyor ve saklıyor. Karar vermiyor.
Birden fazla kullanıcı olunca çıkan tuzak
Bu kısım biraz teknik ama sonucu ilginç, o yüzden anlatayım.
Her kullanıcının verisi ayrı. Veritabanı seviyesinde ayrı, yani yanlış bir sorgu yazsam bile başkasının verisi gelmiyor.
Sorun anlam aramasındaydı. Milyonlarca sayı dizisi arasında en yakınları bulmak pahalı bir iş, o yüzden kısayol kullanılır: sistem hepsine bakmak yerine "muhtemelen yakın olanlara" bakar. Çok hızlı, neredeyse hep doğru.
Neredeyse. Test ettiğimde şunu gördüm:
| yöntem | bulması gereken 5 sonuçtan kaçını buldu |
|---|---|
| hepsine tek tek bak (yavaş yol) | 5 |
| kısayol | 0 |
| kısayol, "daha çok ara" ayarıyla | 0 — 11.943 kayda baktığı hâlde |
| kullanıcıya özel kısayol | 5 |
Sebebi şu: kısayol önce herkesin verisi içinden en yakınları seçiyor, kullanıcı filtresini ondan sonra uyguluyor. Küçük bir kullanıcının kayıtları o ilk listeye hiç giremiyor ve elde sıfır sonuç kalıyor.
Bu, hiçbir hata mesajı vermeyen türden bir arıza. Sistem çalışıyor görünüyor, sadece hiçbir şey bulamıyor. Ölçmeseydim aylarca fark etmezdim.
Çözüm her kullanıcı için ayrı bir kısayol tablosu kurmak — ve bunu ancak veri yeterince büyüdüğünde yapmak, çünkü küçük veride yavaş yol zaten hızlı ve hatasız.
Özet
Kendi sunucumda duruyor, veri bende, hiçbir şey dışarı gitmiyor. Buradaki her tercih ya bir ölçümden ya da gerçekten yaşanmış bir arızadan çıktı — hiçbiri "kulağa mantıklı geliyordu" diye orada değil.
Amaç asistanın daha akıllı olması değil. Aynı şeyi ikinci kez öğrenmek zorunda kalmaması.
Kod: github.com/unkownpr/yadigar — depo şu an private, yani erişim yetkiniz yoksa link sizi boş bir sayfaya götürür. Lisans ve isim kontrolleri bitince açılacak.
Videodaki ses benim, ama o cümleleri hiç söylemedim: eski bir kaydımdan üretilmiş bir kopya. Tamamen kendi bilgisayarımda çalışan bir modelle. Madem yazının iddiası "hafızanız makinenizden çıkmak zorunda değil", bunu anlatan sesin bir servise gitmesi tuhaf olurdu.
Sözlük
Yazıda geçen yabancı terimler. Metindeki terime tıklarsanız buraya gelirsiniz.
MCP (Model Context Protocol) — Yapay zekâ asistanlarına dışarıdan yetenek eklemek için kullanılan ortak bağlantı standardı. Asistanın kodunu değiştirmeden ona yeni bir alet takmayı sağlar; USB'nin cihazlar için yaptığını yazılım için yapıyor. Anthropic tarafından açık standart olarak yayımlandı, bugün birçok asistan destekliyor.
Embedding (gömme) — Bir cümleyi, anlamını temsil eden bir sayı listesine çevirme işlemi. Amaç şu: anlamca yakın cümleler, sayı olarak da birbirine yakın çıksın. Böylece bilgisayar "aynı kelimeler geçiyor mu" diye değil, "aynı şeyi mi anlatıyor" diye arayabiliyor. Bu çeviriyi yapan yapay zekâ modellerine embedding modeli deniyor.
Recall@10 — Bir arama sisteminin başarı ölçüsü. "Doğru cevap, dönen ilk 10 sonucun içinde miydi?" sorusunun yüzdesi. 0,933 demek, yüz aramanın doksan üçünde doğru cevabın ilk onda olduğu anlamına gelir. İlk sırada olması gerekmez — hafıza katmanı asistana bir liste sunar, önemli olan doğru anının o listeye girmesidir.
Ebbinghaus unutma eğrisi — Alman psikolog Hermann Ebbinghaus'un 1885'te yayımladığı çalışma. Öğrenilen bir şeyin, tekrarlanmazsa zamanla giderek hızlanan biçimde unutulduğunu gösteriyor. Grafiği önce hızlı düşen, sonra yavaşlayan bir eğri. Yadigar'daki solma bu eğriyi taklit ediyor: kullanılmayan anı zamanla zayıflıyor, kullanılan anı tazeleniyor.
Satır düzeyi güvenlik (row-level security) — Veritabanının kendi içinde uyguladığı erişim kuralı. Normalde "kimin hangi veriyi görebileceği" uygulama kodunda kontrol edilir; burada kural veritabanına gömülüdür. Uygulamada bir hata olsa, yanlış bir sorgu yazılsa bile başka kullanıcının satırları geri dönmez. Kontrolü unutmanın mümkün olmadığı yere koymak diye özetlenebilir.
Yaklaşık komşu araması (approximate nearest neighbour) — Milyonlarca sayı listesi arasından "en yakın olanları" bulmanın hızlı ama garantisiz yolu. Hepsine tek tek bakmak kesin sonuç verir ama yavaştır; bu yöntem akıllı kısayollarla arama alanını daraltır. Genelde aynı sonucu verir, ama "genelde" kelimesi burada önemli — yazıda anlatılan tuzak tam olarak bundan çıktı.
Tartışma