RAG에서 평가가 중요한 이유
RAG 시스템의 서로 독립적인 두 가지 실패 유형인 검색 실패와 생성 실패를 이해하고, 각각을 진단하려면 별도의 지표가 필요한 이유를 학습합니다.
RAG에서 평가가 중요한 이유은(는) CoddyKit의 무료 AI Engineering Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Engineering Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
측정하지 않으면 개선할 수 없습니다
RAG 시스템은 유창하고 그럴듯한 답변을 반환하기 때문에 작동하는 것처럼 보일 수 있습니다. 하지만 측정하지 않으면 실제로 올바른 청크를 검색하는지 또는 충실한 답변을 생성하는지 알 수 없습니다. 평가를 건너뛴 팀은 감에 의존해 청크 분할 전략과 프롬프트 형식을 조정하며 몇 달을 보내다가 오히려 성능을 떨어뜨렸다는 사실을 발견하는 경우가 많습니다. 엄격한 평가를 통해 RAG 개발은 추측이 아니라 엔지니어링이 됩니다.
서로 독립적인 두 가지 실패 원인
RAG에는 서로 독립적으로 실패할 수 있는 두 가지 뚜렷한 단계가 있습니다. 검색과 생성입니다. 관련 청크가 상위 K개 결과에 포함되지 않으면 검색이 실패합니다. 올바른 정보가 검색되지 않았다면 LLM은 좋은 답변을 생성할 수 없습니다. 올바른 청크가 검색되었지만 LLM이 이를 무시하거나 잘못 읽거나 환각한 정보를 추가하면 생성이 실패합니다. 어떤 구성 요소가 문제를 일으키는지 파악하려면 각 단계에 별도의 지표가 필요합니다.
종단 간 평가에만 의존할 때의 위험
최종 답변의 품질만 측정하면 실패의 원인이 어디에 있는지 알 수 없습니다. 시스템이 30%의 확률로 잘못된 답변을 제공한다고 가정해 보세요. 검색이 올바른 청크를 놓친 것일까요, 아니면 LLM이 좋은 청크를 무시한 것일까요? 최종 오류율만 알고 있다면 어떤 구성 요소를 수정해야 하는지 알 수 없습니다. 두 단계를 별도로 계측하세요. 정답 데이터 세트로 검색 품질을 측정하고, 충실도 점수로 생성 품질을 측정하세요.
# Diagnosis example: which stage is failing?
# Test 1: Is retrieval finding the right chunks?
retrieval_hit_rate = evaluate_retrieval(questions, ground_truth_chunks)
print(f'Retrieval hit rate@5: {retrieval_hit_rate:.1%}')
# If this is low (< 80%), fix chunking and embedding first
# Test 2: Given perfect context, does LLM generate correct answers?
generation_faithfulness = evaluate_generation(questions, perfect_context)
print(f'Generation faithfulness: {generation_faithfulness:.1%}')
# If retrieval is fine but this is low, fix your prompts정답 데이터 세트 구축
평가에는 정답 데이터 세트가 필요합니다. 이는 정답과, 가능하다면 답변이 나온 문서와 청크까지 알고 있는 질문-답변 쌍의 모음입니다. 최소한으로 사용할 수 있는 평가 세트로 실제 사용자 쿼리를 대표하는 질문 50~100개를 수집하세요. 직접 답변을 작성하거나 원본 문서를 읽고 답변을 작성하세요. 사실 확인, 비교, 다단계 추론, 그리고 시스템이 답변을 거부해야 하는 도메인 외 질문 등 다양한 질문 유형을 포함하세요.
# Golden dataset format
golden_dataset = [
{
'question': 'How many vacation days do employees receive in their first year?',
'answer': '15 days',
'relevant_chunks': ['employee_handbook_p24', 'benefits_summary_p3'],
'source_doc': 'employee_handbook_2025.pdf'
},
{
'question': 'What is the parental leave duration for primary caregivers?',
'answer': '16 weeks fully paid',
'relevant_chunks': ['parental_leave_policy_p1'],
'source_doc': 'parental_leave_policy.pdf'
}
]LLM으로 골든 데이터셋 생성하기
질문 100개를 수작업으로 만드는 일은 번거롭습니다. 데이터 생성 LLM을 사용해 이 작업을 빠르게 처리할 수 있습니다. 각 문서 청크를 GPT-4o에 입력하고, 해당 청크에서 답을 찾을 수 있는 다양하고 서로 다른 질문 3~5개와 예상 답변 텍스트를 생성하도록 요청합니다. 품질 문제를 발견할 수 있도록 일부 샘플을 수작업으로 검토합니다. 이 방법을 사용하면 수천 개의 질문으로 빠르게 확장할 수 있지만, 실제 사용자가 제기할 때만 드러나는 예외적인 경우를 놓칠 수 있습니다.
def generate_qa_pairs_for_chunk(chunk_text, llm_client):
prompt = (
'Given the following document excerpt, generate 3 diverse questions '
'that can be answered using ONLY this text. '
'For each question, provide the exact answer from the text.\n\n'
f'Text:\n{chunk_text}\n\n'
'Format each as JSON: {"question": ..., "answer": ...}'
)
response = llm_client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}]
)
return response.choices[0].message.content검색 평가: 적중률
적중률@K는 상위 K개 검색 결과에 관련 청크가 하나 이상 포함된 질문의 비율입니다. 가장 단순하고 직관적인 검색 지표입니다. 적중률@5가 85%라는 것은 질문 100개 중 85개에서 관련 청크가 상위 5개 결과에 포함되었다는 뜻입니다. 검색기가 어떤 부분에서 가장 어려움을 겪는지 파악하려면 문서 유형, 질의 길이, 주제 범주별로 적중률을 따로 추적하십시오.
def compute_hit_rate(golden_dataset, retriever, top_k=5):
hits = 0
for item in golden_dataset:
results = retriever.retrieve(item['question'], top_k=top_k)
retrieved_ids = {r['id'] for r in results}
relevant_ids = set(item['relevant_chunks'])
if retrieved_ids & relevant_ids: # intersection not empty
hits += 1
hit_rate = hits / len(golden_dataset)
print(f'Hit rate@{top_k}: {hit_rate:.1%} ({hits}/{len(golden_dataset)})')
return hit_rate생성 평가: 충실도
충실도는 생성된 답변이 검색된 문맥에서 검증할 수 있는 정보만 포함하는지를 측정합니다. 충실하지 않은 답변은 문맥이 뒷받침하지 않는 사실을 추가하는데, 이를 환각이라고 합니다. 평가용 LLM(또는 사람 평가자)이 답변의 각 문장을 문맥과 대조하고, 검색된 청크가 뒷받침하지 않는 주장을 표시하도록 하여 충실도를 평가합니다. 실제 운영 시스템에서는 충실도 점수 95% 이상을 목표로 합니다.
def evaluate_faithfulness(answer, context, llm_client):
prompt = (
'Given this context and answer, evaluate faithfulness.\n\n'
f'Context: {context}\n\n'
f'Answer: {answer}\n\n'
'For each sentence in the answer, determine if it is '
'supported by the context (FAITHFUL) or not (HALLUCINATED). '
'Return a JSON: {"score": 0.0-1.0, "issues": ["sentence..."]}.'
)
response = llm_client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}]
)
return response.choices[0].message.content생성 평가: 답변 관련성
답변 관련성은 생성된 답변이 실제로 사용자의 질문에 답하는지를 측정합니다. 충실도가 매우 높은 답변이라도 관련 있지만 다른 질문에 답하여 핵심을 놓칠 수 있습니다. 관련성은 충실도와 별도로 측정하십시오. 평가용 LLM을 사용하여 답변이 질문의 요구를 직접 다루는지 1~5점 척도로 평가하게 하십시오. 답변 관련성이 낮다면 프롬프트 구조에 문제가 있거나 검색된 문맥에 실제 답변이 포함되어 있지 않은 경우가 많습니다.
def evaluate_answer_relevance(question, answer, llm_client):
prompt = (
f'Question: {question}\n\n'
f'Answer: {answer}\n\n'
'Rate how well this answer addresses the question on a 1-5 scale:\n'
'5 = fully answers the question\n'
'3 = partially answers but misses key aspects\n'
'1 = does not address the question at all\n\n'
'Return JSON: {"score": 1-5, "reason": "brief explanation"}'
)
response = llm_client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}]
)
return response.choices[0].message.content시간에 따른 지표 추적
평가는 변경 사항을 적용하는 동안 시간에 따라 지표를 추적할 때 가장 큰 가치를 발휘합니다. 타임스탬프와 버전 레이블(예: chunk_size=500, embed=3-small, k=5)을 포함하여 평가 결과를 데이터베이스나 스프레드시트에 저장하십시오. 새로운 청킹 전략이나 임베딩 모델을 시도할 때는 동일한 평가를 실행하고 결과를 비교하십시오. 이렇게 하면 성능 저하를 방지할 수 있습니다. 충실도는 높아졌지만 실수로 적중률이 낮아질 수도 있기 때문입니다. 운영 환경에 변경 사항을 병합하기 전에는 항상 전체 평가를 실행하십시오.
import json
from datetime import datetime
def save_evaluation_results(metrics, config, output_file='eval_history.jsonl'):
record = {
'timestamp': datetime.utcnow().isoformat(),
'config': config,
'metrics': metrics
}
with open(output_file, 'a') as f:
f.write(json.dumps(record) + '\n')
print(f'Saved eval result: hit_rate={metrics["hit_rate"]:.1%}, '
f'faithfulness={metrics["faithfulness"]:.1%}')평가 관점
특정 지표를 넘어, 평가에는 관점의 전환이 필요합니다. RAG를 대화하며 주관적으로 평가하는 챗봇이 아니라, 측정 가능한 성능을 지닌 기계 학습 시스템으로 다루어야 합니다. 성공 기준을 미리 정의하십시오(예: 적중률@5 > 85%, 충실도 > 95%). 고정된 상태로 유지하며 개발 의사 결정에 절대 사용하지 않을 테스트 세트를 마련하십시오. 반복 작업에는 별도의 개발 세트를 사용하십시오. 이러한 규율이 신뢰할 수 있는 RAG를 출시하는 팀과, 인상적인 시연을 선보이지만 운영 환경에서 실패하는 팀을 가릅니다.
테스트 세트와 개발 세트 비교
RAG 평가에도 적용되는 기계 학습의 중요한 원칙은 학습-개발-테스트 분할입니다. 테스트 세트는 완전히 고정해야 하며 개발 의사 결정에 절대 사용해서는 안 됩니다. 청킹 전략, 프롬프트 변경 사항, 임베딩 모델을 실험할 때는 별도의 개발 세트를 사용하십시오. 변경 사항이 운영 환경에 적용할 준비가 되었다고 판단될 때만 테스트 세트를 실행하십시오. 이렇게 분리하면 RAG 파이프라인이 테스트 세트에 과적합되는 것을 방지하고, 최종적으로 보고하는 지표가 실제 일반화 성능을 반영하도록 할 수 있습니다.
import json
from sklearn.model_selection import train_test_split
def split_golden_dataset(all_questions, test_ratio=0.3, seed=42):
dev_set, test_set = train_test_split(
all_questions,
test_size=test_ratio,
random_state=seed
)
print(f'Dev set: {len(dev_set)} questions')
print(f'Test set: {len(test_set)} questions (FROZEN)')
with open('eval/dev_set.json', 'w') as f:
json.dump(dev_set, f, indent=2)
with open('eval/test_set.json', 'w') as f:
json.dump(test_set, f, indent=2)
return dev_set, test_set빠른 확인
이 단원에서 배운 AI 엔지니어링 개념을 이해했는지 확인하십시오.
단원 요약
이 단원에서는 검색과 생성에서 발생하는 서로 독립적인 두 가지 실패 방식과 각각에 별도의 지표가 필요한 이유, 객관적인 평가를 위해 질문-답변-청크 삼중항으로 골든 데이터셋을 구축하는 방법, 핵심 검색 지표인 적중률과 핵심 생성 지표인 충실도 및 답변 관련성, 그리고 성능 저하를 방지하기 위해 시간에 따른 지표 추적이 중요한 이유를 배웠습니다. 다음으로 MRR과 NDCG를 비롯한 구체적인 검색 지표를 구현합니다.
AI 튜터와 함께 Python을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 30
- 레슨
- 120
자주 묻는 질문
“RAG에서 평가가 중요한 이유” 강의는 무료인가요?
네 — “RAG에서 평가가 중요한 이유” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Engineering Academy 강의 전체를 잠금 해제할 수 있습니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“RAG에서 평가가 중요한 이유”에서 뭘 배우나요?
RAG 시스템의 서로 독립적인 두 가지 실패 유형인 검색 실패와 생성 실패를 이해하고, 각각을 진단하려면 별도의 지표가 필요한 이유를 학습합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Engineering Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Engineering Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Engineering Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“RAG에서 평가가 중요한 이유” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Engineering Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Engineering Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- RAG에서 평가가 중요한 이유
- 검색 지표: 적중률, MRR, NDCG
- 생성 지표: 충실도와 답변 관련성
- 자동화된 평가 도구 구축