RAGAS와 DeepEval에 동일한 허위 답변을 입력했습니다. 하나는 0.0점을, 다른 하나는 1.0점을 주었습니다.
요약
RAG 시스템의 충실도(faithfulness)를 측정하는 RAGAS와 DeepEval 지표의 성능 차이를 실험을 통해 분석합니다. DeepEval이 허위 답변을 감지하지 못하는 한계를 지적하며, LLM-as-judge와 결정론적 체크를 병행하는 OpenGATE 방식의 필요성을 제안합니다.
핵심 포인트
- RAGAS는 허위 사실을 감지했으나 DeepEval은 1.0점을 부여하며 실패함
- LLM-as-judge는 비결정론적이며 지표 간 구현 차이가 존재함
- 의료 AI와 같이 신뢰성이 중요한 분야에서는 결정론적 검증이 필수적임
- LLM 판독기와 결정론적 체크를 병행하는 하이브리드 접근 권장
여기 컨텍스트(context)가 답변할 수 없는 질문에 대해, 제공된 적 없는 가격 정보를 주장하는 RAG 시스템의 출력이 있습니다. 저는 이 출력을 가장 인기 있는 두 가지 LLM-as-judge 충실도(faithfulness) 지표에 각각 5회씩 테스트했습니다. 판독기는 판독 안정성에 가장 유리한 설정인 temperature 0의 gpt-4o를 사용했습니다.
RAGAS는 0.000점을 주었습니다.
DeepEval은 5회 반복 모두 1.000점을 주었으며, 그 이유를 다음과 같이 설명했습니다: "실제 출력과 검색된 컨텍스트(retrieval context) 사이에 모순이 없으므로 점수는 1.0입니다." 한 반복 테스트에서는 _"정확성과 일관성을 유지하는 데 훌륭한 성과를 보였습니다!"_라는 코멘트도 추가되었습니다.
두 지표 모두 _충실도(faithfulness)_라고 불립니다. 두 지표 모두 내부적으로는 일관성이 있습니다. 하지만 오직 하나만이 이 허위 사실(fabrication)을 감지했습니다.
저는 왜 이런 일이 발생하는지, 제대로 측정했을 때 무엇을 추가로 발견했는지, 그리고 왜 제 결론이 여러분이 예상할 법한 LLM-as-judge에 대한 비판이 아니라 '둘 다 사용하라' (즉, LLM 판독기와 결정론적 체크(deterministic checks)를 병행하라)인지 설명하고자 합니다.
이것을 측정해야 했던 이유
저는 헬스케어(healthcare)를 위한 AI 도구들을 만듭니다. 의료 작가를 위한 주장 검증(claim verification), 등록된 의료 기기인 환자용 텍스트 단순화 도구, 임상 데이터 비식별화(clinical de-identification) 등이 그 예입니다. 이 분야에서 답변은 소스 자료로부터 정당화될 수 있을 때만 유용하며, 중요한 실패 모드(failure modes)는 매우 조용하게 발생합니다. 예를 들어, 단순화된 퇴원 서신에서 약물 용량이 조용히 누락되거나, 모델이 친절하게 참조 범위를 지어내거나, 컨텍스트에 답이 없음에도 시스템이 자신 있게 답변하는 경우입니다.
저는 이러한 속성들을 기준으로 릴리스(release)를 제어해야 했습니다. 즉, 프롬프트 변경으로 인해 시스템의 신뢰도가 떨어지면 빌드(build)를 실패시켜야 합니다. 하지만 LLM-as-judge 지표를 빌드 제어에 사용하는 것은 까다롭습니다. 실행당 비용이 발생하고, 비결정론적(non-deterministic)이며, (결과적으로 밝혀진 바와 같이) "동일한" 지표의 두 가지 구현체가 서로 다른 것을 측정하기 때문입니다.
그래서 저는 모든 검증이 출력값과 수동으로 라벨링된 골드 케이스 (gold case)의 순수 함수 (pure function)가 되는 OpenGATE를 구축했습니다. 즉, 필수 사실이 포함되어 있어야 하며 (허용 가능한 의역 포함), 답변 내의 모든 숫자는 컨텍스트 (context)로 추적 가능해야 하고, 컨텍스트가 답할 수 없는 경우 시스템은 답변을 유보 (abstain)해야 합니다. 어디에도 채점 모델 (grader model)은 사용하지 않았습니다. 그런 다음, 각 접근 방식이 실제로 무엇을 포착하는지 알아내기 위해 RAGAS 및 DeepEval과 통제된 비교 실험을 수행했습니다.
실험 (The experiment)
27개의 출력물로 구성된 고정된 코퍼스 (corpus): 시스템 출력물 6개 (그 중 3개는 프로덕션 환경에서 추출)와 각각 정확히 하나의 알려진 결함 (defect)을 주입한 변이체 (mutants) — 누락된 사실, 조작된 숫자, 유보 실패, 추가된 모순, 또는 그 자리에서의 의미 반전 (meaning inversion) — 로 구성됩니다. 각 실험군당 5회 반복 수행했습니다. 판정 모델 (Judges)은 gpt-4o를 사용했으며, 온도는 0으로 설정했습니다.
공정성을 위해 세 가지 설계 선택이 중요했습니다. 결함 클래스 (defect classes)는 범위에 따라 그룹화되며 절대 합산되지 않습니다. 결정론적 검증 (deterministic checks)은 의미 반전을 포착할 수 없으므로, 모든 것을 하나의 정확도 수치로 뭉뚱그리는 것은 (어느 방향으로든) 결과를 왜곡하는 것이 될 것입니다. 탐지는 동일한 케이스의 변이되지 않은 기본 출력물과 비교하여 주입된 결함에 대한 반응으로 측정되므로, 기존에 존재하던 특이점이 탐지된 것으로 잘못 계산되지 않습니다. 그리고 출력물은 모든 반복 실험에서 플래그 (flag)가 지정된 경우에만 탐지된 것으로 간주됩니다. 간헐적으로 실패하는 게이트 (gate)는 게이트가 아니기 때문입니다. 모든 입력값, 스크립트, 그리고 반복당 점수는 논문 아티팩트 (paper artifact)에 기록되어 있습니다.
결과는 양면적입니다
판정 모델 (judges)이 압도적으로 승리하는 지점. 의미 반전 (모든 앵커와 숫자는 그대로 유지되지만 "음식과 함께 복용"이 "공복에 복용"으로 바뀌는 경우)에 대해, RAGAS는 4/5를 포착했고 DeepEval은 5/5를 포착했습니다. 결정론적 검증은 0/5를 포착했으며, 앞으로도 항상 그러할 것입니다. 문자열 검증 (string checks)에는 의미에 대한 모델이 없습니다. 이것은 판정 모델의 미미한 우위가 아니라 범주적인 우위이며, 이것이 이 글이 비난을 위한 글이 아닌 이유입니다.
판정 모델 (judges)이 패배하는 지점.
누락 (Omission). 항생제 용량이 누락된 것은 근거 없는 내용을 주장하는 것이 아니기에, 충실도 (faithfulness) 지표는 구조적으로 이를 감지할 수 없습니다. 판정 모델 (judges)은 누락된 사실을 5개 중 0개와 1개만 잡아냈습니다. 반면 결정론적 앵커 체크 (deterministic anchor check)는 5개 중 5개를 모두 잡아냈습니다. 제가 500mg 용량을 삭제한 퇴원 요약서(discharge summary)에 대해, DeepEval은 _"모순되는 내용이 없습니다."_라는 근거와 함께 1.00점을 반환했습니다. 항생제 용량이 누락된 출력값에 대해, 통과 점수를 확신하며 설명한 것입니다.
비용과 속도. 1,000회 평가당 $11.49 (RAGAS) 및 $8.29 (DeepEval)인 반면, [결정론적 체크는] $0.00입니다. 반복당 194초와 119초인 반면, [결정론적 체크는] 3.8밀리초입니다. 이 차이는 모든 커밋 (commit)마다 체크를 수행할 수 있을지, 아니면 모든 답변마다 수행할 수 있을지를 결정합니다.
로컬라이제이션 (Localisation). 결정론적 체크가 실패할 때는 missing fact "500 mg"와 같이 실패 원인을 명시합니다. RAGAS는 스칼라 (scalar) 값을 반환합니다. DeepEval은 때로는 유용한 근거를 반환하지만, 때로는 위에서 언급한 "모순되는 내용이 없습니다"라는 문장을 반환합니다.
제가 가장 중요하게 생각하는 발견은 정의(definition)에 관한 것입니다. RAGAS는 _"모든 주장이 컨텍스트 (context)에 의해 뒷받침되는가?"_라고 묻습니다. DeepEval의 충실도 (faithfulness)는 _"어떤 주장이 컨텍스트와 모순되는가?"_라고 묻습니다. 지어낸 수치는 아무것도 모순시키지 않습니다. 컨텍스트는 그에 대해 침묵하고 있기 때문입니다. 따라서 소스에 포함되지 않은 내용을 주장하는 6개의 출력값에 대해, RAGAS는 5개를 잡아냈으나 DeepEval은 0개를 잡아냈습니다. 명백한 모순에 대해서는 두 모델이 유사하게 일치했습니다 (7/10 대 9/10). 이 차이는 노이즈가 아니라 체계적 (systematic)입니다.
불편한 시사점은 다음과 같습니다. 구현 방식을 읽지 않고 "판정 모델로서의 LLM 충실도 (LLM-as-judge faithfulness)"를 채택하는 팀은 엄격함의 수준을 선택한 것이 아닙니다. 그들은 자신도 모르게 _어떤 실패 모드 (failure mode)에 눈을 감을 것인지_를 선택한 것입니다. 환자를 대면하는 의료 도구의 경우, 지어낸 용량은 가장 중요한 실패 요인이지만, 모순 기반의 판정 모델은 바로 그 부분을 그냥 지나쳐 버립니다.
철회하는 주장
저는 판정 모델의 _불안정성 (instability)_을 입증하기를 기대하며 이 실험을 설계했습니다. 강력한 판정 모델(judge model)을 사용할 경우 그 발견의 힘은 약해지며, 저는 이를 숨기기보다는 보고하고자 합니다. gpt-4o/temp 0 환경에서 반복 실행 시 출력당 평균 점수 범위는 RAGAS의 경우 0.026, DeepEval의 경우 0.013이었습니다. gpt-4o-mini에서 동일한 코퍼스(corpus)를 사용했을 때는 훨씬 더 노이즈가 심했습니다(27개 출력 중 11개가 반복 실행 간에 판결이 변경됨). 따라서 불안정성은 판정 행위 자체의 특성이 아니라, 판정 _모델 (model)_의 특성입니다. 판정 결과에 따라 빌드(build)를 차단(gating)하지 말아야 한다는 주장의 근거는 누락에 대한 맹목성(omission-blindness), 정의적 차이(definitional divergence), 그리고 비용에 기반합니다. 이 중 그 어떤 것도 더 나은 판정 모델이 해결해 줄 수 있는 것이 아닙니다.
결정론적 게이팅(deterministic gating)이 운영 환경에서 잡아낸 것들
이 프레임워크는 4개의 운영 시스템(production systems)에 걸쳐 CI(지속적 통합) 환경에서 실행됩니다. 처음 실행된 결과들은 모두 이전에 알지 못했던 것들이었습니다. 첫째, 조용한 파싱 실패(silent parse failure)로 인해 다중 주장(multi-claim) 판정의 약 50%가 기본값인 "지원되지 않음(Not Supported)"으로 처리되었습니다. 둘째, 비식별화 엔진(de-identification engine)에서 두 개의 이름 캡처 버그가 발견되었습니다(O'Brien과 같은 아포스트로피가 포함된 성씨가 캡처 패턴에서 누락됨). 셋째, 단순화 도구(simplifier)가 퇴원 요약서(discharge summary)에서 항생제 용량을 누락시켰습니다.
제가 가장 인상 깊게 본 실패 사례는 몇 달 후에 발생했습니다. 용량 누락 문제를 수정한 후, 동일한 시스템이 조작된 (fabricated) 숫자를 생성했습니다: "보통 우리는 헤모글로빈 수치가 12 g/dL 이상인 것을 선호합니다" — 이는 임상적으로는 정확하지만, 원문 서신에는 없는 내용이었습니다. 이전의 프롬프트 수정 사항은 _숫자를 절대 누락하거나 변경하지 말 것_이라고 명시했습니다. 이는 수치를 잃어버리는 것은 금지했지만, 수치를 새로 만들어내는 것에 대해서는 침묵했습니다. 마지막 결함을 방어하도록 강화된 프롬프트가 다음 결함에 대해서도 강화되어 있다는 보장은 없습니다. 이것이 바로 한 번 실행하는 감사(audit)가 아니라, 모든 변경 사항에 대해 실행되는 게이트(gate)가 필요한 이유입니다. 녹색 점수표(green scorecard)는 측정값이지, 속성이 아닙니다.
솔직한 주의사항
이 변이체(mutants)들은 실제 환경에서 샘플링된 것이 아니라, 제가 관찰했던 결함들로부터 파생된 합성 데이터입니다. 코퍼스(corpus)는 27개의 출력물로 구성되어 있으며, 하나의 판사 모델(judge model)을 사용했습니다. 또한 제가 결함 분류 체계(defect taxonomy)와 실험의 한 축을 직접 작성했습니다. 이것이 범위(scopes)가 별도로 보고되는 이유이며, 제 접근 방식이 0점을 기록한 역전 클래스(inversion class)가 코퍼스에 포함된 이유이기도 합니다. 전체 논문에는 제가 사전 등록(pre-registered)했으나 아직 실행하지 않은 실험(골드 세트(gold sets)를 위한 독립적인 두 번째 라벨러)을 포함하여, 타당성 위협(threats-to-validity) 섹션이 포함되어 있습니다.
실제로 제가 추천하는 방식
각자가 볼 수 있는 것을 활용하기 위해 두 가지를 모두 사용하십시오. 의미론적 측면(semantics) — 즉 의미의 역전(meaning inversions), 모순(contradiction), 개방형 품질(open-ended quality) — 에 대해서는 LLM 판사(LLM judge)를 사용하십시오. 이 영역에서는 LLM이 범주적으로 훨씬 뛰어납니다. 결정론적 검사(Deterministic checks)는 게이트(gate)로서 사용하십시오. 필수 사실의 존재 여부, 숫자의 추적 가능성, 답변 유보(abstention) 준수 여부 등을 확인합니다. 이는 재현 가능하며, 실패 원인이 명시되고, 무료이며, 모든 커밋(commit)과 모든 답변에 대해 충분히 빠릅니다.
결정론적 방식을 시도해보고 싶다면, MIT 라이선스로 제공되며 API 키 없이 한 줄로 실행할 수 있습니다:
npx @pharmatools/opengate
Python (pip install opengate-grounding):
from opengate_grounding import check_grounding
result = check_grounding(
...
또한 pytest 헬퍼, DeepEval의 GroundingMetric (네, 판사 메트릭(judge metrics)과 함께 통합되어 잘 작동합니다. 그것이 핵심입니다), 회귀(regressions) 발생 시 빌드를 실패시키는 GitHub Action, 그리고 에이전트가 답변하기 전에 스스로의 답변을 확인할 수 있도록 하는 MCP 서버도 있습니다.
저장소(Repo): github.com/nickjlamb/opengate · 논문(Paper): doi.org/10.5281/zenodo.21365095
저는 의료 분야를 위한 AI 도구 구축으로 전향한 메디컬 라이터(medical writer)입니다. 이 포스트의 모든 내용은 커밋된 아티팩트(artifact)로부터 재현 가능합니다. 만약 유효하지 않은 부분을 발견하신다면 이슈(issue)를 제기해 주세요. 그것이 바로 게이트(gate)가 존재하는 이유입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기