12.8.4 검증 결과 리포팅 포맷 설계 (Pass/Fail, Diff 시각화)

12.8.4 검증 결과 리포팅 포맷 설계 (Pass/Fail, Diff 시각화)

비교 판별기의 심장부에서 이루어지는 숨 막히는 동등성(Equality) 검사 연산이 마침내 끝났다면, MLOps 프레임워크 파이프라인의 최종 종착지는 이 난해하고 차가운 이진(Binary) 데이터를, 인간 데이터 사이언티스트의 눈과 AI 에이전트의 피드백(Reflection) 루프가 직관적으로 “읽어내고 단서를 찾을 수 있는” 투명한 메타데이터 포맷으로 렌더링(Rendering)하는 것이다.

오라클은 단순히 콘솔창에 기계적으로 True/False 불리언 값만 덜렁 뱉어놓고 스레드를 종료해 버리는 조악한 룰 엔진이 아니다. 위대한 평가 시스템은 AI 모델 에이전트에게 가혹한 오답(FAIL, EX=0)을 선고해야 할 때조차, 어느 컬럼의 어떤 행(Row)에서 물리적 데이터가 교차로 어긋났는지 완벽하게 역공학(Reverse Engineering)하여 증명해 내는 입체적이고 적나라한 Diff(Difference) 리포트를 수여해야만 한다.

1. 평가 페이로드(Evaluation Payload)의 JSON 스키마 조립

채점 스레드의 최종 결과물은 웹 프런트엔드 대시보드나 CI/CD 파이프라인(Jenkins, GitHub Actions) 로그 수집기로 즉각 전송되어야 하므로, 기계가 쉽게 파싱할 수 있는 JSON 형태의 일관된 상태 객체 스키마로 묶여서 출력된다.

import json
import logging

def generate_immutable_evaluation_report(is_pass: bool, ref_sql: str, gen_sql: str, diff_log: str = None) -> str:
    """
    [Output Layer] 오라클의 최종 채점 트랜잭션 결과를 
    엔터프라이즈 표준 규격화된 JSON MLOps 리포트로 렌더링한다.
    """
    payload = {
        # EX (Execution Accuracy) 메트릭을 위한 핵심 이진 플래그 (1: 정답, 0: 오답)
        "execution_match": 1 if is_pass else 0,
        "status_code": "PASS" if is_pass else "FAIL",
        
        # 모델의 사고 과정을 기록하기 위한 쿼리 아카이브
        "query_architecture_logs": {
            "golden_reference_sql": ref_sql,
            "ai_predicted_sql": gen_sql
        },
        
        # 모델이 실패했을 경우, 뼈아픈 수술(디버깅)을 위한 차집합 텍스트 로그
        "debugging_tensor_diff": diff_log or "Perfect Set Match (EX=1). No difference detected."
    }
    
    # 디버깅 콘솔 출력 및 영구 로깅을 위한 JSON 덤핑
    return json.dumps(payload, indent=4, ensure_ascii=False)

2. Pandas Outer Join을 이용한 상호 차집합(Set Difference) 시각화 로직

이 리포팅 모듈에서 가장 찬란하게 빛나는 것은, 오답(FAIL)이 발생했을 때 역으로 그 구체적인 원인 diff_log를 텍스트로 그려내는 컴포넌트다.
12.5.1절에서 증명했던 양방향 차집합(Set Difference, A \setminus BB \setminus A)의 대수 논리를, Pandas의 데이터프레임 outer merge(병합) 기능을 통해 가장 저렴하고 아름답게 시각적 텍스트로 추출해 낸다.

def extract_tensor_diff_report(ref_df: pd.DataFrame, gen_df: pd.DataFrame) -> str:
    """
    두 텐서의 교집합이 붕괴했을 때, 
    누락된 데이터(Missing)와 잡음으로 초과된 데이터(Extra)를 시각적으로 해부한다.
    """
    if ref_df.empty or gen_df.empty:
        return "[CRITICAL WARNING] One of the tensors is completely empty. Unable to compute diff matrix."

    # 두 데이터프레임을 양방향 외부 조인(Outer Join)으로 융합하고, 병합의 출처(_merge) 표시등을 켠다
    diff_df = pd.merge(ref_df, gen_df, how='outer', indicator=True)
    
    # 1. 정답 공간(Left)에는 존재하는데 AI가 어리석게도 빼먹은 찌꺼기 레코드 추적
    missing_in_gen = diff_df[diff_df['_merge'] == 'left_only'].drop(columns=['_merge'])
    
    # 2. 정답 공간에는 없는데 AI가 환각에 빠져 불필요하게 더 긁어와버린 쓰레기 레코드 추적
    extra_in_gen = diff_df[diff_df['_merge'] == 'right_only'].drop(columns=['_merge'])
    
    report_lines = []
    
    # 대시보드를 너무 길게 오염시키지 않기 위해 최상단 5개의 헤드(head) 단서만 리포팅
    if not missing_in_gen.empty:
        report_lines.append(f"🛑 [MISSING (AI가 누락한 정답 튜플)]\n{missing_in_gen.head(5).to_string()}")
    if not extra_in_gen.empty:
        report_lines.append(f"⚠️ [EXTRA (AI가 환각으로 더 가져온 오답 튜플)]\n{extra_in_gen.head(5).to_string()}")
        
    return "\n\n=================================\n\n".join(report_lines)

[최종 오라클 클래스 시그니처 런타임 렌더링 결과 예시]

{
    "execution_match": 0,
    "status_code": "FAIL",
    "query_architecture_logs": { ... },
    "debugging_tensor_diff": "🛑 [MISSING (AI가 누락한 정답 튜플)]\n  col_index_0  col_index_1\n0 Alice   5000.0\n\n=================================\n\n⚠️ [EXTRA (AI가 환각으로 더 가져온 오답 튜플)]\n  col_index_0  col_index_1\n3   Bob   4500.0"
}

이로써 거칠고 파편화된 RDBMS의 데이터를 메모리로 안전하게 끌어올려 정규화하고, 흔들림 없이 동등성을 검증한 뒤,
패배한 AI 모델 에이전트와 그것을 지켜보는 데이터 엔지니어에게 가장 날카롭고 직관적인 디버깅 단서를 친절하게 떠먹여 주는 **‘엔드투엔드(End-to-End) 결정론적 오라클 평가 프레임워크의 실전 구현’**이 모두 극적이고 완벽하게 대단원의 막을 내렸다.