Bir Arama Destekli Üretim (RAG) sistemi oluşturmak, yalnızca büyük bir dil modelini vektör veritabanına bağlamakla sınırlı değildir. Doğruluk için asıl darboğaz, geri getirme aşamasında yatar. Geri getirici, LLM'e alakasız bağlam getirirse, modelin zekâsından bağımsız olarak nihai yanıt kusurlu olacaktır. Yüksek hassasiyetli RAG'ye ulaşmak için, basit anahtar kelime veya anlamsal eşleştirmenin ötesine geçmeli, birden fazla geri getirme stratejisinin güçlü yönlerini birleştirip sonuçları yeniden sıralama ile rafine etmeliyiz.
Tek Stratejili Geri Getirmenin Sınırlılıkları
Çoğu ilk RAG uygulaması, ya seyrek geri getirmeye (BM25 gibi) ya da yoğun geri getirmeye (Sentence-BERT gibi gömlemeler kullanarak) dayanır. Her birinin belirgin kör noktaları vardır.
- Seyrek Geri Getirme (BM25): Kesin anahtar kelime eşleştirmesinde ve belirli varlık adlarını, kodları veya teknik terimleri anlamada üstündür. Ancak, anlamsal benzerliği veya yeniden ifade etmeyi yakalamakta başarısız olur.
- Yoğun Geri Getirme (Gömlemeler): Anlamsal anlamı ve bağlamı iyi yakalar; aynı kavramı tartışan ancak farklı kelimeler kullanan belgeleri bulmasını sağlar. Ancak, benzersiz tanımlayıcılarla, belirli ürün SKU'ları veya nadir teknik jargonla başa çıkmakta genellikle zorlanır.
Yalnızca birini kullanarak, belirli terimlerdeki hassasiyeti veya anlamsal varyasyonlardaki hatırlamayı feda edersiniz. Hibrit arama, bu zayıflıkları azaltmak için her iki sinyali birleştirir.
Haystack'ta Hibrit Geri Getirici Oluşturma
Haystack çerçevesi, geri getiricileri birleştirmek için zarif bir soyutlama sunar. Bir BM25Retriever ve bir EmbeddingRetriever'ı paralel olarak orkestre edebilir ve ardından sonuçlarını birleştirebilirsiniz.
from haystack import Pipeline
from haystack.components.retrievers.in_memory import BM25Retriever, EmbeddingRetriever
from haystack.components.routers import SwitchRouter
from haystack.components.joiners import DocumentJoiner
from haystack.components.builders import DocumentJoiner
# Geri Getirici Bileşenlerini Başlat
# Not: Gerçek bir hatta, bunları InMemoryDocumentStore'unuza bağlayacaksınız
bm25_retriever = BM25Retriever(document_store, top_k=20)
embedding_retriever = EmbeddingRetriever(document_store, top_k=20)
# Birleştiriciyi Başlat
# Bu bileşen, her iki geri getiriciden gelen belgeleri birleştirir
# score_type, puanların nasıl birleştirileceğini belirler (örn., 'distributional', 'arithmetic')
doc_joiner = DocumentJoiner(
join_mode="concatenate",
duplicate_documents="skip",
score_normalization="min_max",
score_threshold=0.3
)
# Hibrit Arama Hattını Oluştur
pipeline = Pipeline()
pipeline.add_component("bm25", bm25_retriever)
pipeline.add_component("embedding", embedding_retriever)
pipeline.add_component("joiner", doc_joiner)
# Bileşenleri Bağla
# Her iki geri getirici paralel çalışır ve çıktıları birleştiriciye iletilir
pipeline.connect("bm25", "joiner")
pipeline.connect("embedding", "joiner")
Bu yapılandırmada, hat her iki indeksi aynı anda sorgular. DocumentJoiner ardından belge listelerini birleştirir. Önemli olan, BM25 puanlarının (sınırsız ve sorguya bağımlı) ve Kosinüs Benzerlik puanlarının (-1 ile 1 arasında sınırlı) doğrudan karşılaştırılamaması nedeniyle puanları normalize etmenizdir. score_normalization="min_max" kullanarak her iki puan setini ortak bir aralığa ölçeklersiniz, bu da birleştirme sürecinde adil bir rekabet sağlar.
Yeniden Sıralamanın Kritik Rolü
Hibrit arama hatırlamayı iyileştirse de, geri getirilen en üst 20 veya 30 belge hâlâ bir "sonuçlar torbası"dır. Bazıları yalnızca marjinal düzeyde alakalı olabilir. Tüm bunları LLM'e beslemek, bağlam penceresi alanını israf eder ve gürültüye neden olabilir. İşte yeniden sıralama burada devreye girer.
Yeniden sıralayıcılar, Cross-Encoder (Çapraz Kodlayıcı) modellerini kullanır. Vektör geri getirmede kullanılan Bi-Encoder'lardan (sorguyu ve belgeyi bağımsız olarak kodlayan) farklı olarak, Cross-Encoder'lar sorguyu ve belgeyi tek bir dikkat başlığında birlikte işler. Bu, modelin derin, sembol düzeyinde etkileşim gerçekleştirmesine ve çok daha doğru bir alaka puanı sağlamasına olanak tanır.
Yeniden Sıralayıcıyı Hata Entegre Etme
Geri getirme aşamasının sonuna bir SentenceTransformersReRanker veya özel bir API tabanlı yeniden sıralayıcı (Cohere veya Jina gibi) ekleriz. Yeniden sıralayıcı, hibrit aramadan gelen birleşik en üst-N belgeleri alır ve yeniden sıralar, üretici için yalnızca en alakalı en üst-K tanesini seçer.
from haystack.components.rerankers import TransformersSimilarityRanker
# Yeniden Sıralayıcıyı Başlat
# En iyi performans için güçlü bir çapraz kodlayıcı modeli kullanın
re_ranker = TransformersSimilarityRanker(
model="cross-encoder/ms-marco-MiniLM-L-6-v2",
top_k=5,
batch_size=16
)
# Hattı Güncelle
pipeline.add_component("re_ranker", re_ranker)
# Birleştiriciyi yeniden sıralayıcıya bağla
pipeline.connect("joiner", "re_ranker")
Yeniden sıralayıcıda top_k=5 ayarlayarak, LLM'e aktarılan bağlamı dramatik bir şekilde azaltırız. Potansiyel olarak gürültülü 40 belge göndermek yerine, çapraz kodlayıcının yüksek derecede alakalı olarak doğruladığı yalnızca 5 belgeyi göndeririz. Bu genellikle, daha küçük istem boyutları nedeniyle gecikmede azalma ve yanıt hassasiyetinde ölçülebilir bir iyileşme ile sonuçlanır.
Pratik Düşünceler ve Optimizasyon
Bu mimariyi uygulamak, birkaç faktörü dengelemeyi gerektirir:
- Bölme Stratejisi: Belgelerinizin indekslenmeden önce uygun şekilde bölündüğünden emin olun. Bloklar çok büyükse, yeniden sıralayıcı belirli alakalı cümleyi bulmakta zorlanabilir. Çok küçükse, bağlamı kaybedersiniz. %10-20 örtüşme ile 200-500 sembol aralığı iyi bir başlangıç noktasıdır.
- Puan Eşikleri: Zayıf eşleşmeleri elemek için yeniden sıralayıcının çıktısını kullanın. Yeniden sıralamadan sonraki en üst puan belirli bir eşiğin altındaysa (örn., normalize puanlar için 0.4), sistemin zayıf kanıtlara dayalı bir yanıt uydurmak yerine "bilmiyorum" demesi genellikle daha iyidir.
- Model Seçimi: Üretim ortamları için, özellikle yüksek verimli sistemlerde, çapraz kodlamanın hesaplama maliyetini yerel altyapınızdan almak için barındırılan yeniden sıralayıcı API'lerini (Cohere Rerank veya Jina AI Reranker gibi) kullanmayı düşünün.
Sonuç
Yüksek hassasiyetli RAG sihirli bir hile değildir; sağlam bir geri getirme hattı mühendisliğinin sonucudur. Haystack'in bileşen tabanlı mimarisinden yararlanarak, hem anlamsal hem de sözlü sinyalleri yakalamak için hibrit aramayı sorunsuz bir şekilde entegre edebilir, ardından yalnızca en ilgili bağlamın LLM'e ulaşmasını sağlamak için bir çapraz kodlayıcı yeniden sıralayıcı ekleyebilirsiniz. Bu çok aşamalı yaklaşım, halüsinasyonları önemli ölçüde azaltır ve yapay zekâ uygulamalarınızın fiili doğruluğunu artırarak temel bir sohbet robotunu güvenilir, kurumsal düzeyde bir bilgi asistanına dönüştürür.