Abdulaziz Akyol

Kurumsal RAG: şirket dokümanlarıyla konuşan yapay zekâ asistanı nasıl kurulur

Yapay zekâ · Yazılım geliştirme
25 Eylül 2026 · 8 dk okuma · Abdulaziz Akyol

Erişimle zenginleştirilmiş üretim (retrieval-augmented generation, RAG), bir dil modelinin soruyu yanıtlamadan önce şirketin kendi dokümanlarında arama yapıp bulduğu parçalara dayanarak cevap ürettiği mimaridir. Kurumsal bir RAG asistanı yönetmelik, prosedür, sözleşme ve teknik dokümanlar üzerinden, kaynak göstererek ve kullanıcının yetkisini aşmadan yanıt verir.

Terim, 2020’de Lewis ve arkadaşlarının makalesiyle yaygınlaştı. Benim gözlemimde şirketlerin en sık istediği yapay zekâ uygulaması bu; yarım kalanlar arasında da başı çekiyor. Yarım kalmanın nedeni neredeyse hiçbir zaman model değil; veri hazırlığı, yetki ve ölçüm. Bu yazı o üç konuya ağırlık veriyor.

RAG ile ince ayar (fine-tuning) arasındaki fark nedir?

İnce ayar, modelin ağırlıklarını kendi verinizle yeniden eğitmektir ve modele bir davranış, üslup ya da biçim öğretir. RAG ise modeli değiştirmez; her soruda ilgili bilgiyi bulup bağlama koyar.

ÖlçütRAGİnce ayar
Bilgi güncelliğiDoküman değişince indeks güncellenirYeniden eğitim gerekir
Kaynak göstermeDoğal; yanıtın geldiği parça gösterilirZor; bilgi ağırlıklara dağılır
Erişim yetkisiArama aşamasında belge bazında uygulanırUygulanamaz; model öğrendiğini herkese söyler
Silme talebiParça ve vektör silinirModele “unutturmak” pratikte zor
En iyi olduğu işOlgusal soru-cevap, doküman aramaSabit biçim, üslup, alan jargonu

Benim kuralım: bilgi değişiyorsa RAG, davranış değişecekse ince ayar. İkisi birlikte de kullanılabilir ama ilk proje neredeyse her zaman RAG’dir.

RAG hattı nasıl çalışır?

İki ayrı hat var. İndeksleme hattı arka planda çalışır: dokümanlar kaynaktan çekilir, metne ayrıştırılır, parçalara bölünür, her parça için embedding (anlamsal vektör) hesaplanır ve parça; metni, vektörü ve üst verisiyle saklanır. Sorgu hattı her soruda çalışır: kullanıcının yetkileri belirlenir, yetkili parçalar içinde arama yapılır, sonuçlar yeniden sıralanır ve model bu parçalara dayanarak kaynaklı bir yanıt yazar.

Adım 1: Veri hazırlama (PDF ve Office ayrıştırma)

Projenin en az konuşulan ama en çok emek isteyen kısmı burası. En sık karşılaşılan sorunlar:

  • Taranmış PDF’ler: Metin katmanı yoksa önce OCR gerekir; OCR kalitesi, yanıt kalitesinin üst sınırıdır.
  • Tablolar ve çok sütunlu sayfalar: Düz metne çevrilince satırlar karışır. Tabloyu satır satır, sütun başlıklarıyla birlikte metne dönüştürmek gerekir.
  • Üst ve alt bilgiler: Her sayfada tekrarlanan “Gizlidir – Sayfa 3/40” satırları aramayı kirletir.
  • Word ve PowerPoint yapısı: Başlık hiyerarşisi korunursa parçalama çok daha iyi olur. Belgeyi başlıklarıyla birlikte Markdown benzeri bir ara biçime çevirmek işe yarar.
  • Sürüm karmaşası: Aynı prosedürün üç sürümü paylaşılan klasörde duruyorsa asistan eski sürümden yanıt verir. Yalnızca yürürlükteki sürüm indekslenmeli; bunun için her doküman ailesinin bir sahibi olmalı.

Her parçaya doküman kimliği, başlık, sürüm, yürürlük tarihi, sayfa ya da bölüm, kaynak bağlantısı ve erişim grupları üst veri olarak eklenir. Atıf ve yetki bu alanlarla çalışır.

Adım 2: Parçalama (chunking) stratejileri

Parça çok küçükse bağlam kaybolur; çok büyükse arama isabeti düşer ve model gereksiz metin okur.

StratejiNasıl çalışır?Ne zaman?
Sabit boyut + örtüşmeBelirli uzunlukta böler, kenarları örtüştürürYapısı zayıf metinler, ilk deneme
Başlık/bölüm tabanlıMadde, başlık ve bölüm sınırlarından bölerYönetmelik, prosedür, sözleşme
AnlamsalCümle benzerliğinin düştüğü yerden bölerUzun, başlıksız anlatı metinleri
Ebeveyn–çocukKüçük parçayla arar, üst bölümün tamamını modele verirKısa madde, uzun bağlam gerektiğinde

Kurumsal dokümanlarda başlık tabanlı parçalama çoğu zaman en iyi başlangıçtır. Her parçanın başına başlık yolunu ekleyin (“Seyahat Yönetmeliği > 4. Masraflar > 4.2 Konaklama”); madde metni tek başına çoğu zaman anlamsızdır. Boyut ve örtüşmeyi tahminle değil, aşağıda anlatacağım değerlendirme setiyle belirleyin.

Adım 3: Embedding modeli

Embedding modeli metni, anlamca yakın metinlerin birbirine yakın düştüğü bir vektöre çevirir. Üç nokta önemli: Türkçeyi iyi destekleyen çok dilli bir model seçmek, indekslemede ve sorguda aynı modeli kullanmak, modeli değiştirdiğinizde indeksin tamamını yeniden hesaplamak. Bu yüzden her parçada embedding modelinin adını ve sürümünü de saklayın.

Boyut, depolamayı doğrudan belirler. Örnek hesap: 1 milyon parça × 1.024 boyut × 4 bayt (float32) ≈ 4 GB yalnızca vektör verisi; yarım duyarlıklı saklamada bu yarıya iner.

Adım 4: Vektör veri tabanı seçenekleri

SeçenekGüçlü yanıDikkat edilecek nokta
PostgreSQL + pgvectorMevcut veri tabanı, SQL ile yetki filtresi, işlem desteğiÇok büyük ölçekte ayar ve bölümleme ister
Özel vektör veri tabanlarıVektör aramasına odaklı, yatay ölçeklemeYedekleme, yetki ve izleme yeniden kurulur
Vektör destekli arama motorlarıTam metin ve vektör araması tek yerdeİşletme yükü ve lisans modeli
Bulut yönetilen arama servisleriKurulum yok, hızlı başlangıçVeri yeri, maliyet ve bağımlılık

Çoğu şirkette PostgreSQL zaten işletiliyor; bu yüzden ilk sürüm için pgvector makul bir başlangıç. HNSW ve IVFFlat dizinlerini, kosinüs (<=>), L2 (<->) ve iç çarpım (<#>) mesafelerini destekler; dizinlenen vector sütunu 2.000, halfvec sütunu 4.000 boyuta kadar çıkabilir. Türkçe tam metin araması için PostgreSQL’in turkish yapılandırması kullanılabilir:

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE doc_chunks (
    id             bigserial PRIMARY KEY,
    doc_id         text         NOT NULL,
    doc_version    text         NOT NULL,
    page           int,
    content        text         NOT NULL,
    allowed_groups text[]       NOT NULL,   -- kaynak sistemden eşitlenen erişim grupları
    embedding      vector(1024) NOT NULL,   -- boyut, seçilen modele göre
    tsv            tsvector GENERATED ALWAYS AS (to_tsvector('turkish', content)) STORED
);

CREATE INDEX ON doc_chunks USING hnsw (embedding vector_cosine_ops);
CREATE INDEX ON doc_chunks USING gin (tsv);
CREATE INDEX ON doc_chunks USING gin (allowed_groups);

-- Yaklaşık dizinde filtre taramadan sonra uygulanır; yinelemeli tarama (pgvector 0.8.0+) bunu telafi eder.
SET hnsw.iterative_scan = relaxed_order;

SELECT id, doc_id, page, content
FROM doc_chunks
WHERE allowed_groups && $2::text[]      -- kullanıcının grupları, kimlik sağlayıcıdan
ORDER BY embedding <=> $1::vector       -- sorgu vektörü
LIMIT 20;

Buradaki kritik ayrıntı yorum satırında: yaklaşık (approximate) dizinlerde filtre, dizin tarandıktan sonra uygulanır. Kullanıcının yetkili olduğu parça azsa sorgu beklenenden az sonuç döner. Yinelemeli tarama bunu hafifletir; çok kiracılı yapılarda kiracı başına kısmi dizin ya da bölümleme de bir seçenektir.

Adım 5: Hibrit arama ve yeniden sıralama (reranking)

Vektör araması anlamı yakalar ama “PRS-042” gibi prosedür kodlarını, madde numaralarını ve kısaltmaları kaçırabilir; anahtar kelime araması (BM25 ya da PostgreSQL tam metin araması) tam tersi. İkisini birlikte çalıştırıp sonuçları Reciprocal Rank Fusion (RRF) ile birleştirmek pratikte en sağlam yol. RRF, her belgeye her listedeki sırasına göre 1/(k + sıra) puanı verir ve bu puanları toplar; Cormack ve arkadaşlarının 2009 çalışmasında k = 60 kullanılır. Avantajı, iki aramanın puan ölçeklerini eşitlemek zorunda kalmamaktır.

Yeniden sıralama bir adım daha ekler: birleşik listedeki ilk birkaç düzine aday, soru ile parçayı birlikte okuyan bir çapraz kodlayıcı (cross-encoder) ile yeniden puanlanır ve modele yalnızca en iyi birkaç parça gönderilir. Gecikme ve maliyet ekler; etkisini değerlendirme setinde ölçmeden açmayın.

Çalışır bir Python örneği

Aşağıdaki kod yalnızca standart kütüphaneyle (Python 3.10+) çalışır ve hattın mantığını gösterir: paragraf sınırına saygı duyan parçalama, yetki filtresi, vektör ve BM25 araması, RRF ile birleştirme ve kaynaklı istem üretimi. Embedder bir arayüzdür; örnekteki HashingEmbedder yalnızca deneme içindir ve gerçek projede seçtiğiniz embedding modeliyle değiştirilir. Üretilen istemi istediğiniz dil modeline gönderebilirsiniz; kod hiçbir sağlayıcıya bağlı değildir.

"""Sağlayıcıdan bağımsız, yetki filtreli küçük bir RAG hattı (Python 3.10+, yalnızca standart kütüphane)."""
from __future__ import annotations

import hashlib
import math
import re
from collections import Counter
from dataclasses import dataclass
from typing import Protocol


class Embedder(Protocol):
    def embed(self, texts: list[str]) -> list[list[float]]: ...


def tr_lower(text: str) -> str:
    # str.lower() Türkçe I/İ harflerini yanlış çevirir; önce bu ikisini elle eşleriz.
    return text.replace("I", "ı").replace("İ", "i").lower()


def tokenize(text: str) -> list[str]:
    return re.findall(r"\w+", tr_lower(text))


class HashingEmbedder:
    """Deneme amaçlı yer tutucu. Üretimde çok dilli bir embedding modeliyle değiştirin."""

    def __init__(self, dim: int = 512) -> None:
        self.dim = dim

    def embed(self, texts: list[str]) -> list[list[float]]:
        vectors = []
        for text in texts:
            vec = [0.0] * self.dim
            for tok in tokenize(text):
                for gram in {tok[i:i + 4] for i in range(max(1, len(tok) - 3))}:
                    h = int.from_bytes(hashlib.blake2b(gram.encode(), digest_size=8).digest(), "big")
                    vec[h % self.dim] += 1.0 if (h >> 63) & 1 else -1.0
            norm = math.sqrt(sum(v * v for v in vec)) or 1.0
            vectors.append([v / norm for v in vec])
        return vectors


@dataclass(frozen=True)
class Chunk:
    chunk_id: str
    doc_title: str
    page: int
    text: str
    allowed_groups: frozenset[str]


def split_text(text: str, max_chars: int = 1200, overlap: int = 200) -> list[str]:
    """Paragraf sınırlarına saygı duyan, örtüşmeli basit parçalayıcı."""
    paragraphs = [p.strip() for p in re.split(r"\n\s*\n", text) if p.strip()]
    chunks: list[str] = []
    current = ""
    for para in paragraphs:
        if current and len(current) + len(para) + 2 > max_chars:
            chunks.append(current)
            current = current[-overlap:]  # bağlam kopmasın diye kuyruğu taşı
        current = f"{current}\n\n{para}".strip()
    if current:
        chunks.append(current)
    return chunks


class HybridIndex:
    def __init__(self, embedder: Embedder, rrf_k: int = 60) -> None:
        self.embedder = embedder
        self.rrf_k = rrf_k
        self.chunks: list[Chunk] = []
        self.vectors: list[list[float]] = []
        self.term_freqs: list[Counter[str]] = []
        self.doc_freq: Counter[str] = Counter()

    def add(self, chunks: list[Chunk]) -> None:
        self.vectors += self.embedder.embed([c.text for c in chunks])
        for c in chunks:
            tf = Counter(tokenize(c.text))
            self.term_freqs.append(tf)
            self.doc_freq.update(tf.keys())
            self.chunks.append(c)

    def _bm25(self, query: str, ids: list[int], k1: float = 1.5, b: float = 0.75) -> dict[int, float]:
        n = len(self.chunks)
        avg_len = sum(sum(tf.values()) for tf in self.term_freqs) / max(n, 1)
        scores: dict[int, float] = {}
        for i in ids:
            tf, length, score = self.term_freqs[i], sum(self.term_freqs[i].values()), 0.0
            for term in set(tokenize(query)):
                if term in tf:
                    idf = math.log(1 + (n - self.doc_freq[term] + 0.5) / (self.doc_freq[term] + 0.5))
                    score += idf * tf[term] * (k1 + 1) / (tf[term] + k1 * (1 - b + b * length / avg_len))
            if score > 0:
                scores[i] = score
        return scores

    def search(self, query: str, user_groups: set[str], top_k: int = 4, pool: int = 20) -> list[Chunk]:
        # 1) Yetki filtresi sıralamadan ÖNCE uygulanır: kullanıcının göremeyeceği parça aday bile olmaz.
        ids = [i for i, c in enumerate(self.chunks) if c.allowed_groups & user_groups]
        if not ids:
            return []
        # 2) Anlamsal arama: kosinüs benzerliği (vektörler normalize).
        qv = self.embedder.embed([query])[0]
        dense = sorted(ids, key=lambda i: -sum(a * b for a, b in zip(qv, self.vectors[i])))[:pool]
        # 3) Anahtar kelime araması: BM25.
        bm25 = self._bm25(query, ids)
        sparse = sorted(bm25, key=lambda i: -bm25[i])[:pool]
        # 4) Reciprocal Rank Fusion: iki sıralamayı puan ölçeğine bakmadan birleştirir.
        fused: Counter[int] = Counter()
        for ranking in (dense, sparse):
            for rank, i in enumerate(ranking, start=1):
                fused[i] += 1.0 / (self.rrf_k + rank)
        return [self.chunks[i] for i, _ in fused.most_common(top_k)]


def build_prompt(question: str, hits: list[Chunk]) -> str:
    sources = "\n\n".join(
        f"[{n}] {h.doc_title}, s. {h.page}\n{h.text}" for n, h in enumerate(hits, start=1)
    )
    return (
        "Yalnızca aşağıdaki kaynaklara dayanarak yanıt ver. Her cümlenin sonunda kaynağı [n] "
        "biçiminde göster. Kaynaklarda yanıt yoksa 'Bu bilgi dokümanlarda yok.' de.\n\n"
        f"KAYNAKLAR:\n{sources}\n\nSORU: {question}"
    )


if __name__ == "__main__":
    index = HybridIndex(HashingEmbedder())
    docs = [
        ("Seyahat Yönetmeliği", 3, "Yurt içi görevlerde konaklama gideri için üst sınır, "
         "unvan grubuna göre belirlenir.\n\nFaturalar görev dönüşünden sonra 10 iş günü içinde "
         "masraf sistemine yüklenir.", {"tum-calisanlar"}),
        ("Bordro Prosedürü", 7, "Bordro düzeltmeleri yalnızca İnsan Kaynakları bordro ekibi "
         "tarafından yapılır.", {"ik-bordro"}),
        ("BT Güvenlik Politikası", 2, "VPN erişimi için çok faktörlü doğrulama zorunludur.",
         {"tum-calisanlar"}),
    ]
    for n, (title, page, text, groups) in enumerate(docs):
        index.add([
            Chunk(f"{n}-{k}", title, page, part, frozenset(groups))
            for k, part in enumerate(split_text(text))
        ])

    question = "Masraf faturalarını kaç gün içinde yüklemem gerekiyor?"
    hits = index.search(question, user_groups={"tum-calisanlar"})
    for h in hits:
        print(h.chunk_id, h.doc_title, "s.", h.page)
    print(build_prompt(question, hits))  # Bu metni seçtiğiniz dil modeline gönderin.

İki ayrıntıya dikkat edin. Python’un str.lower() fonksiyonu “I” harfini “i”ye çevirir; Türkçede doğrusu “ı”dır. Küçük görünen bu hata “IĞDIR” ile “ığdır” eşleşmesini bozar; tr_lower bu yüzden var. İkincisi, yetki filtresi aramadan önce uygulanıyor: bordro dokümanı, bordro grubunda olmayan kullanıcı için aday listesine hiç girmiyor. Örnekteki doküman metinleri gerçek bir şirkete ait değil, yer tutucudur.

Atıf ve kaynak gösterme

Kurumsal asistanda kaynaksız yanıt, doğru olsa bile güven üretmez. Üç kural öneriyorum:

  1. İstem, modelden her cümleyi numaralı kaynakla bitirmesini, kaynakta olmayanı açıkça söylemesini ister.
  2. Arayüz her numarayı doküman adı, sürüm, sayfa ve bağlantıyla gösterir; kullanıcı tek tıkla asıl belgeyi açar.
  3. Yanıt üretildikten sonra kodla kontrol edilir: modelin gösterdiği numaralar gerçekten getirilen parçalar arasında mı? Var olmayan kaynağa atıf yapan yanıt kullanıcıya gösterilmez.

“Bu bilgi dokümanlarda yok” yanıtı bir hata değil, özelliktir; uydurmak yerine bunu söyleyen asistan güveni daha hızlı kazanır.

Erişim yetkisi: belge seviyesinde ACL

Kurumsal RAG’in en kritik tasarım kararı: yetki modelde değil, arama katmanında uygulanır. “Kullanıcı yetkili değilse bu bilgiyi söyleme” talimatı bir güvenlik kontrolü değildir; modelin bağlamına giren her metin yanıtta görünebilir.

  • Erişim listeleri (ACL) kaynak sistemden indeksleme sırasında alınır ve düzenli aralıklarla yeniden eşitlenir.
  • Kullanıcının grupları her sorguda kimlik sağlayıcıdan gelir; istemciden gelen bir alana güvenilmez.
  • Kaynakta silinen ya da yetkisi değişen dokümanın indeksteki tüm parçaları da güncellenir.
  • Yanıt önbelleği varsa önbellek anahtarı kullanıcının yetki kümesini de içerir; aksi hâlde bir kullanıcının yanıtı başkasına gösterilebilir.

Aynı ilke araç çağıran ajanlar için de geçerli; ayrıntısı yapay zekâ ajanları ve MCP yazısında.

Değerlendirme: doğruluk ve sadakat nasıl ölçülür?

Ölçmeden yapılan her ayar tahmindir. Gerçek kullanıcı sorularından, doğru yanıtlardan ve doğru kaynaklardan oluşan bir “altın set” hazırlayın; soruları doküman sahipleriyle birlikte yazın. Sonra katmanları ayrı ölçün:

KatmanMetrikSorduğu soru
AramaRecall@k, MRRDoğru parça ilk k sonuç içinde mi, kaçıncı sırada?
ÜretimSadakat (faithfulness)Yanıttaki her iddia getirilen parçalarla destekleniyor mu?
ÜretimYanıt uygunluğuYanıt soruyu gerçekten karşılıyor mu?
Uçtan ucaDoğrulukYanıt altın setteki doğru yanıtla uyuşuyor mu?

Sadakat ve yanıt uygunluğunu otomatik ölçmek için Ragas çalışmasındaki gibi dil modelini değerlendirici olarak kullanan yöntemler var; değerlendirici modelin kararlarını belirli aralıklarla insan incelemesiyle örnekleyin. Parça boyutu, embedding modeli ya da istem her değiştiğinde set yeniden çalıştırılmalı.

KVKK ve veri güvenliği

Şirket dokümanları kişisel veri içerir: İK dosyaları, müşteri yazışmaları, sözleşmeler. Başlamadan önce:

  • Kapsamı daraltın: İndekslenecek klasörleri açıkça belirleyin; İK ve hukuk gibi hassas alanları ilk sürümde dışarıda bırakın.
  • Veri yerini belirleyin: Embedding ya da dil modeli yurt dışında çalışıyorsa bu, 6698 sayılı Kanun’un 9. maddesi kapsamında yurt dışına aktarımdır. 7499 sayılı Kanun’la yapılan ve 1 Haziran 2024’te yürürlüğe giren değişiklikle yeterlilik kararı ve standart sözleşme gibi uygun güvenceler öne çıktı; standart sözleşme beş iş günü içinde Kurum’a bildirilmeli (KVKK duyurusu).
  • Vektörleri de koruyun: Vektörler metinden türetilir; temkinli yaklaşım, onları kaynak metinle aynı koruma düzeyinde tutmaktır.
  • Silmeyi uçtan uca tasarlayın: Silme talebinde parça, vektör, önbellek ve kayıtlar birlikte silinmeli.
  • Soru kayıtlarını yönetin: Kullanıcı soruları da kişisel veri içerebilir; saklama süresi belirlenmeli.

Kişisel Verileri Koruma Kurumu’nun 24 Kasım 2025’te yayımladığı Üretken Yapay Zekâ ve Kişisel Verilerin Korunması Rehberi bu değerlendirme için iyi bir başlangıç. Sistem AB’deki kullanıcılara da sunulacaksa AB Yapay Zekâ Yasası rehberine bakın.

Kontrol listesi

  • Sorular olgusal ve bilgi değişken mi? O hâlde RAG.
  • Yalnızca yürürlükteki sürümler indeksleniyor; her doküman ailesinin bir sahibi var.
  • Parçalar başlık yoluyla saklanıyor; kaynak, sayfa, sürüm ve yetki grupları üst veride.
  • Hibrit arama (BM25 + vektör, RRF) açık; yeniden sıralama ölçülerek eklendi.
  • Yetki filtresi aramadan önce uygulanıyor; erişim listeleri düzenli eşitleniyor.
  • Her yanıt kaynak numarası taşıyor; atıflar kodla doğrulanıyor.
  • Altın set var; her değişiklikte arama ve üretim metrikleri yeniden ölçülüyor.
  • Veri yeri, yurt dışına aktarım ve silme süreci KVKK açısından değerlendirildi.

İlk üretim projesinin kapsamı ve 90 günlük planı için CIO’lar için yapay zekâ yol haritası yazısına bakabilirsiniz.

Sık sorulan sorular

RAG nedir?

RAG (retrieval-augmented generation, erişimle zenginleştirilmiş üretim), dil modelinin soruyu yanıtlamadan önce bir doküman koleksiyonunda arama yapıp bulduğu metin parçalarını bağlam olarak kullandığı mimaridir. Böylece model eğitim verisinde olmayan şirket bilgisiyle, kaynak göstererek yanıt verebilir.

RAG mı ince ayar (fine-tuning) mı?

Bilgi değişiyorsa ve kaynak göstermek gerekiyorsa RAG; modelin belirli bir biçimde, üslupta ya da alan jargonuyla yanıt vermesi isteniyorsa ince ayar. Doküman soru-cevabı için ilk proje neredeyse her zaman RAG'dir; belge bazında yetki ve silme talepleri de RAG'de çok daha kolay uygulanır.

Kurumsal RAG için hangi vektör veri tabanı seçilmeli?

Şirket zaten PostgreSQL işletiyorsa pgvector eklentisi iyi bir başlangıçtır: vektör ve tam metin aramasını, yetki filtresini ve işlem desteğini tek veri tabanında toplar. Çok büyük ölçek ya da yoğun eşzamanlı sorgu varsa özel vektör veri tabanları ve arama motorları değerlendirilebilir.

RAG yanıtlarının doğruluğu nasıl ölçülür?

Gerçek kullanıcı sorularından, doğru yanıtlardan ve doğru kaynaklardan oluşan bir altın set hazırlanır. Arama katmanı recall@k ve MRR ile, üretim katmanı ise yanıttaki iddiaların getirilen parçalarla desteklenip desteklenmediğini gösteren sadakat (faithfulness) ve yanıt uygunluğu metrikleriyle ölçülür.

RAG kullanırken KVKK açısından nelere dikkat edilmeli?

İndekslenecek klasörleri daraltın, embedding ve dil modelinin nerede çalıştığını belirleyin (yurt dışındaysa 6698 sayılı Kanun'un 9. maddesi kapsamında aktarım olur), vektörleri kaynak metinle aynı korumada tutun, silme talebinde parça, vektör, önbellek ve kayıtları birlikte silin ve soru kayıtlarının saklama süresini belirleyin.

Kaynaklar

  1. Lewis vd. (2020), Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks arxiv.org
  2. pgvector: Open-source vector similarity search for Postgres (GitHub) github.com
  3. Cormack, Clarke, Büttcher (2009), Reciprocal Rank Fusion outperforms Condorcet and individual Rank Learning Methods plg.uwaterloo.ca
  4. Es vd. (2023), Ragas: Automated Evaluation of Retrieval Augmented Generation arxiv.org
  5. KVKK, Üretken Yapay Zekâ ve Kişisel Verilerin Korunması Rehberi (15 Soruda) kvkk.gov.tr
  6. KVKK, 6698 Sayılı Kanunda Yapılan Değişiklikler Hakkında Kamuoyu Duyurusu kvkk.gov.tr

RAGLLMpgvectorhibrit aramaembeddingKVKKPython Markdown sürümü

İletişim

Konuşalım.