평가(Evals)와 LLM-as-a-Judge: 위치, 장황함, 자기 선호 편향을 제거한다면 모델이 다른 모델을 채점할 수 있다
요약
LLM-as-a-Judge 방식에서 발생하는 위치, 장황함, 자기 선호 편향을 해결하는 방법론을 소개합니다. Swap-and-average, 루브릭 기반 채점, 블라인드 테스트 등을 통해 신뢰할 수 있는 평가 스택을 구축하는 가이드를 제공합니다.
핵심 포인트
- 위치 편향 해결을 위해 답변 순서를 바꿔 두 번 평가하는 Swap-and-average 적용
- 장황함 편향 방지를 위해 루브릭을 활용하여 길이에 대한 보상 금지
- 자기 선호 편향 제거를 위해 작성자를 숨기는 블라인드 처리 및 패널 평가 활용
- 재현 가능한 점수 확보를 위한 Pointwise 평가 루프 구축의 중요성
당신은 스마트한 모델을 구축했습니다. 이제 — 이 모델이 실제로 좋은 모델일까요? 벤치마크(Benchmark)는 리더보드를 위한 하나의 숫자를 제공하지만, 태스크 평가(Task eval)는 모델이 당신의 업무에 적합한지를 알려줍니다. 그리고 대규모로 채점하기 위해, 강력한 모델에게 심판 역할을 맡길 수 있습니다. LLM-as-a-judge(심판으로서의 LLM)는 API 속도로 거의 제로에 가까운 비용을 들여, 두 명의 인간이 서로 동의하는 빈도만큼이나 자주 인간의 선호도와 일치합니다. 문제는 심판이 체크박스 테스트에는 결코 없었던 편향(Bias)을 물려받는다는 점입니다. 저는 각 편향이 판결을 어떻게 뒤집는지, 그리고 각 완화 조치가 이를 어떻게 상쇄하는지를 보여주는 대화형 하네스(Harness)를 구축했습니다. 신뢰할 수 있는 평가 스택(Eval stack)이 어떻게 구성되는지 소개합니다.
Pointwise 평가 루프 — 재현 가능한 점수
공개 벤치마크가 아닌 당신의 태스크부터 시작하세요. 각 케이스를 실행하고, 루브릭(Rubric, 채점 기준)에 따라 답변을 점수 매긴 뒤, 기준치를 통과하면 합격 처리합니다. 이는 결정론적(Deterministic)이기 때문에, 동일한 입력은 실행할 때마다 동일한 숫자를 제공합니다. 따라서 점수 하락은 노이즈가 아닌 실제 **회귀(Regression)**를 의미하며, 비공개 데이터 세트는 공개 벤치마크처럼 훈련 데이터로 유출되지 않습니다.
def run_eval(model, cases, judge, pass_bar=3.0):
results = []
for c in cases: # 당신의 실제 입력
...
심판 프롬프트 작성 — 루브릭 + 파싱 가능한 판결
def judge_pairwise(judge, q, ans1, ans2):
prompt = f"Question: {q}\n[1] {ans1}\n[2] {ans2}\n" \
"Which answer is better? Reply 1 or 2. Judge on the rubric, not length."
...```
## Swap-and-average — 위치 편향 (position bias) 제거
두 가지 순서를 _모두_ 심판하고, 두 방식 모두에서 동일한 답변이 승리할 때만 승리로 간주합니다. 순서에 의존적인 보너스는 각 실행 시 1번 슬롯에 배치되므로, 비교 과정에서 서로 **상쇄 (cancels out)** 됩니다. 이것이 데모에 포함된 "swap & average" 토글입니다.
```python
def debiased_pairwise(judge, q, a, b):
first = judge_pairwise(judge, q, a, b) # 1번 슬롯에 A 배치
second = judge_pairwise(judge, q, b, a) # 1번 슬롯에 B 배치 (순서 변경!)
...```
## Rubric + blind + panel — 장황함 (verbosity) 및 자기 선호 편향 (self-preference) 제거
Swap-and-average는 _순서_를 해결할 뿐, _길이_나 _모델 계열 (family)_ 문제를 해결하지는 않습니다. 길이는 순서에 의존적이지 않기 때문입니다. **장황함 (verbosity)** (심판이 쓸데없는 내용으로 채워진 긴 답변에 보상을 주는 현상)을 해결하려면, 루브릭 (rubric)에 고정하고 길이에 보상을 주는 것을 금지해야 합니다. **자기 선호 편향 (self-preference)** (심판이 자신의 모델 계열을 더 높게 평가하는 현상)을 해결하려면, 심판이 각 답변을 누가 작성했는지 알 수 없도록 **블라인드 (blind)** 처리를 하고, 서로 다른 계열의 심판들로 구성된 **패널 (panel)** 의 결과를 평균 내야 합니다.
```python
prompt += "Do NOT reward longer answers. Judge correctness & relevance only." # 장황함 방지
answers = shuffle_and_strip_model_names([a, b]) # 자기 선호 방지: 심판이 누가 무엇을 썼는지 볼 수 없음
judges = [judge_vega, judge_nova, judge_atlas] # 서로 다른 모델 계열
...```
## 인간과 비교하여 교정(Calibrate)한 후, 출시 여부를 결정(gate)하라
심판이 과연 신뢰할 수 있는가? 심판을 소규모의 **인간 라벨링 앵커 세트 (human-labelled anchor set)** 와 비교하여 일치도를 측정하십시오. 이때 우연한 일치를 보정하는 Cohen's κ (코헨의 카파) 계수를 사용합니다. 심판이 인간의 판단을 따라갈 때에만, 품질이 저하될 경우 출시를 차단(block)하도록 허용하십시오.
```python
agree = mean(judge_label[i] == human_label[i] for i in anchor_set)
kappa = cohens_kappa(judge_labels, human_labels) # 우연을 보정한 값
assert agree > 0.8 and kappa > 0.6, "심판이 출시를 결정하기에 충분히 신뢰할 수 없음"
...```
두 방식 모두 중요합니다. **쌍체 비교 (pairwise)** 방식은 순서(order), 길이(length), 계열 편향(family bias)을 정밀하게 상쇄하여 두 모델 중 사람들이 어떤 모델을 선호하는지 알려줍니다. **점수 산정 (pointwise)** 방식은 출시 여부를 결정할 수 있는 안정적이고 재현 가능한 점수를 제공합니다. 두 방식 모두 심판의 정직함을 유지해 주는 인간 기준 세트 (human anchor set)를 대체할 수는 없습니다. 데모를 통해 동일한 두 답변(답변 A가 진정으로 더 나은 경우)에 대해 각 편향을 하나씩 적용해 보며, 판결이 어떻게 왜곡되는지 확인하고, 해당 수정 사항을 적용하는 즉시 판결이 복구되는 과정을 지켜볼 수 있습니다.
편향을 전환하여 심판이 잘못된 이유로 마음을 바꾸는 것을 관찰한 뒤, 이를 수정해 보세요:
[https://dev48v.infy.uk/ai/days/day38-evals-llm-judge.html](https://dev48v.infy.uk/ai/days/day38-evals-llm-judge.html)
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기