RAG Nedir? Retrieval-Augmented Generation Rehberi

## RAG Nedir, Ne Zaman Gerekir? Retrieval-Augmented Generation (RAG), bir dil modelinin yanıt üretmeden önce harici bir bilgi kaynağından ilgili içer...

RAG Nedir? Retrieval-Augmented Generation Rehberi

RAG Nedir, Ne Zaman Gerekir?

Retrieval-Augmented Generation (RAG), bir dil modelinin yanıt üretmeden önce harici bir bilgi kaynağından ilgili içeriği getirip modele bağlam olarak sunma yaklaşımıdır. Model ağırlıklarına yeni bilgi gömmezsiniz; her sorguda ilgili parçaları getirip istem (prompt) içine yerleştirirsiniz.

RAG şu durumlarda anlamlıdır:

  • Modelin eğitim verisinde bulunmayan veya güncel olmayan bilgiye ihtiyaç varsa (iç dokümanlar, ürün kataloğu, sık değişen veriler).
  • Yanıtın belirli bir kaynağa dayandırılması ve kaynağın gösterilmesi gerekiyorsa.
  • Modeli yeniden eğitmek ya da ince ayar yapmak maliyetli veya gereksizse.

RAG, modelin halüsinasyon üretmesini tamamen engellemez; yalnızca modele doğru bağlamı sağlar. Bağlamın doğru kullanılması yine modelin davranışına bağlıdır.

Önkoşullar ve Kapsam

Bu rehber dil- ve sağlayıcı-bağımsız kavramları anlatır. Kod örnekleri Python içindir; benzer mantık diğer dillerde de geçerlidir. Örneklerde belirli bir SDK sürümü, model adı veya fiyat bilgisi verilmez; çünkü bunlar hızla değişir. Kullandığınız sağlayıcının güncel dokümantasyonundan kendi sürüm ve model bilgilerinizi alın.

Beklenen ön bilgi:

  • HTTP istekleri ve JSON ile çalışma.
  • Temel vektör matematiği (kosünüs benzerliği kavramı).
  • Bir vektör veritabanı veya arama motoru kullanımı.

RAG Hattının Bileşenleri

Tipik bir RAG hattı iki aşamaya ayrılır.

İndeksleme (çevrimdışı):

  1. Kaynak dokümanları topla.
  2. Dokümanları parçalara (chunk) böl.
  3. Her parçayı gömme (embedding) modeliyle vektöre çevir.
  4. Vektörleri meta veriyle birlikte vektör deposuna yaz.

Sorgulama (çevrimiçi):

  1. Kullanıcı sorgusunu aynı gömme modeliyle vektöre çevir.
  2. Vektör deposunda en benzer parçaları ara.
  3. Getirilen parçaları istem içine yerleştir.
  4. Modelden yanıt üret.

Kritik nokta: indeksleme ve sorgulama aşamalarında aynı gömme modelini kullanmalısınız. Farklı modellerin vektörleri aynı uzayda karşılaştırılamaz.

Adım 1: Dokümanları Parçalara Bölme

Parçalama stratejisi RAG kalitesini doğrudan etkiler. Çok küçük parçalar bağlamı koparır; çok büyük parçalar gereksiz içerik taşır ve bağlam penceresini doldurur.

Basit bir yaklaşım, karakter veya token sayısına göre örtüşmeli (overlapping) parçalama yapmaktır:

def chunk_text(text, chunk_size=800, overlap=100):
    if overlap >= chunk_size:
        raise ValueError("overlap, chunk_size'dan küçük olmalı")
    chunks = []
    start = 0
    while start < len(text):
        end = start + chunk_size
        chunks.append(text[start:end])
        start += chunk_size - overlap
    return chunks

Bu fonksiyon metni sabit uzunlukta parçalara böler ve her parçanın son overlap karakterini bir sonraki parçanın başına taşır. Örtüşme, cümle veya fikrin parça sınırında bölünmesinin etkisini azaltır. Beklenen davranış: girdi metni boşsa boş liste döner; overlap değeri chunk_size'a eşit veya büyükse hata yükseltir (aksi halde döngü ilerlemez).

Yapısal dokümanlarda (Markdown, HTML, kod) başlık veya fonksiyon sınırlarına göre bölmek genelde daha iyi sonuç verir. Parça boyutunu ve örtüşmeyi sabit bir kural olarak değil, kendi verinizle ölçerek belirleyin.

Adım 2: Gömme Üretme ve Saklama

Her parçayı bir gömme modeliyle vektöre çevirip vektör deposuna yazarsınız. Aşağıdaki örnek, sağlayıcıdan bağımsız bir arayüz varsayar:

def build_index(chunks, embed_fn, store):
    for i, chunk in enumerate(chunks):
        vector = embed_fn(chunk)
        store.add(
            id=f"chunk-{i}",
            vector=vector,
            metadata={"text": chunk, "source": "docs"}
        )

embed_fn tek bir metni vektöre çeviren fonksiyondur. store.add ise vektörü ve meta veriyi kalıcı hale getirir. Meta veride ham metni saklamak, sorgulama sırasında ayrı bir veritabanı sorgusu yapmadan parçayı isteme koymanızı sağlar.

Gerçek üretimde parçaları tek tek değil, toplu (batch) olarak gömmek daha verimlidir. Sağlayıcıların çoğu toplu gömme uç noktası sunar; istek başına parça sayısı ve boyut sınırlarını sağlayıcı dokümantasyonundan kontrol edin.

Adım 3: Benzerlik Araması

Sorgu geldiğinde aynı gömme fonksiyonuyla vektöre çevirip en yakın parçaları getirirsiniz:

def retrieve(query, embed_fn, store, top_k=5):
    query_vector = embed_fn(query)
    results = store.search(query_vector, top_k=top_k)
    return results

top_k, getirilecek parça sayısıdır. Çok düşük tutmak gerekli bilgiyi kaçırmanıza, çok yüksek tutmak bağlamı gereksiz içerikle doldurmanıza yol açar. Getirilen parçaların benzerlik skorlarını loglayarak top_k değerini kendi verinizle ayarlayın.

Saf vektör araması her zaman yeterli olmaz. Anahtar kelimeye dayalı arama (örneğin BM25) ile vektör aramasını birleştiren hibrit arama, özellikle kısaltma, ürün kodu veya özel isim içeren sorgularda daha iyi sonuç verebilir.

Adım 4: Bağlamı İsteme Yerleştirme

Getirilen parçaları modele verilecek istem içine yerleştirirsiniz:

def build_prompt(query, retrieved):
    context = "\n\n---\n\n".join(
        item["metadata"]["text"] for item in retrieved
    )
    return (
        "Aşağıdaki bağlama dayanarak soruyu yanıtla. "
        "Cevap bağlamda yoksa 'Bu bilgi verilen kaynaklarda yok' de.\n\n"
        f"Bağlam:\n{context}\n\n"
        f"Soru: {query}"
    )

İstemde modele iki şeyi açıkça söylemek önemlidir: yalnızca verilen bağlama dayanması ve bağlamda olmayan bir bilgiyi uydurmaması. Bu, halüsinasyonu azaltır ama garanti etmez.

Yaygın Hatalar

  • Farklı gömme modelleri kullanmak: İndeksleme ve sorgulamada aynı modeli kullanmamak, anlamsız benzerlik skorları üretir.
  • Parçaları bağlamsız bırakmak: Her parçaya kaynak başlığı veya bölüm bilgisi eklemek, modelin parçayı doğru yorumlamasına yardımcı olur.
  • top_k değerini sabit varsaymak: Doğru değer veri kümesine ve sorgu tipine göre değişir; ölçmeden karar vermeyin.
  • Bağlam penceresini taşırmak: Getirilen tüm parçaları sınırsız eklemek, modelin bağlam sınırını aşmasına ve önemli bilginin kaybolmasına yol açar.
  • Güncelleme stratejisini atlamak: Kaynak doküman değiştiğinde indeksi yeniden oluşturmazsanız model eski bilgiyi döndürmeye devam eder.

Güvenlik Etkileri

  • İstem enjeksiyonu: Getirilen içerik kötü niyetli metin içerebilir; örneğin "önceki talimatları yok say" gibi ifadeler. Getirilen parçaları güvenilmeyen veri olarak ele alın ve modele bunların talimat değil, yalnızca kaynak olduğunu belirtin.
  • Yetki sızıntısı: Vektör deposunda erişim kontrolü yoksa, bir kullanıcı yetkisi olmayan dokümanların parçalarını sorgu sonucunda görebilir. Getirme katmanında kullanıcı bazlı filtreleme uygulayın.
  • Hassas veri: Gömme vektörleri ve meta veriler, orijinal metni geri çağırmaya yetecek bilgi taşıyabilir. Depolamayı ve erişimi buna göre koruyun.
  • Kaynak gösterimi: Yanıtla birlikte hangi parçaların kullanıldığını göstermek, hem denetlenebilirliği artırır hem de kullanıcıya yanıtın dayanağını görme imkânı verir.

Değerlendirme

RAG hattını değiştirdiğinizde kaliteyi ölçmeniz gerekir. Basit bir yaklaşım, soru–beklenen yanıt çiftlerinden oluşan küçük bir test seti tutmak ve her değişiklikte getirme kalitesini (doğru parça getiriliyor mu?) ve yanıt kalitesini (yanıt doğru mu?) ayrı ayrı izlemektir. Getirme ve üretim hatalarını ayrı ölçmek, sorunun hangi aşamada olduğunu görmenizi sağlar.

Kapanış

RAG, modeli yeniden eğitmeden güncel ve kaynağa dayalı yanıt üretmenin pratik bir yoludur. Kalite büyük ölçüde parçalama, gömme modeli seçimi, getirme stratejisi ve istem tasarımına bağlıdır. Bu bileşenleri kendi verinizle ölçüp ayarlamak, hazır bir yapılandırmayı kopyalamaktan daha güvenilir sonuç verir.

İLGİLİ İÇERİKLER

Bunları da Okumak İsteyebilirsiniz