ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RAG 성능 측정의 핵심: RAGAS Ground Truth 준비 완벽 가이드
    IT 2026. 3. 27. 22:00
    RAG 성능 측정의 핵심: RAGAS Ground Truth 준비 완벽 가이드

    왜 Ground Truth가 중요한가

    회사에서 RAG(Retrieval-Augmented Generation, 검색 증강 생성) 기반 챗봇을 만들었다고 해봅시다. "우리 제품 보증 기간은 얼마야?"라는 질문에 봇이 "2년입니다"라고 답했는데, 이게 정말 맞는 답일까요? 그리고 검색 과정에서 관련 문서를 제대로 찾았을까요?

    이런 의문을 해결하려면 정답 데이터(Ground Truth)가 있어야 합니다. 정답이 뭔지 모르면 시스템이 잘하고 있는지, 어디가 문제인지 알 수가 없거든요. 마치 시험 채점을 할 때 정답지가 없는 것과 같습니다.

    특히 RAG 시스템은 두 가지를 동시에 평가해야 합니다:

    • 검색 성능: 관련 문서를 제대로 찾았는가?
    • 생성 성능: 찾은 문서를 바탕으로 정확한 답변을 만들었는가?

    RAGAS(RAG Assessment)는 이런 평가를 자동화해주는 도구인데, 핵심 메트릭들은 Ground Truth 없이는 측정이 불가능합니다.

    실생활 활용 사례

    사례 1: 고객 서비스 챗봇 성능 개선

    온라인 쇼핑몰에서 고객 문의를 처리하는 챗봇을 운영한다고 해봅시다. "환불은 언제까지 가능한가요?" 같은 질문에 봇이 정확히 답하는지 확인하려면, 미리 준비된 질문-정답 쌍(Ground Truth)으로 주기적 평가가 필요합니다. 이를 통해 봇의 정확도가 떨어지는 시점을 빠르게 감지하고 개선할 수 있습니다.

    사례 2: 사내 문서 검색 시스템 구축

    회사 내부 규정이나 매뉴얼을 검색하는 시스템을 만들 때도 마찬가지입니다. "연차 사용 규칙이 어떻게 돼?"라는 질문에 시스템이 올바른 규정 문서를 찾고 정확한 답변을 생성하는지 검증하려면, 인사팀에서 작성한 표준 답변(Ground Truth)과 비교 평가해야 합니다.

    RAGAS에서 Ground Truth란 무엇인가

    RAGAS에서는 평가용 정답 데이터를 Ground Truth라 부르고, 이런 데이터로 구성된 전체 테스트 셋을 Golden Set이라 합니다. 두 용어는 본질적으로 같은 의미로, "Gold Standard Test Set"이라고도 부릅니다.

    diagram

    Ground Truth는 두 가지 구성 요소가 있습니다:

    • Ground Truth Answer (reference): 해당 질문에 대한 기대 정답. 사람이 직접 작성한 참조 답변입니다.
    • Ground Truth Contexts (reference_contexts): 그 질문에 답하기 위해 반드시 검색되어야 하는 문서나 문단 목록입니다.

    어떤 메트릭이 Ground Truth를 필요로 하는가

    RAGAS의 모든 메트릭이 Ground Truth를 요구하는 건 아닙니다. 일부는 시스템 응답만으로도 측정 가능하지만, 핵심 성능 지표들은 정답 데이터가 반드시 필요합니다.

    메트릭 Ground Truth 필요 사용 필드 측정 내용
    Context Recall (LLM) ✅ 필요 reference 검색 누락률
    Context Recall (Non-LLM) ✅ 필요 reference_contexts 검색 누락률
    Context Precision ✅ 필요 reference 또는 reference_contexts 검색 정밀도
    Answer Correctness ✅ 필요 reference 답변 정확도
    Answer Similarity ✅ 필요 reference 답변 유사도
    Faithfulness ❌ 불필요 - 응답 신뢰도
    Answer Relevancy ❌ 불필요 - 응답 관련성

    이 중에서도 특히 Context RecallAnswer Correctness는 RAG 시스템의 핵심 성능을 보여주는 지표입니다. Context Recall은 "필요한 문서를 빠뜨리지 않고 잘 찾았는가"를, Answer Correctness는 "찾은 문서로 정확한 답을 만들었는가"를 측정합니다.

    RAGAS 데이터 포맷 이해하기

    이 단계를 왜 하는지: RAGAS는 버전에 따라 데이터 포맷이 다르므로, 현재 사용하는 버전에 맞는 형식으로 Ground Truth를 준비해야 합니다.

    v0.2 (최신 버전) - SingleTurnSample 방식

    최신 버전에서는 SingleTurnSample 클래스를 사용합니다. 각 대화 턴을 하나의 샘플로 표현하는 방식입니다.

    from ragas import EvaluationDataset, SingleTurnSample
    
    samples = [
        SingleTurnSample(
            user_input="한국의 수도는 어디인가?",
            retrieved_contexts=["한국의 수도는 서울이다. 서울은 한강 유역에 위치한다."],
            response="한국의 수도는 서울입니다.",
            reference="서울",                          # Ground Truth 정답
            reference_contexts=[                       # Ground Truth 컨텍스트
                "한국의 수도는 서울이다. 서울은 한강 유역에 위치한다."
            ]
        ),
    ]
    
    dataset = EvaluationDataset(samples=samples)
    
    💡 실행 결과:
    EvaluationDataset 생성 완료
    - 샘플 개수: 1
    - 포함된 필드: user_input, retrieved_contexts, response, reference, reference_contexts
    - 평가 가능한 메트릭: Context Recall, Answer Correctness, Context Precision

    v0.1 (레거시 버전) - HuggingFace Dataset 방식

    구 버전에서는 HuggingFace의 Dataset 형식을 사용했습니다. 기존 프로젝트가 이 방식을 쓰고 있다면 참고하세요.

    from datasets import Dataset
    
    eval_dataset = Dataset.from_dict({
        "question": ["한국의 수도는 어디인가?"],
        "answer": ["한국의 수도는 서울입니다."],        # RAG 시스템이 생성한 답변
        "contexts": [["한국의 수도는 서울이다."]],       # RAG 시스템이 검색한 컨텍스트
        "ground_truth": ["서울"]                        # 사람이 작성한 정답
    })
    

    버전 간 필드 매핑

    v0.1 (구버전) v0.2 (신버전) 설명
    question user_input 사용자 질문
    answer response RAG 시스템 응답
    contexts retrieved_contexts 검색된 컨텍스트
    ground_truth reference Ground Truth 정답
    (없음) reference_contexts Ground Truth 컨텍스트

    Context Recall 측정 원리

    이 개념을 왜 알아야 하는지: Context Recall은 RAG 시스템의 검색 성능을 보여주는 핵심 지표입니다. 이 계산 원리를 이해해야 Ground Truth를 제대로 작성할 수 있습니다.

    Context Recall은 "Ground Truth에 있는 정보 중에서 실제로 검색된 비율"을 측정합니다. 쉽게 말해, 정답에 필요한 정보를 얼마나 빠뜨리지 않고 찾았는지를 보는 거죠.

    diagram

    위 예시에서 Ground Truth에는 두 가지 정보가 있습니다:

    1. "서울 인구 950만명" (검색 컨텍스트에서 뒷받침됨)
    2. "수도권 전체 2600만명" (검색 컨텍스트에서 빠짐)

    따라서 2개 정보 중 1개만 뒷받침되므로 Context Recall = 0.5가 됩니다.

    LLM 기반 vs Non-LLM 기반 측정

    Context Recall 측정 방식은 두 가지가 있습니다:

    # LLM 기반 (의미적 매칭)
    from ragas.metrics import LLMContextRecall
    from ragas import evaluate
    
    results = evaluate(
        dataset=dataset,
        metrics=[LLMContextRecall()],
        llm=evaluator_llm,
    )
    
    💡 실행 결과:
    {'LLMContextRecall': 0.75}
    
    # 의미적으로 유사한 문장도 매칭됨
    # 예: "서울 인구는 950만" ≈ "서울시 인구 950만명"
    # Non-LLM 기반 (문자열 매칭)
    from ragas.metrics import NonLLMContextRecall
    
    sample = SingleTurnSample(
        user_input="서울의 인구는?",
        retrieved_contexts=["서울특별시의 인구는 약 950만 명이다."],
        reference_contexts=[  # 이 방식에서는 reference_contexts 사용
            "서울특별시의 인구는 약 950만 명이다.",
            "수도권 전체 인구는 약 2,600만 명이다."
        ],
    )
    # reference_contexts 2개 중 1개만 검색됨 → recall = 0.5
    
    ⚡ 성능 비교:
    • LLM 기반: 높은 정확도, 의미적 매칭, 비용/시간 소요
    • Non-LLM 기반: 빠른 속도, 정확한 문자열 매칭 필요, 저비용

    LLM 기반은 의미적으로 유사한 문장도 매칭해주지만, Non-LLM 기반은 정확한 문자열 일치를 요구합니다. 정확도를 원한다면 LLM 기반을, 속도와 비용을 고려한다면 Non-LLM 기반을 선택하세요.

    Ground Truth 준비 방법

    이 단계를 왜 하는지: 좋은 Ground Truth가 있어야 정확한 평가가 가능합니다. 다음 세 가지 방법 중 상황에 맞는 방식을 선택해야 합니다.

    방법 1: 수동 작성 (가장 정확)

    도메인 전문가가 직접 질문-정답 쌍을 작성하는 방법입니다. 시간이 오래 걸리지만 가장 정확합니다.

    ground_truth_data = [
        {
            "user_input": "RAGAS에서 faithfulness란 무엇인가?",
            "reference": "Faithfulness는 생성된 답변이 주어진 컨텍스트에 의해 사실적으로 뒷받침되는 정도를 측정하는 메트릭이다. 답변에 포함된 모든 주장이 제공된 문서에서 검증 가능해야 한다.",
            "reference_contexts": [
                "Faithfulness metric measures how factually consistent the generated answer is with the given context."
            ]
        },
        # 더 많은 QA 쌍들...
    ]
    

    주의사항: 도메인 지식이 있는 사람이 작성해야 하고, 질문마다 완전하고 정확한 답을 만드는 데 시간이 많이 소요됩니다. 하지만 가장 신뢰할 수 있는 평가 기준이 됩니다.

    방법 2: RAGAS TestsetGenerator로 자동 생성

    RAGAS가 원본 문서를 분석해서 자동으로 테스트 데이터를 생성해주는 방법입니다. 빠르지만 검토가 필요합니다.

    from ragas.testset import TestsetGenerator
    from langchain_community.document_loaders import DirectoryLoader
    
    # 1단계: 원본 문서 로드
    loader = DirectoryLoader("./documents/", glob="**/*.txt")
    documents = loader.load()
    
    # 2단계: 테스트셋 자동 생성
    generator = TestsetGenerator(llm=generator_llm)
    testset = generator.generate_with_langchain_docs(
        documents=documents,
        testset_size=20,  # 생성할 QA 쌍 개수
    )
    
    💡 실행 결과:
    문서 처리 중... 100%|██████████| 15/15 files
    테스트셋 생성 중... 100%|██████████| 20/20 samples
    
    생성 완료:
    - 총 QA 쌍: 20개
    - 단순 질문: 8개 (40%)
    - 추론 질문: 7개 (35%)
    - 멀티홉 질문: 5개 (25%)

    주의사항: 자동 생성된 데이터는 반드시 도메인 전문가가 검토해야 합니다. LLM이 만든 테스트 데이터에는 hallucination(환각)이 포함될 수 있기 때문입니다.

    결과 확인: 생성된 후에는 몇 개 샘플을 직접 확인해보세요. 질문이 자연스러운지, 정답이 정확한지 체크가 필요합니다.

    # 생성된 데이터 확인
    print(f"생성된 QA 쌍 개수: {len(testset)}")
    for i, sample in enumerate(testset[:3]):  # 처음 3개만 확인
        print(f"\n질문 {i+1}: {sample.user_input}")
        print(f"정답: {sample.reference}")
    
    🔍 샘플 출력 예시:
    생성된 QA 쌍 개수: 20
    
    질문 1: Context Precision은 어떻게 계산되는가?
    정답: Context Precision은 검색된 컨텍스트 중에서 질문과 실제로 관련있는 컨텍스트의 비율을 측정한다.
    
    질문 2: RAG 시스템에서 retrieval과 generation의 차이점은?
    정답: Retrieval은 사용자 질문과 관련된 문서를 찾는 과정이고, generation은 찾은 문서를 바탕으로 답변을 생성하는 과정이다.

    방법 3: 기존 QA 데이터 변환

    이미 FAQ나 고객 문의 데이터가 있다면, 이를 RAGAS 포맷으로 변환할 수 있습니다.

    import pandas as pd
    
    # 기존 FAQ 데이터 로드
    qa_data = pd.read_csv("faq_data.csv")  # question, expected_answer 컬럼 포함
    
    samples = []
    for _, row in qa_data.iterrows():
        # 현재 RAG 시스템으로 실제 검색 및 생성 수행
        retrieved = my_rag.retrieve(row["question"])
        response = my_rag.generate(row["question"])
        
        # RAGAS 포맷으로 변환
        sample = SingleTurnSample(
            user_input=row["question"],
            retrieved_contexts=[doc.page_content for doc in retrieved],
            response=response,
            reference=row["expected_answer"],  # 기존 FAQ 정답 활용
        )
        samples.append(sample)
    

    장점: 실제 사용자 질문을 바탕으로 하므로 현실적인 평가가 가능합니다. 기존에 축적된 데이터를 활용할 수 있어 효율적입니다.

    주의사항: 기존 FAQ 답변의 품질을 미리 확인하고, 현재 문서와 일치하는지 검증해야 합니다. 오래된 정보가 포함되어 있을 수 있기 때문입니다.

    Ground Truth 작성 Best Practices

    이 가이드를 왜 따라야 하는지: 잘못 작성된 Ground Truth는 평가 결과를 왜곡시킵니다. 다음 원칙들을 지켜야 정확한 성능 측정이 가능합니다.

    1. 완전한 문장으로 작성하기

    ❌ 잘못된 예: reference="서울"

    ✅ 올바른 예: reference="한국의 수도는 서울이다."

    이유: Context Recall은 Ground Truth를 문장 단위로 분해해서 측정합니다. 단답형으로 쓰면 분해가 제대로 안 되어 측정이 부정확해집니다.

    2. 핵심 정보를 빠짐없이 포함하기

    # 복합 질문의 예
    user_input = "서울의 인구와 면적은?"
    
    # ❌ 불완전한 Ground Truth
    reference = "서울의 인구는 약 950만 명이다."
    
    # ✅ 완전한 Ground Truth  
    reference = "서울의 인구는 약 950만 명이고, 면적은 605.21㎢이다."
    

    이유: Ground Truth에 누락된 정보는 recall 측정 대상에서 빠집니다. 질문에 대한 완전한 답을 적어야 정확한 평가가 가능합니다.

    3. reference_contexts는 실제 청크 사용하기

    # 실제 문서를 chunking했을 때의 텍스트를 그대로 사용
    reference_contexts = [
        "서울특별시는 대한민국의 수도이며 최대 도시이다. 인구는 약 950만 명(2023년 기준)으로 전국 인구의 약 18%를 차지한다.",
        "서울의 총 면적은 605.21㎢로, 이는 전국 토지 면적의 0.6%에 해당한다. 25개 자치구로 구성되어 있다."
    ]
    

    이유: NonLLMContextRecall에서는 문자열 정확 매칭을 하므로, 실제 검색되는 청크와 동일한 텍스트여야 합니다.

    4. 다양한 질문 유형 포함하기

    • 사실 확인: "제품 보증 기간은?"
    • 비교/대조: "A와 B의 차이점은?"
    • 인과관계: "왜 이런 현상이 발생하는가?"
    • 요약: "이 정책의 주요 내용은?"
    • 멀티홉: "A의 특징과 B의 장점을 결합하면?" (여러 문서 조합)

    이유: 실제 사용자는 다양한 형태의 질문을 하므로, 골고루 테스트해야 시스템의 전반적 성능을 파악할 수 있습니다.

    5. 적정 크기 유지하기

    • 최소: 30~50개 (빠른 테스트용)
    • 이상적: 100개 이상 (신뢰할 만한 평가용)
    • 실무: 도메인별로 20~30개씩 분할해서 관리

    도메인별 분할 예시:

    도메인 QA 쌍 수 질문 예시
    제품 정보 25개 "보증 기간은?", "사용법은?"
    정책/규정 30개 "환불 조건은?", "배송 정책은?"
    기술 지원 20개 "오류 해결 방법은?", "설정 변경은?"

    6. 주기적 업데이트 하기

    원본 문서가 변경되거나 새로운 정책이 추가되면, Ground Truth도 함께 업데이트해야 합니다. 오래된 정답 데이터는 잘못된 평가 결과를 만듭니다.

    # Ground Truth 버전 관리 예시
    ground_truth_v1_0 = "제품 보증 기간은 1년이다."  # 구 정책
    ground_truth_v1_1 = "제품 보증 기간은 2년이다."  # 신 정책
    
    # 날짜별 버전 기록
    version_history = {
        "2024-01-01": "v1.0",  # 1년 보증
        "2024-06-01": "v1.1"   # 2년 보증으로 변경
    }
    
    💡 업데이트 체크리스트:
    • 월 1회 원본 문서 변경사항 확인
    • Ground Truth 답변과 현재 정책 일치성 검증
    • 사용자 피드백으로 발견된 오답 수정
    • 새로 추가된 문서에 대한 QA 쌍 추가

    흔한 실수와 해결법

    실수 1: Ground Truth Answer를 너무 짧게 쓰기

    문제: reference="서울" 처럼 한 단어로만 쓰는 경우

    결과: 문장 분해가 안 되어 Context Recall 측정이 부정확해집니다.

    해결법: 완전한 문장으로 작성하세요. reference="한국의 수도는 서울이다."

    실수 2: reference와 reference_contexts 혼동

    문제: LLM 기반 메트릭에서 reference_contexts를 쓰거나, Non-LLM 기반에서 reference를 쓰는 경우

    해결법:

    • LLM 기반 Context Recall → reference 사용
    • Non-LLM 기반 Context Recall → reference_contexts 사용

    실수 3: 검색 결과를 그대로 Ground Truth로 복사

    문제: RAG 시스템이 검색한 컨텍스트를 reference_contexts에 그대로 넣는 경우

    결과: Context Recall이 항상 1.0이 나와서 평가가 무의미해집니다.

    해결법: Ground Truth는 독립적으로 작성하고, 시스템 출력과 비교해야 합니다.

    diagram

    실수 4: Ground Truth 없이 핵심 메트릭 측정 시도

    문제: reference 필드 없이 Context Recall이나 Answer Correctness를 측정하려는 경우

    결과: 에러 발생 또는 측정 불가

    🚨 에러 예시:
    ValueError: reference field is required for LLMContextRecall metric
    DatasetValidationError: Missing required field 'reference_contexts' for NonLLMContextRecall

    해결법: 해당 메트릭들은 반드시 정답 데이터가 필요하므로, Ground Truth를 먼저 준비하세요.

    마무리

    RAGAS Ground Truth 준비는 RAG 시스템 평가의 핵심입니다. 시간이 다소 걸리더라도 처음에 제대로 만들어두면, 시스템 개선 과정에서 객관적이고 일관된 평가 기준을 제공합니다.

    특히 실무에서는 도메인 전문가와 개발자가 협력해서 Ground Truth를 작성하고, 정기적으로 업데이트하는 것이 중요합니다. 좋은 평가 데이터가 있어야 좋은 RAG 시스템을 만들 수 있습니다.

    다음 단계로는 실제 RAGAS 평가를 실행하고 결과를 해석하는 방법을 다뤄보겠습니다. Ground Truth가 준비되었다면 이제 시스템의 실제 성능을 측정할 차례입니다.


    이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.

Designed by Tistory.