RAG asistanımda ilk kelimeyi 50 saniyeden 4 saniyeye indirmek
Portfolyom için kurduğum RAG asistanı ilk sürümde bir cevaba başlamak için 25–50 saniye bekletiyordu. Neyi ölçtüğümü, neyi yerelde bırakıp neyi buluta taşıdığımı ve bu kararın bedelini anlatıyorum.
Başlangıç
Portfolyoma ziyaretçilerin benim hakkımda soru sorabileceği bir asistan ekledim: "Göktuğ'a Sor". Mimari klasik bir RAG: soru gelince önce bilgi tabanında arama yapılıyor, bulunan parçalar dil modeline veriliyor, model yalnızca bu parçalara dayanarak cevap yazıyor.
İlk hedefim her şeyin kendi sunucumda çalışmasıydı: arama da, cevabı yazan dil modeli de. Sunucu 4 çekirdekli, 8 GB bellekli, ekran kartı olmayan ve başka siteleri de barındıran paylaşımlı bir makine. Dil modeli olarak Ollama üzerinde çalışan, 3 milyar parametreli küçük bir model (qwen2.5:3b) seçtim.
Ölçünce görünen tablo
Asistan doğru cevap veriyordu ama ölçtüğümde tablo şöyleydi:
- Yeni bir soruda ilk kelime 20–25 saniyede geliyordu; model bellekten boşaltılmışsa bu süre ~60 saniyeye çıkıyordu.
- Cevap saniyede 5–6,6 token hızında akıyordu.
- Model yüklüyken Ollama yaklaşık 3,1 GB bellek tutuyordu.
Gerçek bir ziyaretçinin ilk sorusu 56 saniye bekledikten sonra zaman aşımına uğradı. Bir portfolyo ziyaretçisi bir dakika beklemez; birkaç saniye içinde bir şey görmezse sekmeyi kapatır.
Yol boyunca bir sürpriz daha çıktı: modelin istem önbelleği (prompt cache) zamanla büyüyüp 8 GB'a doğru gidiyor ve servise koyduğum 4 GB'lık bellek sınırına çarpıyordu. Önbelleği LLAMA_ARG_CACHE_RAM=256 ile sınırlayınca sorun kalktı. Ama asıl sorun duruyordu: bu işlemcide 3 milyarlık bir model, sohbet için fazla yavaştı.
Neyi nerede çalıştırmalı
Sistemi iki parçaya ayırıp her birine ayrı baktım:
- Arama (embedding + BM25): hafif, hızlı ve bilgi tabanımla iç içe. Sunucuda kalmasında sorun yoktu.
- Cevap üretimi (dil modeli): ağır ve CPU'da yavaş. Darboğaz buradaydı.
Bu yüzden yalnızca cevap üretimini, OpenAI uyumlu bir API üzerinden bulut dil modeline (MiniMax) taşıdım. Kodda değişen tek şey sağlayıcı katmanı oldu: .env dosyasındaki bir ayarla yerel modele geri dönebiliyordum. Arama ve embedding modeli sunucuda kaldı. Embedding modelini ise her soruda yeniden yüklenmesin diye sürekli bellekte tuttum (~0,8 GB).
Geçişte küçük bir detayla uğraşmam gerekti: kullandığım model cevaptan önce bir "düşünme" metni üretiyor. Akan cevabın içinden bu bölümü ayıklayan bir filtre yazdım; ziyaretçi yalnızca cevabı görüyor.
Sonuç
- İlk kelime ortalama ~4 saniyeye indi.
- Cevaplar saniyede ~54 token hızında akmaya başladı.
- 40 soruluk doğruluk testi geçişten hemen sonra 40/40 geçti; doğruluk düşmedi.
Bedeli de var: ziyaretçi soruları artık bir dış servise gidiyor ve her soru küçük bir maliyet demek. Bunu hem kötüye kullanıma hem maliyete karşı ziyaretçi başına ve günlük toplam soru sınırlarıyla kontrol altına aldım.
Sonrası
Hızlandırdıktan sonra bile asistan sunucuda yaklaşık 1 GB bellek tutmaya devam ediyordu ve paylaşımlı bir sunucuda bu, diğer işlerden alınan bir pay demekti. Bir süre sonra asistanı kapatmaya karar verdim. Kod ve bilgi tabanı duruyor; kaynaklar el verdiğinde geri açmak tek komut.
Öğrendiklerim
- Önce ölç. "Yerel model yavaş olur" bir tahmindir; "ilk kelime 25 saniye" bir veridir ve karar vermeyi kolaylaştırır.
- Sistemi parçalarına ayır. Her şeyi buluta taşımak gerekmedi; yalnızca darboğazı taşımak yetti.
- Kararı geri alınabilir tut. Sağlayıcıyı tek bir ayara bağlamak, denemeyi de geri dönmeyi de ucuzlattı.
- Doğruluğu her değişiklikten sonra yeniden ölç. Hız kazanırken kaliteyi kaybetmediğimi doğruluk testi söyledi, ben değil.