Yunus Emre Alpak

Geriye Bakınca — Mnemo'dan Çıkardığım 8 Ders · Mnemo Serisi 5/5

2026 · 05 · 237 dk okuma

Beş hafta önce "asistanlarım birlikte hatırlasın" diye başladığım yolculuğun sonunda elimde çalışan bir servis var. Ama daha değerlisi başka bir şey: bu süreçte aldığım kararların hangilerinin hâlâ doğru durduğunu, hangilerinin bana ders olduğunu anladım. İşte 8 ders, dürüstçe.

Serinin son yazısı. Şimdiye kadar "neden", "temel mimari", "akıl" ve "yaşayan hafıza" tarafları vardı. Burada projeyi bir bütün olarak değerlendiriyorum — neyi doğru yaptım, neyi farklı yapardım, neyi başkasına da öneririm.

1. Boş bir tabloyla başlamak öğretici

Mnemo'nun Phase 1 migration'ı, gerçekten kullanılmayacak alanları bile içeriyordu — consolidated_from, consolidated_into, expires_at, attachments. Phase 3-5'te lazım olacaklardı. Phase 1'de "premature engineering" gibi görünebilirdi.

Ama geri dönüp baktığımda, bu erteleme değil öngörüydü. Çünkü:

Bu erken eklemenin filtresi: o alanın bugün tek cümlelik bir use case'i var mı? Yoksa "ileride güzel olur" hayali mi? Birinci ise ekle, ikinci ise ekleme.

Bu filtre beni "her ihtimale karşı" şişirmekten korudu. Ama "öngörülü" davranmayı da engellemedi.

2. State-ful sistem sayısı = operasyonel yorgunluk

Bu hâlâ Mnemo'nun en sağlam kararlarından biri. Tek PostgreSQL, yanında pgvector ve pg_trgm extension'ları. Yanına Redis koymadım. Elasticsearch koymadım. Ayrı vector DB koymadım.

Sonuç:

Bu sayı küçük göründüğünde fark hissedilmez. Ama "5 farklı state-ful sistem yöneten Mnemo" ile "1 PostgreSQL kullanan Mnemo" arasındaki operasyonel yük farkı 1 değil, 10'dur. Çünkü problemler arası karmaşık etkileşimler ekleniyor.

Yeni bir servis kurarken sorulacak ilk soru hâlâ aynı: "Kaç state-ful sistemim olacak?" Cevap 2 veya daha fazla ise, ikinci kez düşünülmeli.

3. Interface açık tut, implementasyonu erteleme

Embedder interface'ini Phase 2'de yazdım. İçinde sadece Voyage implementasyonu vardı (artı bir test fixture olarak Noop). Ollama implementasyonu yok. ColPali yok. Sentence Transformers yok.

Ama interface oradaydı. Switch cmd/mnemo/main.go'da hazırdı:

switch cfg.EmbeddingProvider {
case "voyage": embedder = NewVoyageEmbedder(...)
default: embedder = NewNoopEmbedder(...)
}

Yarın Ollama eklemek istersem — yeni bir struct yazarım, switch'e bir case eklerim. Test edilebilir, geri alınabilir, izole bir değişiklik.

Ders: interface'i baştan tasarla, ama tüm implementasyonları baştan yazma. Bu strateji "ileriye dönük esneklik" ile "şimdiye odak"ı birleştiriyor. Hangisinden de fazlasını yapmıyorsun.

4. Senkron ve async aynı sistemde yaşayabilir

Mnemo'nun en güzel kararlarından biri buydu. İki ayrı ingestion yolu var:

İki yol farklı SLA'larla yaşıyor. Birincisi interactive (latency önemli, embedding 300ms'ye razıyım). İkincisi bulk (latency önemsiz, batch verimliliği önemli).

İlk içgüdü "her şeyi async yap, tutarlı ol" diyebilirdi. Ama bu yanlış olurdu. Tutarlılık her yerde aynı şekilde yapmak değil, ihtiyaçla aynı çizgide olmak.

İnteractive kullanıcı (Claude remember çağırıyor) "ben bunu kaydettim" cevabını embedding hazır olduğunda istiyor. Çünkü bir sonraki recall'da o memory'i bulmak istiyor. Eğer "kaydettim" desem ama embedding NULL olsa, recall onu bulamayacaktı.

Otomatik event (Vault dosya yükledi) hiç bir interactive yanıt beklemiyor. Olay DB'de durduğu sürece güvende. Embedding 30 saniye sonra dolsa kimseyi etkilemiyor.

İki SLA, iki yol, tek sistem. Bu disiplin transfer edilebilir bir tasarım kararı.

5. LLM-first API tasarımı yeni bir disiplin

REST yazarken yıllarca düşündüğümüz şeyler — versioning, idempotency, error codes, pagination — hâlâ önemli. Ama LLM-first API yazarken yeni bir boyut ekleniyor: tool description'lar prompt mühendisliğidir.

Bir tool'un description'ı, bir LLM'in onu doğru zamanda doğru parametrelerle çağırıp çağırmamasını belirler. Bu yüzden:

Bu disiplini yeterince ciddiye almazsan, teknik olarak doğru bir API yaparsın ama LLM kullanmaz. Mnemo'da ilk versiyondaki "Searches memories" gibi yetersiz description'lar, kullanım oranını gözle görülür biçimde düşürmüştü.

Ders: API description'larını LLM'in göreceği bir prompt olarak yaz, dokümanın bir parçası olarak değil.

6. Decay metaforu psikolojik değil teknik karar

"Biyolojik hafıza" metaforu romantik gelebilir — sanki Mnemo "insan gibi" unuttuğunu söyleyen bir pazarlama hilesi gibi. Ama altında çok somut bir teknik karar var.

Decay olmadan ne olur? Korpus zamanla şişer. Eski, alakasız hafızalar yeni sorgulara cevap olmaya başlar. Vector similarity yüksekken strength düşük olan bir kayıt artık kaale alınmaz olur. Bu doğal bir prioritization mekanizması.

Decay olmadan bunu manuel yapmak gerekirdi: cron job yazıp eski hafızaları silmek, threshold'lar koymak, false positive'lerle uğraşmak. Decay formülü bu işi sürekli, sezgisel ve kullanıcı erişimine duyarlı şekilde yapıyor.

Aynı zamanda reinforcement (recall edince clock'un sıfırlanması) kullanım sıklığına göre prioritization sağlıyor. Sık bakılan hafıza güçlü kalıyor, hiç bakılmayan soluyor.

Ders: psikolojik gibi görünen tasarım kararları çoğu zaman pratik problemleri çözüyor. Metaforu küçümseme; altındaki teknik motivasyonu gör.

7. Honest trade-off listesi tutmak

Mnemo'nun mimari dokümanında bilinçli olarak bir "Eleştiriye Açık Noktalar" bölümü var. Orada:

Bu listeyi neden yazdım? İki sebepten:

1. Gelecekteki bana borç defterleri. Üç ay sonra "burayı niye böyle yaptım acaba" diye dönüp baktığımda, cevap orada. "Bilerek yapmadım, evet biliyorum eksik" diye yazılı.

2. Dürüstlük. Her sistemin trade-off'ları var. Bunları gizlersen, sonradan bug çıktığında "biz bunu düşünmemiştik" hissi olur. Yazılı olduğunda "biz biliyorduk, henüz çözmedik" oluyor — daha sağlıklı bir pozisyon.

Ders: kendi sistemine eleştirel bir göz tutmak, bütün avantajlı bir göz tutmaktan daha verimli. "Biliyorum bu zayıf" yazılı bir not, sonraki refactor'ün ilk satırı oluyor.

8. Sibling project'lerle paralel kal

Mnemo, Vault'la kasten benzer şekilde deploy ediliyor:

Tek ayrılık: zerolog vs slog. Çünkü gerçek bir teknik fark vardı.

Bu paralellik operasyonel zihinsel yükü dramatik biçimde azaltıyor. Sunucuda iki servis var ama tek bir "deploy mantığı" var. Birini onarmayı bildiğimde diğerini de biliyorum. SSH atıp docker compose ps çektiğimde çıktı format'ı tanıdık.

Bu kasıtlı bir tasarım kararı. "Mnemo'ya özgü bir şeyler yapayım" cazibesine yenilmedim. Çünkü o cazibenin maliyeti çok yüksek — her servis biraz farklı şekilde deploy edilen bir kar topu olur.

Ders: sibling project'lerle bilinçli paralellik kur. Sadece teknik fark gerçek bir kazanım sağlıyorsa farklılaş. Aksi takdirde operasyonun düşmanı olursun.

Mnemo şu an ne yapıyor?

Beş hafta sonra Mnemo:

Hâlâ küçük. Hâlâ tek kullanıcılı. Ama her geçen hafta daha "yaşayan" hissi veriyor. Çünkü kendisi besleniyor, ben elimle yazmıyorum.

Mnemo nereye gidiyor?

Yakında:

Uzakta:

Ama bunların hiçbiri zorunlu değil. Mnemo bugünkü haliyle de bana hizmet veriyor. Her özellik gerçek bir ihtiyaç doğduğunda gelecek — özellik için özellik eklemeyeceğim. Bu disiplin, ilk yazıdaki manifestoyla uyumlu.

Asıl ders

Bu seriyi yazarken kendime şu soruyu sordum: "Mnemo bana ne öğretti?" Cevap teknik olabilirdi — pgvector, MCP, NATS, decay formülleri. Ama gerçek cevap daha basitti.

"Bir asistanın gerçekten faydalı olması için, onun seninle birlikte hatırlaması gerekiyor."

Bu, model boyutu sorunu değil. Token limiti sorunu değil. Bağlam penceresi sorunu değil. Bu, ekosistem tasarımı sorunu. Hangi servisin hangi hafızaya yazdığı, hangisinin oradan okuduğu, hafıza katmanının kim olduğu.

Mnemo benim için bu sorunun cevabı. Senin için belki başka bir şey olur — kendi yazdığın bir hafıza, kullandığın hazır bir sistem, ya da sadece bir Notion sayfası. Önemli olan biçimi değil; bir hafıza katmanının var olması.

Çünkü asistanların unutmadığı bir gelecek, onlara her seferinde her şeyi yeniden anlatmadığın bir gelecek. Ve o gelecek, üzerine düşünmeye değer.

Seriyi bitirirken

Beş yazı oldu. Burada hiç kod yoktu ama umarım kararların ardındaki düşünceyi hissettin. Eğer kendi hafıza katmanını kurmak istersen, Mnemo'nun kodu açık — repository'i incele, kendi versiyonunu yaz, başka diller ve framework'lerde dene. Önemli olan şu: kendi asistanına ne hatırlamasını istersin?

O sorunun cevabı, senin ilk Phase 1'in olur.