跳到主要内容

Ragas RAG 평가 프레임워크

📅 작성일: 2026-02-13 | 수정일: 2026-02-14 | ⏱️ 읽는 시간: 약 3분

Ragas(RAG Assessment)는 RAG(Retrieval-Augmented Generation) 파이프라인의 품질을 객관적으로 평가하기 위한 오픈소스 프레임워크입니다. Agentic AI 플랫폼에서 RAG 시스템의 성능을 측정하고 지속적으로 개선하는 데 필수적입니다.

개요

RAG 평가가 필요한 이유

RAG 시스템은 여러 컴포넌트(검색, 생성, 컨텍스트 처리)로 구성되어 있어 전체 품질을 측정하기 어렵습니다:

Ragas vs AWS Bedrock RAG Evaluation

AWS Bedrock RAG Evaluation GA

AWS Bedrock RAG Evaluation은 2025년 3월 GA되었습니다. Bedrock 네이티브 통합으로 별도 설정 없이 RAG 평가를 수행할 수 있습니다.

Ragas vs AWS Bedrock RAG 评估
比较项Ragas (开源)AWS Bedrock RAG Evaluation
部署方式Self-hostedAWS托管
评估 LLM外部 API (OpenAI等)Bedrock模型
指标5个核心指标4个核心指标
定制化高 (Python代码)中等 (API参数)
成本LLM API成本Bedrock调用成本
集成需要手动集成Bedrock原生
适用场景需要精细控制快速生产部署

AWS Bedrock RAG Evaluation 메트릭:

  • Context Relevance: 검색된 컨텍스트가 질문과 관련있는지
  • Coverage: 답변이 질문의 모든 측면을 다루는지
  • Correctness: 답변이 정확한지 (ground truth 대비)
  • Faithfulness: 답변이 컨텍스트에 충실한지

Ragas 핵심 메트릭

Ragas 核心指标
Faithfulness
生成质量
答案是否忠实于上下文
Answer Relevancy
生成质量
答案是否与问题相关
Context Precision
检索质量
检索上下文的精度
Context Recall
检索质量
是否检索到必要信息
Answer Correctness
综合质量
答案的准确性
Ragas 0.2+ API 변경사항

Ragas 0.2 이상에서 context_relevancy 메트릭은 제거되었습니다. 컨텍스트 품질 평가는 context_precisioncontext_recall을 조합하여 수행하세요.

설치 및 기본 설정

Python 환경 설정

# Ragas 설치 (0.2+ 권장)
pip install "ragas>=0.2" langchain-openai datasets

# 추가 의존성
pip install pandas numpy

기본 평가 코드

from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall,
)
from datasets import Dataset

# 평가 데이터셋 준비
eval_data = {
"question": [
"Kubernetes에서 GPU 스케줄링은 어떻게 하나요?",
"Karpenter의 주요 기능은 무엇인가요?",
],
"answer": [
"Kubernetes에서 GPU 스케줄링은 NVIDIA Device Plugin을 통해 수행됩니다...",
"Karpenter는 자동 노드 프로비저닝, 통합(consolidation), 드리프트 감지 기능을 제공합니다...",
],
"contexts": [
["GPU 스케줄링은 Device Plugin을 통해...", "NVIDIA GPU Operator는..."],
["Karpenter는 Kubernetes 노드 자동 스케일러로...", "NodePool CRD를 통해..."],
],
"ground_truth": [
"NVIDIA Device Plugin과 GPU Operator를 사용하여 GPU 리소스를 스케줄링합니다.",
"Karpenter는 자동 노드 프로비저닝, 통합, 드리프트 감지, 중단 처리 기능을 제공합니다.",
],
}

dataset = Dataset.from_dict(eval_data)

# 평가 실행 (에러 핸들링 포함)
try:
results = evaluate(
dataset,
metrics=[
faithfulness,
answer_relevancy,
context_precision,
context_recall,
],
)
print(results)
except Exception as e:
print(f"평가 중 오류 발생: {e}")
# 로깅 또는 재시도 로직

핵심 메트릭 상세 설명

1. Faithfulness (충실도)

답변이 제공된 컨텍스트에 얼마나 충실한지 측정합니다. 환각(hallucination)을 감지하는 데 핵심적인 메트릭입니다.

from ragas.metrics import faithfulness

# Faithfulness 계산 과정:
# 1. 답변을 개별 주장(claims)으로 분해
# 2. 각 주장이 컨텍스트에서 추론 가능한지 검증
# 3. 검증된 주장 수 / 전체 주장 수 = Faithfulness 점수

# 점수 해석:
# 1.0: 모든 주장이 컨텍스트에서 지원됨
# 0.5: 절반의 주장만 컨텍스트에서 지원됨
# 0.0: 어떤 주장도 컨텍스트에서 지원되지 않음 (심각한 환각)

2. Answer Relevancy (답변 관련성)

답변이 질문에 얼마나 관련있는지 측정합니다.

from ragas.metrics import answer_relevancy

# Answer Relevancy 계산 과정:
# 1. 답변에서 역으로 질문을 생성
# 2. 생성된 질문과 원본 질문의 유사도 계산
# 3. 여러 번 반복하여 평균 계산

# 점수 해석:
# 높은 점수: 답변이 질문에 직접적으로 관련됨
# 낮은 점수: 답변이 질문과 동떨어진 내용을 포함

3. Context Precision (컨텍스트 정밀도)

검색된 컨텍스트 중 실제로 유용한 정보의 비율을 측정합니다.

from ragas.metrics import context_precision

# Context Precision 계산:
# - Ground truth 답변을 생성하는 데 필요한 컨텍스트 식별
# - 상위 랭킹 컨텍스트에 유용한 정보가 있는지 확인
# - 높은 순위에 관련 컨텍스트가 있을수록 높은 점수

4. Context Recall (컨텍스트 재현율)

정답을 생성하는 데 필요한 정보가 검색된 컨텍스트에 포함되어 있는지 측정합니다.

from ragas.metrics import context_recall

# Context Recall 계산:
# 1. Ground truth를 개별 문장으로 분해
# 2. 각 문장이 검색된 컨텍스트에서 추론 가능한지 확인
# 3. 추론 가능한 문장 수 / 전체 문장 수 = Recall 점수

종합 평가 파이프라인

전체 RAG 시스템 평가

import os
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall,
answer_correctness,
)
from datasets import Dataset
from langchain_openai import ChatOpenAI, OpenAIEmbeddings

# LLM 설정 (평가용)
os.environ["OPENAI_API_KEY"] = "your-api-key"

def evaluate_rag_pipeline(questions, rag_chain, ground_truths):
"""RAG 파이프라인 종합 평가"""

answers = []
contexts = []

for question in questions:
# RAG 체인 실행
result = rag_chain.invoke({"query": question})
answers.append(result["result"])
contexts.append([doc.page_content for doc in result["source_documents"]])

# 평가 데이터셋 구성
eval_dataset = Dataset.from_dict({
"question": questions,
"answer": answers,
"contexts": contexts,
"ground_truth": ground_truths,
})

# 전체 메트릭으로 평가
results = evaluate(
eval_dataset,
metrics=[
faithfulness,
answer_relevancy,
context_precision,
context_recall,
answer_correctness,
],
)

return results

# 사용 예시
questions = [
"EKS에서 Karpenter를 설정하는 방법은?",
"GPU 노드 자동 스케일링 구성 방법은?",
"Inference Gateway의 동적 라우팅 설정은?",
]

ground_truths = [
"Karpenter는 Helm 차트로 설치하고 NodePool CRD를 정의하여 설정합니다.",
"DCGM Exporter 메트릭과 KEDA를 연동하여 GPU 사용률 기반 스케일링을 구성합니다.",
"Gateway API의 HTTPRoute를 사용하여 가중치 기반 트래픽 분배를 설정합니다.",
]

# 평가 실행
results = evaluate_rag_pipeline(questions, rag_chain, ground_truths)
print(results.to_pandas())

평가 결과 분석

import pandas as pd
import matplotlib.pyplot as plt

def analyze_evaluation_results(results):
"""평가 결과 분석 및 시각화"""

df = results.to_pandas()

# 메트릭별 평균 점수
metrics_summary = df.mean(numeric_only=True)
print("=== 메트릭별 평균 점수 ===")
print(metrics_summary)

# 문제 영역 식별
print("\n=== 개선 필요 영역 ===")
for metric, score in metrics_summary.items():
if score < 0.7:
print(f"⚠️ {metric}: {score:.2f} - 개선 필요")
elif score < 0.85:
print(f"📊 {metric}: {score:.2f} - 양호")
else:
print(f"✅ {metric}: {score:.2f} - 우수")

# 시각화
fig, ax = plt.subplots(figsize=(10, 6))
metrics_summary.plot(kind='bar', ax=ax, color=['#4285f4', '#34a853', '#fbbc04', '#ea4335', '#9c27b0', '#00bcd4'])
ax.set_ylabel('Score')
ax.set_title('RAG Pipeline Evaluation Results')
ax.set_ylim(0, 1)
ax.axhline(y=0.7, color='r', linestyle='--', label='Minimum Threshold')
ax.legend()
plt.tight_layout()
plt.savefig('rag_evaluation_results.png')

return metrics_summary

# 분석 실행
summary = analyze_evaluation_results(results)

CI/CD 파이프라인 통합

GitHub Actions 워크플로우

# .github/workflows/rag-evaluation.yml
name: RAG Pipeline Evaluation

on:
push:
paths:
- 'src/rag/**'
- 'data/knowledge_base/**'
pull_request:
paths:
- 'src/rag/**'
schedule:
- cron: '0 0 * * *' # 매일 자정

jobs:
evaluate:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install dependencies
run: |
pip install ragas langchain-openai datasets pandas

- name: Run RAG Evaluation
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
python scripts/evaluate_rag.py --output results/evaluation.json

- name: Check Quality Gates
run: |
python scripts/check_quality_gates.py results/evaluation.json

- name: Upload Results
uses: actions/upload-artifact@v4
with:
name: evaluation-results
path: results/

- name: Comment PR with Results
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('results/evaluation.json'));

let comment = '## RAG Evaluation Results\n\n';
comment += '| Metric | Score | Status |\n';
comment += '|--------|-------|--------|\n';

for (const [metric, score] of Object.entries(results.metrics)) {
const status = score >= 0.7 ? '✅' : '⚠️';
comment += `| ${metric} | ${score.toFixed(2)} | ${status} |\n`;
}

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});

품질 게이트 스크립트

# scripts/check_quality_gates.py
import json
import sys

QUALITY_GATES = {
"faithfulness": 0.8,
"answer_relevancy": 0.75,
"context_precision": 0.7,
"context_recall": 0.7,
}

def check_quality_gates(results_file):
with open(results_file) as f:
results = json.load(f)

failed_gates = []

for metric, threshold in QUALITY_GATES.items():
score = results["metrics"].get(metric, 0)
if score < threshold:
failed_gates.append({
"metric": metric,
"score": score,
"threshold": threshold,
})

if failed_gates:
print("❌ Quality gates failed:")
for gate in failed_gates:
print(f" - {gate['metric']}: {gate['score']:.2f} < {gate['threshold']}")
sys.exit(1)
else:
print("✅ All quality gates passed!")
sys.exit(0)

if __name__ == "__main__":
check_quality_gates(sys.argv[1])

Kubernetes Job으로 정기 평가

평가 Job 정의

apiVersion: batch/v1
kind: CronJob
metadata:
name: rag-evaluation
namespace: genai-platform
spec:
schedule: "0 6 * * *" # 매일 오전 6시
jobTemplate:
spec:
template:
spec:
containers:
- name: evaluator
image: your-registry/rag-evaluator:latest
env:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: openai-credentials
key: api-key
- name: MILVUS_HOST
value: "milvus-proxy.ai-data.svc.cluster.local"
- name: RESULTS_BUCKET
value: "s3://rag-evaluation-results"
command:
- python
- /app/evaluate.py
- --config=/app/config/evaluation.yaml
- --output=s3
resources:
requests:
cpu: "1"
memory: "2Gi"
limits:
cpu: "2"
memory: "4Gi"
restartPolicy: OnFailure
serviceAccountName: rag-evaluator

평가 설정 ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
name: rag-evaluation-config
namespace: genai-platform
data:
evaluation.yaml: |
evaluation:
metrics:
- faithfulness
- answer_relevancy
- context_precision
- context_recall

test_sets:
- name: "general_knowledge"
path: "s3://test-data/general.json"
weight: 0.4
- name: "technical_docs"
path: "s3://test-data/technical.json"
weight: 0.6

quality_gates:
faithfulness: 0.8
answer_relevancy: 0.75
context_precision: 0.7
context_recall: 0.7

alerts:
slack_webhook: "https://hooks.slack.com/..."
threshold_drop: 0.1 # 10% 이상 하락 시 알림

평가 결과 해석 및 개선 가이드

비용 최적화 전략

RAG 평가는 LLM API 호출이 필요하므로 비용이 발생합니다. 다음 전략으로 비용을 최적화하세요:

💰 成本优化策略
采样评估
仅评估代表性样本而非整个数据集
50-80%
缓存
缓存并重用相同的问答对
30-50%
批处理
将多个评估批量处理
20-30%
使用更便宜的模型
使用 GPT-3.5 而非 GPT-4 (精度权衡)
90%
增量评估
仅重新评估更改的部分
60-90%
import hashlib
import json
from functools import lru_cache

class CachedEvaluator:
"""캐싱을 활용한 비용 최적화 평가기"""

def __init__(self, cache_file='eval_cache.json'):
self.cache_file = cache_file
self.cache = self._load_cache()

def _load_cache(self):
try:
with open(self.cache_file, 'r') as f:
return json.load(f)
except FileNotFoundError:
return {}

def _save_cache(self):
with open(self.cache_file, 'w') as f:
json.dump(self.cache, f)

def _get_cache_key(self, question, answer, contexts):
"""평가 항목의 고유 키 생성"""
content = f"{question}|{answer}|{'|'.join(contexts)}"
return hashlib.md5(content.encode()).hexdigest()

def evaluate_with_cache(self, dataset, metrics):
"""캐시를 활용한 평가"""
cached_results = []
new_items = []

for item in dataset:
cache_key = self._get_cache_key(
item['question'],
item['answer'],
item['contexts']
)

if cache_key in self.cache:
cached_results.append(self.cache[cache_key])
else:
new_items.append(item)

# 새로운 항목만 평가
if new_items:
new_dataset = Dataset.from_dict({
k: [item[k] for item in new_items]
for k in new_items[0].keys()
})

new_results = evaluate(new_dataset, metrics=metrics)

# 캐시 업데이트
for item, result in zip(new_items, new_results):
cache_key = self._get_cache_key(
item['question'],
item['answer'],
item['contexts']
)
self.cache[cache_key] = result

self._save_cache()
cached_results.extend(new_results)

return cached_results

# 사용 예시
evaluator = CachedEvaluator()
results = evaluator.evaluate_with_cache(dataset, metrics)

AWS Bedrock RAG Evaluation 사용

AWS Bedrock RAG Evaluation을 사용하면 Bedrock 네이티브 통합으로 더 간편하게 평가할 수 있습니다:

import boto3

bedrock = boto3.client('bedrock-agent-runtime')

# RAG 평가 실행
response = bedrock.evaluate_rag(
evaluationJobName='rag-eval-2026-02-13',
evaluationDatasetLocation={
's3Uri': 's3://my-bucket/eval-dataset.jsonl'
},
evaluationMetrics=[
'CONTEXT_RELEVANCE',
'COVERAGE',
'CORRECTNESS',
'FAITHFULNESS'
],
modelId='anthropic.claude-3-sonnet-20240229-v1:0',
outputDataConfig={
's3Uri': 's3://my-bucket/eval-results/'
}
)

job_id = response['evaluationJobId']

# 평가 결과 조회
result = bedrock.get_evaluation_job(evaluationJobId=job_id)
print(f"Status: {result['status']}")
print(f"Metrics: {result['metrics']}")

Bedrock RAG Evaluation 장점:

  • ✅ Bedrock 모델과 네이티브 통합
  • ✅ S3 기반 대규모 배치 평가
  • ✅ CloudWatch 자동 메트릭 게시
  • ✅ IAM 기반 접근 제어
  • ✅ 별도 인프라 불필요

비용 비교 (1000개 평가 기준):

成本比较 (基于1000次评估)
方式预期成本设置复杂度
Ragas + OpenAI GPT-4$50-100中等
Ragas + OpenAI GPT-3.5$5-10中等
Bedrock RAG Eval (Claude 3 Sonnet)$20-40
Bedrock RAG Eval (Claude 3 Haiku)$5-15

메트릭별 개선 방향

개선 체크리스트

🔧 改进清单
Faithfulness < 0.7
可能原因
LLM 忽略上下文
解决方案
在提示中强调"仅使用上下文"
Context Precision < 0.6
可能原因
检索质量低
解决方案
升级嵌入模型,添加重排序
Context Recall < 0.6
可能原因
缺少相关文档
解决方案
增加 k 值,增强知识库
Answer Relevancy < 0.7
可能原因
答案分散
解决方案
结构化提示,指定输出格式

관련 문서

권장 사항
  • 평가 데이터셋은 최소 50개 이상의 다양한 질문을 포함하세요
  • Ground truth는 도메인 전문가가 검증한 정답을 사용하세요
  • 정기적인 평가를 통해 시간에 따른 품질 변화를 추적하세요
주의사항
  • Ragas 평가는 LLM API 호출이 필요하므로 비용이 발생합니다
  • 대규모 평가 시 배치 처리와 캐싱을 활용하세요
  • 평가 결과는 사용된 LLM에 따라 달라질 수 있습니다