k
korAI
고급 전체
🔥 고급2026-04-1111분

평가 파이프라인 — 프롬프트 변경을 CI에서 막는 회귀 테스트

LLM 기능에도 테스트가 있어야 한다. 골든셋·자동 채점·점수 임계선으로 나쁜 변경을 머지 전에 차단.

evalci운영

왜 필요하나

프롬프트 한 줄 바꿨을 뿐인데 특정 엣지 케이스가 깨진다. QA가 전부 수동으로 돌릴 수 없고, 배포 후 발견하면 늦다. 프롬프트도 코드다, 같은 CI 게이트를 거쳐야 한다.

골든셋 구성

  • 30~200개 케이스 (너무 많으면 CI가 느려짐)
  • 각 케이스: { id, input, tags, expected OR rubric }
  • 버그로 발견된 케이스는 반드시 셋에 추가 — 회귀 방지
  • 민감정보 제거 후 커밋
{
  "id": "classify-refund-urgent-001",
  "tags": ["classifier", "urgent"],
  "input": "내일까지 환불 안 해주면 신고합니다",
  "expected": { "intent": "refund", "urgency_min": 4 }
}

채점 방식 3가지

1. 정확 매칭 — 분류/추출

score = actual.intent === expected.intent ? 1 : 0

2. 숫자 허용 범위 — 점수, 확률

score = Math.abs(actual.score - expected.score) <= 0.1 ? 1 : 0

3. LLM-as-judge — 글쓰기, 요약

const judge = await client.messages.create({
  model: "claude-opus-4-7",
  max_tokens: 200,
  tools: [{ name: "grade", input_schema: { type: "object", properties: {
    pass: { type: "boolean" }, reason: { type: "string" },
  }, required: ["pass", "reason"] }}],
  tool_choice: { type: "tool", name: "grade" },
  messages: [{
    role: "user",
    content: `루브릭:\n${rubric}\n\n답변:\n${actual}\n\n루브릭을 모두 만족하는가?`,
  }],
})

러너 (CI 호환)

// scripts/eval.ts
import fs from "node:fs"
import { runCase } from "./run-case"

const cases = JSON.parse(fs.readFileSync("evals/golden.json", "utf8"))
const results = await Promise.all(cases.map(runCase))

const pass = results.filter(r => r.pass).length
const rate = pass / cases.length

console.log(`${pass}/${cases.length} (${(rate*100).toFixed(1)}%)`)

// 태그별 분해
const byTag: Record<string, {pass: number; total: number}> = {}
for (const r of results) {
  for (const t of r.tags) {
    byTag[t] ??= { pass: 0, total: 0 }
    byTag[t].total++
    if (r.pass) byTag[t].pass++
  }
}
console.table(byTag)

// 기준선
const THRESHOLD = 0.90
if (rate < THRESHOLD) {
  console.error(`FAIL: ${rate} < ${THRESHOLD}`)
  process.exit(1)
}

GitHub Actions

name: eval
on: pull_request
jobs:
  eval:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npx tsx scripts/eval.ts
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY_EVAL }}

: 평가 전용 키를 별도로 발급 + 월 예산 상한 설정. PR 폭증 시 비용 폭파 방지.

결과 기록

  • 커밋 SHA × 모델 × 프롬프트 버전별로 점수 DB에 적재
  • 대시보드: "지난 30일 통과율 추이"
  • 실패 케이스는 PR 코멘트로 자동 리포트

흔한 실수

  • 골든셋이 너무 쉬움 → 점수 100% 고정, 회귀 못 잡음
  • 프롬프트에 골든셋 입력과 비슷한 예시 박기 → overfitting
  • LLM-as-judge를 같은 모델로 → 자기 편향. 반드시 더 강한 모델로 채점

체크리스트

  • [ ] 골든셋 30+ 케이스
  • [ ] 태그로 분류
  • [ ] CI에서 자동 실행
  • [ ] 임계선 미만이면 머지 차단
  • [ ] 실패 케이스 PR에 코멘트
  • [ ] 버그 발견 시 즉시 셋에 추가