C.W.K.
Stream
Lesson 04 of 09 · published

Evaluation Lifecycle

~22 min · evals, lifecycle, process

Level 0Guesser
0 XP0/55 lessons0/10 achievements
0/150 XP to next level150 XP to go0% complete

Eval 은 한 번 만들고 끝나는 deliverable 이 아니야

실제 프로젝트에서 가장 흔한 eval 실패는 'launch sprint 때 eval 만들고 다신 안 봤어' 야. 3개월 뒤 eval 은 여전히 pass 하는데 사용자는 Slack 에서 불평해. dataset 은 시간에 얼어붙었는데 product 는 움직였어.

건강한 eval 은 연속 loop 으로 돌아:

  1. Define — 보호할 만한 동작 골라서 success 가 뭔지 적어.
  2. Curate — 그 동작을 대표하는 dataset 모으기, 실패 잘 나오는 edge case 포함.
  3. Measure — system 돌리고, output score 매기고, 결과 요약.
  4. Diagnose — 뭐가 실패하면 aggregate 만 보지 말고 실제 output 들 봐.
  5. Improve — prompt, model, retrieval, tool 바꾸고 다시 측정.
  6. Monitor — production traffic sample. live distribution 이 offline dataset 에서 drift 하면 refresh.

diagnose 단계가 팀이 컨닝하는 곳

'pass rate 가 92% 에서 88% 로 떨어졌네' 보고 prompt 만지작거리고 싶은 유혹 생겨. 하지마. 실패 열어. output 읽어. aggregate score 는 화재경보지 — 실패는 진짜 불이야. 열에 아홉, regression 은 특정 input cluster 에 몰려 있어 (새로운 entity 타입, 더 긴 document, 새 언어) — 그리고 옳은 fix 는 targeted 야, global prompt rewrite 가 아니야.

원칙: Aggregate score 는 답이 아니라 질문이야. 항상 실패를 읽어.

monitor 단계가 팀이 멈추는 곳

refresh 안 되는 eval suite 는 박물관 전시품이 돼: 향수 자극하지만 무의미하고, 정치적으로 제거 비용 비싸. 분기별 review 잡아. 최근 production 대화 50개 sample. offline dataset 이 여전히 그것들 닮았는지 체크. 아니면 refresh.

Code

Lifecycle 을 make / just / task target 으로·bash
# Each step is a command anyone on the team can run.
just eval-define     # opens BEHAVIOR.md and the rubric template
just eval-curate     # samples production logs into datasets/staging.jsonl
just eval-run        # runs the full suite, writes results/<timestamp>.json
just eval-diff       # diffs the latest run against the previous baseline
just eval-failures   # opens failures in a side-by-side viewer
just eval-monitor    # samples last 7 days of prod, flags distribution drift
Diagnose 패턴 — 고치기 전에 cluster 먼저·python
from collections import Counter

def cluster_failures(results):
    """Group failures by tag so you don't fix the wrong thing."""
    failures = [r for r in results if not r["passed"]]
    by_tag = Counter()
    for f in failures:
        for tag in f.get("tags", ["untagged"]):
            by_tag[tag] += 1
    return by_tag.most_common()

# Output:
# [("long_documents", 14), ("polish_language", 8), ("untagged", 3), ...]
# Now you know: 14 of your 25 failures are long documents.
# Fix that cluster, not the prompt at large.

External links

Exercise

팀의 현재 eval workflow 를 6단계 lifecycle 에 매핑해. 빠진 단계가 뭐야? 가장 많은 가치를 풀어줄 단계 (보통 'diagnose' 또는 'monitor') 골라서 팀 의례에 추가해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.