Buğra Şıkel
Mail Sınıflandırmada LLM Yerine Karar Modeli: Jev ile Gemini’yi 317 Gerçek Mailde Karşılaştırdım

Kişisel Gmail kutumu bir süredir n8n ile saatte bir otomatik etiketliyorum. İlk kurduğum düzen klasikti: yeni mailleri 20’lik paketler hâlinde tek bir Gemini 2.5 Flash istemine veriyor, cevaptaki JSON’u ayrıştırıp etiketleri basıyordum. Çalışıyordu, ama her seferinde aklımın bir köşesinde aynı soru vardı: bu kadar basit bir işi, yani “bu mail hangi kutuya girer?” sorusunu, serbest metin üreten bir modele yaptırmak gerçekten doğru araç mı?
Bu yazıda, sınıflandırma işini metin üretmeyen, yalnızca karar veren bir modele, TypeSafe’in OpenRouter üzerinden sunduğu Jev‘e taşıdığım deneyi anlatıyorum. İki modeli 317 gerçek mailde karşılaştırdım, geçişten sonraki ilk günlerin gerçek maliyet ve gecikme verilerini topladım, ayrıca Jev’i bir Instagram içerik akışında “hakem” olarak denedim. Kısa özet: doğrulukta başabaş, güvenilirlik ve maliyette net bir kazanç, en büyük ders ise modelle değil kategori tanımlarıyla ilgili.
İçindekiler
- Jev Nedir? Metin Üretmeyen Bir Model
- Eski Düzen: Tek İstemde 20 Mail
- Test Düzeni: 117 + 200 Gerçek Mail
- İlk Deneme: Kısa Tanımlarla %84 Uyum
- Sonuçlar: Başabaş, Ama Hatalar Farklı
- Üretimde Hız ve Maliyet
- İkinci Deney: İçerik Denetiminde Hakem Olarak Jev
- Ne Zaman Karar Modeli, Ne Zaman LLM?
- Kendin Dene: Açık Kaynak n8n Akışı
- Sınırlamalar
Jev Nedir? Metin Üretmeyen Bir Model
Jev tipli bir karar modeli. Ona serbest bir istem yazmıyorsunuz; bir durum (state) ve adlandırılmış sorular veriyorsunuz. Her soru sabit bir tipte cevaplanıyor:
| Tip | Siz verirsiniz | Geri dönen |
|---|---|---|
noul |
Evet/hayır sorusu ve iki tarafın ölçütleri | Cevabın “evet” olma olasılığı |
choice |
En fazla 255 adlandırılmış seçenek ve her birinin ölçütü | Seçilen seçenek, her seçeneğin olasılığı ve bir güven değeri |
score |
2 ila 10 sıralı düzey | Düzeyler üzerinde ağırlıklı bir puan |
Model metin yazamadığı için JSON’u bozamıyor, listede olmayan bir kategori uyduramıyor, cevabın başına “Elbette, işte sonuç:” diye bir cümle ekleyemiyor. Mail sınıflandırmada kullandığım istek kabaca şöyle (kategoriler kısaltıldı):
POST https://openrouter.ai/api/alpha/decisions
{
"model": "typesafe/jev-1.13",
"state": {
"from": "kargo@ornek-magaza.com",
"subject": "Siparişiniz kargoya verildi",
"snippet": "Paketiniz yola çıktı, takip numaranızla izleyebilirsiniz..."
},
"questions": {
"category": {
"type": "choice",
"instructions": "Classify this email received in a personal Gmail inbox into exactly one category. Decide by what the email is about and why it was sent, not only by who sent it.",
"criteria": {
"Alışveriş & Kargo": "Shopping, food delivery and marketplaces: orders, purchase e-invoices, shipment tracking...",
"Promosyon & Reklam": "Marketing from ANY company: discounts, campaigns, newsletters, product updates...",
"Abonelik & Hizmetler": "Transactional messages about the user's own subscriptions and service accounts... Not newsletters or product updates.",
"Diğer": "Personal or miscellaneous emails that do not clearly fit any category"
}
}
}
}
Üretimdeki gerçek bir yanıt (olasılıklar kısaltıldı) ise şöyle görünüyor:
{
"model": "typesafe/jev-1.13-20260917",
"answers": {
"category": {
"type": "choice",
"choice": "Abonelik & Hizmetler",
"probabilities": { "Abonelik & Hizmetler": 0.95, "Promosyon & Reklam": 0.05, "Bankacılık": 0, ... },
"confidence": 0.94
}
},
"usage": { "input_tokens": 1138, "output_tokens": 170, "cost": 4.7796e-05 }
}
Dikkat edin: kategori adları Türkçe, ölçütler İngilizce. Etiket adlarını Gmail’de gördüğüm gibi bıraktım; ölçütleri ise daha kesin yazabildiğim için İngilizce tuttum. Jev bu karışımla sorunsuz çalıştı.
Eski Düzen: Tek İstemde 20 Mail
Eski akışta Gemini 2.5 Flash’a 20 maili tek seferde verip her mail için bir kategori içeren bir JSON dizisi istiyordum. Bu düzenin, doğruluktan bağımsız, yapısal zayıf noktaları var:
- Ayrıştırma riski: Cevap bir kod bloğuna sarılabilir, eksik gelebilir ya da geçersiz JSON olabilir. Tek bir bozuk cevap, paketteki 20 mailin hepsini boşa düşürür.
- Uydurma kategori: “Promosyon & Reklam” tanımlıyorsunuz, model “Bülten” diyebiliyor. Etiket eşleşmiyor.
- Paket içi etkileşim: Aynı istemdeki mailler birbirinin kararını etkileyebiliyor. Maliyeti düşürmek için yapılan paketleme, kararları birbirine bağımlı hâle getiriyor.
Jev’le her maile ayrı ve bağımsız bir istek gidiyor. Bunun maliyeti artırması beklenir; aşağıda göreceğiniz gibi artırmadı.
Test Düzeni: 117 + 200 Gerçek Mail
Karşılaştırmayı kendi kişisel kutumda, iki ayrı küme üzerinde yaptım:
- Geliştirme kümesi (117 mail): Kategori tanımlarını bu mailler üzerinde düzelttim. Yani bu kümedeki sonuç iyimser.
- Doğrulama kümesi (200 mail): Tanımlar son hâlini aldıktan sonra, hiç bakmadığım 200 mail. Asıl ölçü bu.
Gemini tarafında yeni bir çağrı yapmadım: eski akışın bu maillere zaten bastığı etiketleri kullandım. Jev’in önünde, her iki düzende de ortak olan iki basit kural var: kendi adresimden gelen mailler “Otomasyon”, iş yerimin adı geçen mailler “İş” etiketine gidiyor. Bu kurallar geliştirme kümesinde 14, doğrulama kümesinde 64 maili yakaladı. Bu mailler iki tarafta da aynı sonucu verdiği için sonuçları hem tüm küme hem de yalnızca modele giden mailler için ayrı ayrı veriyorum.
Doğru cevabı, iki modelin anlaşmadığı maillere tek tek bakarak belirledim. Gerçekten iki kategoriye de uyan mailler için (geliştirmede 10, doğrulamada 24 mail) birden fazla kabul edilebilir cevap tanımladım. Bir uyarı: hakemlik Gemini’nin mevcut etiketleri üzerinden yürüdüğü için ölçüm Gemini lehine eğilimli. Bunun somut örneklerini aşağıda göreceksiniz.
İlk Deneme: Kısa Tanımlarla %84 Uyum
İlk denemede kategorileri kısa tek cümlelerle tanımladım. Sonuç hayal kırıklığıydı: Jev, geliştirme kümesinde Gemini ile yalnızca 117 mailin 98’inde (%84) aynı kararı verdi. Hatalarına bakınca tablo çok netti: 10 hatanın 9’unda Jev maili “Abonelik & Hizmetler” kategorisine atmıştı. Bültenler, ikinci el ilan siteleri, güvenlik uyarıları… Kategori bir çöp kutusuna dönmüştü.
Sorun modelde değil, tanımdaydı. İlk tanım şuydu:
Abonelik & Hizmetler: Subscription and service accounts, payment receipts or
service notices (Netflix, Spotify, YouTube, Apple, Adobe, GitHub, AWS,
Cloudflare, Google, OpenAI etc.)
Bu tanım, “Cloudflare’den gelen her şey buraya” diye okunabiliyor. Son hâli ise neyin dahil olmadığını da söylüyor:
Abonelik & Hizmetler: Transactional messages about the user's own subscriptions
and service accounts: receipts, renewals, payment confirmations, plan or account
changes, terms/policy updates, membership sign-ups (...). Not newsletters or
product updates.
Aynı mantıkla diğer kategorileri de gerçek mail türlerime göre yeniden yazdım. Promosyon tanımına “Marketing from ANY company” ifadesini ve bülten, ürün güncellemesi, markaların doğum günü mailleri gibi örnekleri ekledim. Talimat metnine de tek bir cümle ekledim: “Decide by what the email is about and why it was sent, not only by who sent it.” Gönderene göre değil, mailin amacına göre karar ver. Bu cümle, aynı şirketten gelen fatura ile bülteni ayırmak için kritikti.
Tanımlar netleşince uçurum kapandı. Buradan çıkan ders, bu yazının geri kalanından daha önemli olabilir: Sınıflandırmada kaliteyi belirleyen en büyük kaldıraç, kategori tanımlarıdır. Yeni bir mail türü yanlış kutuya gidiyorsa, önce modeli değil tanımı düzeltin.
Sonuçlar: Başabaş, Ama Hatalar Farklı
Son tanımlarla sonuçlar şöyle:
| Küme | Jev (mail başı karar) | Gemini (toplu istem) | |
|---|---|---|---|
| Geliştirme, tümü | 117 | 114 (%97,4) | 115 (%98,3) |
| Geliştirme, yalnızca model | 103 | 100 (%97,1) | 101 (%98,1) |
| Doğrulama, tümü | 200 | 195 (%97,5) | 196 (%98,0) |
| Doğrulama, yalnızca model | 136 | 132 (%97,1) | 133 (%97,8) |
Kâğıt üzerinde Gemini her iki kümede de bir mail önde. Ama hatalara tek tek bakınca tablo değişiyor. Jev’in yedi hatasından en az üçü, aslında tanıma harfiyen uyduğu için “hata” sayıldı:
- Bir havayolunun doğum günü kutlama maili: Jev Promosyon dedi, hakem Seyahat. Oysa tanımda “birthday greetings from brands” açıkça Promosyon’a yazılı.
- Bir bulut sağlayıcısının etkinlik daveti: Jev Promosyon dedi, hakem Etkinlik. Tanımda Etkinlik “kullanıcının satın aldığı biletler”, etkinlik pazarlaması ise Promosyon.
- Bir şirketin e-Arşiv faturası: Jev Alışveriş dedi, hakem Faturalar. Tanımda Faturalar yalnızca elektrik, su, doğalgaz, internet ve telefon için.
Jev’in gerçekten tartışmasız kaçırdıkları ise iCloud+ paket güncellemesi (Abonelik yerine Promosyon) ve bir ödeme altyapısının “hoş geldiniz” maili (Abonelik yerine Alışveriş) gibi, iki kategorinin sınırındaki mailler oldu.
Gemini’nin hataları ise daha çok “gönderene göre” karar verme tipindeydi:
- İkinci el ilan sitesinden “İlanınızla ilgili soru soruldu”: Gemini Diğer, doğrusu Alışveriş.
- Google’dan “Son ödemenizi kontrol edin”: Gemini Bankacılık, doğrusu Abonelik.
- Bir yemek siparişi uygulamasının e-Arşiv faturası: Gemini Abonelik, doğrusu Alışveriş.
- Bir geliştirici aracının bülteni: Gemini Abonelik, doğrusu Promosyon.
Hakemin eğilimini de hesaba katınca, en dürüst okuma şu: doğrulukta başabaş.
Bir de Jev’in döndürdüğü güven değerine baktım. Modele giden 239 mailde, doğru cevapların %89’unda güven 0,9 ve üstündeydi. Yedi hatanın güvenleri ise 0,53, 0,56, 0,58, 0,60, 0,76, 0,89 ve 1,0. Yani düşük güven iyi bir uyarı işareti, ama garanti değil: 0,61’lik bir eşik yedi hatanın dördünü yakalardı, bedeli de 232 doğru cevabın 6’sının gereksiz yere incelemeye düşmesi olurdu. Eşiğin altında kalan mailleri “İncelenecek” gibi ayrı bir etikete atmak makul bir ek adım.
Üretimde Hız ve Maliyet
Karşılaştırmadan sonra akışı üretimde Jev’e geçirdim. Geçişten sonraki ilk iki buçuk günün gerçek verileri (50 mail):
| Ölçüt | Değer |
|---|---|
| Mail başı maliyet (medyan) | 0,000049 $ |
| 50 mailin toplam maliyeti | 0,0025 $ |
| Mail başı girdi tokenı (örnek) | 1138 |
| Mail başı süre (medyan, 5 paralel istekle) | ~0,4 sn |
| Geçersiz cevap / uydurma kategori | 0 |
Jev’de girdi tokenı milyon başına 0,042 $, çıktı ücretsiz. Mail başı tokenların çoğu kategori tanımlarından geliyor. Günde 20 mail alan bir kutu için bu, ayda yaklaşık 3 sente denk geliyor. Mail başına ayrı istek atmak, yani paket içi etkileşimi tamamen ortadan kaldırmak, bu fiyatla bir maliyet sorunu olmaktan çıkıyor.
Akışta bir de güvenlik ağı var: Jev’e ulaşılamazsa o saat hiçbir mail etiketlenmiyor, “işlendi” işareti basılmıyor ve bir sonraki saatte aynı mailler tekrar deneniyor. Yanlış etiket basmaktansa hiç basmamak, geri dönüşü kolay olan tercih.
İkinci Deney: İçerik Denetiminde Hakem Olarak Jev
Jev’i ikinci olarak, sosyal medyasını yönettiğim bir restoranın otomatik Instagram akışında denedim. Orada Gemini fotoğrafı görüyor ve her gönderi için üç alternatif başlık ve açıklama yazıyor. Soru, hangisinin yayınlanacağıydı. Kurduğum düzen şu: Gemini görür ve yazar, Jev karar verir. Her aday ayrı bir istekle Jev’e gidiyor; başlığın dili, ana yemeğe odaklanıp odaklanmadığı, açıklamanın fotoğrafa sadık olup olmadığı gibi sorular soruluyor ve ağırlıklı bir puan hesaplanıyor. (LLM çıktısını otomatik denetleme üzerine daha genel bir çerçeve için Otonom PR İncelemelerinde False-Positive Gürültüsünü Bastıran 5 Prompt Deseni yazısına da bakabilirsiniz.)
Türkçe metin denetiminde Jev çok iyi ayırt etti:
- Yarım kalmış başlık: “Izgara ateşinden sıcacık dürüme” başlığı, sonu datif ekiyle havada kaldığı için dil puanında 3 üzerinden 0,82 aldı. Diğer başlıklar 2,3–2,9 arasındaydı.
- Odağı kaçan başlık: Ana yemek yerine garnitürü anlatan “Köz biberler ve çıtır ekmekler” (0,09) ve “Renkli garnitürlerin sıcak buluşması” (0,13) başlıkları, “Ateşte mühürlenmiş etin dokusu” (0,95) gibi yemeğe odaklanan başlıklardan net biçimde ayrıldı.
- Yanlış ürün ve uydurma ayrıntı: Başka bir yemeği anlatan metne “ürünle uyumlu” sorusunda 0,02, fotoğrafta olmayan bir ayrıntıdan bahseden açıklamaya “fotoğrafa sadık” sorusunda 0,05 verdi.
Ama zayıf olduğu yerler de öğretici oldu:
- Ürün tanıma: Jev görsel görmüyor; ürünü ancak Gemini’nin yazdığı metin betiminden seçebiliyor. Gemini’nin 0,9 ve üstü güvenle doğru tanıdığı 8 üründen 4’ünde Jev yanlış seçti. Bu yüzden ürünün kimliği hiçbir zaman Jev’e bırakılmadı; o iş katalog ve Gemini’de kaldı.
- “Ana sorun ne?” sorusu: Tek seçimli bir “en önemli sorun” sorusu, iyi adaylarda bile mutlaka bir sorun seçti (çoğunlukla “klişe”). 37 adayın hiçbirinde “sorun yok” seçeneğinin olasılığı %15’i geçmedi. Bu soruyu kapı olarak değil, yalnızca revizyon ipucu olarak kullanıyorum.
- Ortalama tuzağı: Birden fazla satırlık bir metnin dil kalitesini tek bir ortalama puanla sorduğumda, tek bir bozuk satır (“Yoruma bekliyoruz”) ortalamada kayboldu. Soruyu “en zayıf satırın dil kalitesi ne?” diye değiştirince sorun çözüldü.
Ne Zaman Karar Modeli, Ne Zaman LLM?
İki deneyden çıkardığım pratik kurallar:
- Cevabın şekli belliyse karar modeli: Kategori seçmek, evet/hayır demek, bir ölçekte puanlamak. Format hatası sıfır, maliyet çok düşük, her karar bağımsız.
- Görmek ya da yazmak gerekiyorsa LLM: Görsel analizi, metin üretimi, revizyon. Jev bunları yapmıyor; yapmaya çalışmıyor.
- İkisini birleştirin: LLM adayları üretsin, karar modeli puanlasın ve kapıları uygulasın. Karar modeline bir şeyi tanıma işini değil, verilen metni değerlendirme işini verin.
- Tanımlara yatırım yapın: Kısa tanım, çöp kutusu kategori üretir. Neyin dahil olmadığını yazın.
- Ortalamaya değil en kötüye sorun: Bir metnin tek bir kötü parçası yayını bozmaya yetiyorsa, soruyu en zayıf parçaya göre kurun.
Kendin Dene: Açık Kaynak n8n Akışı
Mail etiketleme akışını anonimleştirip açık kaynak olarak paylaştım: github.com/bugraskl/n8n-gmail-ai-labeler. İçinde n8n’e doğrudan içe aktarılabilir workflow, İngilizce varsayılan kategori seti, kurallar, eksik Gmail etiketlerini otomatik oluşturma ve Jev’e erişimi olmayanlar için deneysel bir “düz LLM” modu var. Instagram tarafındaki “Gemini yazar, Jev karar verir” düzeninin tamamı da github.com/bugraskl/n8n-instagram-autopilot reposunda.
Sınırlamalar
- Bu bir benchmark değil, tek bir kişisel mail kutusunda yapılmış dürüst bir deney. Küme boyutları küçük; bir mail farkı istatistiksel olarak anlamlı değil.
- Doğru cevaplar tek bir hakemin kararı ve Gemini’nin mevcut etiketleri üzerinden kuruldu; sonuçlar bu yüzden Gemini lehine eğilimli.
- Jev’in OpenRouter uç noktası alfa aşamasında. Erişim, fiyat ve API şekli değişebilir.
- Jev yalnızca metin görüyor. Görsel içerikli kararlar için önce bir LLM’in betim yazması gerekiyor ve bu betimdeki hatalar karara aynen taşınıyor.
- Maliyet ve gecikme verileri ilk iki buçuk günlük, 50 maillik üretim trafiğinden. Uzun vadeli ortalamalar farklı olabilir.
Özetle: mail sınıflandırmada Jev, Gemini ile aynı doğruluğu çok daha düşük maliyetle ve sıfır format hatasıyla verdi. Ama asıl kazanç modeli değiştirmekten değil, kategorileri gerçek maillerime bakarak yeniden tanımlamaktan geldi. Bir sınıflandırıcı kuruyorsanız, önce tanımlarınızı düzeltin, sonra model seçin.
Bunları da beğenebilirsiniz

Duyarlı/Responsive Tasarım Neden Bu Kadar Önemli?
Duyarlı/Responsive tasarım nedir? İlk olarak, responsive tasarımın ve nasıl çalıştığının hızlı bir açıklamasını yapalım. Esasen, responsive tasarım, bir web sitesini, içeriğini ve öğelerini görüntülendiği ekran…
Devamını Oku

Endüstriyel Yapay Zeka Modellerinde Nondeterministik Hataların Kök Neden Analizi ve Reproducible Çözümler
Endüstriyel yapay zeka sistemlerinde ortaya çıkan nondeterministik hatalar, güvenilirliği ve performansı ciddi şekilde etkileyebilir. Bu blog yazısı, bu tür hataların kök nedenlerini analiz etmek ve endüstriyel AI modellerinde tekrarlanabilir sonuçlar elde etmek için pratik çözüm yolları sunmaktadır.
Devamını Oku

Dağıtık Sistemlerde Context Propagation Hataları: İzlenebilirlik Kayıplarını Teşhis Etme
Heterojen mikroservis ağlarında context propagation hatalarını teşhis etme stratejilerini öğrenin ve üretim ortamındaki izlenebilirlik açıklarını kapatın.
Devamını Oku