AI/Natural language processing

[NLP] RAG 성능 평가방법 : RAGAS를 이용해 데이터셋 생성부터 평가까지

hjjummy 2025. 8. 26. 17:19

RAG 모델을 한 번쯤 만들어 본 사람이라면 이런 고민을 해본 적이 있을 것이다.

"모델이 답변을 만들어 내고 있긴 한데, 정확히 얼마나 잘하고 있는 걸까?"
"결과가 별로일 때 내 검색 단계가 문제인지, 아니면 생성 단계가 문제인지 어떻게 구분할 수 있지?"

 

 

이럴 때 단순히 사람이 직접 눈으로 확인하는 방식만으로는 한계가 있다. 데이터셋이 많아질 수록 평가 비용은 기하 급수적으로 커지고, 결국 객관성이 떨어진다. 

 

여기서 등장한 도구가 바로 RAGAS (Retrieval-Augmented Generation Evaluation System) 이다. RAGAS는 말 그대로 RAG 과정을 자동화된 방식으로 평가할 수 있게 해주는 라이브러리다.


1. RAGAS란 무엇인가?

논문 : https://arxiv.org/abs/2309.15217
공식 페이지 : https://docs.ragas.io/en/stable/getstarted/

 

RAGAS는 RAG모델이 정확하고, 관련성 높은 답변을 생성하고 있는지를 점수화하여 평가하는 라이브러리이다.

 

 

핵심 특징을 정리하면 다음과 같다.

  • 자동화된 평가: 수동 레이블링 없이 합성 테스트셋을 만들고 평가 가능
  • 4가지 평가 지표 제공: Faithfulness, Answer Relevancy, Context Precision, Context Recall 등
  • 데이터셋 생성 기능 포함: 단순한 평가뿐만 아니라 테스트셋 생성까지 지원
  • LangChain 친화적: 문서 로더, LLM, 임베딩 등 LangChain 생태계와 쉽게 연동 가능

즉, 단순한 점수 매기기를 넘어 "검색 단계가 부족한지", "생성 단계가 문제인지" 같은 디버깅 힌트까지 제공한다는 점에서 유용하다.

 

평가 흐름은 보통 이렇게 진행된다.

1. llm통해 테스트셋 생성 → 문서 기반 Q&A 쌍 확보
2. RAG 모델 응답 수집 → RAG 파이프라인을 돌려 답변 생성
3. 정답과 비교 → RAGAS 지표로 점수 계산
4. 지표 분석 → 검색 단계 / 생성 단계 성능 분리해서 해석

2. 합성 테스트 데이터셋 만들기

RAGAS의 재미있는 기능 중 하나는 합성 테스트 데이터셋 생성이다. 
보통 평가를 하려면 질문 + 정답 + 컨텍스트가 있어야 하는데, 이걸 사람이 직접 만드는 건 비용이 크다.

RAGAS는 문서에서 자동으로 질문과 답변 쌍을 뽑아내고, 유형별로 조합해 준다.

 

테스트셋(question + ground_truth) 만드는 과정

from langchain_community.document_loaders import PDFPlumberLoader
from ragas.testset.generator import TestsetGenerator
from ragas.testset.evolutions import simple, reasoning, multi_context, conditional
from ragas.llms import LangchainLLMWrapper
from ragas.embeddings import LangchainEmbeddingsWrapper
from ragas.testset.docstore import InMemoryDocumentStore

from langchain_openai import ChatOpenAI, OpenAIEmbeddings

# PDF 문서 로딩
loader = PDFPlumberLoader("data/dataset2.pdf")
docs = loader.load()

# 목차, 끝 페이지 제외
docs = docs[3:-1]

# 데이터셋 생성기
generator_llm = ChatOpenAI(model="gpt-4o-mini")
critic_llm = ChatOpenAI(model="gpt-4o-mini")
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

docstore = InMemoryDocumentStore.from_documents(docs)

generator = TestsetGenerator.from_langchain(
    generator_llm,
    critic_llm,
    embeddings,
    docstore=docstore,
)

# 질문 유형별 분포 설정
distributions = {
    simple: 0.4,       # 단순 질의
    reasoning: 0.2,    # 추론이 필요한 질의
    multi_context: 0.2,# 여러 문서 맥락이 필요한 질의
    conditional: 0.2   # 조건부 질의
}

# 테스트셋 생성 (10개 샘플)
testset = generator.generate_with_langchain_docs(
    documents=docs,
    test_size=10,
    distributions=distributions,
    with_debugging_logs=True,
    raise_exceptions=False,
)

# Pandas DataFrame으로 변환
test_df = testset.to_pandas()

ragas.testset.* 관련 모듈들을 가져와서 테스트셋 생성하였다. 

이렇게 하면 문서 기반으로 질문-답변-정답이 포함된 테스트셋을 자동으로 뽑아준다.

 

위의 코드에서 라이브러리의 핵심 기능은 아래와 같다.

 

RAG 평가용 테스트셋 생성

generator = TestsetGenerator.from_langchain(
    generator_llm,
    critic_llm,
    ragas_embeddings,
    docstore=docstore,
)

RAGAS는 단순히 질문을 생성하는 것뿐 아니라, 생성된 질문/답변의 품질 평가를 자동화하기 위해 LLM과 임베딩을 결합한다.
여기서 TestsetGenerator가 바로 RAGAS가 제공하는 “합성 QA 테스트셋 생성기”이다.

 

질문 유형 분포 지정

distributions = {simple: 0.4, reasoning: 0.2, multi_context: 0.2, conditional: 0.2}

RAGAS의 강점 중 하나는 “테스트셋을 단순 질문, 추론형 질문, 다중 문맥 질문, 조건부 질문” 등 다양한 유형으로 나눠서 자동 생성할 수 있다는 점이다.

 

테스트셋 생성 및 변환

testset = generator.generate_with_langchain_docs(...)
test_df = testset.to_pandas()

 

generate_with_langchain_docs는 RAGAS에서 제공하는 테스트셋 생성 메서드이고, 마지막에 DataFrame으로 변환해서 분석할 수 있게 한다.

 

기본 언어는 영어로 생성이 되는데, 필요하면 DeepL과 같은 번역API 와 연동해서 한국어 데이터셋으로 바꿀 수도 있다.


 

3. 평가 지표: 무엇을 측정할 것인가?

테스트셋이 준비되면 이제 모델을 평가할 차례다.

RAGAS는 크게 네 가지 주요 지표를 제공한다.

 

기존 LLM의 성능평가 지표는 주로 생성된 텍스트 품질을 측정하는데 집중하여 BLEU나 ROUGE와 같은 지표를 사용하여 생성된 결과물과 참조 텍스트 간의 유사성을 계산한다. 이러한 방식은 기계 번역이나 텍스트 요약 등에서 효과적이다.

 

반면 RAG 파이프라인은 '검색'과 '생성'의 두과지 과정을 포함하므로  RAG에서는 단순히 생성된 텍스트의 품질뿐만 아니라, 모델이 검색한 정보의 관련성과 유용성, 그리고 그 정보가 생성된 답변에 얼마나 잘 반영 되었는지를 평가해야 한다.

검색과 생성에 사용하는 평가지표는 각각 2가지로 총 4가지이다.

 

Faithfulness 답변이 문서에 충실한가? 할루시네이션 여부
Answer Relevancy 답변이 질문과 얼마나 관련 있는가? 질문-답변의 관련성
Context Precision 관련된 문서가  상위에 배치되었는가? 검색 품질의 정밀도
Context Recall 필요한 문서를 얼마나 잘 가져왔는가? 검색 품질의 재현율

(1) Faithfulness

  • 답변이 실제 문서 근거에 충실한지 평가
  • 할루시네이션이 발생하면 점수가 떨어진다

(2) Answer Relevancy

  • 생성된 답변아 질문과 적절한지
  • 보통 cosine similarity 기반으로 측정

(3) Context Precision

  • ground-truth 문서가 검색 결과의 상위에 포함되었는지 확인
  • 값이 높을수록 검색 단계가 잘 작동하고 있다는 의미

(4) Context Recall

  • 답변에 필요한 문서들을 얼마나 잘 가져왔는지 확인
  • 검색된 문서가 LLM이 생성한 답변과 얼마나 일치하는 지 측정한다.
  • 재현율이 낮다면 검색 단계에서 중요한 문서를 놓치고 있다는 의미

 


4. 평가 하기

실제로 평가를 돌릴 때는 4가지 입력이 필요하다.

  1. question: 테스트셋에서 뽑은 질문
  2. ground_truth: 테스트셋 생성 시 함께 저장된 정답 텍스트
  3. context: RAG 검색기로부터 가져온 문서 조각들
  4. answer: RAG 모델이 생성한 응답
 즉,  "데이터셋 생성” 단계에서 question + ground_truth 를 준비하고 
“평가” 단계에서는 여기에 구축한 RAG 시스템에서 얻은 answer와 검색한 context를 합쳐서 평가를 수행하는 것이다.

 

 

RAG 시스템이 생성한 결과물(rag_results)을 RAGAS 지표로 평가하는 과정

from ragas import evaluate
from ragas.metrics import AnswerRelevancy, Faithfulness, ContextRecall, ContextPrecision

from ragas.llms import LangchainLLMWrapper
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o-mini")
evaluator_llm = LangchainLLMWrapper(llm)

results = evaluate(
    dataset=rag_results,
    metrics=[
        AnswerRelevancy(llm=evaluator_llm),
        Faithfulness(llm=evaluator_llm),
        ContextRecall(llm=evaluator_llm),
        ContextPrecision(llm=evaluator_llm),
    ],
)
results

https://milvus.io/docs/ko/integrate_with_ragas.md

 

앞 단계에서 만든 테스트셋(question + ground_truth)와 RAG 실행 결과로 얻은 answer + context를 합쳐서, 최종 성능을 수치로 계산하는 단계이다.

 

 


왜 RAGAS가 중요한가?

위의 글을 요약하자면 ,, RAG 파이프라인은 크게 두 단계로 나뉘는데 검색-생성 이다.

 

검색(Search) 단계에서는 '관련 문서를 잘 가져오는가?' 를 확인해야하고

생성(Generation) 단계에서는 '문서에 충실하고 질문에 맞는 답변을 하는가?' 를 평가해야한다.

 

문제가 생겼을 때, 보통은 "답변이 이상하다"라는 결과만 보고 원인을 짐작한다. 하지만 이건 감에 의존하는 방식이다.

RAGAS를 쓰면, 각 지표를 통해 검색 문제인지, 생성 문제인지를 분명히 구분할 수 있다.
결국 이게 모델 개선 방향을 정하는 나침반 역할을 해준다.

 

RAGAS는 단순 평가 도구뿐만 아니라, RAG 모델 디버깅 툴 같은 역할이라는 생각도 든다.

다음 글에서는, 내가 실제로 RAGAS 지표를 가지고 BM25 vs Milvus vs Hybrid Search ( BM25 + Milvus ) 세팅을 비교한 결과를 공유해 보려고 한다.
"검색기의 선택이 답변 품질에 어떤 영향을 주는가?" 이 주제로 성능 변화 그래프와 함께 다뤄볼 예정이다.