
EvalMaster: AI 에이전트 평가 (Evals)를 위한 실무 커리큘럼 구축
요약
EvalMaster는 AI 에이전트의 성능을 체계적으로 측정하고 검증하기 위한 실무 중심의 교육 프로젝트입니다. Agno와 Pydantic 등을 활용하여 에이전트의 정확성, 도구 사용, 근거 제시 능력을 테스트할 수 있는 실행 가능한 Python 코드베이스를 제공합니다.
핵심 포인트
- 에이전트 성능의 드리프트(Drift) 현상을 가시화하고 관리하는 방법 제시
- 정확성, 구조, 도구 사용, 근거 제시 등 핵심 평가 지표 학습
- Agno, Pydantic, asyncio를 활용한 가벼운 평가 아키텍처 구축
- 단순한 답변 확인을 넘어 관찰 가능한 테스트 환경 구축 강조
EvalMaster는 이론을 읽는 것에 그치지 않고 직접 실행하며 에이전트 평가 (Agent Evaluation)를 이해하고자 하는 개발자들을 위한 교육 프로젝트입니다. 이 프로젝트는 Agno, Pydantic, Rich, asyncio, 그리고 예제들이 기본적으로 오프라인에서 작동할 수 있도록 만드는 최소한의 스캐폴딩 (Scaffolding)을 사용하여 평가 (Evals)의 핵심 아이디어들을 실행 가능한 Python 코드베이스로 패키징합니다.
핵심 교훈은 간단합니다. 에이전트를 구축하고 있다면, "답변이 괜찮아 보이는가?" 이상의 것이 필요합니다. 정확성 (Exactness), 구조 (Structure), 도구 사용 (Tool use), 근거 제시 (Grounding), 견고성 (Robustness), 그리고 다단계 궤적 (Multi-step trajectories)의 품질을 측정하는 평가 (Evals)가 필요합니다.
EvalMaster가 존재하는 이유
많은 AI 프로젝트들이 데모로 시작하여 예상치 못한 결과로 끝납니다. 프롬프트 (Prompt)는 수동으로 시도한 예제에서는 잘 작동하지만, 모델이 변경되거나, 도구 스키마 (Tool schema)가 바뀌거나, 컨텍스트 (Context)가 길어지면 동작이 드리프트 (Drift)됩니다.
EvalMaster는 그러한 드리프트 (Drift)를 가시화하도록 설계되었습니다.
다음과 같은 질문에 답하는 데 도움을 줍니다:
- 프롬프트 재작성 (Prompt rewrite) 후에도 에이전트가 여전히 올바른 도구를 호출했는가?
- 새로운 모델이 품질을 개선했는가, 아니면 단순히 더 장황해졌는가?
- RAG 시스템이 실제로 소스에 근거(Grounded)하고 있는가?
- 지원 에이전트가 적절한 시점에 상담원에게 연결(Escalate)하는가?
- 판사 모델 (Judge model)이 스스로의 판단과 불일치하는 경우가 얼마나 빈번한가?
핵심은 불확실성을 제거하는 것이 아닙니다. 불확실성을 관찰 가능하고 테스트 가능한 것으로 바꾸는 것이 목적입니다.
아키텍처 개요
아키텍처는 의도적으로 가볍게 설계되었습니다:
config.py: 제공자 (Provider)를 선택합니다.common.py: 타입이 지정된 평가 (Eval) 객체들을 정의합니다.runtime_utils.py: 점수 산정 (Scoring) 및 보고 (Reporting) 도우미를 포함합니다.00_부터08_까지의 각 폴더는 하나의 평가 패턴 (Evaluation pattern)을 가르칩니다.07_real_world_projects/: 아이디어들을 실제 애플리케이션에 연결하는 방법을 보여줍니다.
기술 선택
왜 이 도구들을 사용했을까요?
- Agno: 프로젝트에 일관된 에이전트 인터페이스와 팀/도구 추상화 (abstractions)를 제공합니다.
- Pydantic: 평가 (eval) 입출력의 타입을 지정하고 명시적으로 유지합니다.
- Rich: 터미널에서 출력을 읽기 쉽고 발표하기 좋은 형태로 만들어 줍니다.
- asyncio: 배치 평가 (batched evaluation)를 실용적으로 수행할 수 있게 합니다.
- pandas + matplotlib: 간단한 분석 및 보고를 지원합니다.
- pytest: 스캐폴딩 (scaffold)이 계속 실행 가능한 상태로 유지됨을 보장합니다.
- python-dotenv: 비밀 정보와 프로바이더 (provider) 설정을 코드와 분리하여 관리합니다.
몇 가지 중요한 설계 결정 (Design Decisions)
1. 오프라인 우선 (Offline First)
데모는 라이브 API 호출 없이 실행됩니다. 이는 사용자가 아직 자격 증명 (credentials)을 설정하지 않았더라도, 커리큘럼을 첫날부터 바로 실행할 수 있어야 하기 때문에 중요합니다.
2. 공유된 스코어링 프리미티브 (Shared Scoring Primitives)
이 프로젝트는 완전 일치 (exact match), 스키마 체크 (schema checks), 도구 호출 검증 (tool-call validation), 그라운딩 (grounding), 그리고 판사 기반 스코어링 (judge-based scoring)을 위한 스코어링 헬퍼들을 재사용합니다. 이를 통해 예제들의 일관성을 유지하고, 각 레슨이 별개의 미니 프레임워크로 변질되는 것을 방지합니다.
3. 설정을 통한 프로바이더 전환 (Provider Switching Through Config)
의도는 프로바이더 변경을 코드 재작성이 아닌 설정 (configuration)의 문제로 만드는 것입니다.
PROVIDER = os.getenv("PROVIDER", "openai")
def get_model(model_id: str | None = None):
...
4. 구조화된 평가 아티팩트 (Structured Evaluation Artifacts)
타입이 지정된 EvalCase, EvalResult, EvalSuite 객체를 사용함으로써, 데이터의 형태를 추측할 필요 없이 코드를 직렬화 (serialized)하고, 버전 관리하며, JSON 또는 CSV로 내보낼 수 있습니다.
커리큘럼 구성 내용
기초 (Foundations)
첫 번째 섹션에서는 다음을 설명합니다:
- 평가 (evals)란 무엇인가
- 평가가 테스트 (tests)와 어떻게 다른가
- 규칙 (rules)부터 인간 검토 (human review)까지의 스펙트럼
- 코딩 전에 평가를 작성해야 하는 시점
결정론적 평가 (Deterministic Evals)
이 섹션에서는 다음을 다룹니다:
- 완전 일치 (exact match)
- 정규 표현식 검증 (regex validation)
- JSON 스키마 체크 (JSON schema checks)
- 도구 호출 검증 (tool call validation)
- 지연 시간 (latency) 및 비용 스코어링
- 사실적 그라운딩 (factual grounding)
LLM-as-Judge 평가 (LLM-as-Judge Evals)
이 섹션에서는 다음 방법을 보여줍니다:
- 단일 판사(single judge) 실행
- 답변 간 쌍체 비교 (pairwise comparison)
- 루브릭 기반 채점 (rubric-based grading) 적용
- 판사의 분산(variance) 및 편향(bias) 고려
에이전트 특화 평가 (Agent-Specific Evals)
이 섹션은 다음 사항에 집중합니다:
- 도구 선택 (tool selection)
- 다단계 궤적 (multi-step trajectories)
- 메모리 회상 (memory recall)
- 추론 흔적 (reasoning traces)
- 목표 달성 (goal completion)
- 멀티 에이전트 핸드오프 (multi-agent handoffs)
- 적대적 강건성 (adversarial robustness)
데이터셋 관리 (Dataset Management)
데이터셋 섹션에서는 다음을 시연합니다:
- 골든 세트 (golden set) 생성
- 합성 케이스 생성 (synthetic case generation)
- 콘텐츠 해싱 및 버전 관리 (content hashing and versioning)
- 엣지 케이스 마이닝 (edge-case mining)
- 저장을 위한 Pydantic 스키마 (Pydantic schemas)
대규모 평가 실행 (Running Evals At Scale)
이 섹션은 다음을 다룹니다:
- 비동기 실행 (asynchronous execution)
- 동시성 제한 (concurrency limits)
- 재시도 로직 (retry logic)
- 증분 영속성 (incremental persistence)
- 회귀 게이트 (regression gates)
- 터미널 대시보드 (terminal dashboards)
결과 해석 (Interpreting Results)
이 섹션은 다음 질문에 답하는 데 도움을 줍니다:
- 어떤 집계 지표 (aggregation metric)를 신뢰해야 하는가?
- 신뢰 구간 (confidence interval)이 중요한 시점은 언제인가?
- 실패 모드 (failure modes)를 어떻게 클러스터링할 것인가?
- 결과를 어떻게 명확하게 보고할 것인가?
실무 프로젝트 (Real-World Projects)
마지막 애플리케이션 스타일 예제는 다음을 다룹니다:
- RAG 평가
- 고객 지원 평가
- 코드 생성 평가
예제: 궤적 평가 (Trajectory Eval)
이 프로젝트에서 가장 중요한 아이디어 중 하나는 에이전트를 단순히 최종 문자열이 아닌 하나의 시퀀스 (sequence)로 평가해야 한다는 것입니다.
def score(case: EvalCase, steps: list[TrajectoryStep]):
correctness = 1.0 if any(step.kind == "message" and step.content == "done" for step in steps) else 0.0
efficiency = 1.0 if len(steps) <= 2 else 0.5
...
이 패턴이 중요한 이유는 두 에이전트가 서로 매우 다른 경로를 거치면서도 동일한 최종 답변을 생성할 수 있기 때문입니다.
예제: 비동기 평가 러너 (Async Eval Runner)
러너는 평가를 확장하기 위한 실무적인 패턴을 보여줍니다:
async def run_eval_runner(cases, worker, concurrency: int = 5):
sem = asyncio.Semaphore(concurrency)
for coro in asyncio.as_completed([guarded(case) for case in cases]):
...
여기서 유용한 점은 단순히 병렬성 (parallelism)만이 아닙니다. 그것은 다음의 조합입니다:
- 동시성 제어 (concurrency control)
- 재시도 (retries)
- 증분 저장 (incremental saving)
- 진행 상황 가시성 (progress visibility)
예시: RAG 지표 (RAG Metrics)
RAG 프로젝트는 평가를 여러 관점으로 나눕니다:
- 충실도 (faithfulness)
- 답변 관련성 (answer relevance)
- 컨텍스트 재현율 (context recall)
- 컨텍스트 정밀도 (context precision)
이러한 분리는 중요합니다. 왜냐하면 "답변이 좋다"와 "검색(retrieval)이 좋다"는 서로 같은 것이 아니기 때문입니다.
프로젝트 확장 방법
EvalMaster를 포크(fork)한다면, 다음과 같은 유용한 기능들을 추가할 수 있습니다:
- 엄격함(strict), 관대함(lenient), 전문가(expert) 페르소나를 가진 더 풍부한 판사(judge) 추상화
- 의미론적 유사성 (semantic similarity)을 위한 실제 임베딩 (embeddings)
- 과거 평가 실행 기록을 위한 아티팩트 저장소 (artifact store)
- SQLite 기반의 케이스/결과 지속성 (persistence)
- 트렌드 차트가 포함된 대시보드
- 비용을 고려한 선택 기능이 포함된 모델 라우팅 평가 (model routing evals)
- 프롬프트 민감도 실험 (prompt sensitivity experiments)
- 승인 절차가 포함된 인간 검토 큐 (human review queue)
CLI 엔트리 포인트 (CLI Entry Point)
커리큘럼을 더 쉽게 탐색할 수 있도록, EvalMaster에는 이제 typer 기반의 간단한 CLI가 포함되어 있습니다.
python3 cli.py list
python3 cli.py run foundations
python3 cli.py run projects
이를 통해 사용자가 개별 파일 경로를 일일이 기억하지 않아도 학습 경로를 쉽게 찾을 수 있습니다.
기여 방법 (How To Contribute)
기여하는 가장 쉬운 방법은 다음과 같습니다:
- 모듈 하나를 선택합니다.
- 케이스나 지표를 하나 더 추가합니다.
- 테스트를 업데이트합니다.
- 관련 스크립트를 실행하고 출력을 검사합니다.
- 새로운 평가가 왜 중요한지 설명하는 PR(Pull Request)을 제출합니다.
이것은 좋은 기여 모델입니다. 모든 개선 사항은 단순히 코드만 추가하는 것이 아니라, 피드백 루프 (feedback loop)를 더욱 긴밀하게 만들어야 하기 때문입니다.
이것이 실무에서 중요한 이유
평가 (evals)의 진정한 가치는 운영 환경(production)의 질문에 빠르게 답해야 할 때 나타납니다:
- 이 모델 업데이트가 무언가를 망가뜨렸는가?
- 새로운 프롬프트가 특정 작업에는 더 좋지만 다른 작업에는 더 나쁜가?
- 잘못된 형식의 입력 (malformed inputs)을 안전하게 처리하고 있는가?
- 수동 스팟 체크 (manual spot checks)에 의존하지 않고 이것을 배포할 수 있는가?
EvalMaster는 그러한 사고방식을 연습할 수 있는 압축적인 방법입니다.
출력
Code & more: https://www.dailybuild.xyz/project/182-eval-master
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
