
임계값 테스트는 에이전트 성능 저하를 감지하지 못합니다; 우리는 29개의 PR로 검증된 통계적 대안을 구축했습니다
요약
LLM 에이전트의 성능 변화가 단순 노이즈인지 실제 성능 저하인지 통계적으로 검증하는 라이브러리 'agent-eval'을 소개합니다. 기존의 임계값 기반 테스트가 놓치는 미세한 성능 변화를 p-value와 효과 크기를 통해 정확히 포착합니다.
핵심 포인트
- 단순 임계값 테스트의 한계인 샘플링 노이즈 문제를 지적함
- p-value와 효과 크기를 활용한 통계적 회귀 테스트 방식 도입
- LangGraph, CrewAI 등 주요 프레임워크의 실제 PR을 통해 검증 완료
- pip install agent-regress-cli로 간편하게 사용 가능
Rudrendu Paul과 Sourav Nandy가 공동 작성했습니다.
Repo: github.com/RudrenduPaul/agent-eval, LLM 에이전트를 위한 통계적 회귀 테스트 (regression-testing) 라이브러리입니다. pip install agent-regress-cli.
시스템 프롬프트의 한 줄을 수정했습니다. 다음 날 실행된 평가 (eval) 결과에서 정확도가 3포인트 하락했습니다. 이것이 실제 성능 저하 (regression)일까요, 아니면 단순한 LLM 샘플링 노이즈 (sampling noise)일까요? 대부분의 평가 스위트 (eval suites)는 이를 알려줄 수 없습니다. 왜냐하면 행동의 전체 분포 (distribution)가 어떻게 변화했는지 측정하는 대신, 단일 응답이 임계값 (threshold)을 통과했는지 여부만 확인하기 때문입니다. 프롬프트를 미세하게 조정하거나, GPT-4o에서 더 저렴한 티어로 교체하거나, LangGraph 또는 CrewAI의 의존성 (dependency)을 조용히 업데이트하더라도, 평가 스위트는 상관없이 여전히 초록색(통과)을 표시할 수 있습니다.
agent-eval은 그 질문에 직접적으로 답합니다. 버전 A에서 에이전트를 50번 실행하고 버전 B에서 50번 실행한 다음, p-value (p-값)와 효과 크기 (effect size)를 보고하여 실제로 무언가 변했는지 알 수 있게 해줍니다:
from agent_regress import compare
report = compare(
...
다음은 저장소의 실제 실행 예시에서 포착된 성능 저하 (regression)의 모습입니다:
이 스크린샷 하나에 핵심 가치가 담겨 있습니다: agent-eval은 버전당 500회의 실제 시행 (trials)을 수행하고, 단순히 낮은 점수를 보고하는 대신 통계적으로 확신할 수 있는 REGRESSED (성능 저하) 판정을 보고합니다.
우리는 단순히 그것을 출시하고 끝내고 싶지 않았습니다. 사람들이 오늘날 에이전트 (agents)를 실행하는 프레임워크 (frameworks)에서 발생하는 실제적이고, 병합되었으며, 논쟁의 여지가 있는 코드 변경 사항들에 대해 이 도구가 실제로 견뎌낼 수 있는지 알고 싶었습니다. 그래서 우리는 6개의 리포지토리 (repos)에서 239개의 실제 병합된 PR (Pull Requests)을 추출했습니다: LangGraph, CrewAI, OpenAI Agents SDK, 그리고 EleutherAI의 lm-evaluation-harness, DeepEval, 그리고 Hugging Face의 evaluate (프레임워크 통합에 집중하기 전, 동일한 제안을 바탕으로 건전성 검사를 수행했던 세 가지 인접 평가 및 벤치마크 도구들)가 포함됩니다. 각 PR에 대해 우리는 간단한 질문을 던졌습니다: 만약 agent-eval을 정확히 이러한 종류의 변경 사항에 적용한다면, 그것이 해당 변경 사항에 대한 초기 제안(cold pitch)에서 주장하는 바를 전달할 수 있을까? 이 글의 나머지 부분에서는 우리의 도구가 첫 번째 호출에서 충돌했던 부분을 포함하여, 해당 캠페인이 발견한 내용들을 다룹니다.
Gartner는 2027년 말까지 에이전트형 AI (agentic AI) 프로젝트의 40% 이상이 폐기될 것으로 예상하며, 가장 자주 언급되는 이유는 "비용 상승, 불분명한 비즈니스 가치, 또는 부적절한 리스크 제어"입니다 (Gartner, 2025년 6월). "부적절한 리스크 제어"는 종종 이 문제의 다른 모습일 뿐입니다: 마지막 배포 (deploy) 이후 에이전트의 동작이 실제로 변했는지 아무도 말할 수 없다는 것입니다.
임계값 테스트가 이를 놓치는 이유
대부분의 평가 (eval) 도구들은 한 가지 질문에 답합니다: 이 응답이 통과했는가? DeepEval, Promptfoo, Braintrust는 모두 루브릭 점수 (rubric score), 완전 일치 (exact match), 또는 판사 모델 (judge-model)의 판결과 같은 임계값 (thresholds)을 중심으로 구축되었습니다. 이들 중 어떤 것도 동일한 시스템의 두 버전 사이에서 에이전트의 동작이 유의미하게 변화했는지 알려주지 않습니다. v1과 v2 사이의 3점 정확도 하락은 실제적인 변화일 수도 있고, 단순히 일반적인 LLM 샘플링 분산 (sampling variance)일 수도 있습니다. 분포 테스트 (distributional test) 없이는 그 차이를 구별할 수 없습니다. 팀들은 보통 작은 하락은 무시하고 리스크를 감수하거나, 모든 것을 에스컬레이션(escalating)하여 온콜 (on-call) 순번을 잘못된 경보 (false alarms)로 가득 채우게 됩니다.
평가 (eval) 공간은 도구가 부족하지 않으며, 점차 통합되고 있습니다. OpenAI는 2026년 3월에 Promptfoo를 인수하였으며, 이를 오픈 소스로 유지하되 팀은 내부로 흡수했습니다. 이는 평가 레이어 (eval layer)가 사람들이 실제로 그 위에 구축하는 인프라가 되고 있다는 신호입니다. DeepEval과 Braintrust는 응답이 루브릭 (rubric)을 통과했는지, 정확히 일치하는지, 또는 판사 모델 (judge-model) 점수가 얼마인지에 답하는 데 여전히 강력합니다. 하지만 이 세 가지 중 어느 것도 두 버전 사이에서 동작이 변화했는지에 대한 p-값 (p-value), 효과 크기 (effect size), 또는 부트스트랩 신뢰 구간 (bootstrap confidence interval)을 보고하지 않습니다. 이는 그들이 답하도록 설계된 질문과는 다른 통계적 질문입니다.
주변 생태계가 계속 성장함에 따라 이러한 구분은 더욱 중요해집니다. 이 글을 쓰는 시점을 기준으로 LangGraph 하나만 해도 GitHub 스타 37,447개를 기록하고 있으며, PyPI 다운로드 수는 월간 약 6,670만 회에 달합니다. CrewAI는 55,648개의 스타와 월간 약 1,130만 회의 다운로드를 기록하고 있습니다. 많은 프로덕션 에이전트 (production agents)들이 일반적인 릴리스 주기 (release cadence)에 따라 버전을 변경하며, 임계값 평가 (threshold evals)만으로는 특정 릴리스가 실제 동작을 변화시킨 것인지 아니면 단순히 점수만 변화시킨 것인지 자체적으로 알려줄 수 없습니다.
통계가 실제로 작동하는 방식
세 가지 통계 도구가 실제 작업을 수행합니다. Mann-Whitney U 검정은 두 점수 분포가 정규 분포라고 가정하지 않고 비교하는데, 이는 LLM 출력 점수가 보통 정규 분포를 따르지 않기 때문에 중요합니다. 부트스트랩 신뢰 구간 (bootstrap confidence interval, 1,000회 재표본 추출)은 그 유의성 판단에 규모를 더하여, 변화가 실제로 얼마나 컸는지를 측정합니다. Cohen's d는 통계적으로 유의미한 것과 운영적으로 유의미한 것을 구분합니다. p = 0.001이고 d = 0.04인 변화는 실제로는 존재하지만 무의미한 반면, p = 0.06이고 d = 0.5인 변화는 크기가 크며 확인을 위해 더 많은 샘플이 필요합니다. 기본 신뢰 구간 (CI) 게이트는 p < 0.05와 d ≥ 0.2를 모두 만족할 때만 작동하며, 이를 통해 50회 실행 비교가 노이즈 때문에 빌드를 실패하게 만드는 것을 방지합니다.
비용 절감을 위해 GPT-4o를 GPT-4o-mini로 교체했을 때, 해당 도구의 자체 데모 비교에서 이 수치들이 어떻게 나타나는지는 다음과 같습니다:
- 버전 A에 대한 50회 실행: 평균 도구 정확도 (mean tool accuracy) 0.840, 표준 편차 (SD) 0.060
- 버전 B에 대한 50회 실행: 평균 도구 정확도 (mean tool accuracy) 0.700, 표준 편차 (SD) 0.090
- p = 0.0031, Cohen's d = -0.610, 95% 신뢰 구간 (CI) [-0.221, -0.067]
- 판정 (Verdict): 성능 저하 (REGRESSED), 배포 차단 (block the deploy)
우리는 M3 Pro에서 n=50일 때 비교당 약 27ms의 통계적 오버헤드 (statistical overhead)를 측정했습니다. 실제 병목 현상은 에이전트 호출 (agent calls) 자체이며, 수학적 계산은 거의 영향을 미치지 않습니다.
이 중 어느 것도 생소한 것이 아닙니다. 핵심 호출은 scipy의 한 줄 코드일 뿐이며, 우리가 이를 솔직하게 밝히는 이유는 이 도구가 실제로 제 역할을 다하는 지점이 어디인지가 중요하기 때문입니다. 어떤 평가 (eval) 플랫폼이라도 오후 한나절이면 이러한 통계 기능을 덧붙일 수 있습니다. 복제하기 어려운 부분은 버전별 성능 저하 이력 (version-specific regression history)과 프레임워크 통합 (framework integrations)입니다. 왜냐하면 이러한 요소들이 매번 별도의 테스트 하네스 (harness)를 수동으로 만들지 않고도 CI 환경에서 실제 에이전트로부터 통계 데이터를 유용하게 사용할 수 있게 만들기 때문입니다. 이것이 더 저렴한 모델로 교체하는 것과 같은 '믿음의 도약 (leap of faith)'을 검증 가능한 주장으로 바꾸어 줍니다. p-값 (p-value)과 Cohen's d가 첨부된 '성능 저하 (REGRESSED)' 판정은 해당 결정을 뒷받침하거나, 제품이 출시되기 전에 그 결정을 무산시킵니다.
모든 비교를 무너뜨렸을 법한 버그
여기서부터 이야기는 단순한 기능 목록을 넘어섭니다. 우리가 프레임워크 통합을 홍보 문구로 작성할 만큼 신뢰하기 전, 자체 저장소(repo) 외부의 누구에게도 도구를 보여주기 전에 첫 번째 검증 단계를 수행했습니다. 우리는 LangGraph, CrewAI 또는 OpenAI Agents SDK에서 실제로 머지된(merged) PR을 가져와서, agent-eval이 해당 PR에 대한 홍보 문구에서 주장하는 것과 같은 비교 결과를 실제로 생성할 수 있는지 확인했습니다.
우리가 발견한 가장 첫 번째 문제는 P0(최우선 순위)였습니다. openai_agents_runner()가 agent.run(query)를 호출하고 있었습니다. 해당 메서드는 실제 SDK의 Agent 클래스에는 존재하지 않으며, 오직 Runner.run(agent, input)만 존재합니다. 우리는 이를 직접 확인했습니다: hasattr(agents.Agent(...), 'run')은 False를 반환하고, hasattr(agents.Runner, 'run')은 True를 반환합니다. 이 통합 과정은 어떤 테스트 스위트, 어떤 에이전트, 어떤 주장에서도 첫 번째 호출 시 AttributeError를 발생시켰습니다. 이는 전체 통합 과정을 중단시키는 치명적인 충돌(hard crash)이었습니다. 이 잘못된 메서드 이름 하나가 캠페인에서 발견한 29개의 코드 수정 가능한 격차 중 15개, 즉 전체의 51.7%를 차지했습니다.
우리는 커밋 히스토리에서 가져온 실제 수정 전 코드를 실행하여, 현재 설치된 실제 OpenAI Agents SDK를 대상으로 해당 충돌을 실시간으로 재현했습니다:
이것은 모형(mockup)이 아닙니다. 실제 SDK를 대상으로 실행하여 모든 비교를 망가뜨린 실제 AttributeError를 발생시킨, 수정 전 커밋의 실제 버그가 있는 호출 지점입니다.
우리는 호출 지점을 수정하고 계속 진행했습니다. 그렇게 큰 충돌은 좀처럼 단독으로 발생하지 않으며, 이번에도 마찬가지였습니다. langgraph_runner()는 호출할 때마다 thread_id와 체크포인트 연속성(checkpoint continuity)이 없는 새로운 상태가 없는(stateless) 딕셔너리를 생성했기 때문에, 다회차 대화(multi-turn conversations)를 전혀 표현할 수 없었습니다. 한편 crewai_runner()는 전체 Crew.kickoff()를 래핑(wrap)할 뿐이었고, 특정 도구의 동작을 격리할 방법이 없었습니다. run_suite()에는 캐시 방지(cache-busting)를 위한 논스(nonce)가 없었는데, 이는 자체적인 영구 결과 캐시를 가진 프레임워크(LangGraph의 cache_policy가 실제 사례임)의 경우, 전체 통계적 접근 방식이 의존하는 반복 샘플링 분산(repeated-sampling variance)을 조용히 붕괴시킨다는 것을 의미했습니다. 마지막 문제는 자세히 살펴보니 두 번째 버그로 이어졌습니다. 하류(downstream)의 상태 축소(state-narrowing) 로직의 일부가 우리가 추가한 캐시 방지 키를 누락시키고 있었습니다. 재검토(Re-review)를 통해 이를 잡아냈으며, 첫 번째 검토에서는 놓쳤던 부분입니다.
두 개의 커밋이 대부분을 해결했습니다. 8411eb5는 P0와 다른 16개의 격차를 수정하여 테스트 스위트를 121개에서 264개로 통과시켰습니다. f752c11는 두 번째 독립적인 재검증(re-validation) 과정에서 발견된 7개의 잔여 격차 중 6개를 해결했으며, 여기에는 스토어 레이어의 비동기 취소 생존성 버그(async cancellation liveness bug)가 포함됩니다. 나머지 7번째 격차는 LangGraph 인터럽트/재개 보고서와 관련되어 있어, 이를 확인하기 위해 추가적인 수동 재검증 과정이 필요했습니다.
두 검증 과정 모두 첫 번째 시도에서 동일한 실수를 발견했습니다. 제안된 수정 사항이 기술적으로 정확하지만 아직 작업 트리(working tree)에 커밋되지 않은 코드를 인용한 것이었습니다. 이러한 종류의 오류는 자신의 수정 사항을 신뢰하는 대신 실제로 적대적 점검(adversarial check)을 실행해야만 알 수 있으며, 우리는 이 교훈을 두 번이나 얻어야 했습니다. 이것은 자체 보고된 '이제 고쳐졌다'라는 주장의 구체적이고 반복 가능한 실패 모드이므로, 아래의 검증 방법론은 첫 번째 답변을 받아들이는 대신 모든 판결을 제안-반박(propose-then-refute) 단계로 실행합니다.
29개의 실제 병합된 PR과 이를 테스트하는 과정
우리는 위의 모든 수정 사항을 실제로 병합된 풀 리퀘스트(pull request, PR)에 근거했습니다. 전체 검증 세트는 6개 레포지토리에 걸쳐 239개의 행을 다루었습니다. 그중 209개는 기반이 되는 PR이 발표자가 가정했던 것과 같은 행동 드리프트 위험(behavioral-drift risk)을 지니지 않았기 때문에 제외했습니다. 예를 들어, 문서 전용 변경 사항, 사소한 수정 사항, 또는 아예 존재하지 않는 PR 등이었습니다. 코드 격차가 실제적이고 수정 가능했던 29개 행 중 모두가 현재 통과하고 있습니다. 추가로 한 행(@sibblegp)도 코드 격차가 완전히 해결되었지만, 엔지니어링으로 아무리 노력해도 고칠 수 없는 이유 때문에 PASS 상태를 유지합니다. 즉, 그 주장을 근거로 삼을 만한 실제 병합된 PR이 없기 때문입니다.
이 29개의 행은 세 가지 프레임워크와 위의 대부분의 수정 범주를 아우르는 대표적인 단면입니다:
| PR | Repo | 변경 사항 | agent-eval이 이를 테스트하기 위해 필요했던 사항 |
|---|---|---|---|
| langgraph #5243 | LangGraph | 기존의 타입이 지정되지 않은 config['configurable']을 대체하는 새로운 타입 지정 context= API | langgraph_runner()가 config, context, thread_aware 키워드 인자(kwargs)를 갖게 되어 두 호출 방식이 직접 비교 가능해짐 |
| ... |
위의 모든 링크는 실제 병합된 PR로 연결됩니다. 이는 29개 중 14개를 포함합니다. 실제 PR 링크(또는 기록이 없는 경우 정직한 메모)와 모든 행에 대한 정확한 수정 커밋(fixing commit)이 포함된 전체 목록은 저장소의 docs/validation.md에 있습니다. 29개 전체에 걸친 패턴은 동일합니다: agent-eval의 통계(statistics)를 특정 프레임워크의 실제 API 표면(API surface)에 연결하는 배관(plumbing) 작업이 불완전했으며, 이는 유지 관리자(maintainers)가 실제로 배포한 내용을 대상으로 테스트함으로써만 드러났습니다.
지원되는 프레임워크 (Supported frameworks)
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기