에이전트 평가(Agent Evals) 단축하기: 계층 순서는 선호도가 아닌 지연 시간 예산입니다
요약
에이전트 평가 시스템 구축 시 모든 체크를 병렬로 수행하는 대신, 지연 시간과 비용을 고려한 계층적 순서(ordering)를 적용해야 합니다. 결정론적인 외부 증거를 우선 배치하여 불필요한 LLM 판사 호출을 방지함으로써 효율성을 극대화할 수 있습니다.
핵심 포인트
- 평가를 단순 보고서가 아닌 실행을 차단하는 '게이트'로 설계해야 함
- 지연 시간과 비용 예산에 따라 평가 항목의 순서를 결정해야 함
- Tier 1: 위조 불가능한 외부 관찰 증거(JSON 유효성 등) 우선 배치
- Tier 2: 통계적 신호(임베딩 유사도 등)를 통한 검증
- Tier 3: 주관적 판단을 위한 모델 기반 판사(LLM judge)는 마지막에 배치
철저해 보이지만 은밀하게 망가져 있는 평가(eval) 레이어를 구축하는 유혹적인 방법이 있습니다. 바로 모든 실행(run)에 대해 모든 체크를 수행하고, 모든 점수를 수집한 다음, 마지막에 통과/실패를 결정하는 방식입니다. 이는 엄격해 보입니다. 하지만 또한 느리고, 비용이 많이 들며, 무엇보다 최악인 점은 — 모델 기반 판사(model-as-judge)가 이미 결정론적(deterministic)인 엄격한 체크에서 실패한 실행에 대해 거부권을 행사하게 만든다는 것입니다.
해결책은 더 많은 체크를 추가하는 것이 아닙니다. 바로 **순서(ordering)**입니다. 평가를 실행하는 순서는 스타일의 선택이 아닙니다. 그것은 지연 시간(latency)과 비용 예산이며, 당신이 실제로 무엇을 신뢰하는지를 인코딩합니다.
실수: 평가를 게이트(gate)가 아닌 보고서(report)로 취급하는 것
대부분의 팀이 처음 만드는 평가 하네스(harness)는 팬아웃(fan-out) 방식입니다. 형식 체크(format check), 유사도 체크(similarity check), 그리고 LLM 판사(LLM judge)를 병렬로 시작하고, await Promise.all을 사용하여 대시보드에 집계합니다. 평균값이 특정 임계값을 넘으면 통과(Green)로 표시합니다.
문제는 그 하네스가 실시간으로 실행을 _차단(block)_하기를 원할 때, 즉 재시도 게이트(retry gate), CI 체크, 발행 전 가드(pre-publish guard)로 사용하려 할 때 나타납니다. 이제 가장 느리고, 가장 비싸며, 가장 신뢰도가 낮은 구성 요소(판사)가, 이미 2ms 체크가 결정해 버린 결정을 위한 임계 경로(critical path)에 놓이게 됩니다. 만약 에이전트가 유효하지 않은 JSON을 출력했다면, 판사가 의견을 낼 여지도 없습니다. 당신은 이미 도착과 동시에 폐기된 출력을 채점하기 위해 모델 호출 비용과 4초의 p95 지연 시간을 지불하고 있는 것입니다.
평가-로서-보고서(Eval-as-report)와 평가-로서-게이트(eval-as-gate)는 서로 다른 작업입니다. 게이트는 핫 패스(hot path)에 위치할 수 있을 만큼 충분히 빠르고, 결정론적(deterministic)이며, 저렴해야 합니다. 보고서는 아무도 그것을 기다리지 않기 때문에 느리고 심도 있게 진행될 수 있습니다.
증거에는 독립성 축이 있으며, 이것이 순서를 결정합니다
순서가 중요한 이유는 단지 성능 때문만이 아닙니다. 모든 증거가 같은 종류의 증거는 아니기 때문입니다. 이것이 agent-eval의 핵심 아이디어입니다. 체크 항목을 비용 축이 아닌, 독립성(independence) 축 — 즉, 테스트 중인 에이전트가 신호를 얼마나 위조할 수 있는지 — 에 따라 순위를 매기십시오.
- Tier 1 — 에이전트가 위조할 수 없는 외부 관찰 가능한 증거. 유효한 JSON. 에이전트가 작성했다고 주장한 파일이 실제로 존재함. 코드가 컴파일됨. 테스트 통과. 타임아웃(timeout) 내에 완료됨. 출력이 비어 있지 않음. 이것들은 품질에 대한 주장이 아니라 세상에 대한 사실들입니다.
- Tier 2 — 에이전트가 작성하지 않은 베이스라인(baseline)에 대한 통계적 신호. 출력물과 작업 명세(task spec) 사이의 임베딩 유사도(embedding similarity). 길이 및 반복의 무결성(sanity). 차이점(diff)이 실제로 무언가를 변경했는지 여부. 에이전트는 베이스라인을 작성하지 않았으므로, 이를 쉽게 속일 수 없습니다.
- Tier 3 — 모델 기반 판사(model-as-judge). 공유된 기질(shared-substrate)을 가진 의견(opinion). 어조, 유용성, "이 논증이 일관적인가"와 같은 주관적인 영역에 유용합니다. 이것은 신호(signal)일 뿐이며, 결코 판결(verdict)이 아닙니다.
이것이 "저렴함에서 비쌈"으로 이어지는 순위가 아니라, 독립성 순위라는 점에 주목하십시오. 이것이 우연히 비용과 상관관계가 있어 순서를 정하면 비용도 절감되지만, Tier 1이 가장 먼저 오는 이유는 그것이 _위조 불가능(unforgeable)_하기 때문이며, 따라서 Tier 1의 실패는 결정적입니다. 컴파일되지 않은 출력물을 그 어떤 의견도 구제할 수 없습니다.
이 축에서 도출되는 두 가지 엄격한 규칙
Tier 1+2는 실시간 게이트(gate)입니다. Tier 3는 오프라인 전용입니다. Tier 1과 Tier 2는 결정론적(deterministic)이며, 비용이 거의 들지 않고, 한 자릿수 밀리초(ms) 내에 실행되므로 실행을 차단할 수 있습니다. Tier 3는 사용량 기반 요금이 부과되고, 느리며, 비결정론적(non-deterministic)이므로 핫 패스(hot path)에 위치할 수 없습니다. 판사를 실시간 결정 경계(decision boundary) 뒤에 두면, 정규 표현식(regex)으로 이미 해결된 문제에 대해 불안정하고 비싼 의존성(dependency)이 되어버립니다.
Tier 1+2는 궤적(trajectories)을 점수화할 수 있지만, Tier 3는 그렇지 못할 수 있습니다. 에이전트의 _추론 흔적(reasoning trace)_에 대해 결정론적 및 통계적 검사를 하루 종일 수행할 수 있습니다. 예를 들어 "말한 대로 도구를 호출했는가", "검색된 청크(chunk)에 인용된 사실이 실제로 포함되어 있는가" 등을 확인할 수 있습니다. 하지만 모델이 다른 모델의 추론을 판단하는 것은 **순환적(circular)**입니다. 판사와 피판단자가 동일한 기질을 공유하며 독립적인 정답(ground truth)이 없기 때문입니다. 따라서 Tier 3는 피판단 에이전트가 작성할 수 없었던 결과물, 즉 그것을 생성한 사고의 사슬(chain of thought)이 아닌 최종 출력물만을 검사해야 합니다.
연결 방식: 팬아웃(fan out)하지 말고 단락(short-circuit)시키세요
게이트(gate)를 '실패 시 즉시 중단(fail-fast)' 파이프라인으로 구성하는 방법은 다음과 같습니다. Tier 1이 먼저 실행되고 단락(short-circuit)됩니다. Tier 2는 Tier 1을 통과했을 때만 실행됩니다. Tier 3는 인라인(inline)으로 전혀 실행되지 않으며, 오프라인 점수 산정(offline scoring)을 위해 큐(queue)에 대기합니다.
type Verdict = { pass: boolean; tier: 1 | 2 | 3; reason: string };
type Check = {
...
판단(judge) 결과는 나중에 대시보드에 **"증거가 아닌 의견(opinion, not evidence)"**이라고 명확히 표시되어 나타납니다. 이는 사용자의 작업, 재시도(retry), 또는 배포(deploy)를 절대 차단하지 않습니다. 대신 Tier 1+2가 추론할 수 없는 약 20%의 주관적인 영역(subjective tail)에 정보를 제공합니다.
그리고 이 80/20 법칙이 바로 핵심적인 보상입니다. 실제 운영 환경에서 치명적인 실패들—오래된 출력물(stale output), 충돌(crash), 잘못된 형식(malformed format), 환각된 파일 경로(hallucinated file path), 빈 응답(empty response), SLO 초과(SLO blown)—은 모델 호출 전, 약 0달러의 비용으로 Tier 1+2에서 모두 포착됩니다. 당신은 오직 취향의 문제만이 남은 소수의 진정한 사례를 위해서만 비싸고 모호한 판단 모델(fuzzy judge)을 예약해 두는 것입니다.
트레이스(trace)가 게이트를 정직하게 만듭니다
fileExists(o.claimedPath)와 o.diffLines 안에는 숨겨진 핵심 가정이 있습니다. 즉, 해당 입력값들은 에이전트의 자기 보고(self-report)가 아니라 실제(real) 것이어야 한다는 점입니다. 만약 당신의 Tier 1 체크가 "에이전트가 파일을 작성했다고 말했는가?"를 읽는다면, 당신은 에이전트에게 펜을 쥐여주고 스스로 채점하게 만든 셈입니다. 그것은 더 이상 Tier 1이 아닙니다. 불리언(boolean)의 옷을 입고 있는 Tier 3일 뿐입니다.
이것이 바로 게이트에 신뢰할 수 있는 트레이스(trace)가 필요한 이유이며, AgentLens가 이 워크플로우의 나머지 절반인 이유입니다. agent-eval은 _출력물(output)_을 점수화하고 게이트를 통과시키지만, AgentLens는 _에이전트가 그 결과에 도달한 과정의 트레이스(trace of how the agent got there)_를 캡처합니다. 즉, 모든 모델 호출과 도구 단계(tool step), (템플릿화된 것이 아닌) 해결된 입력값(resolved inputs), 그리고 가공되지 않은 출력물(raw outputs)을 포착합니다. 그 트레이스는 바로 Tier 1+2가 점수를 매기기 위해 필요한, 에이전트가 조작할 수 없는(unforgeable) 에이전트 비작성 기질(agent-didn't-author substrate)입니다. 이것이 없다면 "파일이 존재함"은 "에이전트가 파일이 존재한다고 주장함"으로 격하되며, 당신의 독립적인 게이트는 조용히 자기 평가(self-assessment)로 붕괴됩니다.
다르게 말하자면, 에이전트 평가(agent-eval)는 실행 결과가 좋은지 _아닌지(whether)_를 알려주지만, AgentLens는 왜(why) 그런지를 알려주며 — 결정적으로 — 에이전트 자신의 서사(narration) 대신(instead of) 검증할 수 있는 게이트용 그라운드 트루스(ground truth)를 제공합니다. 이들은 하나의 단위로 배포되어야 합니다. 정직한 트레이스(trace)가 없는 게이트는 게이트가 아니기 때문입니다.
핵심 요약 (The takeaway)
평가 계층(eval layer)을 마지막에 점수를 집계하는 점수판처럼 취급하는 것을 멈추십시오. 독립성에 따라 순서를 정하고, 위조 불가능한 첫 번째 실패가 발생하면 즉시 단락(short-circuit)시키며, 판독기(judge)는 지연 시간(latency)과 비결정성(non-determinism)이 누구에게도 해를 끼치지 않도록 오프라인 상태로 유지하고, 에이전트가 작성할 수 없었던 트레이스를 전체 시스템에 제공하십시오. 이 순서는 선호의 문제가 아닙니다. 그것은 아키텍처(architecture)입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기