왜 단일 응답은 믿기 어려운가
LLM은 temperature가 0이 아니면 같은 프롬프트에도 매번 다른 답을 낸다. 특히 추론이 여러 단계로 이어지는 작업(수식 계산, 분류 근거 설명, 코드 생성)에서는 중간 단계 하나가 틀어지면 최종 답이 통째로 바뀐다. 단일 호출로 받은 답이 맞을 확률이 70%라면, 프로덕션에서 10건 중 3건은 조용히 틀린 채 통과한다는 뜻이다. 문제는 이 오류가 예외를 던지지 않는다는 데 있다. 그럴듯한 형식으로 틀리기 때문에 후단에서 걸러내기 어렵다.
self-consistency의 핵심 아이디어
self-consistency는 같은 질문을 여러 번(보통 5~10회) 샘플링한 뒤 최빈값(다수결)을 최종 답으로 채택하는 방법이다. 전제는 단순하다. 올바른 추론 경로는 여러 갈래로 도달할 수 있어 서로 수렴하지만, 틀린 경로는 제각각 흩어진다. 따라서 답이 몰리는 쪽이 맞을 가능성이 높다. 프롬프트를 고치거나 모델을 파인튜닝하지 않고, 호출 방식만 바꿔 정확도를 끌어올릴 수 있다는 점이 실무에서 매력적이다.
기본 구현
추론 과정은 다양하게 두고(temperature를 올려 샘플 다양성 확보), 정답만 정규화해서 집계하는 것이 요령이다. 답을 뽑아내는 파서와 정규화가 품질을 좌우한다.
from collections import Counter
import anthropic, re
client = anthropic.Anthropic()
def extract_answer(text: str) -> str | None:
m = re.search(r"정답:\s*([A-D])", text)
return m.group(1) if m else None
def self_consistency(prompt: str, n: int = 7) -> tuple[str, float]:
votes = []
for _ in range(n):
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
temperature=0.8, # 경로 다양성 확보
messages=[{"role": "user", "content": prompt}],
)
ans = extract_answer(resp.content[0].text)
if ans:
votes.append(ans)
if not votes:
return None, 0.0
top, cnt = Counter(votes).most_common(1)[0]
return top, cnt / len(votes) # 답과 합의 비율(신뢰도) 반환
합의 비율을 신뢰도 신호로 쓰기
다수결만 취하고 버리면 아깝다. 득표 비율은 그 자체로 유용한 신뢰도 지표다. 7표 중 7표가 몰린 답과 4표에 그친 답은 위험도가 다르다. 임계값 미만이면 사람 검토 큐로 보내거나 재질의하는 식으로 라우팅하면, 정확도와 자동화율을 동시에 관리할 수 있다.
answer, agreement = self_consistency(prompt, n=7)
if agreement >= 0.7:
route = "auto" # 자동 처리
elif agreement >= 0.5:
route = "review" # 사람 검토
else:
route = "escalate" # 재질의 또는 상위 모델
비용·지연과의 트레이드오프
n번 호출하면 비용과 지연도 n배다. 모든 요청에 일괄 적용하는 것은 대개 과하다. 실무에서는 아래처럼 성격에 맞춰 선택한다.
| 방식 | 비용 | 정확도 | 적합한 경우 |
|---|---|---|---|
| 단일 호출 | 1x | 기준 | 저위험·대량 트래픽 |
| self-consistency n=5 | 5x | 상승 | 추론형·중위험 작업 |
| 단일 + 재시도(불일치 시) | 1~3x | 중간 | 비용 민감 구간 |
병렬 호출로 지연은 상당 부분 상쇄할 수 있으나 비용은 줄지 않는다. 먼저 저비용으로 2~3회만 돌려 합의가 나오면 조기 종료(early stopping)하고, 갈리면 표를 늘리는 적응형 전략이 실용적이다.
주의점
- 정답 공간이 열린 작업에는 부적합. 자유 서술·요약처럼 표현이 무한히 갈리는 출력은 최빈값이 성립하지 않는다. 답이 유한한 집합(분류, 수치, 라벨)으로 정규화될 때 효과가 크다.
- 파서가 곧 병목. "정답: B"와 "B가 맞습니다"를 다르게 세면 표가 흩어진다. 구조화 출력(JSON)이나 tool use로 답 필드를 강제하면 집계가 안정된다.
- 다수결이 편향을 증폭할 수 있다. 모델이 특정 오답으로 일관되게 쏠리면 투표해도 그 오답이 이긴다. self-consistency는 랜덤 오차를 줄일 뿐 체계적 편향은 못 잡는다.
- temperature가 0에 가까우면 무의미. 샘플이 거의 동일해 다양성이 없으면 투표 이득이 사라진다.
정리
self-consistency는 모델을 바꾸지 않고 호출 패턴만으로 신뢰도를 올리는 저위험 기법이다. 핵심은 세 가지다. 답이 유한 집합으로 정규화되는 작업에만 쓸 것, 득표 비율을 신뢰도 신호로 활용해 라우팅할 것, 그리고 조기 종료로 비용을 통제할 것. 전 요청에 일괄 적용하기보다 위험도가 높은 구간에 선택적으로 배치하는 편이 비용 대비 효과가 가장 좋다.