🔥 고급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에 코멘트
- [ ] 버그 발견 시 즉시 셋에 추가