Çoğu RAG eğitimi, tam da canlı ortamın başladığı yerde sona erer. Dokümanlarınızı 512 token'lık parçalara (chunk) böler, bunları tek bir embedding modeli üzerinden geçirir ve basit bir top-k geri çağırma (retrieval) yöntemiyle bir vektör veritabanını çağırırsınız. Bir demoda bu oldukça ikna edici görünür. Bota şirketinizin izin politikasını sorarsınız ve o da size tutarlı bir paragraf döndürür. Herkes onaylar. Ne yazık ki, demolar yanıltıcıdır.

Canlı ortam, her türlü kestirme yolu açığa çıkarır. Sabit parçalar (fixed chunks), yasal sözleşmeleri tazminat maddelerinin tam ortasından kesip atar. API dokümantasyonu, aslında ihtiyacınız olan sinyali boğan, üst üste binen bir gürültü yığınına dönüşür. Gecikme süresi (latency), kullanıcılar cevabı almadan sorguyu terk edene kadar artar. Biz bu duvara çarptık ve her şeyi yeniden inşa etmek zorunda kaldık. Geri çağırma katmanımız, "anlamsal arama ve umut etme" yönteminden, ölçümlenmiş ve enstrümante edilmiş bir boru hattına (pipeline) dönüştü. Sonuç, %95 geri çağırma (recall) oranı ve gecikmede %40 azalma oldu. İşte gerçekten işe yarayanlar:

Parçalama Stratejisini Dokümana Uyarlayın

512 token'lık varsayılan değerin devam etmesinin sebebi doğru olması değil, kolay olmasıdır. Farklı dokümanlar anlamı farklı şekillerde taşır ve parçalama (chunking) stratejiniz bunu yansıtmalıdır.

Yasal sözleşmeler için yapısal sınırları gözeten özyinelemeli (recursive) parçalama kullanın. Hukuki dil iç içe geçmiş bir yapıdadır. Bir madde, üzerindeki bölüme bağlıdır ve cümle ortasındaki sabit bir kesinti, bir yükümlülüğün mantığını yok eder. Özyinelemeli parçalama, bir token sınırını dayatmadan önce doğal ayırıcıları —önce paragrafları, sonra cümleleri— kullanarak bölme işlemi yapmaya çalışır. Bu, tazminat veya sorumluluk maddelerini bozulmadan korur.

API dokümantasyonu için fonksiyona duyarlı (function-aware) parçalama kullanın. Geliştiriciler rastgele paragraflar aramazlar; uç noktalar (endpoints), parametreler ve hata imzaları ararlar. Bir parça; tam fonksiyon imzasını, açıklamasını ve dönüş şemasını (return schema) tek bir mantıksal birim olarak içermelidir. Eğer bu bloğu ortadan ikiye bölerseniz, geri çağırma sistemi bağlamın sadece yarısını döndürür ve üretim modeli (generation model) geri kalanını halüsinasyon görerek uydurur.

Destek talepleri (support tickets) için konuşma turlarını takip eden anlamsal (semantic) parçalamaya güvenin. Destek yazışmaları doğrusal ve tekrarlayıcıdır. Bir müşteri sorunu tekrarlar, bir temsilci günlükleri (logs) ister, müşteri de onları ekler. Her tur kendi başına anlamsal bir birimdir. Turlara göre parçalama, kimin neyi ne zaman söylediğini korur; bu da kullanıcı "Temsilci Salı günü ne önerdi?" diye sorduğunda kritik önem taşır.

Dahili wikiler için ajan tabanlı (agentic) parçalamayı deneyin. Bir LLM'e bir bölümü verin ve bir konunun nerede bittiğini ve diğerinin nerede başladığını karar vermesini isteyin. Bu, veri alım (ingest) aşamasında daha maliyetlidir ancak wikiler karmaşıktır. Sayfalar farklı ekiplerden gelen ilgisiz güncellemeler içerir ve insan tarafından tanımlanan sınırlar nadiren işe yarar. Bir modelin konu değişikliklerine göre sınırlar çizmesine izin vermek, gürültüyü önemli ölçüde azaltır.

Tek bir boru hattında birden fazla strateji çalıştırmak, veri alım aşamasında dokümanları türlerine göre etiketlemeyi gerektirir. Bu küçük şema disiplini, karşılığını anında verir.

Arama Yöntemlerini Birleştirin, Tek Bir Tanesini Seçmeyin

Vektör araması niyeti anlar ancak tam eşleşmelerde (exact matches) rutin olarak başarısız olur. Bir hata kodu ERR_CONNECTION_REFUSED veya belirli bir SKU isterseniz, yoğun (dense) embedding'ler genellikle kavramsal olarak benzer ancak gerçekte yanlış sonuçlar döndürür. Klasik bir anahtar kelime tabanlı seyrek (sparse) geri çağırma yöntemi olan BM25, tam dizelerle harika çalışır ancak anlamsal nüansları kaçırır. Her ikisine de ihtiyacınız var.

Hibrit geri çağırma (hybrid retrieval) kullanın. Vektör araması ve BM25'i paralel olarak çalıştırın. Ardından bunları Reciprocal Rank Fusion (RRF) ile birleştirin. RRF, her iki yöntemin de ilgili olduğuna karar verdiği dokümanları ödüllendirirken, her iki yaklaşımdan da güçlü adayları yüzeye çıkarmaya devam eder. Matematik basittir ve sonuç stabildir: Tek bir geri çağırma yöntemi nihai sıralamaya hükmetmez.

Birleştirmeden sonra bir cross-encoder yeniden sıralayıcı (reranker) ekleyin. İlk aşama —vektör artı seyrek geri çağırma— hızlı ve geniştir. Cross-encoder daha sonra her bir sorgu-doküman çiftini tam dikkatle (full attention) puanlar; yani adayı orijinal soruyla birlikte gerçekten okur. Evet, bu gecikmeyi artırır. Bizim durumumuzda yaklaşık elli ila yüz milisaniye kadar. Ancak hassasiyetteki (precision) artış o kadar keskindir ki, bu takas (trade-off) barizdir. Geri çağırma (recall) oranını önemsiyorsanız, bunu atlamayı göze alamazsınız.

İndeksi Düzeltmeden Önce Sorguyu Düzeltin

Kullanıcılar sorgularını arama motorunuz için yazmazlar. Onları insanlar için yazarlar. "Çalışmıyor" yaygın bir destek sorgusudur. Belirsiz bir özellik açıklaması, yaygın bir dahili wiki aramasidir. Eğer indeksi bu ham girdiyle aratırsanız, karşılığında çöp veri alırsınız.

Sorguyu, retriever'a ulaşmadan önce dönüştürün.

Kullanıcının sorusunun birden fazla versiyonunu oluşturmak için sorgu genişletme (query expansion) kullanın. Eğer birisi “server down” yazarsa, sisteminiz “service unavailable”, “502 error” ve “connection timeout” terimlerini de aramalıdır. Bu niyet varyantlarını kapsamak, geri çağırma (recall) oranımızı %78'den %96'ya çıkardı. Bu tek bir adımdır ve elde edilen kazanca kıyasla maliyeti neredeyse yok denecek kadar azdır.

Karmaşık sorular için sorgu ayrıştırma (query decomposition) kullanın. Bir kullanıcı “Eski faturalandırma API'sinden yeni olana nasıl geçerim ve hangi köklü değişiklikler (breaking changes) kurumsal hesapları etkiliyor?” gibi bir şey sorduğunda, bunu alt sorulara bölün. Bir alt soru taşıma adımlarını hedefler; bir diğeri ise kurumsal hesaplara özel köklü değişiklikleri hedefler. Her biri dizinin (index) farklı bir bölümüne ulaşır. Sonraki aşamadaki dil modeli, gürültülü bir bağlam penceresi üzerinden tahmin yürütmek yerine, iyi geri çağrılmış parçalardan (chunks) nihai cevabı sentezler.

Hiperparametre Tahmin Etmeyi Bırakın

Birden fazla parçalama (chunking) stratejisine, hibrit geri çağırmaya (hybrid retrieval) ve sorgu dönüşümüne sahip olduğunuzda, karşınıza kombinatoryal bir problem çıkar. Parça boyutu (chunk size), örtüşme (overlap), füzyon ağırlıkları (fusion weights), yeniden sıralayıcı derinliği (reranker depth) ve genişletme sayısı birbirleriyle etkileşim halindedir. Bunlardan birini tek başına değiştirmek, diğerini bozar. Bu alan üzerinde ızgara araması (grid search) yapmak israf ve yavaştır.

Bunun yerine Bayesyen optimizasyon (Bayesian optimization) kullanın. Bunu bir makine öğrenmesi ince ayar (tuning) işi gibi ele alın. Hedefinizi net bir şekilde tanımlayın: Gecikmeyi (latency) belirli bir sınırın altında tutarken geri çağırmayı (recall) maksimize edin. Bir "altın veri seti" (golden dataset) oluşturun — hangi parçaların geri çağrılması gerektiğini tam olarak bildiğiniz birkaç yüz temsili soru. Ardından Bayesyen aramanın konfigürasyon alanını verimli bir şekilde keşfetmesine izin verin. Bu yöntem, neyin işe yaradığına dair olasılıksal bir model oluşturur ve ardından en umut verici bölgeleri test eder.

Her aday konfigürasyon, staging aşamasına ulaşmadan önce altın veri setinden geçmelidir. Eğer yeni bir parça boyutu geri çağırmayı düşürürse veya daha ağır bir yeniden sıralayıcı (reranker) sizi gecikme bütçesinin dışına iterse, optimizasyon bunu otomatik olarak yakalar. Bu, işin içine kişisel görüşlerin girmesini engeller. 256 mı yoksa 512 token mı “daha iyi” diye tartışmayı bırakır ve sonuçları okumaya başlarsınız.

Sonuç

Boru hattındaki (pipeline) değişiklikler tam da umduğumuz gibi katlanarak etki etti.

  • Recall@10 %78'den %95'e yükseldi.
  • P95 gecikmesi (latency) 850 ms'den 320 ms'ye düştü.
  • Halüsinasyon oranı %12'den %3'e geriledi.
  • Sorgu başına maliyet %38 azaldı; bunun temel nedeni, daha iyi geri çağırma sayesinde daha küçük bir üretim (generation) modeli ve daha az prompt token'ı kullanabilmemizdir.

Gecikmedeki azalma ekipteki bazı insanları şaşırttı. Yeniden sıralayıcılar (rerankers) ve sorgu genişletme eklemek işleri yavaşlatacakmış gibi görünüyor. Ancak geri çağırma kalitesi arttığı için, üretim modeli daha az yönlendirmeye (prompting), daha az tahmine ve daha az yeniden denemeye ihtiyaç duydu. İyi bir geri çağırma, sonraki tüm aşamaları daha ucuz hale getirir.

Geri Çağırmayı Bir Altyapı Gibi Ele Alın

Geri çağırma (retrieval), bir kez çalıştırıp unutacağınız bir notebook değildir. O bir altyapıdır ve kod gibi yönetilmelidir. Parçalama (chunking) stratejilerinizi versiyonlayın. Hukuk ekibi yeni bir sözleşme şablonu yayınladığında, özyinelemeli ayırıcınızı (recursive splitter) üretim ortamına (production) ulaşmadan önce test edin. Altın veri setinizi geçen çeyrekten kalma statik bir CSV olarak değil, yaşayan belgeler olarak sürdürün. Değerlendirmelerinizi CI süreçlerinde otomatize edin; böylece bir embedding modelini veya bir füzyon ağırlığını değiştiren bir pull request, bir insan tarafından incelenmeden önce geri çağırma ve gecikme sayılarını içeren bir yorum alsın.

Kullanıcılarınız hangi embedding modelini çalıştırdığınızı asla sormayacaktır. Parçalama sezginizle (chunking heuristic) veya yeniden sıralayıcı mimarinizle ilgilenmeyecekler. Onlar cevabın doğru olup olmadığıyla, hızlı gelip gelmediğiyle ve ona güvenip güvenemeyecekleriyle ilgilenirler. Bu güveni kazanan bir boru hattı (pipeline) inşa edin, bunu dürüstçe ölçün ve geri çağırmayı sonradan akla gelen bir detay gibi görmeyi bırakın.

Kaynak: Optimizing RAG At Scale
Tartışmaya katılın: GyaanSetu AI Community