🏠 Ana Sayfa 📖 Sözlük 💬 Doküman asistanı
Ana sayfaGüvenlik, Kalite & YönetişimRAGAS Değerlendirme

📊RAGAS Değerlendirme Framework'ü

📺 Daha Fazlası İçin İzleyin

RAGAS (Retrieval-Augmented Generation Assessment), RAG sistemlerinin kalitesini ölçmek için kullanılan standart değerlendirme framework'üdür. Komtaş'ta RAGAS, her RAG pipeline'ı için zorunlu kalite kapısı olarak kullanılmaktadır.

📌 Politika
Komtaş'ta üretime alınan her RAG sistemi, RAGAS metriklerinden tamamını asgari eşik değerlerinin üzerinde geçmelidir. Eşiklerin altında kalan sistemler üretime alınamaz.

4.1 RAGAS Metrikleri — Detaylı Kılavuz

🎯 Faithfulness
Minimum Eşik: ≥ 0.85
Cevabın, alınan bağlam belgelerine dayandırılabilirliğini ölçer. Halüsinasyonu doğrudan tespit eder.
score = |doğrulanabilir_ifadeler| / |toplam_ifadeler|
🔍 Answer Relevancy
Minimum Eşik: ≥ 0.80
Üretilen cevabın, orijinal soruyla ne kadar ilgili olduğunu ölçer. İlgisiz veya eksik cevapları tespit eder.
score = mean(cosine_sim(reverse_questions, original_q))
📐 Context Precision
Minimum Eşik: ≥ 0.75
Alınan bağlam belgelerinin ne kadarının gerçekten kullanıldığını ölçer. Gürültülü retrieval'ı tespit eder.
score = |kullanılan_chunks| / |alınan_chunks|
📚 Context Recall
Minimum Eşik: ≥ 0.80
Doğru cevap için gerekli bilgilerin ne kadarının bağlamda bulunduğunu ölçer. Eksik retrieval'ı tespit eder.
score = |bulunan_bilgi_parçaları| / |gerekli_bilgi_parçaları|
🎛️ Context Relevancy
Minimum Eşik: ≥ 0.70
Alınan bağlamın soru ile genel ilişkisini ölçer. İlgisiz chunk'ların oranını belirler.
score = |ilgili_sentences| / |toplam_sentences|
✅ Answer Correctness
Minimum Eşik: ≥ 0.80
Üretilen cevabın, referans (ground truth) cevapla olgusal doğruluğunu ölçer. F1 skorunu kullanır.
score = 0.75×F1_faktüel + 0.25×semantic_similarity

RAGAS Python Implementasyonu

from ragas import evaluate
from ragas.metrics import (
    faithfulness,
    answer_relevancy,
    context_precision,
    context_recall,
    context_relevancy,
    answer_correctness
)
from ragas.llms import LangchainLLMWrapper
from ragas.embeddings import LangchainEmbeddingsWrapper
from langchain_anthropic import ChatAnthropic
from langchain_openai import OpenAIEmbeddings
from datasets import Dataset
import pandas as pd

# Model ve embedding konfigürasyonu
llm = LangchainLLMWrapper(ChatAnthropic(model="claude-opus-4-6"))
embeddings = LangchainEmbeddingsWrapper(OpenAIEmbeddings(model="text-embedding-3-small"))

# Test dataset oluşturma
def create_ragas_dataset(qa_pairs: list[dict]) -> Dataset:
    """
    qa_pairs: [{"question": "...", "answer": "...", "contexts": [...], "ground_truth": "..."}]
    """
    return Dataset.from_dict({
        "question": [p["question"] for p in qa_pairs],
        "answer": [p["answer"] for p in qa_pairs],
        "contexts": [p["contexts"] for p in qa_pairs],
        "ground_truth": [p["ground_truth"] for p in qa_pairs]
    })

# Değerlendirme çalıştırma
def run_ragas_evaluation(dataset: Dataset) -> dict:
    metrics = [
        faithfulness,
        answer_relevancy,
        context_precision,
        context_recall,
        context_relevancy,
        answer_correctness
    ]
    
    result = evaluate(
        dataset=dataset,
        metrics=metrics,
        llm=llm,
        embeddings=embeddings,
        raise_exceptions=False
    )
    
    return result.to_pandas()

# Eşik kontrolü
THRESHOLDS = {
    "faithfulness": 0.85,
    "answer_relevancy": 0.80,
    "context_precision": 0.75,
    "context_recall": 0.80,
    "context_relevancy": 0.70,
    "answer_correctness": 0.80
}

def check_quality_gate(scores: dict) -> tuple[bool, list[str]]:
    """Kalite kapısı kontrolü — CI/CD pipeline için"""
    failures = []
    for metric, threshold in THRESHOLDS.items():
        if scores.get(metric, 0) < threshold:
            failures.append(
                f"{metric}: {scores[metric]:.3f} < {threshold} (BAŞARISIZ)"
            )
    return len(failures) == 0, failures

# Kullanım
if __name__ == "__main__":
    dataset = create_ragas_dataset(load_test_cases("tests/rag_testcases.json"))
    scores_df = run_ragas_evaluation(dataset)
    avg_scores = scores_df.mean().to_dict()
    
    passed, failures = check_quality_gate(avg_scores)
    
    if not passed:
        print("❌ Kalite Kapısı BAŞARISIZ:")
        for f in failures: print(f"  - {f}")
        exit(1)  # CI/CD pipeline'ı durdur
    else:
        print("✅ Tüm RAGAS metrikleri eşiklerin üzerinde")
📌 Kod Notları
  • RAGAS metrikleri: Faithfulness: Yanıt bağlam dışı bilgi içeriyor mu? Answer Relevancy: Yanıt soruyla alakalı mı? Context Recall: Doğru belgeleri getirdi mi? Context Precision: Gereksiz belge var mı?
  • Test dataset kalitesi: RAGAS sonuçları ancak test veri setinin kalitesi kadar güvenilirdir. Ground truth cevaplarını domain uzmanlarıyla doğrulayın.
  • CI/CD entegrasyonu: RAGAS'ı CI pipeline'a eklemek, bir PR'ın RAG kalitesini düşürüp düşürmediğini otomatik tespit eder. faithfulness < 0.8 eşiğinin altında build'i durdurabilirsiniz.
  • LLM-as-judge: RAGAS bazı metrikleri değerlendirmek için bir LLM kullanır. Değerlendirici modelin iyi seçilmesi (genellikle GPT-4 sınıfı) sonuçların güvenilirliğini doğrudan etkiler.

4.2 CI/CD Entegrasyonu

# .github/workflows/rag_quality.yml
name: RAG Quality Gate

on:
  pull_request:
    paths:
      - 'rag/**'
      - 'prompts/**'
      - 'embeddings/**'

jobs:
  ragas-evaluation:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install dependencies
        run: pip install ragas langchain-anthropic datasets
      
      - name: Run RAGAS evaluation
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          python scripts/run_ragas_evaluation.py \
            --testset tests/rag_testcases.json \
            --output reports/ragas_scores.json
      
      - name: Check quality gates
        run: python scripts/check_quality_gates.py reports/ragas_scores.json
      
      - name: Upload RAGAS report
        uses: actions/upload-artifact@v3
        with:
          name: ragas-report
          path: reports/ragas_scores.json
      
      - name: Comment PR with scores
        uses: actions/github-script@v6
        with:
          script: |
            const scores = require('./reports/ragas_scores.json');
            const body = \`## RAGAS Değerlendirme Sonuçları
            | Metrik | Skor | Eşik | Durum |
            |--------|------|------|-------|
            \${Object.entries(scores).map(([k,v]) => 
              \`| \${k} | \${v.toFixed(3)} | \${THRESHOLDS[k]} | \${v >= THRESHOLDS[k] ? '✅' : '❌'} |\`
            ).join('\n')}\`;
            
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body
            });

4.3 Langfuse Entegrasyonu

from langfuse import Langfuse
from langfuse.decorators import observe, langfuse_context
from ragas import evaluate

langfuse = Langfuse(
    public_key=os.getenv("LANGFUSE_PUBLIC_KEY"),
    secret_key=os.getenv("LANGFUSE_SECRET_KEY"),
    host=os.getenv("LANGFUSE_HOST", "http://langfuse:3000")
)

@observe(name="rag-pipeline-evaluation")
def evaluate_and_trace(question: str, answer: str, contexts: list, ground_truth: str):
    """RAG değerlendirmesini Langfuse'a trace et"""
    
    # RAGAS değerlendirmesi
    dataset = create_ragas_dataset([{
        "question": question,
        "answer": answer,
        "contexts": contexts,
        "ground_truth": ground_truth
    }])
    
    scores = run_ragas_evaluation(dataset)
    
    # Langfuse'a skor gönder
    trace_id = langfuse_context.get_current_trace_id()
    
    for metric_name, score_value in scores.items():
        langfuse.score(
            trace_id=trace_id,
            name=f"ragas_{metric_name}",
            value=float(score_value),
            comment=f"RAGAS {metric_name} skoru"
        )
    
    return scores
📌 Kod Notları
  • Span hiyerarşisi: Trace → Span → Generation şeklinde iç içe yapı oluşturulur. Her @observe yeni bir span açar; LLM çağrıları otomatik generation olarak kaydedilir.
  • flush(): Uygulama kapatılmadan önce mutlaka çağrılmalıdır. Langfuse olayları batch'ler hâlinde gönderir; flush() bekleyen batch'leri zorla gönderir ve veri kaybını önler.
  • score(): İnsan veya otomatik değerlendirme sonuçlarını trace'e ekler. Bu skorlar dashboard'da kalite trendi analizi için kullanılır.

4.4 Uygulama Politikaları ve Senaryolar

Kullanım SenaryosuKritik MetriklerMinimum EşikEskalasyon
Hukuki Doküman Analizi Faithfulness, Answer Correctness Faithfulness ≥ 0.92, Correctness ≥ 0.90 Hukuk ekibi incelemesi
Müşteri Destek Bot Answer Relevancy, Context Recall Relevancy ≥ 0.82, Recall ≥ 0.80 İnsan operatöre yönlendir
Ürün Kataloğu Arama Context Precision, Context Relevancy Precision ≥ 0.78, Relevancy ≥ 0.72 Re-ranking yeniden ayarla
İç Bilgi Tabanı Tüm metrikler Tüm metrikler ≥ standart eşik Chunk stratejisi gözden geçir
Finansal Raporlama Faithfulness, Correctness Faithfulness ≥ 0.95, Correctness ≥ 0.92 CFO onayı gerekli
✅ Best Practice — Düşük Skor Karar Ağacı
  1. Faithfulness düşükse: Chunk boyutunu küçült, context sınırını artır, hallucination'ı azaltmak için temperature'ı düşür
  2. Context Recall düşükse: top_k değerini artır, embedding modelini değiştir, hybrid search (dense+sparse) ekle
  3. Context Precision düşükse: Re-ranker ekle (Cohere Rerank), similarity threshold'u yükselt
  4. Answer Relevancy düşükse: System prompt'u güçlendir, query rewriting ekle