왜 기본값이 문제가 되는가

많은 서비스가 온도(temperature)와 top-p를 API 기본값(보통 1.0)으로 둔 채 운영한다. 하지만 이 두 파라미터는 출력의 결정성과 다양성을 직접 좌우한다. 온도가 높으면 로짓 분포가 평탄해져 저확률 토큰이 자주 뽑히고, top-p는 누적 확률 상위 집합으로 후보를 잘라낸다. 코드 생성이나 JSON 추출처럼 정답이 좁은 태스크에 기본값을 쓰면 파싱 실패, 스키마 위반, 재현 불가능한 버그가 늘어난다. 반대로 카피라이팅에 온도를 0으로 두면 매번 같은 문장만 반복된다. 즉 문제는 모델이 아니라 태스크와 샘플링 설정의 불일치다.

온도와 top-p가 실제로 하는 일

온도는 소프트맥스 직전 로짓을 나눈다. T<1이면 분포가 뾰족해져 최상위 토큰에 확률이 쏠리고, T>1이면 평탄해진다. top-p(nucleus sampling)는 확률 높은 순으로 토큰을 더해 누적이 p에 도달하면 나머지를 버린다. 핵심은 두 값을 동시에 극단으로 조정하지 말라는 것이다. 온도로 분포 모양을 정하고, top-p로 꼬리(long tail)를 잘라내는 안전장치로 쓰는 조합이 실무에서 다루기 쉽다.

태스크별 권장 프리셋

태스크temperaturetop-p목표
코드 생성 / 수정0.0~0.21.0결정성, 재현성
JSON·구조화 추출0.01.0스키마 준수
RAG 요약·분류0.2~0.40.9사실성 우선
일반 대화0.6~0.80.95자연스러움
브레인스토밍·카피0.9~1.10.9~1.0다양성

수치는 출발점이다. 모델 계열마다 로짓 스케일이 달라 같은 0.7이라도 체감 다양성이 다르므로, 자체 평가셋으로 A/B를 돌려 보정해야 한다.

라우팅 코드로 관리하기

프롬프트마다 값을 하드코딩하면 관리가 안 된다. 태스크 라벨을 기준으로 프리셋을 매핑하는 얇은 라우터를 두면 일관성과 실험이 쉬워진다.

from dataclasses import dataclass

@dataclass
class SamplingConfig:
    temperature: float
    top_p: float

PRESETS = {
    "code":     SamplingConfig(0.1, 1.0),
    "extract":  SamplingConfig(0.0, 1.0),
    "rag":      SamplingConfig(0.3, 0.9),
    "chat":     SamplingConfig(0.7, 0.95),
    "creative": SamplingConfig(1.0, 0.95),
}

def resolve(task: str) -> SamplingConfig:
    return PRESETS.get(task, PRESETS["chat"])

cfg = resolve("extract")
params = {"temperature": cfg.temperature, "top_p": cfg.top_p}

설정 외부화와 실험

프리셋을 코드에 묻어두면 튜닝할 때마다 배포가 필요하다. YAML로 분리해 두면 운영 중 값 조정과 버전 관리가 편하다.

sampling:
  code:     { temperature: 0.1, top_p: 1.0 }
  extract:  { temperature: 0.0, top_p: 1.0 }
  rag:      { temperature: 0.3, top_p: 0.9 }
  chat:     { temperature: 0.7, top_p: 0.95 }
  creative: { temperature: 1.0, top_p: 0.95 }
defaults:
  fallback_task: chat
  seed: 42   # 재현이 필요한 평가 파이프라인에서만 고정

주의점과 흔한 실수

  • 온도와 top-p 동시 조정: 둘 다 강하게 낮추면 사실상 그리디 디코딩이 되어 의도치 않게 다양성이 완전히 사라진다. 한쪽을 기준으로 삼아라.
  • 결정성 오해: temperature=0이라도 부동소수점 연산, 병렬 처리, 서버 배치 구성 때문에 출력이 완전히 동일하지 않을 수 있다. seed 지원 여부는 모델·버전마다 다르다.
  • 평가 없는 튜닝: 체감으로 값을 바꾸지 말고, 태스크별 지표(파싱 성공률, 정답 일치율, 중복도)를 정해 회귀를 감지하라.
  • 구조화 출력: JSON이 목표라면 온도만 낮추기보다 스키마 강제·함수 호출 기능을 함께 쓰는 편이 안정적이다.

정리

온도와 top-p는 품질 문제를 조용히 만드는 파라미터다. 태스크를 결정성이 필요한 쪽과 다양성이 필요한 쪽으로 나누고, 프리셋을 외부 설정으로 관리하며, 평가셋으로 보정하는 세 단계만 지켜도 재현성과 출력 품질이 눈에 띄게 안정된다. 기본값을 그대로 두는 것이 가장 흔하고 비용이 큰 실수다.