Cross-model judge — Sonnet + Opus 교차 검증
앞 두 편에서 세운 판정자는 아직 결정적인 문제 하나가 남아 있다.
판정자를 한 개만 쓴다는 것.
한 개 판정자는 아무리 median·σ로 다듬어도 자기 편향은 스스로 못 본다. 특히 답을 생성한 모델과 판정 모델이 같은 계열이면 self-preference bias가 확 붙는다. 이번 글은 판정자를 두 개 세우고 두 판정자 사이의 disagreement를 지표로 쓰는 법을 다룬다.
왜 두 모델을 쓰나
Judge bias 4종 중 하나가 self-preference bias였다.
답 생성: Sonnet 4.6
답 판정: Sonnet 4.6 ← self-preference 위험
같은 계열의 판정자는 자기가 만든 답의 문체·구조·설명 방식을 좋아하는 경향이 있다. Sonnet이 만든 답을 Sonnet에게 판정시키면 점수가 살짝 후해진다. 이건 계열이 완전히 같지 않아도(예: GPT-4가 GPT-4o를 판정) 관측되는 편향이다.
해결 방법은 개념적으론 간단하다: 판정자를 다른 모델로 하나 더 얹는다.
답 생성: Sonnet 4.6
1차 판정: Sonnet 4.6 → score_A
2차 판정: Opus 4.7 → score_B
disagreement: |score_A - score_B|
두 판정자의 점수가 크게 다르면 그 자체가 신호다. "이 답은 판정하기 어려운 답이다"라는 신호.
Judge alignment / cross-model agreement 개념
두 판정자 사이의 일치도를 재는 지표를 몇 개 알아두면 편하다.
상관계수 (Pearson / Spearman)
전체 evaluation set에서 두 판정자가 매긴 점수들의 상관을 본다.
0.9 이상이면 두 판정자가 대체로 같은 방향을 본다.
0.7 이하로 떨어지면 두 판정자의 기준이 다르다는 뜻.
절대 편차 disagreement
disagreement = |score_A - score_B|
케이스 단위로 얼마나 갈리는지 본다. 상관계수는 전체 경향을 보고, disagreement는 개별 케이스를 본다. 둘 다 봐야 한다.
κ (Cohen's kappa)
라벨링에서 자주 쓰던 지표. 여기서는 점수를 이산화(예: pass/fail, 상/중/하) 한 뒤 두 판정자의 카테고리 일치도를 본다.
disagree_mean을 파이프라인 지표로
지금 프로젝트에서는 disagreement 평균을 파이프라인 대시보드에 얹었다.
metric_group = {
faithfulness_median : 0.942
faithfulness_σ : 0.03
disagree_mean : 0.071
hallucination_count : 0
}
disagree_mean = 0.071이라는 숫자의 감각은 이렇다.
0.00 ~ 0.05: 두 판정자가 거의 완벽히 일치. 판정을 신뢰해도 됨
0.05 ~ 0.10: 대체로 일치. 이번 실측 영역
0.10 ~ 0.20: 주의. 특정 종목·질문 유형에서 갈릴 가능성
0.20 이상: 판정 rubric을 다시 봐야 함
0.071이면 두 판정자가 대체로 같은 방향을 본다는 뜻이다. 그 안에서도 케이스별로 disagreement가 큰 것들만 골라내서 사람 리뷰로 넘긴다. 15종목 중 상위 disagreement 2건 정도가 매번 사람 눈에 걸리는데, 그 2건이 실제로 판정하기 애매한 답이다.
Cross-model judge를 언제 켜고 언제 끄나
두 모델을 항상 쓰는 건 낭비다. Opus는 Sonnet 대비 몇 배 비싸다. 그래서 트리거 기반으로 켠다.
default: Sonnet 판정만 사용
(median, σ 안정화 포함)
trigger cross-model:
- Sonnet σ > 0.15 (판정자가 스스로 흔들림)
- Sonnet score < 0.6 or > 0.98 (극단값 검증)
- 새 프롬프트 배포 직후 1주 (회귀 감지 강화)
이 정책이면 cross-model 판정 비용은 전체 판정 비용의 15% 정도로 유지된다. 신뢰도는 챙기고 비용은 안 튄다.
새 프롬프트 배포 직후에는 왜 강화하나
프롬프트를 바꾸면 답의 문체가 바뀔 수 있고, 문체가 바뀌면 self-preference bias가 어느 방향으로 얼마나 뛸지 모른다. 배포 직후 1주는 두 판정자로 같이 봐서 "혼자만 신난 판정자"가 있는지 확인한다.
실측: cross-model이 잡아낸 케이스
한 iteration에서 실제로 다음 케이스가 걸렸다.
답: "A사 3분기 매출은 2조 원으로, 전년 대비 소폭 개선되었습니다.
회사는 향후 반도체 부문 투자를 확대할 계획으로 알려집니다."
컨텍스트: [실적 발표문 전문. "소폭 개선"이라는 표현 없음.
"투자 확대 계획"에 대한 언급 없음.]
Sonnet 판정: 0.89 ("첫 문장 근거 있음, 두 번째 문장은 애매")
Opus 판정: 0.62 ("두 문장 모두 컨텍스트 밖 진술 포함")
disagreement: 0.27
Sonnet은 "소폭 개선"을 "숫자가 있으니 근거 있음"으로 관대하게 봤고, Opus는 그 표현 자체를 근거 없는 것으로 봤다. 어느 쪽이 정답인지는 별개 문제지만, disagreement가 0.27이라는 것 자체가 "이 답은 판정이 갈리는 답"이라는 신호다.
사람 리뷰 결과: Opus 판정이 맞았다. "소폭 개선"이라는 표현은 컨텍스트 문서 어디에도 없었다. 이 케이스는 프롬프트에 "정도 부사(소폭·크게·급격히)를 쓰려면 컨텍스트에 해당 표현이 있어야 한다"는 조항을 추가하는 근거가 됐다.
두 모델이 늘 같을 필요는 없다
Cross-model judge의 목적은 "두 판정자를 늘 일치시키는 것"이 아니다. 목적은 불일치가 나타나는 곳을 정확히 찾아내는 것이다.
일치 → 판정을 그대로 쓴다
불일치 → 그 케이스를 사람이 본다
불일치 패턴 → 프롬프트/rubric 개선의 근거
즉 disagreement는 "지표"가 아니라 "탐지기"에 가깝다. disagreement가 0에 가까울 필요 없다. 튀는 순간이 있어야 판정 체계 자체가 개선된다.
시리즈 마무리
3편에 걸쳐 판정자 이야기를 정리했다.
01: LLM-as-a-Judge 왜 필요한가 + RAGAS 5개 지표 정식 명명
02: 판정자 편향과 안정화 (median, σ, rubric)
03: 판정자를 두 개 쓰는 이유와 방법
여기까지 세우면 파이프라인 회귀를 사람이 매번 안 보고도 잡을 수 있다. 자동 판정자는 대체가 아니라 눈이 하나 더 늘어난 것이라고 생각하면 편하다.
다음 시리즈(rag-quality)에서는 판정 결과를 실제로 개선하기 위한 두 축 — 상류 데이터 클리닝과 grounded generation 프롬프트 — 을 다룬다.