들어가기 전에
RAG 시스템의 성능을 객관적으로 평가하려면 먼저 시험지가 필요합니다.
RAG가 정답 문서를 제대로 찾았는지 확인하려면 어떤 문서가 정답인지 알고 있어야 합니다. 생성된 답변이 정확한지 평가하려면 사용자의 질문에 대한 기대 답변도 준비되어 있어야 하죠.
예를 들어 다음과 같은 질문이 있다고 가정해보겠습니다.
A사의 2025년 2분기 영업이익은 얼마인가요?
RAG가 다음과 같이 답변했습니다.
A사의 2025년 2분기 영업이익은 35억 원입니다.
겉으로 보기에는 그럴듯한 답변입니다. 하지만 평가하려면 최소한 다음 정보를 알고 있어야 합니다.
- 기대 답변은 35억 원인가?
- 정답이 포함된 문서는 무엇인가?
- 문서 안에서 실제 정답이 들어 있는 청크는 무엇인가?
- 검색된 다른 문서들은 질문과 얼마나 관련이 있는가?
이 정보가 없다면 답변이 맞는지 사람이 매번 직접 확인해야 합니다. 임베딩 모델을 바꾸거나 청킹 방식을 변경했을 때 성능이 실제로 좋아졌는지도 동일한 기준으로 비교하기 어렵습니다.
그래서 RAG 평가에서는 질문과 기대 답변, 정답 문서와 정답 청크를 미리 정리한 평가 데이터셋이 필요합니다.
이번 글에서는 RAG 평가 데이터셋에 어떤 정보가 들어가야 하는지, 사람이 직접 만든 질문과 LLM으로 생성한 질문은 무엇이 다른지, Hard Negative는 왜 필요한지, 평가 데이터를 구성할 때 어떤 편향과 오염을 조심해야 하는지 정리해보겠습니다.
평가 데이터셋은 RAG를 위한 시험지입니다
평가 데이터셋을 학교 시험에 비유하면 이해하기 쉽습니다.
시험 문제만 있고 정답지가 없다면 학생의 점수를 계산할 수 없습니다. 정답지만 있고 어떤 내용을 평가하려는 시험인지 정해져 있지 않다면 점수의 의미도 분명하지 않습니다.
RAG도 마찬가지입니다. 질문만 모아두는 것으로는 충분하지 않습니다.
질문마다 어떤 답변을 기대하는지, 어떤 문서가 근거인지, 어떤 청크가 직접적인 정답을 포함하는지 함께 정리해야 합니다.
가장 기본적인 평가 데이터는 다음과 같이 구성할 수 있습니다.
{
"question": "A사의 2025년 2분기 영업이익은 얼마인가요?",
"reference_answer": "35억 원입니다.",
"relevant_documents": [
"financial-report-2025-q2"
],
"relevant_chunks": [
"financial-report-2025-q2-chunk-17"
],
"relevance_scores": {
"financial-report-2025-q2-chunk-17": 3
},
"question_type": "single_hop_fact"
}
각 필드는 서로 다른 평가에 사용됩니다.
question
→ RAG 시스템에 입력할 질문
reference_answer
→ 기준이 되는 기대 답변
relevant_documents
→ 질문에 답하기 위해 검색되어야 하는 문서
relevant_chunks
→ 실제 정답 근거가 포함된 청크
relevance_scores
→ 각 문서나 청크가 질문에 얼마나 관련 있는지 나타내는 점수
question_type
→ 질문의 특성과 난이도를 구분하기 위한 유형
질문과 기대 답변만 있으면 최종 답변의 정확성을 평가할 수 있습니다.
정답 문서와 정답 청크까지 있으면 Retriever의 Recall@K, MRR, NDCG 같은 검색 지표도 계산할 수 있습니다.
관련도 점수까지 있으면 단순히 관련 있음과 관련 없음으로 나누는 것을 넘어, 직접적인 정답 근거와 참고용 문서를 구분해서 평가할 수 있습니다.
Ground Truth와 Golden Dataset은 무엇이 다를까요?
RAG 평가 자료를 찾아보면 Ground Truth와 Golden Dataset이라는 표현을 자주 볼 수 있습니다.
두 용어는 조직이나 평가 도구에 따라 조금씩 다르게 사용되기 때문에 절대적인 표준 정의가 있는 것은 아닙니다. 실무에서는 보통 다음과 같은 의미로 구분할 수 있습니다.
Ground Truth
Ground Truth는 특정 질문에 대해 정답이라고 간주하는 기준 정보입니다.
예를 들어 다음 정보가 Ground Truth가 될 수 있습니다.
질문: A사의 2025년 2분기 영업이익은 얼마인가요?
기대 답변: 35억 원입니다.
정답 문서: 2025년 2분기 실적 보고서
정답 청크: 영업이익은 35억 원으로 전년 동기 대비 8% 증가했습니다.
즉, Ground Truth는 개별 평가 샘플에 붙는 정답 레이블에 가깝습니다.
Golden Dataset
Golden Dataset은 검토가 완료된 고품질 Ground Truth 샘플을 모아놓은 평가 데이터셋을 의미하는 경우가 많습니다.
단순히 질문과 답변을 많이 모았다고 Golden Dataset이 되는 것은 아닙니다.
다음과 같은 조건을 만족해야 합니다.
- 질문이 실제 사용자의 질문 패턴을 반영합니다.
- 기대 답변이 원본 문서로 검증되어 있습니다.
- 정답 문서와 청크가 정확하게 연결되어 있습니다.
- 질문 유형과 난이도가 한쪽으로 치우치지 않습니다.
- 중복되거나 지나치게 비슷한 질문이 제거되어 있습니다.
- 학습 데이터와 평가 데이터가 분리되어 있습니다.
- 문서가 변경되었을 때 함께 갱신할 수 있습니다.
쉽게 정리하면 Ground Truth는 개별 문제의 정답이고, Golden Dataset은 검증된 문제와 정답을 모아놓은 시험지라고 볼 수 있습니다.
먼저 무엇을 평가할지 정해야 합니다
평가 데이터셋을 만들 때 가장 먼저 질문을 생성하면 안 됩니다.
먼저 RAG가 어떤 사용자를 위해 어떤 질문에 답해야 하는지 정해야 합니다.
예를 들어 사내 규정 검색 RAG를 평가한다고 가정해보겠습니다. 사용자는 다음과 같이 나뉠 수 있습니다.
- 신입 직원
- 팀 관리자
- 인사 담당자
- 재무 담당자
- 시스템 관리자
같은 문서를 보더라도 각 사용자가 하는 질문은 다릅니다.
신입 직원은 다음처럼 질문할 수 있습니다.
연차는 언제부터 사용할 수 있나요?
인사 담당자는 더 구체적인 조건을 포함해서 질문할 수 있습니다.
입사 1년 미만 직원의 연차 발생 기준과 미사용 연차 처리 방식을 알려주세요.
시스템 관리자는 문서의 위치나 적용 버전을 물을 수도 있습니다.
2026년 개정 연차 규정이 적용된 문서는 무엇인가요?
특정 유형의 질문만 평가하면 실제 사용 환경에서의 성능을 제대로 확인하기 어렵습니다.
따라서 평가 데이터셋을 만들기 전에 다음 내용을 정리하는 것이 좋습니다.
- 누가 이 RAG를 사용하는가?
- 어떤 문서를 검색하는가?
- 사용자는 어떤 목적으로 질문하는가?
- 정확한 사실 하나를 찾는가?
- 여러 문서를 비교하거나 종합해야 하는가?
- 답이 없는 질문에는 어떻게 대응해야 하는가?
이 과정에서 정의한 사용자와 사용 시나리오가 평가 데이터셋의 범위를 결정합니다.
평가 샘플에는 무엇이 들어가야 할까요?
평가 목적에 따라 필요한 필드는 달라지지만 RAG 전체를 평가하려면 다음 정도의 정보를 준비하는 것이 좋습니다.
evaluation_sample = {
"id": "hr-leave-001",
"question": "입사 1년 미만 직원의 연차는 어떻게 발생하나요?",
"reference_answer": (
"입사 1년 미만인 직원은 1개월을 개근할 때마다 "
"1일의 유급휴가가 발생합니다."
),
"relevant_documents": [
"leave-policy-2026"
],
"relevant_chunks": [
"leave-policy-2026-section-3-chunk-2"
],
"relevance_scores": {
"leave-policy-2026-section-3-chunk-2": 3,
"leave-policy-2026-section-4-chunk-1": 1
},
"question_type": "single_hop_fact",
"difficulty": "easy",
"persona": "new_employee",
"answerable": True,
"source_version": "2026-01",
"review_status": "approved"
}
여기에 포함된 모든 필드가 필수는 아닙니다. 다만 평가 데이터가 커질수록 질문과 답변 외의 메타데이터가 중요해집니다.
ID
각 샘플을 식별하기 위한 고유한 값입니다.
특정 질문의 평가 결과가 낮을 때 로그와 평가 데이터를 연결하려면 안정적인 ID가 필요합니다.
기대 답변
기대 답변은 가능한 한 원본 문서의 내용으로 검증해야 합니다.
지나치게 긴 모범 답변을 만들기보다 반드시 포함되어야 할 핵심 사실을 명확하게 적는 것이 좋습니다.
예를 들어 다음 질문이 있다고 하겠습니다.
배송비 환불 기준을 알려주세요.
기대 답변을 지나치게 장황하게 작성하면 평가 모델이 문장 표현의 차이에 영향을 받을 수 있습니다.
상품 불량 또는 오배송으로 반품하는 경우에는 판매자가
왕복 배송비를 부담하며, 단순 변심으로 반품하는 경우에는
구매자가 배송비를 부담합니다.
이처럼 답변에 반드시 들어가야 할 조건과 사실을 중심으로 작성하는 편이 좋습니다.
정답 문서와 정답 청크
문서 단위와 청크 단위를 함께 관리하는 것이 좋습니다. 문서 전체는 정답 문서이지만 검색된 청크에는 정답이 없을 수 있기 때문입니다.
정답 문서: 배송 및 환불 정책
정답 청크: 상품 불량이나 오배송으로 반품하는 경우 왕복 배송비는 판매자가 부담합니다.
검색 시스템이 청크 단위로 동작한다면 문서 단위 평가만으로는 실제 검색 실패를 정확하게 찾기 어렵습니다.
관련도 점수
모든 관련 문서가 같은 중요도를 가지는 것은 아닙니다. 다음처럼 관련도를 단계별로 정의할 수 있습니다.
3점: 질문의 답을 직접 포함한 핵심 근거
2점: 답변에 실질적으로 도움이 되는 보조 근거
1점: 주제는 관련 있지만 답변에는 거의 기여하지 않는 문서
0점: 질문과 관련 없는 문서
이 기준은 NDCG와 같이 관련도의 차이를 반영하는 검색 지표에 활용할 수 있습니다.
중요한 것은 점수 자체보다 평가자들이 같은 기준으로 판단할 수 있도록 구체적인 가이드라인을 만드는 것입니다.
사람이 직접 만든 질문은 현실적이지만 비용이 큽니다
가장 신뢰하기 쉬운 방법은 실제 사용자가 할 만한 질문을 사람이 직접 작성하는 것입니다.
특히 도메인을 잘 아는 사람이 질문과 기대 답변을 만들면 실제 업무에서 중요한 조건과 예외 사항을 반영할 수 있습니다.
예를 들어 휴가 규정 문서에 다음 내용이 있다고 가정해보겠습니다.
경조 휴가는 사유가 발생한 날을 기준으로 사용할 수 있으며,
휴일이 포함된 경우에도 휴가 일수에 산입합니다.
문서 내용을 그대로 질문으로 바꾸면 다음과 같은 질문이 나올 수 있습니다.
경조 휴가는 언제부터 사용할 수 있나요?
하지만 실제 담당자는 현장에서 자주 발생하는 예외를 알고 있습니다.
부모님 장례가 금요일에 발생하면 주말도 경조 휴가 일수에 포함되나요?
두 번째 질문이 실제 사용자에게는 더 중요할 수 있습니다. 사람이 직접 질문을 만드는 방식의 장점은 다음과 같습니다.
실제 업무에서 사용하는 표현을 반영할 수 있습니다.
문서에 명시되지 않은 애매한 부분을 발견할 수 있습니다.
중요한 예외 조건과 경계 사례를 포함할 수 있습니다.
도메인 특화 용어와 약어를 자연스럽게 사용할 수 있습니다.
답변할 수 없는 질문도 현실적으로 구성할 수 있습니다.
반면 단점도 분명합니다.
질문을 많이 만들수록 시간과 비용이 증가합니다.
작성자의 지식과 경험에 따라 질문이 편향될 수 있습니다.
쉬운 질문이나 익숙한 업무에 집중될 수 있습니다.
사람마다 정답 문서와 관련도 판단이 다를 수 있습니다.
그래서 모든 평가 질문을 사람이 직접 만드는 방식은 품질은 높지만 규모를 키우기 어렵습니다.
LLM으로 평가 질문을 만들어도 될까요?
LLM을 사용하면 문서에서 질문과 기대 답변을 빠르게 생성할 수 있습니다.
예를 들어 다음 청크가 있다고 가정해보겠습니다.
회원 탈퇴가 완료된 계정의 개인정보는 즉시 파기합니다.
다만 전자상거래법에 따라 거래 기록은 5년간 별도로 보관합니다.
LLM에 다음과 같은 형식으로 요청할 수 있습니다.
아래 문서를 바탕으로 실제 사용자가 할 법한 질문을 만들어주세요.
조건:
- 문서의 문장을 그대로 복사하지 않습니다.
- 질문에 답하려면 문서의 핵심 내용을 이해해야 합니다.
- 기대 답변과 근거 문장을 함께 반환합니다.
- 문서만으로 답할 수 없는 내용은 추가하지 않습니다.
- JSON 형식으로 반환합니다.
문서:
{document}
생성된 결과는 다음과 같은 형태가 될 수 있습니다.
{
"question": "회원 탈퇴 후에도 주문 기록이 남아 있나요?",
"reference_answer": "네. 개인정보는 파기되지만 거래 기록은 관련 법률에 따라 5년간 별도로 보관됩니다.",
"evidence": "전자상거래법에 따라 거래 기록은 5년간 별도로 보관합니다.",
"question_type": "single_hop_fact"
}
합성 질문의 장점은 다음과 같습니다.
- 많은 문서에서 빠르게 질문을 생성할 수 있습니다.
- 문서별 평가 샘플 수를 일정하게 맞출 수 있습니다.
- 특정 질문 유형을 지정해서 생성할 수 있습니다.
- 사람이 쉽게 떠올리지 못한 표현을 만들 수 있습니다.
- 평가 데이터가 없는 초기 단계에서 빠르게 시작할 수 있습니다.
하지만 합성 질문에는 중요한 한계가 있습니다.
질문이 문서 표현과 너무 비슷할 수 있습니다
문서를 보고 바로 질문을 생성하면 문서에 사용된 핵심 단어가 질문에도 그대로 포함되기 쉽습니다.
문서:
회원 탈퇴 시 거래 기록은 5년간 보관합니다.
합성 질문:
회원 탈퇴 시 거래 기록은 몇 년간 보관하나요?
이 질문은 검색하기 너무 쉽습니다.
실제 사용자는 다음처럼 표현할 수 있습니다.
계정을 지워도 예전에 주문한 내역이 남아 있나요?
평가 질문이 원문과 지나치게 비슷하면 검색 성능이 실제보다 높게 측정될 수 있습니다.
LLM이 문서에 없는 내용을 추가할 수 있습니다
질문을 다양하게 만들도록 요청하다 보면 원본 문서만으로 답할 수 없는 조건을 추가할 수 있습니다.
문서:
거래 기록은 5년간 보관합니다.
잘못 생성된 질문:
해외 사용자의 거래 기록도 5년간 보관하나요?
원본 문서에는 국내외 사용자 구분이 없습니다.
이 질문을 그대로 평가 데이터에 넣으면 기대 답변의 근거가 불분명해집니다.
특정 질문 형태로 편향될 수 있습니다
같은 프롬프트와 모델로 대량 생성하면 다음처럼 비슷한 문장 구조가 반복될 수 있습니다.
- ~은 무엇인가요?
- ~은 언제 적용되나요?
- ~은 몇 년간 보관되나요?
실제 사용자는 짧은 키워드, 구어체, 오타, 후속 질문 등 더 다양한 방식으로 질문합니다.
따라서 합성 질문은 자동 생성으로 끝내지 않고 사람이 검수해야 합니다.
사람과 LLM을 함께 사용하는 것이 현실적입니다
사람이 직접 만든 질문과 LLM이 생성한 질문 중 하나만 선택할 필요는 없습니다.
실무에서는 두 방식을 결합하는 것이 현실적입니다.
실제 사용자 질문과 전문가 작성 질문
→ 평가 데이터의 중심이 되는 핵심 세트
LLM으로 생성한 합성 질문
→ 문서 범위와 질문 유형을 넓히는 보조 세트
사람의 검수
→ 잘못된 질문과 근거가 불분명한 샘플 제거
예를 들어 다음과 같은 과정으로 만들 수 있습니다.
- 실제 사용자 로그에서 대표 질문을 수집합니다.
- 도메인 전문가가 중요한 질문과 예외 사례를 추가합니다.
- 아직 질문이 없는 문서에서는 LLM으로 합성 질문을 생성합니다.
- 질문 표현과 난이도가 비슷한 샘플을 제거합니다.
- 기대 답변과 정답 청크를 사람이 검증합니다.
- 질문 유형별 비율을 확인합니다.
- 최종 검수가 끝난 샘플만 Golden Dataset에 포함합니다.
이 방법을 사용하면 실제성을 유지하면서 문서와 질문 유형의 범위를 넓힐 수 있습니다.
Hard Negative는 왜 필요할까요?
평가 데이터에 정답 문서만 표시하면 RAG가 어느 정도로 정교하게 문서를 구분하는지 확인하기 어렵습니다.
예를 들어 질문이 다음과 같다고 하겠습니다.
A사의 2025년 2분기 영업이익은 얼마인가요?
다음 문서는 명백한 정답입니다.
A사의 2025년 2분기 영업이익은 35억 원입니다.
다음 문서는 질문과 전혀 관련이 없습니다.
사내 주차장 이용 시간은 오전 7시부터 오후 11시까지입니다.
RAG가 두 문서를 구분하는 것은 어렵지 않습니다. 하지만 다음 문서가 함께 있다면 어떨까요?
A사의 2024년 2분기 영업이익은 53억 원입니다.
회사명, 분기, 영업이익이라는 핵심 단어가 모두 들어 있습니다. 연도만 다릅니다.
이처럼 질문과 매우 비슷해 보이지만 실제 정답은 아닌 문서를 Hard Negative라고 합니다.
RAG 평가에서 사용할 수 있는 Hard Negative의 예시는 다음과 같습니다.
- 회사명은 같지만 기간이 다른 문서
- 제품명은 같지만 버전이 다른 문서
- 질문의 주제는 같지만 정답 수치가 없는 문서
- 비슷한 정책이지만 적용 대상이 다른 문서
- 같은 문서의 인접 청크이지만 정답 문장이 없는 청크
- 정답과 유사한 표현을 사용하지만 다른 조건을 설명하는 문서
Hard Negative가 포함되어야 RAG가 단순한 키워드 일치에 의존하는지, 질문의 조건까지 제대로 이해하는지 평가할 수 있습니다.
Hard Negative를 찾는 간단한 방법
현재 검색 시스템을 이용해 정답이 아닌 상위 검색 결과를 후보로 모을 수 있습니다.
def collect_hard_negative_candidates(
question: str,
relevant_chunk_ids: set[str],
retrieved_chunks: list[dict],
limit: int = 5,
) -> list[dict]:
candidates = []
for chunk in retrieved_chunks:
if chunk["chunk_id"] in relevant_chunk_ids:
continue
candidates.append({
"chunk_id": chunk["chunk_id"],
"content": chunk["content"],
"retrieval_score": chunk["score"],
})
if len(candidates) >= limit:
break
return candidates
검색 점수는 높지만 정답으로 표시되지 않은 청크를 Hard Negative 후보로 수집하는 방식입니다.
다만 자동으로 수집한 후보를 바로 Negative로 확정하면 안 됩니다.
정답 레이블에 빠진 관련 문서일 수도 있기 때문입니다. 이를 False Negative라고 합니다.
Hard Negative
→ 정답과 비슷하지만 실제로는 관련 없는 문서
False Negative
→ Negative로 표시했지만 실제로는 정답에 도움이 되는 문서
False Negative가 평가 데이터에 들어가면 RAG가 좋은 문서를 찾아도 오히려 감점될 수 있습니다.
따라서 Hard Negative 후보는 사람이 직접 확인하거나 별도의 검수 단계를 거쳐야 합니다.
질문 유형을 나눠야 병목이 보입니다
평가 질문을 무작위로 많이 모으는 것만으로는 충분하지 않습니다.
질문의 특성에 따라 RAG가 어려워하는 지점이 다르기 때문입니다.
평가 목적에 맞춰 다음처럼 질문 유형을 구성할 수 있습니다.
단일 사실 질문
하나의 청크에서 정답을 찾을 수 있는 질문입니다.
회원 탈퇴 후 거래 기록은 몇 년간 보관하나요?
기본적인 검색과 답변 생성 능력을 확인할 수 있습니다.
조건이 포함된 질문
기간, 대상, 상태와 같은 조건을 정확하게 구분해야 합니다.
입사 1년 미만 직원에게 적용되는 연차 기준은 무엇인가요?
유사한 문서 중 올바른 조건을 찾는 능력을 평가할 수 있습니다.
비교 질문
두 개 이상의 대상이나 기준을 비교해야 합니다.
일반 회원과 판매자 회원의 탈퇴 절차는 어떻게 다른가요?
여러 청크나 문서를 함께 검색해야 할 수 있습니다.
Multi-hop 질문
한 문서에서 찾은 정보를 바탕으로 다른 문서까지 확인해야 합니다.
A 상품에 적용되는 환불 정책은 무엇이며, 해당 정책에서 정한 반품 가능 기간은 며칠인가요?
상품의 정책 유형을 먼저 찾고, 해당 정책 문서에서 기간을 다시 확인해야 할 수 있습니다.
표와 숫자 질문
표, 통계, 수치 계산이 필요한 질문입니다.
1분기와 2분기의 영업이익 차이는 얼마인가요?
문서 파싱과 숫자 처리 능력을 함께 평가할 수 있습니다.
자연어 변형 질문
문서에 나온 표현과 다른 단어를 사용한 질문입니다.
계정 없애면 예전 주문 기록도 바로 지워지나요?
동의어나 구어체 표현을 RAG가 이해하는지 확인할 수 있습니다.
대화형 후속 질문
이전 질문의 문맥이 있어야 이해할 수 있습니다.
사용자:
회원 탈퇴 후 거래 기록은 얼마나 보관하나요?
사용자:
그 기간이 지나면 어떻게 되나요?
질문 재작성과 대화 문맥 처리 능력을 평가할 수 있습니다.
답변할 수 없는 질문
지식 베이스에 답이 없는 질문도 반드시 포함해야 합니다.
내년에 개인정보 보관 기간이 변경될 예정인가요?
문서에 예정된 변경 내용이 없다면 RAG는 모른다고 답해야 합니다.
답이 있는 질문만 평가하면 모델이 근거 없이 답을 만들어내는 문제를 확인하기 어렵습니다.
질문 유형의 비율도 중요합니다
평가 데이터셋에 단순 사실 질문만 많으면 전체 점수는 높게 나올 수 있습니다.
하지만 실제 사용자가 비교 질문이나 조건이 복잡한 질문을 많이 한다면 그 점수는 실제 품질을 대표하지 못합니다.
예를 들어 다음과 같은 평가 데이터셋이 있다고 가정해보겠습니다.
단일 사실 질문: 90개
비교 질문: 5개
Multi-hop 질문: 3개
답변 불가능 질문: 2개
전체 정확도가 높더라도 복잡한 질문에 대한 성능은 거의 검증되지 않은 상태입니다.
질문 유형의 비율을 정할 때는 실제 사용자 로그를 참고하는 것이 가장 좋습니다.
아직 사용자 로그가 없다면 서비스에서 예상되는 주요 사용 시나리오를 기준으로 구성한 뒤, 운영 데이터가 쌓일 때마다 비율을 조정할 수 있습니다.
중요한 것은 모든 유형을 같은 비율로 만드는 것이 아니라 실제 사용 환경을 대표하도록 만드는 것입니다.
학습 데이터와 평가 데이터가 섞이면 안 됩니다
평가 데이터셋을 만들 때 가장 주의해야 할 문제 중 하나가 데이터 오염입니다.
RAG 프로젝트에서는 다음과 같은 상황에서 평가 데이터가 오염될 수 있습니다.
- 평가 질문을 임베딩 모델 파인튜닝에 사용했습니다.
- 평가 질문과 정답 문서 쌍을 Reranker 학습에 사용했습니다.
- 평가 결과가 낮은 질문을 반복해서 보며 프롬프트를 수정했습니다.
- 평가 질문을 합성할 때 사용한 문서와 거의 같은 문서를 학습에 사용했습니다.
- 같은 원본 문서에서 생성된 유사 질문이 학습 세트와 평가 세트에 나뉘어 들어갔습니다.
평가 질문을 보고 시스템을 계속 수정하면 해당 질문에는 점점 잘 답하게 됩니다.
하지만 새로운 질문에도 잘 답하는지는 알 수 없습니다.
쉽게 말하면 시험 문제를 미리 보고 답을 외운 뒤 같은 문제로 다시 시험을 보는 것과 같습니다.
행 단위가 아니라 문서 단위로 분리합니다
같은 문서에서 생성된 질문을 무작위로 나누면 매우 비슷한 질문이 학습 세트와 평가 세트에 함께 들어갈 수 있습니다.
학습 질문: 회원 탈퇴 후 거래 기록은 몇 년간 보관하나요?
평가 질문: 계정을 삭제해도 거래 기록을 5년간 보관하나요?
표현만 다를 뿐 사실상 같은 문제입니다. 그래서 가능하다면 질문 행 단위가 아니라 원본 문서, 문서 그룹, 기간을 기준으로 데이터를 분리하는 것이 좋습니다.
Train
→ 모델이나 검색 설정을 학습하는 데 사용
Validation
→ 파라미터와 프롬프트를 조정하는 데 사용
Test
→ 최종 성능을 확인하는 데만 사용
Test 세트는 가능하면 자주 들여다보지 않고, 최종 비교 시점에만 사용하는 것이 좋습니다.
최신 문서를 별도로 보관할 수도 있습니다
오래된 공개 문서에서 생성한 질문은 LLM이 사전 학습 과정에서 이미 접했을 가능성을 완전히 배제하기 어렵습니다.
중요한 평가에서는 최근 추가된 내부 문서나 특정 시점 이후의 문서를 별도 평가 세트로 구성할 수 있습니다.
시간을 기준으로 나누면 기존 문서에 맞춰 개선한 시스템이 새로운 문서에서도 잘 동작하는지 확인할 수 있습니다.
합성 데이터 자체가 편향될 수 있습니다
데이터 오염과 함께 평가 편향도 주의해야 합니다.
평가 데이터셋을 만드는 사람이나 생성 모델의 특성이 질문에 반영될 수 있기 때문입니다.
작성자 편향
도메인 전문가가 질문을 만들면 전문 용어와 정식 표현을 많이 사용할 수 있습니다.
하지만 실제 사용자는 약어, 오타, 모호한 표현을 사용할 수 있습니다.
모델 편향
LLM으로 질문을 생성하면 문법적으로 완성된 질문이 과도하게 많아질 수 있습니다.
실제 사용자 질문: 반품 배송비 누가 냄?
합성 질문: 상품 반품 시 배송비 부담 주체는 누구인가요?
두 질문은 같은 의미이지만 검색 난이도는 다를 수 있습니다.
문서 편향
질문을 문서에서만 생성하면 지식 베이스에 존재하는 정보만 평가하게 됩니다.
실제 사용자가 자주 묻지만 문서에는 없는 질문을 발견하지 못할 수 있습니다.
난이도 편향
질문 생성 모델은 명확한 한 문장에서 답을 찾을 수 있는 쉬운 질문을 선호할 수 있습니다.
표, 각주, 여러 문서에 걸친 정보, 예외 조건은 평가 데이터에서 빠질 가능성이 있습니다.
이러한 편향을 줄이려면 다음 방법을 사용할 수 있습니다.
- 실제 사용자 로그를 일정 비율 포함합니다.
- 여러 직무의 검수자가 질문을 작성합니다.
- 질문 유형과 난이도를 명시적으로 지정합니다.
- 서로 다른 생성 프롬프트와 모델을 사용합니다.
- 구어체, 약어, 오타가 포함된 질문을 별도로 만듭니다.
- 답이 없는 질문과 애매한 질문을 포함합니다.
- 문서별·주제별 샘플 수를 확인합니다.
평가 데이터의 품질을 검사하는 코드
평가 데이터가 많아지면 사람이 모든 오류를 찾기 어렵습니다. 다음과 같은 기본 검증은 코드로 자동화할 수 있습니다.
from collections import Counter
from typing import Any
def validate_evaluation_dataset(
samples: list[dict[str, Any]],
) -> list[str]:
errors: list[str] = []
seen_questions: set[str] = set()
for index, sample in enumerate(samples):
sample_id = sample.get("id", f"row-{index}")
question = sample.get("question", "").strip()
reference_answer = sample.get("reference_answer", "").strip()
relevant_documents = sample.get("relevant_documents", [])
relevant_chunks = sample.get("relevant_chunks", [])
if not question:
errors.append(f"{sample_id}: 질문이 없습니다.")
if not reference_answer and sample.get("answerable", True):
errors.append(f"{sample_id}: 기대 답변이 없습니다.")
normalized_question = " ".join(question.lower().split())
if normalized_question in seen_questions:
errors.append(f"{sample_id}: 중복 질문입니다.")
else:
seen_questions.add(normalized_question)
if sample.get("answerable", True) and not relevant_documents:
errors.append(f"{sample_id}: 정답 문서가 없습니다.")
if sample.get("answerable", True) and not relevant_chunks:
errors.append(f"{sample_id}: 정답 청크가 없습니다.")
question_types = Counter(
sample.get("question_type", "unknown")
for sample in samples
)
if len(question_types) == 1:
errors.append(
"모든 질문의 유형이 같습니다. "
"평가 범위가 한쪽으로 치우쳤을 수 있습니다."
)
return errors
이 코드는 다음 항목을 확인합니다.
- 질문과 기대 답변이 비어 있지 않은가?
- 답할 수 있는 질문에 정답 문서와 청크가 연결되어 있는가?
- 같은 질문이 중복되어 있지 않은가?
- 질문 유형이 하나로만 구성되어 있지 않은가?
여기에 프로젝트 상황에 맞는 검증을 추가할 수 있습니다.
- 정답 청크가 실제 정답 문서에 속하는가?
- 기대 답변의 핵심 사실이 정답 청크에 존재하는가?
- 관련도 점수가 정해진 범위 안에 있는가?
- 폐기된 문서 버전을 참조하고 있지 않은가?
- 개인정보나 민감 정보가 포함되어 있지 않은가?
- Train과 Test에 유사한 질문이 중복되어 있지 않은가?
자동 검증은 형식 오류를 찾는 데 유용하지만, 질문의 자연스러움과 정답의 타당성까지 완전히 판단할 수는 없습니다.
최종 Golden Dataset에는 사람의 검수 과정이 필요합니다.
평가 데이터는 한 번 만들고 끝나는 자료가 아닙니다
RAG의 지식 베이스는 계속 변합니다.
정책이 개정되고 상품 정보가 바뀌며 새로운 문서가 추가됩니다. 기존 문서가 삭제되거나 청킹 방식이 바뀌면서 청크 ID가 달라질 수도 있습니다.
이때 평가 데이터가 이전 문서를 계속 참조하면 정상적인 RAG도 오답으로 평가될 수 있습니다.
그래서 평가 데이터에도 버전 관리가 필요합니다.
{
"dataset_version": "2026-07-01",
"source_version": "policy-v3",
"created_at": "2026-07-01",
"reviewed_at": "2026-07-15",
"reviewer": "hr-policy-team",
"status": "active"
}
문서가 변경되었을 때는 다음 항목을 확인해야 합니다.
- 기대 답변이 여전히 유효한가?
- 정답 문서가 삭제되거나 교체되지 않았는가?
- 정답 청크 ID가 변경되지 않았는가?
- 관련도 점수를 다시 판단해야 하는가?
- 질문이 현재 정책에서도 답할 수 있는가?
평가 데이터는 제품 코드와 마찬가지로 관리해야 하는 자산입니다.
Golden Dataset을 만드는 현실적인 순서
지금까지의 내용을 실제 작업 순서로 정리하면 다음과 같습니다.
처음부터 수천 개의 완벽한 평가 샘플을 만들 필요는 없습니다.
- RAG의 사용자와 주요 사용 시나리오를 정의합니다.
- 평가해야 할 문서와 기능의 범위를 정합니다.
- 실제 사용자 질문과 전문가 작성 질문을 수집합니다.
- 부족한 문서와 질문 유형은 LLM으로 보완합니다.
- 각 질문의 기대 답변을 원본 문서로 검증합니다.
- 정답 문서와 정답 청크를 연결합니다.
- 필요하다면 관련도 점수를 부여합니다.
- 검색 상위 결과에서 Hard Negative 후보를 수집합니다.
- False Negative가 없는지 사람이 검수합니다.
- 질문 유형과 난이도의 분포를 확인합니다.
- Train, Validation, Test 데이터를 문서 단위로 분리합니다.
- 중복, 누락, 오래된 문서를 자동으로 검사합니다.
- 검수가 완료된 샘플만 Golden Dataset에 포함합니다.
- 문서와 사용자 패턴의 변화에 맞춰 주기적으로 갱신합니다.
적은 수로 시작하더라도 실제로 중요한 질문과 실패하기 쉬운 질문을 포함하는 것이 중요합니다.
샘플 수만 많은 데이터셋보다, 평가 목적과 정답 근거가 명확한 데이터셋이 더 유용합니다.
중간 정리
| 구성 요소 | 역할 | 주의할 점 |
| 질문 | 실제 사용자 요청을 재현 | 문서 표현을 그대로 복사하지 않기 |
| 기대 답변 | 생성 답변 평가의 기준 | 원본 문서로 검증하기 |
| 정답 문서 | 검색되어야 할 문서 정의 | 문서 버전 함께 관리하기 |
| 정답 청크 | 직접적인 근거 위치 정의 | 실제 검색 단위와 맞추기 |
| 관련도 점수 | 문서별 중요도 구분 | 평가 기준을 구체적으로 작성하기 |
| 합성 질문 | 평가 범위와 규모 확장 | 사람이 검수하고 실제 질문과 혼합하기 |
| Hard Negative | 유사한 오답 문서 구분 능력 평가 | False Negative 여부 확인하기 |
| 질문 유형 | 특정 유형의 병목 분석 | 실제 사용자 분포를 반영하기 |
| 데이터 분리 | 과적합과 오염 방지 | 질문이 아닌 문서 단위로 분리하기 |
| 버전 관리 | 문서 변경에 대응 | 오래된 정답과 청크 제거하기 |
평가 데이터셋의 핵심은 질문을 많이 모으는 것이 아닙니다.
- 실제 사용자를 대표하는 질문인가?
- 기대 답변이 근거 문서로 검증되었는가?
- 검색되어야 하는 문서와 청크가 명확한가?
- 쉬운 질문과 어려운 질문이 적절히 포함되어 있는가?
- 학습에 사용한 데이터와 분리되어 있는가?
이 질문에 답할 수 있어야 평가 점수도 의미를 가질 수 있습니다.
마치며
RAG 평가 지표를 계산하는 것 자체는 어렵지 않습니다. 하지만 그 점수를 믿을 수 있으려면 먼저 신뢰할 수 있는 평가 데이터셋이 필요합니다.
질문과 기대 답변만 있으면 최종 답변의 정확성을 확인할 수 있습니다. 정답 문서와 정답 청크를 추가하면 검색 성능도 평가할 수 있습니다. 관련도 점수와 Hard Negative까지 준비하면 검색 결과의 순위와 조건 구분 능력을 더 세밀하게 살펴볼 수 있습니다.
다만 평가 데이터가 많다고 해서 반드시 좋은 것은 아닙니다.
원문 표현을 그대로 바꾼 쉬운 합성 질문만 수천 개 있는 데이터셋은 실제 사용자 질문을 제대로 대표하지 못할 수 있습니다. 반대로 실제 사용자가 자주 묻는 질문, 복잡한 조건이 포함된 질문, 여러 문서를 확인해야 하는 질문, 답변할 수 없는 질문이 고르게 포함되어 있다면 비교적 작은 데이터셋도 중요한 병목을 발견하는 데 도움이 됩니다.
사람이 만든 질문은 현실적인 사용 패턴과 도메인 지식을 반영할 수 있지만 만드는 비용이 큽니다. LLM으로 생성한 질문은 빠르게 범위를 넓힐 수 있지만 표현과 난이도가 편향될 수 있습니다.
그래서 두 방식을 적절히 섞고, 최종적으로 사람이 정답과 근거를 검증하는 과정이 필요합니다.
결국 좋은 Golden Dataset은 다음 세 가지를 갖춰야 합니다.
- 실제 사용 환경을 대표하는 질문
- 원본 문서로 검증된 정답과 근거
- 학습 과정과 분리된 공정한 평가 구조
RAG를 개선하는 과정에서는 임베딩 모델이나 프롬프트만큼 평가 데이터셋도 중요한 자산입니다.
시험지가 잘못되어 있다면 높은 점수도 믿을 수 없고, 낮은 점수를 보고 엉뚱한 부분을 개선할 수도 있습니다.
평가 데이터셋을 만드는 일은 단순히 테스트용 질문을 준비하는 작업이 아닙니다. 우리가 만든 RAG가 무엇을 잘해야 하는지 구체적으로 정의하는 과정입니다.
참고 자료
- Ragas 공식 문서 - Testset Generation
- Ragas 공식 문서 - Testset Generation for RAG
- Ragas 공식 문서 - Persona Generation
- RAGEval: Scenario Specific RAG Evaluation Dataset Generation Framework
- Dense Passage Retrieval for Open-Domain Question Answering
- Passage-based BM25 Hard Negatives: A Simple and Effective Negative Sampling Strategy for Dense Retrieval
- BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models
- LatestEval: Addressing Data Contamination in Language Model Evaluation through Dynamic and Time-Sensitive Test Construction
'AI' 카테고리의 다른 글
| [바미] RAG는 왜 틀린 답을 할까? (0) | 2026.07.26 |
|---|---|
| [바미] 검색 결과는 몇 개까지 봐야 할까? - 상위 K개 평가 이해하기 (0) | 2026.07.25 |
| [바미] RAG가 틀렸을 때 RAG의 문제일까? LLM의 문제일까? (2) | 2026.07.23 |
| [바미] RAG 검색 성능은 어떻게 평가할까? - Precision부터 NDCG까지 (2) | 2026.07.22 |
| [바미] Claude Sonnet 5가 공개되었습니다. (0) | 2026.07.01 |