당신의 평가(Evals) 또한 불안정합니다: 재현할 수 없는 통과율(Pass Rate)을 신뢰하는 것을 멈추세요
요약
LLM 에이전트 평가(Evals) 시스템 자체가 비결정론적일 수 있다는 위험성을 경고합니다. 채점 모델의 변동성, 인프라 문제, 모호한 루브릭으로 인해 발생하는 '불안정한 평가(Flaky evals)' 문제를 지적하며 신뢰할 수 있는 품질 게이트 구축의 필요성을 강조합니다.
핵심 포인트
- 채점 모델(Judge) 자체가 비결정론적이라 결과가 변할 수 있음
- 온도(Temperature)를 0으로 설정해도 완벽한 결정론은 보장되지 않음
- 입력값의 표류(Drift) 등 인프라 환경이 평가 결과에 영향을 미침
- 모호한 루브릭은 변동성을 높이므로 정교하고 세분화된 기준이 필요함
- 평가 시스템을 불안정한 테스트 코드처럼 취급하고 관리해야 함
우리는 지난 2년 동안 에이전트(Agents)는 비결정론적(Non-deterministic)이라는 사실을 모두에게 가르쳐 왔습니다. 동일한 프롬프트(Prompt)를 사용하더라도 실행할 때마다 결과가 다릅니다. 괜찮습니다. 우리는 이를 내면화했습니다. 우리는 동일성을 주장하는 것을 멈췄고, 모델 기반 평가(Model-as-judge evals)를 구축했으며, 이를 CI(지속적 통합)에 도입했습니다.
그러고 나서 우리는 은연중에 평가(Evals) 자체는 결정론적(Deterministic)일 것이라고 가정했습니다. 하지만 그렇지 않습니다.
당신의 평가 스위트(Eval suite)는 또 다른 비결정론적 시스템을 채점하는 비결정론적 시스템입니다. 만약 당신의 채점기(Grader)가 얼마나 흔들리는지 측정하지 않았다면, 당신에게는 품질 게이트(Quality gate)가 없는 것입니다. 당신은 그저 실험실 가운을 입은 동전 던지기를 가지고 있을 뿐입니다.
나에게 이를 가르쳐 준 버그
우리는 고객 지원 에이전트에 대해 모델 기반 평가(Model-as-judge)를 수행했습니다: "응답이 고객이 명시한 문제를 올바르게 해결합니까? PASS 또는 FAIL을 반환하세요." 몇 주 동안 초록색(Green)이 유지되었습니다. 그러다 릴리스(Release)가 나갔고, 대시보드는 여전히 초록색이었지만, 불만 사항은 급증했습니다.
나는 저장된 동일한 200개의 응답에 대해 정확히 동일한 평가를 다시 실행했습니다. 그중 14개의 판결이 뒤집혔습니다. 에이전트가 변해서가 아닙니다. 응답은 디스크에 고정되어 있었습니다. _채점기(Judge)_가 마음을 바꾼 것입니다. 온도(Temperature), 샘플링(Sampling), 모델 측의 업데이트 등 이유는 알 수 없습니다. 나의 "97% 통과율(Pass rate)"은 97% +/- 내가 한 번도 측정하지 못한 무언가였으며, 그 무언가는 퇴보(Regression)를 숨길 수 있을 만큼 충분히 컸습니다.
평가가 틀린 것이 아니었습니다. 그것은 _불안정(Flaky)_했습니다. 그리고 불안정한 게이트는 게이트가 없는 것보다 더 나쁩니다. 왜냐하면 근거 없는 자신감을 만들어내기 때문입니다.
불안정한 평가(Flaky evals)가 발생하는 세 가지 원인
1. 채점 모델(The judge model). 모든 LLM-as-judge 호출은 채점 대상이 되는 대상과 동일한 분산(Variance)을 상속받습니다. temperature: 0으로 실행하면 이를 줄일 수 있지만, "줄이는 것"이 "제거하는 것"은 아닙니다. 제공업체(Providers)는 온도가 0일 때조차 결정론(Determinism)을 보장하지 않으며, 조용한 모델 버전 업데이트는 하룻밤 사이에 당신의 기준선(Baseline)을 초기화해 버립니다.
2. 채점기를 둘러싼 하네스(The harness around the judge). 검색된 컨텍스트(Retrieved context), 도구가 해결된 순서, 잘린 입력(Truncated input), 채점기가 실제로 본 내용을 변화시킨 속도 제한(Rate-limit) 재시도 등이 있습니다. 채점기는 완벽하게 일관된 답변을 내놓았을지 모릅니다. 하지만 입력값이 표류(Drift)했기 때문에, 지난번과는 다른 질문에 대한 답변을 한 것입니다.
3. 당신만의 루브릭 (Rubric). "이 답변이 좋은가?"는 사양(Spec)이 아닙니다. 모호한 루브릭(Rubric)은 변동성(Variance)을 판사(Judge)의 해석 영역으로 밀어넣으며, 그 영역은 당신이 관찰할 수 없는 곳입니다. 정교하고 세분화된 루브릭은 그 변동성을 억제합니다.
이 중 오직 하나만이 "모델이 무작위적이다"라는 점에 주목하십시오. 나머지 두 가지는 인프라(Infrastructure) 문제이며, 단순히 PASS/FAIL 결과만으로는 이를 구분할 수 없습니다.
당신의 평가(Eval)를 불안정한(Flaky) 테스트 코드처럼 취급하십시오. 실제로 그러하기 때문입니다.
백엔드 엔지니어들은 이미 비결정론적(Non-deterministic) 체크를 처리하는 방법을 알고 있습니다. 불안정한 테스트를 그대로 배포하는 것이 아니라, 격리(Quarantine)하고, 그 불안정성 비율(Flake rate)을 측정하며, 수정하거나 삭제합니다. 여기서도 동일한 규율이 필요합니다.
첫째, 점수를 신뢰하기 전에 불안정성(Flake)을 수치화하십시오. 각 판사(Judge) 호출을 N번 실행하고 평균이 아닌 일치도(Agreement)를 확인하십시오:
type Verdict = "PASS" | "FAIL";
interface JudgeResult {
...
핵심은 마법 같은 0.8이라는 숫자가 아닙니다. 핵심은 이제 UNSTABLE이 일급 객체(First-class) 결과값이 되었다는 점입니다. 판사가 5번 중 3번을 뒤집는 케이스는 60%의 통과율이 아닙니다. 그것은 고장 난 체크이며, 위안을 주는 숫자로 조용히 평균화될 것이 아니라, 명확하게 실패를 알리고 격리되어야 합니다.
둘째 — 그리고 이는 모두가 건너뛰는 절반의 과정입니다 — 불일치(Disagreement)를 디버깅할 수 있어야 합니다. 판사가 왜 의견이 갈렸는지 알 수 없다면, 특정 케이스가 UNSTABLE하다는 사실을 아는 것은 무용지물입니다. 이를 위해서는 그 5번의 실행 각각에 대한 트레이스(Trace)가 필요합니다. 즉, 판사가 실제로 받은 최종 프롬프트(Resolved prompt), 검색된 컨텍스트(Retrieved context), 도구 출력값(Tool outputs), 판사의 가공되지 않은 완성본(Raw judge completion)이 필요합니다. 요약본이 아니라, 바이트(Bytes) 단위의 데이터가 필요합니다.
이것이 바로 2계층 분리(Two-layer split)가 제 역할을 하는 지점입니다.
이것은 제가 계속해서 강조하는 워크플로우이며, 이는 하나의 루프를 구성하는 두 개의 절반이지, 마지막에 끼워 맞추는 두 개의 별개 제품이 아닙니다.
agent-eval은 출력을 점수화하고 게이트를 통과시키는(Scores and gates the output) 계층입니다. 이는 결정론적 체크(Deterministic checks)와 모델 기반 판사(Model-as-judge) 단계를 실행하며, 앞서 언급한 안정성/일치도를 계산합니다. 또한 "에이전트가 답변했다"라는 상태를 CI(지속적 통합)가 조치할 수 있는 PASS / FAIL / UNSTABLE 상태로 전환하는 역할을 합니다. 즉, 판결(Verdict)을 소유합니다.
AgentLens는 해당 판결(verdict)이 어떻게 발생했는지의 흔적을 포착하는 계층입니다. 에이전트 실행과 심사관(judge) 실행 모두에 대해 해결된 입력값(resolved inputs)과 원시 출력값(raw outputs)을 포함한 모든 모델 호출 및 도구 단계(tool step)를 기록합니다. 이 부분이 설명(explanation)을 소유합니다.**
두 가지가 모두 필요합니다. 왜냐하면 평가 점수만으로는 세 가지 불안정성 근원지 중 어느 것을 건드렸는지 알 수 없기 때문입니다. agent-eval이 특정 사례를 UNSTABLE로 표시할 때, 다섯 개의 AgentLens 흔적을 나란히 가져와 보면 원인이 즉시 파악됩니다. 만약 해결된 심사관 입력값이 실행 간에 동일한데도 판결이 뒤집혔다면, 그것은 심사관 모델(judge model)의 문제입니다. 루브릭을 강화하거나 버전을 고정하세요. 만약 입력값이 다르다면, 그것은 결코 심사관 문제가 아니었습니다. 당신의 _하네스(harness)_가 비결정적(non-deterministic)이며 에이전트의 컨텍스트가 실행 간에 표류했기 때문입니다. 같은 UNSTABLE 플래그지만 정반대의 해결책입니다. 판결은 그것이 불안정하다는 것을 알려줄 뿐이고, 흔적(trace)은 왜 그런지 알려주며, 이 '왜'가 유일하게 조치가 가능한 부분입니다.
흔적 없이 모든 불안정한 평가는
우리는 에이전트(agents)가 비결정론적(non-deterministic)이라는 사실에 대해 혹독한 경험을 통해 겸손함을 배웠습니다. 평가(eval) 레이어 또한 동일한 확률적(stochastic) 요소들로 구축되어 있으며, 따라서 동일한 의구심을 가질 가치가 있습니다. 재현할 수 없는 초록색 대시보드는 품질 신호가 아닙니다. 그것은 당신이 스스로에게 들려주는 이야기일 뿐이며, 그것이 사실인지 확인하는 유일한 방법은 채점자(grader)를 채점하고 그 점수를 증명하는 흔적(trace)을 보관하는 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기