본문 바로가기
Databricks/RAG

RAG 품질 ① 평가 — MLflow Evaluation 기반 검색·생성 품질 정량 측정

by 여행을 떠나자! 2026. 7. 4.

📚 시리즈 — RAG 품질

 

 

 

1. RAG 파이프라인과 평가 개요

RAG는 크게 검색(Retrieval)증강(Augmentation)생성(Generation) 세 단계로 구성됩니다. 평가도 이 세 단계에 맞춰 진행해야 합니다.

 

왜 단계별로 평가해야 하나요?

문제 상황 원인 단계 평가하지 않으면?
엉뚱한 답변이 나옴 검색 단계에서 관련 없는 문서를 가져옴 생성 모델 탓으로 오해할 수 있음
답변에 빠진 내용이 있음 검색 단계에서 필요한 문서를 못 찾음 어디서 정보가 누락됐는지 모름
답변이 문서와 다른 내용을 포함 생성 단계에서 환각(Hallucination) 발생 검색은 정상인데 전체를 다시 손봄

단계별 평가 = 문제가 생겼을 때 어디를 고쳐야 하는지 바로 알 수 있음


 

2. MLflow Evaluation Scorer

Scorer는 MLflow가 제공하는 자동 평가기입니다. 사람이 답변을 일일이 읽고 "좋다/나쁘다"를 판단하는 대신, Scorer가 LLM Judge(LLM-as-a-Judge)¹ 또는 규칙 기반 로직으로 각 응답을 Pass/Fail·Yes/No·점수로 정량화해 줍니다.

¹ LLM-as-a-Judge: LLM(예: GPT-4, Claude 등)을 평가자로 사용해 다른 LLM의 출력을 채점하는 기법. Zheng et al.(2023)의 "Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena" 논문에서 널리 알려진 이후 MLflow·RAGAS·OpenAI Evals 등 주요 평가 프레임워크의 표준 방식으로 자리잡았습니다. 이 가이드에서는 줄여서 LLM Judge로 표기합니다.

  • 입력: 사용자 질문(inputs), RAG가 생성한 응답(outputs), 필요 시 기대값(expectations)
  • 처리: LLM Judge 또는 규칙 기반 로직으로 응답 품질을 판정
  • 출력: 개별 Trace 단위 Assessment(Pass/Fail) + Run 단위 Metric(평균값)

 

Scorer를 쓰는 이유

수동 평가 Scorer 자동 평가
100건 평가에 수 시간 소요 같은 양을 몇 분 내 처리
사람마다 기준이 달라 편차 발생 동일 Judge로 일관된 판정
버전별 반복 평가가 어려움 코드 변경마다 재실행해 품질 회귀 추적 가능

 

Scorer 유형 개요

MLflow Scorer는 커스터마이즈 수준에 따라 4가지로 나뉩니다.

유형 설명 예시
Built-in LLM Judge MLflow가 내장한 평가 프롬프트로 즉시 동작. 설정 없이 import해서 호출 Correctness(), RetrievalRelevance()
Guidelines Judge 자연어 규칙(예: "한국어로 답변")을 전달하면 내장 LLM Judge가 해당 규칙의 준수 여부를 판정 Guidelines(guidelines="한국어로 답변")
Custom LLM Judge 평가 프롬프트 전체를 직접 작성해 LLM Judge를 새로 만든다. 복합 기준·도메인 특화 평가에 사용 make_judge(instructions="...")
Code-based Scorer LLM 없이 파이썬 함수가 직접 규칙(길이·포맷·특정 단어 포함 등)으로 판정 @scorer def my_check(...)

이 가이드는 RAG 에이전트 품질 평가가 목적이므로, 예제는 Built-in LLM Judge와 Guidelines Judge에 집중합니다. Custom LLM Judge(make_judge)와 Code-based Scorer(@scorer)는 가이드 범위를 벗어나며, 필요 시 공식 문서를 참조하세요.

참고: Databricks MLflow 3부터 새로운 평가 API인 mlflow.genai.evaluate()가 권장됩니다. 아래는 이 API 기준입니다.

 

2.1 Scorer와 Ground Truth

Scorer는 Ground Truth 필요 여부에 따라 두 가지로 나뉩니다. 이 구분이 중요한 이유는, Ground Truth가 필요한 Scorer를 사용하려면 평가 데이터에 expectations(expected_facts, expected_response) 컬럼을 반드시 준비해야 하기 때문입니다.

쉬운 비유: - Ground Truth 불필요 = 전문가가 답안을 읽고 "이 답변이 논리적인가?" 판단하는 것 (모범 답안 없어도 가능) - Ground Truth 필요 = 모범 답안과 학생 답안을 나란히 놓고 "이 내용이 포함되어 있는가?" 대조하는 것

 

2.2 전체 Scorer 목록

MLflow가 제공하는 주요 Scorer 9개를 RAG 3단계에 맞춰 배치한 지도입니다. 별표(★)는 Ground Truth가 필요한 Scorer를 뜻합니다.

참고: 에이전트의 툴 호출 품질 평가에는 ToolCallCorrectness, ToolCallEfficiency 등의 Scorer를 사용할 수 있습니다. 이 가이드는 RAG 평가에 초점을 맞추므로 다루지 않으며, 필요 시 공식 문서를 참조하세요.

참고: 챗봇 등 여러 턴에 걸친 대화 평가에는 ConversationCompleteness, UserFrustration, ConversationalSafety 등의 Scorer를 사용할 수 있습니다. 이 가이드는 단일 질의 RAG 평가에 초점을 맞추므로 다루지 않으며, 필요 시 공식 문서를 참조하세요.

 

2.3 검색(Retrieval) 단계 Scorer

검색 단계는 "올바른 문서를 잘 찾아왔는가?"를 평가합니다.

Scorer Ground Truth 설명 쉬운 비유 점수
RetrievalRelevance 불필요 가져온 각 문서 조각이 질문과 관련이 있는지 개별 평가합니다. 도서관에서 빌려온 책 5권이 모두 내가 찾는 주제인지 확인 문서별 pass / fail (검색 문서 수만큼 Judge 호출 → 최종 Pass율로 집계)
RetrievalSufficiency 필요 (expected_facts 또는 expected_response 택1) 가져온 문서들을 통합해, Ground Truth에 답하기에 충분한 정보를 담고 있는지 평가합니다. 시험 답안을 쓰기에 참고 자료가 충분한지 확인 전체 yes / no (쿼리당 Judge 1회 호출)

예시:

질문: "MLflow 모델 레지스트리란 무엇인가요?"

검색된 문서 5개가 다음과 같이 섞여있다고 가정:

━ RetrievalRelevance (5회 Judge 호출, 문서별 pass/fail) ━
  문서1  "모델 레지스트리 개요"           → pass ✓
  문서2  "모델 버전 관리"                → pass ✓
  문서3  "스테이지 전환"                 → pass ✓
  문서4  "Spark 설정"                   → fail ✗ (관련 없음)
  문서5  "데이터 파이프라인"             → fail ✗ (관련 없음)
  ── 최종 Metric: 3/5 = 60% Pass율

━ RetrievalSufficiency (1회 Judge 호출, 전체 yes/no) ━
  5개 문서 전체를 합쳐서 expected_facts와 대조
  "이 세트로 정답을 구성하기에 충분한가?"
  → yes ✓  (또는 no)

핵심 차이: RetrievalRelevance는 문서별 정밀도(precision)를, RetrievalSufficiency는 전체 충분도(recall)에 가까운 관점을 측정합니다.

 

2.4 증강(Augmentation) 단계 Scorer

증강 단계는 "검색된 문서가 답변 생성에 적절히 활용되었는가?"를 평가합니다.

Scorer Ground Truth 설명 쉬운 비유 점수
RetrievalGroundedness 불필요 생성된 답변이 검색된 문서에 근거하고 있는지 평가합니다. 문서에 없는 내용을 지어낸 것(환각)이 없는지 확인합니다. 레포트를 쓸 때 참고문헌에 없는 내용을 지어내지 않았는지 확인 yes / no (주장별)

예시:

검색된 문서: "MLflow는 2018년에 Databricks에서 만든 오픈소스 플랫폼입니다."

[근거 있는 답변] RetrievalGroundedness = yes ✓
  "MLflow는 2018년에 Databricks에서 개발한 오픈소스 플랫폼입니다."

[환각이 포함된 답변] RetrievalGroundedness = no ✗
  "MLflow는 2018년에 Databricks에서 개발했으며, 현재 1억 명이 사용합니다."
  → "1억 명이 사용" ← 문서에 없는 내용을 지어냄 (환각)

 

2.5 생성(Generation) 단계 Scorer

생성 단계는 "최종 답변의 품질이 좋은가?"를 평가합니다.

Scorer Ground Truth 설명 쉬운 비유 점수
Correctness 필요 (expected_facts 또는 expected_response 택1) Ground Truth에 정의된 내용이 답변에 빠짐없이 포함되어 있는지 평가합니다. expected_facts는 핵심 사실 리스트, expected_response는 완성된 모범 답안으로 지정 (공식 권장: expected_facts). 시험 답안이 모범 답안과 맞는지 채점 yes / no
Equivalence 필요 답변이 expected_response의미적으로 동등한지 평가합니다. 두 답변이 표현은 달라도 본질적으로 같은 말인지 비교 yes / no
Completeness 불필요 사용자의 질문(inputs)에 포함된 모든 질문 항목에 응답(outputs)이 빠짐없이 답변했는지 평가합니다. 기대값 없이 질문 자체의 구조와 응답만으로 판정합니다. 3가지를 물어봤는데 3가지 모두 답했는지 확인 yes / no
RelevanceToQuery 불필요 답변이 질문에 대해 직접적으로 대답하고 있는지 평가합니다. "서울의 날씨"를 물었는데 서울 날씨에 대해 답했는지 확인 yes / no
Fluency 불필요 답변이 문법적으로 올바르고 자연스러운지 평가합니다. 글이 매끄럽게 읽히는지 확인 yes / no
Safety 불필요 답변에 유해하거나 부적절한 내용이 없는지 평가합니다. 답변이 누군가에게 해가 되지 않는지 확인 yes / no
Guidelines 불필요 사전에 정의한 규칙(예: "한국어로 답변", "3문장 이내")을 지켰는지 평가합니다. 사내 답변 규정을 지켰는지 확인 yes / no

예시:

질문: "파이썬의 리스트와 튜플의 차이는?"
expectations: {"expected_facts": ["리스트는 mutable", "튜플은 immutable"]}

[정확한 답변] Correctness = yes ✓
  "리스트는 변경할 수 있지만, 튜플은 한번 만들면 변경할 수 없습니다."

[부정확한 답변] Correctness = no ✗
  "리스트와 튜플은 동일하며, 둘 다 수정이 가능합니다."

 

2.6 Scorer별 입력 데이터 요건

평가 데이터의 각 필드는 Scorer가 참조하는 입력입니다. 먼저 어떤 Scorer를 쓸지 정한 뒤, 그 Scorer가 요구하는 필드만 준비하면 됩니다.

Scorer × 필요 데이터 매트릭스

단계 Scorer inputs outputs expected_facts expected_response Trace(RETRIEVER)
검색 RetrievalRelevance
검색 RetrievalSufficiency ¹
증강 RetrievalGroundedness
생성 Correctness ¹
생성 Equivalence
생성 Completeness
생성 RelevanceToQuery
생성 Fluency
생성 Safety
생성 Guidelines ²

¹ RetrievalSufficiency·Correctnessexpected_factsexpected_response택1로 동작합니다. 둘을 모두 주면 expected_facts가 우선 사용됩니다.

² Guidelines는 코드에서 guidelines="..." 파라미터로 규칙을 별도 전달합니다.

expected_facts vs expected_response 선택 원칙 (Correctness·RetrievalSufficiency에 적용) - 핵심 사실이 여러 개expected_facts (Q&A RAG·서술형에 적합, 공식 권장) - 모범 답안과 문장 단위 일치expected_response (요약·번역·고정 포맷에 적합)

Equivalence는 설계상 expected_response 전용입니다 (문장 단위 동등성이 평가 목적).


 

3. RAG 프로젝트에서 관리해야 할 핵심 지표

 

3.1 품질 관리 프로세스

위 프로세스의 2번(Baseline Evaluation)과 5번(재평가)에서 실행할 지표는 3.2에서, 본 가이드 시나리오의 권장 구성 및 목표값은 3.3에서 다룹니다.

Scorer별 개선 조치 가이드

위 프로세스의 4. 개선 작업 단계에서 우선 시도해볼 방향입니다. 각 Scorer의 Pass율이 목표에 못 미칠 때 참고하세요.

단계 Scorer 낮을 때 조치 방법
검색 RetrievalRelevance 검색 알고리즘 튜닝, Reranking 도입, Top-K 조정
검색 RetrievalSufficiency 청크 크기 조정, 임베딩 모델 변경, 문서 전처리 개선
증강 RetrievalGroundedness 프롬프트에 "문서에 근거하여 답변하세요" 강화, temperature 낮추기
생성 Correctness 검색 + 생성 양쪽 개선, 프롬프트 최적화
생성 Completeness 프롬프트에 "모든 질문 항목에 빠짐없이 답하세요" 명시, 다중 질문 처리 로직 강화, few-shot 예시 추가
생성 RelevanceToQuery 프롬프트에서 질문 집중도 개선, 답변 범위 제한
생성 Safety 안전 가드레일 추가, 출력 필터링
생성 Guidelines 시스템 프롬프트에 규칙 명시, few-shot 예시 추가

 

3.2 RAG와 관련된 지표

RAG 품질 관리 = "검색이 잘 되는가?" + "답변이 정확한가?" + "안전한가?"

이 세 가지 질문에 대한 답을 숫자로 측정하고, 추이를 관리하면, RAG 에이전트의 품질은 지속적으로 높아집니다.

 

3.3 본 가이드 시나리오의 Scorer 권장 구성

시나리오 전제

본 가이드는 다음 조건을 상정합니다.

항목
대화 방식 단일 턴 Q&A
언어 한국어 응답
검색 대상 사내 지식베이스
배포 CI 통합, 매 변경마다 평가 실행
Ground Truth expected_facts 확보됨
Tracing 검색 함수에 @mlflow.trace(span_type="RETRIEVER") 셋업 완료

필수 Scorer (매 CI 실행마다 측정)

이 5개는 본 시나리오의 핵심 품질 지표로 모두 통과되어야 배포 가능합니다.

⚠️ 중요: 아래 목표는 예시 기준값입니다. 실제 프로젝트에서는 도메인 민감도, 사용자 기대, 리스크 수준에 따라 팀 합의를 거쳐 조정하세요.

# 단계 Scorer 목표(예시) 목적
1 증강 RetrievalGroundedness Pass율 ≥ 90% 환각(Hallucination) 방지 — 답변이 검색된 문서에 근거하는지
2 생성 Correctness Pass율 ≥ 80% 사실 커버리지 — expected_facts를 빠짐없이 포함하는지
3 생성 Completeness Pass율 ≥ 85% 복합 질문에서 모든 항목에 답했는지
4 생성 RelevanceToQuery Pass율 ≥ 80% 질문에 직접 응답하는지
5 생성 Safety Pass율 ≥ 90% 유해·부적절 응답 차단

선택 Scorer (필요 시점에 추가)

목적 Scorer 목표(예시) 추가 가치 도입 시점
검색 심화 진단 RetrievalRelevance Pass율 ≥ 80% 각 문서의 관련성 — 검색 알고리즘 튜닝의 핵심 지표 Correctness 낮을 때 원인 분리 필요 시 (§4.7)
검색 심화 진단 RetrievalSufficiency Pass율 ≥ 70% 검색된 문서 집합이 정답을 구성하기 충분한지
사내 규정 검증 Guidelines Pass율 ≥ 95% "한국어로 답변", 금지어 등 자연어 규칙 준수 사내 답변 규정 검증이 필요해질 때

제외 Scorer (본 시나리오에 부적합)

Scorer 제외 이유
Equivalence expected_response 기반 엄격 동치 평가 — 일반 Q&A RAG에는 과도 (요약·번역용에 적합)
Fluency 한국어 LLM 응답은 문법적으로 안정적 — 측정 가치 낮음
ToolCallCorrectness / ToolCallEfficiency 에이전트 툴 호출 평가용 — RAG 범위 밖
Multi-turn Scorer 전체 대화형 평가용 — 단일 턴 시나리오 밖

 

4. MLflow Evaluation 실습 (Python)

 

4.1 환경 설정

pip install "mlflow[databricks]>=3.1.0"
# (OSS MLflow에서 OpenAI를 Judge 백엔드로 쓰는 경우에만) pip install openai

ℹ️ 참고 — 환경별 지원: mlflow.genai.evaluate()와 대부분의 예약 Scorer는 오픈소스 MLflow 3에서도 동작합니다. 다만 일부 Judge(현 시점 기준 Safety, RetrievalRelevance 등)는 Databricks Managed MLflow 전용으로 제공되며 점차 OSS로 이관 중입니다. 프로덕션 모니터링 lifecycle SDK 등 일부 관리형 기능은 Databricks 전용입니다. 최신 지원 범위는 공식 문서를 참조하세요.

 

4.2 샘플 Evaluation 데이터 생성

실제 RAG 시스템 없이도 평가 흐름을 체험할 수 있도록, 질문(inputs)Ground Truth(expectations) 만 담은 샘플 데이터를 만듭니다. outputs(응답)와 Trace는 §4.5에서 predict_fn=mock_rag_pipeline을 지정하면 MLflow가 실행 시 자동 생성하므로, 데이터에는 포함하지 않습니다.

# -------------------------------------------------------
# 샘플 Evaluation 데이터 (§4.5에서 그대로 재사용)
# 각 레코드: inputs(질문) + expectations(Ground Truth: expected_facts)
#   · outputs는 predict_fn이 런타임에 생성
#   · Trace(RETRIEVER span)도 predict_fn 실행 중 자동 기록
# -------------------------------------------------------
eval_data = [
    {
        "inputs": {"question": "MLflow 모델 레지스트리란 무엇인가요?"},
        "expectations": {
            "expected_facts": [
                "모델의 라이프사이클을 관리하는 중앙 저장소이다",
                "모델 버전 관리를 지원한다",
                "스테이지 전환(Staging, Production) 기능을 제공한다",
            ],
        },
    },
    {
        "inputs": {"question": "MLflow Tracking은 어떤 정보를 기록하나요?"},
        "expectations": {
            "expected_facts": [
                "파라미터를 기록한다",
                "메트릭을 기록한다",
                "아티팩트를 기록한다",
            ],
        },
    },
    {
        "inputs": {"question": "Unity Catalog와 MLflow의 관계는?"},
        "expectations": {
            "expected_facts": [
                "Unity Catalog는 Databricks의 거버넌스 솔루션이다",
                "MLflow 모델 레지스트리와 통합된다",
                "접근 제어와 lineage 추적 기능을 제공한다",
            ],
        },
    },
]

print(f"Evaluation 데이터: {len(eval_data)}건")
print("첫 번째 질문:", eval_data[0]["inputs"]["question"])

데이터 스키마 요약: MLflow genai.evaluate()inputs, outputs, expectations, trace 네 필드를 인식합니다. 본 예제처럼 predict_fn을 함께 넘기면 outputstrace는 자동으로 채워지므로, 데이터에는 inputsexpectations만 두면 됩니다.

 

4.3 Mock RAG 파이프라인 구성 (MLflow Tracing 적용)

실제 벡터DB나 LLM 없이도 평가 흐름을 이해할 수 있도록, 간단한 목업(mock) RAG를 만듭니다. 이때 @mlflow.trace 데코레이터를 함께 사용해야 검색 단계 Scorer를 동작시킬 수 있습니다. (자세한 이유는 다음 4.4절 참고)

여기서 작성하는 mock_rag_pipeline 함수는 4.5절에서 mlflow.genai.evaluate(predict_fn=mock_rag_pipeline, ...) 형태로 전달되며, MLflow가 내부적으로 호출해 응답과 Trace를 자동 생성합니다.

🔑 핵심 스키마 규칙: RETRIEVER span의 반환값은 반드시 mlflow.entities.Document 객체 리스트(또는 호환 dict {"page_content": ..., "metadata": ...})여야 합니다. 문자열 리스트만 반환하면 MLflow Retrieval Judge가 context를 파싱하지 못해 retrieval_groundedness·retrieval_sufficiency·retrieval_relevance가 모두 Fail로 나옵니다. 아래 mock_retrieve는 이 규칙을 지켜 list[Document]를 반환합니다.

import mlflow
from mlflow.entities import Document

# -------------------------------------------------------
# Mock RAG 파이프라인
#   · mock_retrieve  : list[Document]를 반환해 Retrieval Judge가 context를 인식하도록 함
#   · mock_generate  : 검색된 문서를 기반으로 미리 준비된 응답 반환 (LLM 호출 대용)
#   · mock_rag_pipeline : 전체 체인을 하나의 Trace로 묶는 엔트리포인트
# -------------------------------------------------------

# 가상의 문서 저장소 (실제로는 벡터DB에 해당)
MOCK_DOCUMENTS = {
    "MLflow 모델 레지스트리": [
        "MLflow 모델 레지스트리는 ML 모델의 라이프사이클을 관리하는 중앙 저장소입니다.",
        "모델 버전 관리, 스테이지 전환(Staging, Production), 모델 공유를 지원합니다.",
    ],
    "MLflow Tracking": [
        "MLflow Tracking은 머신러닝 실험의 파라미터, 메트릭, 아티팩트를 기록하는 컴포넌트입니다.",
        "실험을 비교하고 재현하는 데 활용됩니다.",
    ],
    "Unity Catalog": [
        "Unity Catalog는 Databricks의 통합 데이터 거버넌스 솔루션입니다.",
        "MLflow 모델 레지스트리와 통합되어 접근 제어와 lineage 추적을 제공합니다.",
    ],
}

# 가상의 응답 저장소 (실제로는 LLM이 생성)
MOCK_ANSWERS = {
    "MLflow 모델 레지스트리란 무엇인가요?": (
        "MLflow 모델 레지스트리는 ML 모델의 전체 라이프사이클을 관리하는 "
        "중앙 저장소입니다. 모델 버전 관리, 스테이지 전환(Staging → Production), "
        "그리고 팀 간 모델 공유 기능을 제공합니다."
    ),
    "MLflow Tracking은 어떤 정보를 기록하나요?": (
        "MLflow Tracking은 실험의 파라미터, 메트릭, 아티팩트를 기록합니다. "
        "예를 들어 학습률, 정확도, 그리고 학습된 모델 파일 등을 저장할 수 있습니다."
    ),
    "Unity Catalog와 MLflow의 관계는?": (
        "Unity Catalog는 Databricks의 통합 거버넌스 솔루션으로, "
        "MLflow 모델 레지스트리와 통합되어 모델에 대한 접근 제어와 "
        "lineage 추적을 제공합니다."
    ),
}


@mlflow.trace(span_type="RETRIEVER")
def mock_retrieve(question: str) -> list[Document]:
    """질문에 대해 관련 문서 조각을 검색하는 목업 함수.

    span_type="RETRIEVER"로 지정하고 list[Document]를 반환하면,
    MLflow가 이 span의 출력을 'retrieved context'로 인식하여
    RetrievalRelevance / RetrievalGroundedness / RetrievalSufficiency가 자동 평가한다.
    """
    for keyword, docs in MOCK_DOCUMENTS.items():
        if keyword.lower() in question.lower():
            return [
                Document(
                    page_content=text,
                    metadata={"source": f"mock-{keyword}-{i}"},
                )
                for i, text in enumerate(docs)
            ]
    return [Document(page_content="관련 문서를 찾을 수 없습니다.", metadata={"source": "mock-empty"})]


@mlflow.trace(span_type="LLM")
def mock_generate(question: str, context: list[Document]) -> str:
    """검색된 문서를 기반으로 답변을 생성하는 목업 함수"""
    return MOCK_ANSWERS.get(question, "답변을 생성할 수 없습니다.")


@mlflow.trace   # 최상위 함수에도 trace를 붙이면 전체 호출 체인이 하나의 Trace로 묶인다
def mock_rag_pipeline(question: str) -> str:
    """검색 → 증강 → 생성의 전체 RAG 파이프라인 목업"""
    # 1단계: 검색
    retrieved_docs = mock_retrieve(question)
    # 2단계 + 3단계: 증강 & 생성
    answer = mock_generate(question, retrieved_docs)
    return answer


# 테스트 — 실행하면 MLflow UI의 Traces 탭에 단계별 span이 기록된다
test_question = "MLflow 모델 레지스트리란 무엇인가요?"
retrieved = mock_retrieve(test_question)
print(f"질문: {test_question}")
print(f"검색된 문서 수: {len(retrieved)}  (첫 문서: {retrieved[0].page_content[:40]}...)")
print(f"생성된 답변: {mock_rag_pipeline(test_question)}")

Tracing이 하는 일: @mlflow.trace는 함수 호출의 입력·출력·지연시간을 MLflow에 자동 기록합니다. 이 기록(Trace)은 크게 두 가지 목적으로 사용됩니다. 1. Observability: UI에서 각 단계가 어떤 입출력을 주고받았는지 시각적으로 확인 2. Evaluation: 검색 단계 Scorer가 retrieved context를 Trace에서 자동으로 추출

 

4.4 Tracing과 Scorer: 어떤 평가에 Trace가 필요한가?

MLflow의 일부 Scorer는 단순히 inputs/outputs만 보지 않고, RAG 내부 단계의 입출력(특히 검색된 문서)을 알아야 평가가 가능합니다. 이 내부 정보는 Trace를 통해서만 전달됩니다.

Scorer별 Trace 필요 여부

Scorer Trace 필요? 이유
RetrievalRelevance 필수 span_type="RETRIEVER" span의 반환값을 읽어 문서별 관련성 평가
RetrievalGroundedness 필수 Retrieved context와 답변을 대조하여 환각 여부 판정
RetrievalSufficiency 필수 Retrieved context가 Ground Truth에 답하기 충분한지 판정
RelevanceToQuery ❌ 불필요 질문과 답변만 비교
Correctness ❌ 불필요 답변과 expected_facts 비교
Completeness ❌ 불필요 질문 항목과 답변만 비교
Safety, Fluency, Guidelines ❌ 불필요 답변 텍스트 자체만 분석

핵심 규칙: 이름에 Retrieval이 포함된 Scorer는 모두 "검색된 문서(retrieved context)" 정보가 필요하며, 공식 문서 기준 Trace를 유일한 입력 소스로 사용합니다.

retrieved context 공급 방식

predict_fn 내부의 검색 함수에 @mlflow.trace(span_type="RETRIEVER") 데코레이터를 부착하면, Judge가 Trace에서 자동으로 추출합니다. 본 가이드의 4.5절 실행 예시가 이 표준 방식을 사용합니다.

참고: outputs 딕셔너리에 retrieved_context 같은 임의 필드를 넣어도 예약 Retrieval Scorer는 이를 인식하지 않습니다(공식 문서에 해당 경로 명시 없음). 이미 검색된 문서를 외부에서 가져와 수동 평가해야 하는 경우에는 커스텀 @scorer 내부에서 Judge API를 직접 호출하거나, 실행 시점에 @mlflow.trace 컨텍스트로 검색 결과를 기록해야 합니다.

Trace/retrieved context 없이 실행하면?

@mlflow.trace도 없고 outputs.retrieved_context도 없는 상태에서 RetrievalRelevance 등을 호출하면, MLflow는 retrieved context를 찾지 못해 해당 Scorer는 skip되거나 에러를 발생시킵니다. 반대로 Trace만 잘 남기면, 이후에도 Trace를 재활용해 여러 Scorer를 반복 평가할 수 있습니다.

 

4.5 MLflow Evaluation 실행

predict_fn@mlflow.trace가 붙어 있으면 MLflow가 실행 중 Trace를 자동 수집하고, 검색 단계 Scorer까지 함께 실행할 수 있습니다. 본 시나리오(§3.3)의 필수 5개 + 선택 2개 Scorer를 한 번에 평가합니다.

§4.2에서 정의한 eval_data를 그대로 전달하면, MLflow가 각 레코드의 inputsmock_rag_pipeline에 넣어 outputs와 Trace를 런타임에 생성한 뒤 Scorer에 넘겨줍니다.

import mlflow
from mlflow.genai.scorers import (
    # 필수 Scorer (§3.3 기준)
    Correctness,
    Completeness,
    RelevanceToQuery,
    Safety,
    RetrievalGroundedness,    # Trace 필요
    # 선택 Scorer — 검색 심화 진단
    RetrievalRelevance,       # Trace 필요
    RetrievalSufficiency,     # Trace 필요 + Ground Truth 필요
)

result = mlflow.genai.evaluate(
    data=eval_data,                  # ← §4.2에서 정의한 eval_data 그대로 재사용
    predict_fn=mock_rag_pipeline,    # ← §4.3의 @mlflow.trace 적용 목업 파이프라인
    scorers=[
        # 필수 Scorer
        Correctness(),
        Completeness(),
        RelevanceToQuery(),
        Safety(),
        RetrievalGroundedness(),
        # 선택 Scorer (검색 심화 진단)
        RetrievalRelevance(),
        RetrievalSufficiency(),
    ],
)

print("=== Metrics ===")
print(result.metrics)
# Trace와 함께 기록된 결과는 Databricks UI의
# "GenAI 앱 & 에이전트" Evaluation 화면에서 단계별로 확인 가능

 

4.6 Evaluation 결과 확인

평가 결과는 두 가지 방법으로 확인할 수 있습니다.

방법 1: Databricks 워크스페이스 UI (권장)

Databricks 워크스페이스에서 실행한 경우, GenAI 앱 & 에이전트 Evaluation 화면에서 시각적으로 확인할 수 있습니다.

UI 영역 확인할 수 있는 내용
Assessments 컬럼 헤더 각 Scorer별 Pass율·AVG 집계 (예: Correctness 100%, precision 0.67)
Expectations 컬럼 각 쿼리에 설정한 Ground Truth 원문 (예: expected_facts 리스트)
Trace 행 개별 질문별 요청·응답·실행 시간·State, Scorer별 Pass/Fail 상세

Trace 목록 경로: Experiment 왼쪽 사이드바 Observability > Traces(Experiment 전체 trace) 또는 특정 Run 상세 페이지 상단의 Traces(해당 Run에서 생성된 trace만)에서 확인합니다. Evaluation > Evaluation runs에서 Run을 클릭하면 하단에 같은 Trace 목록이 함께 펼쳐집니다.

UI 용어 안내: Databricks UI에서 Scorer의 판정 결과는 Assessment, expectations에 담긴 Ground Truth 원문은 Expectations로 표시됩니다. 이는 UI 표시 구분이며 Scorer의 분류 체계가 아닙니다.

UI 컬럼이 Scorer 클래스명과 달라 헷갈릴 때부록 A.1 UI 표기 ↔ Scorer 매핑을 참조하세요. Run Overview의 Metrics 카드 기본 5행만 노출되는 현상 등 UI 보기 팁은 부록 A.2에 있습니다.

방법 2: 코드에서 결과 분석

import mlflow

# experiment_id를 먼저 조회 (search_runs는 experiment_ids를 요구)
experiment = mlflow.get_experiment_by_name(
    "/Users/you@example.com/rag-eval-test/rag_eval_experiment"
)
runs = mlflow.search_runs(
    experiment_ids=[experiment.experiment_id],
    order_by=["start_time DESC"],
    max_results=1,
)

# MLflow 3의 실제 Metric 컬럼 네이밍: `<scorer>/mean`
print(runs[[
    "run_id",
    "metrics.correctness/mean",
    "metrics.safety/mean",
    "metrics.retrieval_groundedness/mean",
]])

Metric 컬럼 네이밍 규칙: mlflow.genai.evaluate()는 각 Scorer 결과를 <scorer_name>/mean 형태로 기록합니다(예: correctness/mean, safety/mean, retrieval_relevance/mean, retrieval_relevance/precision/mean). 과거 pass_rate 표기는 MLflow 3에서 사용되지 않으므로 mean을 사용하세요. 실제 워크스페이스에서 생성된 모든 컬럼명은 다음 스니펫으로 확인할 수 있습니다.

python print([c for c in runs.columns if c.startswith("metrics.")])

 

4.7 전체 Evaluation 흐름 다이어그램

 

4.8 Evaluation 결과 읽는 법: Scorer 간 상관관계 해석

Evaluation 결과를 볼 때, 개별 Scorer만 보는 것이 아니라 Scorer들의 조합을 해석하는 것이 중요합니다.

패턴 의미 조치 방향
RetrievalGroundedness 높음 + RetrievalSufficiency 낮음 가져온 문서 안에서는 환각 없이 답변하지만, 충분한 문서를 못 찾고 있음 검색 개선 (임베딩 모델, 청크 전략, Reranking)
RetrievalGroundedness 낮음 + RetrievalRelevance 높음 관련 문서는 잘 찾지만, 답변 시 문서에 없는 내용을 지어냄 생성 개선 (프롬프트 강화, temperature 낮추기)
RelevanceToQuery 낮음 + Safety 높음 답변이 안전하지만 질문과 동떨어진 내용을 답함 프롬프트에서 질문 집중도 개선
Correctness 낮음 + RetrievalGroundedness 높음 문서에 근거하여 답변하지만 문서 자체에 정답이 부족 검색 범위 확대 또는 문서 보강

위 4가지 패턴을 문제 진단 의사결정 트리로 시각화하면 다음과 같습니다.

핵심: 하나의 Scorer만 보지 말고, 검색 Scorer와 생성 Scorer를 함께 보면 문제의 원인이 검색인지 생성인지 문서 코퍼스인지 바로 판단할 수 있습니다. 위 트리의 분기점 2개(RetrievalGroundedness, RetrievalSufficiency)가 핵심 진단 레버입니다.

 

4.9 실제 실행 결과 (Databricks 워크스페이스 검증)

§4.2~§4.6 예제를 sandbox 워크스페이스에서 Serverless Job으로 실행해 수정본을 검증했습니다 (검증 시점 sandbox 기준 — 현재는 apne2 로 이전).

실행 환경

항목
MLflow mlflow[databricks]>=3.1.0 (environment_version 3)
Compute Serverless notebook job
Experiment /Users/you@example.com/rag-eval-test/rag_eval_experiment
Run name guide-v2-all-scorers
Duration 36.7s
실행 일시 2026-04-20

실행 결과 Metrics

MLflow 3의 Metric 컬럼 네이밍은 <scorer>/mean 입니다.

단계 Metric 해석
검색 retrieval_relevance/mean 0.667 문서 6개 중 4개 관련, 2개 Fail (Unity Catalog 문서 세트)
검색 retrieval_relevance/precision/mean 0.667 검색 문서 precision 동일
검색 retrieval_sufficiency/mean 1.000 expected_facts 커버에 충분
증강 retrieval_groundedness/mean 0.667 3건 중 2건에서 답변이 문서에 근거
생성 correctness/mean 1.000 expected_facts를 모두 포함
생성 completeness/mean 0.333 3건 중 1건만 Pass — 아래 해석 참고
생성 relevance_to_query/mean 1.000 질문에 직접 응답
생성 safety/mean 1.000 유해 응답 없음

UI 스크린샷 — Run Overview (Metrics 목록)

Run 상세 페이지의 Metrics 섹션에 8개 Scorer 결과가 completeness/mean ~ safety/mean 순으로 나열됩니다. Latest/Min/Max 컬럼이 동일한 이유는 단일 Evaluation Run이기 때문이며, 반복 실행 시 차트로 트렌드를 추적할 수 있습니다.

UI 스크린샷 — Traces 탭 (질문별 Assessment)

상단 Assessments 헤더에 Correctness 100% · Relevance 100% · Retrieval relevance 67% · Retrieval sufficiency 100%가 집계로 표시되고, 각 Trace 행에서 문서별 Pass/Fail이 "Fail (2)" 처럼 문서 개수와 함께 나타납니다. Unity Catalog 질문 행의 Retrieval relevance가 유일한 Fail 포인트입니다.

반복 실행 시 UI — variant별 비교 (Evaluation Runs 탭)

"Latest/Min/Max 컬럼이 동일한 이유는 단일 Evaluation Run이기 때문"이라는 설명을 직접 확인하기 위해, 동일 노트북을 variant 위젯 파라미터로 3가지 품질 수준에서 반복 실행했습니다.

variant Mock 답변 특징 기대 결과
baseline §4.3의 기본 답변 Correctness 1.0 · Completeness 부분
degraded 핵심 사실을 의도적으로 생략한 간략 답변 Correctness·Completeness 모두 하락
improved 모든 expected_facts를 명시적으로 커버 Completeness 1.0 달성

세 Run을 동일 Experiment(rag_eval_experiment)에 기록하면 Evaluation Runs 탭이 자동으로 variant별 차이를 펼쳐 보여줍니다.

Metric 차트로 트렌드 추적

Experiment Runs 뷰의 Chart 모드(compareRunsMode=CHART)로 전환하면 Scorer별 막대 차트에 여러 Run이 함께 overlay 되어 variant 간 차이가 한 캔버스에 나타납니다.

위 스크린샷은 completeness/meancorrectness/mean 차트에 4개 Run(guide-v2-all-scorers / variant-improved / variant-baseline / variant-degraded)이 막대로 병치된 모습입니다.

  • correctness/mean 차트에서 variant-degraded만 0.0으로 뚝 떨어진 막대가 드러나 "답변 간략화 → 사실 커버리지 붕괴"를 즉시 시각 확인할 수 있습니다.
  • completeness/mean 차트는 variant-improved만 1.0으로 튀어 "불릿 구조로 하위 항목을 명시한 개선이 효과를 냈다"를 보여줍니다.

Chart 모드 진입 경로: Experiment 페이지에서 Runs 테이블 상단 좌측의 3개 뷰 토글(Table / Chart / Artifact) 중 두 번째를 선택하거나, URL 쿼리에 compareRunsMode=CHART를 추가합니다. 개별 Run Overview의 Model metrics 탭은 단일 Run 내부의 Metric만 보여주므로 교차 비교에는 Runs 뷰의 Chart 모드를 사용해야 합니다.

결과 해석

(1) 핵심 검증 — list[Document] 스키마로 전환하니 검색 Scorer가 실제로 작동합니다.

이전 버전에서는 mock_retrievelist[str]을 반환해 retrieval_groundedness/mean, retrieval_sufficiency/mean이 모두 0%로 기록됐습니다. 수정본(§4.3)에서는 mlflow.entities.Document 객체 리스트를 반환하도록 바꿨고, 그 결과 두 Metric이 각각 0.667, 1.000 으로 상승했습니다. "Retrieval Judge가 RETRIEVER span을 읽지 못한다"는 증상이 해소됐다는 것이 이번 검증의 핵심 수확입니다.

(2) retrieval_relevance 67% — Judge가 "더 엄격"하게 판정

Unity Catalog 질문에 대해 Mock이 반환한 문서 2개 중 하나("Unity Catalog는 Databricks의 통합 데이터 거버넌스 솔루션입니다.")를 Judge가 관련 문서로 인정하지 않아 Fail (2) 처리되었습니다. Mock 데이터의 범용 설명이 질문의 초점(MLflow와의 관계)과 완전히 일치하지 않기 때문이며, 실제 RAG에서는 Reranking/청크 전략으로 precision을 끌어올리는 대표 케이스입니다.

(3) completeness/mean 33.3% — 질문 내부 다중 항목 커버리지 부족

Completeness Judge는 "질문 내부에 포함된 모든 항목에 답했는가"를 보는데, Mock 답변이 간결해 일부 질문의 암묵적 하위 항목을 다 다루지 못해 3건 중 1건만 Pass로 판정됐습니다. 이는 Mock 답변의 한계이며, 프로덕션에서는 프롬프트에 "질문의 모든 하위 항목에 빠짐없이 답하세요" 지시 추가로 개선할 수 있는 전형적인 패턴입니다(§3.1 개선 가이드 참조).

핵심 시사점: - RETRIEVER span의 반환 스키마가 검색 Scorer의 전제조건입니다. list[Document] 준수 시 Judge가 context를 정상 파싱합니다. - 단일 Scorer 수치보다 Scorer 조합(§4.7 패턴표)이 중요합니다. 이번 Run은 retrieval_groundedness < retrieval_sufficiency 패턴이므로, §4.7의 "가져온 문서 안에서는 부분적으로 환각이 섞였으나, 문서 자체의 사실 커버리지는 충분" 상황에 해당합니다. - completeness가 낮고 correctness가 높은 경우는 "사실은 맞지만 설명이 부족" 한 답변 스타일을 시사하며, 프롬프트 튜닝 우선순위를 가리킵니다.


 

부록 A: Databricks UI 안내

 

A.1 UI 표기 ↔ Scorer 매핑

Databricks UI에 표시되는 컬럼 이름은 Scorer 클래스 이름과 약간 다릅니다. 아래 매핑을 참고하세요.

단계 UI 컬럼 (Assessments 패널) Scorer 클래스 Metric 키 (metrics.*)
검색 Retrieval relevance RetrievalRelevance() retrieval_relevance/mean
검색 precision RetrievalRelevance() 부가 지표 retrieval_relevance/precision/mean
검색 Retrieval sufficiency RetrievalSufficiency() retrieval_sufficiency/mean
증강 Retrieval groundedness RetrievalGroundedness() retrieval_groundedness/mean
생성 completeness Completeness() completeness/mean
생성 Correctness Correctness() correctness/mean
생성 Relevance RelevanceToQuery() relevance_to_query/mean
생성 Safety Safety() safety/mean

RetrievalRelevance() 1개 → UI 컬럼 2개

코드에서 RetrievalRelevance()를 한 번 지정해도 UI에는 두 컬럼이 생성됩니다.

  • Retrieval relevance: 쿼리 단위 Pass/Fail. 검색된 문서 중 하나라도 Judge가 관련 없다고 판정하면 Fail. 행 셀에 Fail (2) 처럼 표시되며, 괄호는 검색된 문서 수입니다.
  • precision: 쿼리 단위 관련 문서 비율(0~1 수치). Pass/Fail이 아니라 AVG로 집계됩니다.

두 지표의 Run 평균 관계:

retrieval_relevance/mean            = 쿼리 중 Pass 비율          (쿼리 단위 지표)
retrieval_relevance/precision/mean  = 쿼리별 precision의 산술 평균  (문서 단위 지표)

이 Run에서는 두 값이 우연히 0.667로 같지만, 일반적으로는 다릅니다. "쿼리 전체가 깨끗한가"(엄격)와 "문서 비율이 얼마나 깨끗한가"(완화)로 관점이 달라서입니다.

 

A.2 Databricks UI 보기 팁

(1) Run Overview의 Metrics 카드는 기본 5행만 노출

Metrics (8) 같이 괄호 안 숫자가 실제 기록된 Metric 전체 수입니다. 테이블 안쪽을 스크롤하거나 상단 Model metrics 탭으로 이동하면 8개 Metric을 한 번에 볼 수 있고, 반복 실행 시 히스토리 차트도 제공합니다.

(2) Traces 탭 Assessments 컬럼은 일부만 기본 노출

Assessments 헤더에 (4/8) 처럼 표시되면 일부 Scorer가 기본 컬럼에서 빠진 상태입니다. 화면 우측 Columns 버튼 → Assessments 메뉴에서 나머지 Scorer를 체크하면 쿼리별 Pass/Fail이 함께 표시됩니다.

(3) Evaluation Runs 탭에서 버전 비교

Experiment의 Evaluation runs 메뉴는 여러 Run을 한 테이블에 펼쳐 Scorer */mean 컬럼을 나란히 보여줍니다. 프롬프트·검색 전략을 바꿔 재실행한 뒤 회귀 여부를 한눈에 보기 좋습니다.

(4) Expectations 컬럼

Assessments 패널 오른쪽의 Expectations 컬럼은 Scorer 결과가 아니라 평가 데이터에 넣은 expected_facts / expected_response 원문을 그대로 표시합니다. Judge의 rationale과 대조하며 읽을 때 유용합니다.


 

부록 B: RAGAS 프레임워크 참고

⚠️ 이 부록은 용어 대조용 배경 지식입니다. 본 가이드의 프로젝트 구현은 MLflow만 사용하며, RAGAS를 직접 도입하지 않습니다. 다른 팀/논문에서 RAGAS 용어를 마주쳤을 때 MLflow Scorer와 어떻게 대응되는지 빠르게 확인하기 위한 용도이며, RAGAS를 실제 사용하려면 공식 문서를 참조하세요.

 

B.1 RAGAS란?

RAGAS(Retrieval Augmented Generation Assessment)는 RAG 시스템 평가를 위한 오픈소스 프레임워크로, LLM Judge를 사용해 RAG의 각 단계를 자동 평가합니다. 2023년 논문 기반이며 Apache 2.0 라이선스로 배포됩니다.

  • GitHub: https://github.com/explodinggradients/ragas
  • 공식 문서: https://docs.ragas.io/en/latest/

 

B.2 RAGAS 주요 Metric 이름 (v0.2+ 기준)

RAGAS는 평가 항목을 Metric이라고 부릅니다. MLflow 대응은 부록 C에서 상세히 다룹니다.

단계 Metric (v0.2+ 클래스) 간단 설명
검색 ContextRecall 정답이 검색된 문서에 얼마나 포함됐는지
검색 ContextPrecision 관련 문서가 상위에 위치하는지
생성 Faithfulness 답변이 검색 문서에 근거하는지 (환각 탐지)
생성 ResponseRelevancy 답변이 질문에 적절한지
생성 FactualCorrectness 답변이 정답과 사실적으로 일치하는지
생성 SemanticSimilarity 답변과 정답의 의미적 유사도

v0.1의 소문자 함수명(faithfulness 등)은 deprecated이며 v1.0에서 제거 예정이므로 최신 코드는 v0.2+ 클래스명을 사용합니다.


 

부록 C: MLflow Scorer vs RAGAS Metric 비교

⚠️ 용어 매핑용 참고 자료: 본 프로젝트는 MLflow 중심이며, 아래는 RAGAS 용어를 마주쳤을 때 MLflow Scorer로 치환하기 위한 대조표입니다.

 

C.1 대응표

 

C.2 상세 비교표

비교 항목 MLflow RAGAS
공식 명칭 Scorer Metric
검색 평가 RetrievalRelevance, RetrievalSufficiency ContextRecall, ContextPrecision
생성 평가 Correctness, RelevanceToQuery, Safety, Fluency, Guidelines Faithfulness, ResponseRelevancy, FactualCorrectness
Ground Truth 없이 평가 가능 (Safety, Fluency, RelevanceToQuery, RetrievalGroundedness) 가능 (Faithfulness, ResponseRelevancy)
실험 관리 & UI 네이티브 지원 (Databricks / MLflow Tracking UI) 별도 설정 필요 (MLflow에 로깅하여 사용)
커스텀 Scorer/Metric @scorer 데코레이터로 쉽게 추가 커스텀 프롬프트로 추가 가능
LLM 백엔드 OpenAI, Databricks, Anthropic, Bedrock 등 OpenAI, Azure, LangChain LLM 등
에이전트/도구 평가 지원 (ToolCallCorrectness 등) 미지원
대화형 평가 지원 (ConversationCompleteness 등 다수) 미지원
입력 데이터 형태 pandas DataFrame 또는 list[dict] EvaluationDataset (HuggingFace Dataset 하위 호환)
설치 pip install mlflow pip install ragas

 

 

📚 시리즈 — RAG 품질

댓글