Retrieval-Augmented Generation (RAG)

Kendini İyileştiren RAG: Karmaşık Çok Kademeli Sorgular İçin İteratif Döngüler

Geleneksel Geri Getirme Destekli Üretim (RAG) sistemleri genellikle çok kademeli sorgularla başa çıkmakta zorlanır. Bu tür sorular, birden fazla farklı kaynaktan veya akıl yürütme adımından bilgi sentezlemeyi gerektirir. Örneğin, "Python'ın yazarının kurduğu şirketin piyasaya sürdüğü ilk ürün neydi?" sorusu, önce yazarı (Guido van Rossum) belirlemeyi, ardından kurduğu şirketi bulmayı (Cwi'de çalışsa da, soru daha sonra katıldığı veya ayrıldığı belirli bir girişim şirketine atıfta bulunuyor olabilir) ve son olarak ürün lansman verilerini geri getirmeyi gerektirir. Tek bir geri getirme adımı, bu boşlukları kapatmak için gereken tam bağlamı nadiren sağlar.

Kendini İyileştiren RAG, Dil Modelinin (LLM) yalnızca bir üretici olarak değil, aynı zamanda bir planlayıcı ve eleştirmen olarak hareket ettiği iteratif bir döngü tanıtarak bu sınırlamayı ele alır. Geri getirilen bağlamın sorguyu yanıtlamak için yeterli olup olmadığını değerlendirir. Değilse, mevcut kısmi anlama dayalı olarak yeni, daha hedefli arama sorguları üretir, yeni belgeler geri getirir ve kendinden emin bir yanıt üretebilene veya maksimum iterasyon sınırına ulaşıncaya kadar süreci tekrarlar.

İteratif Döngünün Mimarisi

Kendini iyileştiren bir RAG sisteminin temel mantığı, her iterasyon içindeki üç aşama etrafında döner:

  1. Sorgu Ayrıştırma ve Değerlendirme: LLM, orijinal soruyu ve mevcut bağlamı (geri getirilen parçaları) alır. Bağlamın, soruyu kesin olarak yanıtlamak için yeterli bilgiyi içerip içermediğini belirler.
  2. Yeni Sorgu Üretimi: Bağlam yetersizse, LLM eksik bilgi parçasını belirler ve onu geri getirmek için spesifik bir arama sorgusu oluşturur.
  3. Geri Getirme ve Biriktirme: Yeni sorgu vektör veritabanına gönderilir. Sonuçlar mevcut bağlama eklenir ve döngü tekrarlanır.

Python'da Uygulama

Aşağıda, akışı göstermek için LangChain kavramlarını kullanan basitleştirilmiş bir uygulama bulunmaktadır. Bu örneğin, `vectorstore` ve `llm`'nin başlatıldığı varsayılır.


from langchain.llms import LLM
from langchain.vectorstores import VectorStore
from langchain.chains import RetrievalQA

class SelfRefiningRAG:
    def __init__(self, llm: LLM, vectorstore: VectorStore, max_iterations: int = 3):
        self.llm = llm
        self.vectorstore = vectorstore
        self.max_iterations = max_iterations

    def retrieve(self, query: str) -> list:
        # Standart vektör benzerlik araması
        return self.vectorstore.similarity_search(query, k=3)

    def is_sufficient(self, question: str, context: list) -> bool:
        prompt = f"""
        Soru: {question}
        Bağlam: {context}
        
        Bağlam, soruyu yanıtlamak için yeterli bilgiyi içeriyor mu?
        Yalnızca "Evet" veya "Hayır" ile yanıtla.
        """
        response = self.llm(prompt)
        return response.strip().lower() == "evet"

    def generate_next_query(self, question: str, context: list) -> str:
        prompt = f"""
        Orijinal Soru: {question}
        Mevcut Bağlam: {context}
        
        Mevcut bağlam, soruyu yanıtlamak için yeterli değil.
        Eksik bilgiyi belirleyin ve o eksik bilgiyi geri getirmek için
        tek bir arama sorgusu oluşturun.
        Yalnızca arama sorgusunu çıktı olarak verin.
        """
        return self.llm(prompt).strip()

    def run(self, question: str) -> str:
        context_docs = []
        
        for i in range(self.max_iterations):
            # 1. Geri Getirme
            if not context_docs:
                # İlk iterasyon orijinal soruyu kullanır
                context_docs = self.retrieve(question)
            else:
                # Sonraki iterasyonlar iyileştirilmiş bir sorgu kullanır
                new_query = self.generate_next_query(question, context_docs)
                new_docs = self.retrieve(new_query)
                context_docs.extend(new_docs)
            
            # 2. Değerlendirme
            if self.is_sufficient(question, [d.page_content for d in context_docs]):
                break

        # 3. Nihai Üretim
        final_context = "\n\n".join([d.page_content for d in context_docs])
        final_prompt = f"""
        Bağlam: {final_context}
        Soru: {question}
        Yanıt:
        """
        return self.llm(final_prompt)

Etkinlik ve Kalite İçin Optimizasyon

Yukarıdaki mantık işlevsel olsa da, üretim sistemleri sonsuz döngüleri önlemek ve gecikmeyi azaltmak için optimizasyonlar gerektirir.

1. Bağlamın Çıkarılması (Deduplication)

İteratif geri getirme, aynı belgeleri çoğu zaman birden fazla kez çeker. Yeni sonuçları context_docs'a eklemeden önce bir çıkarım adımı uygulayın (örneğin, belge kimliği hash'i veya içerik benzerliği kullanarak). Bu, prompt'un gereksiz yere şişmesini önler.

2. Erken Durdurma Kriterleri

is_sufficient kontrolü pahalıdır (bir LLM çağrısı gerektirir). Bunu, önce daha ucuz bir sezgisel yöntem kullanarak (örneğin, anahtar kelime örtüşmesi) veya LLM değerlendirmesini yalnızca geri getirilen belgelerin belirli bir ilgili eşik değerinin altında puan alması durumunda sınırlayarak optimize edebilirsiniz.

3. Sorgular için Yapılandırılmış Çıktı

Serbest metinli sonraki sorgular yerine, LLM'in net ve spesifik bir arama terimi sağlamasını sağlamak için yapılandırılmış çıktı (JSON) kullanın. Bu, sonraki iterasyonlarda vektör aramasının hassasiyetini artırır.

Pratik Örnek: Çok Kademeli Akıl Yürütme

Şu sorguyu düşünün: "React'in yazarının kurduğu teknoloji girişimini satın alan şirketin CEO'su kimdi?"

  1. İterasyon 1:
    • Geri Getirme: "React'in yazarı" için arama -> "Jordan Walke" bulunur.
    • Değerlendirme: Hayır, girişim şirketini veya CEO'yu bilmiyoruz.
    • Yeni Sorgu: "Jordan Walke hangi girişim şirketini kurdu?"
  2. İterasyon 2:
    • Geri Getirme: "Jordan Walke 8080 Labs'i kurdu" bulunur.
    • Değerlendirme: Hayır, onu kimin satın aldığını veya mevcut CEO'nun kim olduğunu bilmiyoruz.
    • Yeni Sorgu: "8080 Labs'i kim satın aldı ve CEO'ları kim?"
  3. İterasyon 3:
    • Geri Getirme: 8080 Labs'in Facebook (Meta) tarafından satın alındığı bulunur. Meta'nın CEO'su (Mark Zuckerberg) geri getirilir.
    • Değerlendirme: Evet, yeterli bilgi mevcut.
    • Nihai Yanıt: "Mark Zuckerberg, 8080 Labs'i satın alan Meta'nın CEO'sudur."

Sonuç

Kendini iyileştiren RAG, statik geri getirmeyi dinamik, ajan tabanlı bir sürece dönüştürür. LLM'in anlayışını iteratif olarak iyileştirmesine ve belirli eksik bilgi parçalarını talep etmesine izin vererek, karmaşık çok kademeli sorgularda doğruluğu önemli ölçüde artırabilirsiniz. Ancak, birden fazla LLM ve geri getirme çağrısı nedeniyle artan gecikme ve API maliyetleri pahasına gelir. Bu deseni dikkatli bir şekilde kullanın ve akıl yürütmenin derinliğinin ek yükü haklı çıkardığı yüksek değerli sorgular için ayırın. Daha basit görevler için, tek geçişli RAG en verimli seçim olmaya devam etmektedir.

Share: