Modül 6 · RAG and Agentic Search · ⏱ 5 dakika

RAG akışını uygulamak

Implementing the RAG flow

Orijinal İngilizce video — Anthropic Academy / JWPlayer. Aşağıdaki Türkçe metin dersi birebir özetler.

Bu modül için tahmini süre: 5 dakika

Genel bakış

RAG akışını kavramsal olarak öğrendiğimize göre, bu derste implementasyonunu adım adım yapıyoruz. Belgeyi chunk’lara böleceğiz, embedding üreteceğiz, bunları bir vector store’a kaydedeceğiz, kullanıcı sorgusunu embed edip similarity search ile en alakalı chunk’ları bulacağız.

RAG akışını kavramsal olarak anladığımıza göre, şimdi adım adım implementasyonunu yapalım. Text’i chunk’lamayı, embedding üretmeyi, vector database’de saklamayı ve similarity search yapmayı gösteren komple bir örneği inceleyeceğiz.

Beş adımlı RAG implementasyonu

Implementasyonumuz daha önce tartıştığımız aynı beş adımı izler:

  1. Text’i section’a göre chunk’la
  2. Her chunk için embedding üret
  3. Bir vector store oluştur ve her embedding’i ekle
  4. Kullanıcının sorusu için embedding üret
  5. En alakalı chunk’ları bulmak için store’da ara

Bu diyagram, kullanıcı sorgularını embedding’lere dönüştürdüğümüzü ve en alakalı içeriği bulmak için vector database’imizde nasıl arama yaptığımızı gösterir.

Adım 1: Text’i chunk’lamak

Önce belgemizi yükler ve yönetilebilir section’lara böleriz:

with open("./report.md", "r") as f:
    text = f.read()

chunks = chunk_by_section(text)
chunks[2]  # Test to see the table of contents

Belgemizi mantıksal bölümlere ayırmak için daha önceki aynı chunk_by_section function’ını kullanırız.

Adım 2: Embedding üretmek

Sonra, tüm chunk’larımız için bir kerede embedding oluştururuz:

embeddings = generate_embedding(chunks)

Embedding function’ı hem tek string hem de string listesini ele alacak şekilde güncellendi; bu, batch processing için daha verimli hale getiriyor.

Adım 3: Vector database’de saklamak

Şimdi vector store’umuzu oluştururuz ve onu embedding’ler ve ilişkili text’leriyle doldururuz:

store = VectorIndex()

for embedding, chunk in zip(embeddings, chunks):
    store.add_vector(embedding, {"content": chunk})

Hem embedding’i hem de orijinal text content’i sakladığımıza dikkat et. Bu kritiktir, çünkü daha sonra search yaptığımızda yalnızca sayısal embedding değerlerini değil, gerçek text’i döndürmemiz gerekir.

Orijinal text’i neden saklarız?

Vector database’imizi sorguladığımızda, yalnızca embedding sayılarını geri almak işe yaramaz. Bu embedding’leri üretmek için kullanılan gerçek text’e ihtiyacımız var. Bu yüzden database’imizde her embedding’in yanında orijinal chunk text’ini (veya en azından ona bir referansı) saklarız.

Adım 4: Kullanıcı sorgularını işlemek

Bir kullanıcı soru sorduğunda, sorgusu için bir embedding üretiriz:

user_embedding = generate_embedding("What did the software engineering dept do last year?")

Adım 5: Alakalı içeriği bulmak

Son olarak, en benzer chunk’ları bulmak için vector store’umuzu ararız:

results = store.search(user_embedding, 2)

for doc, distance in results:
    print(distance, "\n", doc["content"][0:200], "\n")

Bu search, en alakalı iki chunk’ı, similarity skorları (cosine distance’ları) ile birlikte döndürür.

Search sonuçları, belgemizin hangi bölümlerinin kullanıcının sorusuyla en alakalı olduğunu similarity skorlarıyla birlikte gösterir.

Sonuçları yorumlamak

Software engineering departmanı hakkındaki örnek sorgumuzu çalıştırdığımızda şunu alırız:

  • Section 2: Software Engineering — 0.71 distance ile (en yakın eşleşme)
  • Methodology section — 0.72 distance ile (ikinci en yakın)

Daha düşük distance değerleri daha yüksek benzerlik anlamına gelir, dolayısıyla Section 2 sorgumuza en alakalı olandır.

Sırada ne var?

Bu implementasyon temel use case’lerde iyi çalışır, ama beklendiği gibi performans göstermeyen senaryolar da vardır. Sonraki bölümlerde RAG sistemimizi daha sağlam ve doğru hale getirecek iyileştirmeleri inceleyeceğiz.

Temel çıkarım şu: RAG’in özü, text’i sayılara (embedding’lere) dönüştürmek, bu sayıları verimli şekilde saklamak ve kullanıcılar soru sorduğunda alakalı içeriği bulmak için matematiksel benzerlik kullanmaktır.

Temel çıkarımlar

  • Beş adımlı akış: chunk, embed, store, embed query, search
  • Embedding üretirken batch işlem yapmak verimlidir
  • Vector store’a hem embedding hem orijinal text yazılır; geri yalnızca embedding dönerse işe yaramaz
  • Search sonucu cosine distance ile sıralanır; küçük değer en alakalı chunk demektir
  • Bu temel implementasyon her durumda yeterli değildir; sonraki bölümler iyileştirmelere odaklanır