AI가 같은 질문에 매번 다르게 답하는 이유 — 온도를 0으로 두면 진짜 똑같아지나 재봤습니다 (2026.7)

"어제 잘 되던 프롬프트를 오늘 그대로 넣었는데 답이 다르다." 다들 겪는 일이고, 돌아오는 조언도 늘 같습니다. temperature를 낮추세요. 그런데 이 조언에는 아무도 확인 안 해 본 착각이 하나 얹혀 있습니다.

낮추면 몇 %가 같아지는지 숫자로 말해주는 글을 못 찾았거든요. 조언만 있고 계량은 없는 게 이 주제의 함정이에요. 그래서 직접 쟀습니다. 같은 프롬프트를 조건별로 8번씩, 무료 로컬 일꾼 두 명에게 총 96번 넣고 나온 답을 글자 단위로 대조했습니다. 2026년 7월 29일 측정입니다.

결론부터 한 줄로. 내 PC에서 요청을 하나씩 굴린 조건에서는 temperature를 0으로 두는 것만으로 세 작업 전부 글자 하나까지 같아졌습니다. seed는 손댈 필요도 없었어요. 대신 훨씬 불편한 걸 하나 주웠습니다. 완벽하게 재현되는 오답이요.

축은 딱 하나만 움직였습니다

비교가 성립하려면 변수 하나만 건드려야 합니다. 같은 인턴에게 같은 문제지를 주고 책상 조명만 바꿔 보는 셈이죠. 그래서 모델도 프롬프트도 통째로 고정하고 디코딩 설정만 세 가지로 갈아 끼웠습니다.

조건 설정 흔히 도는 조언과의 관계
A 기본값 아무것도 지정 안 함 대부분의 사람이 쓰는 상태
B temp0 temperature: 0 "온도를 낮추세요" 그 자체
C temp0+seed temperature: 0 + seed: 42 그 조언의 최대치

이번에 굴린 gemma3:4b의 기본값은 temperature 1, top_k 64, top_p 0.95였습니다(모델 설정 조회로 확인). "기본값 = 온도 1"이라는 게 A 조건의 정체입니다.

작업은 셋. 앞의 둘은 AI를 반복 업무에 끼워 넣을 때 실제로 시키는 일이고, 셋째는 대조군입니다.

  • 문의 분류 — 고객 문의 10건을 환불·배송·교환·상품문의·기타로 분류해 JSON으로 출력. 10건 중 4건은 사람이 봐도 갈릴 만한 문장을 일부러 심었습니다. 전부 자명하면 모든 조건이 100%로 나와 측정이 무의미해지니까요.
  • 발주 메일 추출 — 두 건의 발주가 섞인 한국어 이메일에서 업체명·담당자·품목·수량·단가·납기일·총금액 7개 항목을 뽑아 구조화.
  • 제목 5개 짓기(대조군) — 자유 생성. 여기서는 매번 다른 게 정상입니다.

일꾼은 gemma3:4b(전 작업)와 qwen3-vl:8b(문의 분류만 교차확인). 둘 다 이미 PC에 있던 무료 오픈웨이트 모델이고, 그래픽카드는 RTX 4070 Ti SUPER 16GB 한 장, 요청은 한 번에 하나씩만 보냈습니다. 이 마지막 조건이 뒤에서 아주 중요해집니다.

채점은 눈으로 안 했습니다. 정규화한 문자열을 쌍쌍이 비교하는 채점 스크립트를 따로 짰고, 스크립트 자체도 37개 단언으로 자체검증한 뒤 돌렸습니다. 실제로 그 자체검증이 채점기 버그를 하나 잡았습니다(품목 코드 SB-204를 숫자 −204로 읽던 문제).

96번의 결과 — 온도 0에서는 전부 100%였습니다

숫자부터 놓겠습니다. '완전일치'는 8회분을 두 개씩 짝지어(28쌍) 글자까지 같았던 비율입니다.

작업 / 일꾼 A 기본값 B temp0 C temp0+seed
문의 분류 · gemma3:4b 57.1% 100% 100%
발주 추출 · gemma3:4b 100% 100% 100%
제목 5개 · gemma3:4b 0% 100% 100%
문의 분류 · qwen3-vl:8b 100% 100% 100%

조건별 출력 완전일치율을 비교한 막대 차트 — 모델 기본값·temperature 0·temperature 0에 seed 고정 세 조건

B와 C가 전부 같습니다. 우연이 아니라 당연한 결과예요. 온도 0은 "매번 확률이 가장 높은 토큰만 고르라"는 뜻이라 뽑기 자체가 사라지고, 뽑기가 없으면 뽑기용 난수인 seed는 쓸 자리가 없습니다. 실제로 B와 C의 출력 파일은 글자까지 동일했습니다. ollama 공식 문서도 seed는 "재현 가능한 출력을 위해" 쓰는 값이라고만 적어 뒀지, 온도 0에서 추가 효과가 있다고는 말하지 않습니다.

여기서 이미 써먹을 결론이 하나 나옵니다. 온도 0으로 굴리는 자동화라면 seed까지 챙길 필요가 없습니다. 챙겨서 손해는 없지만, 안 챙겼다고 불안해할 이유도 없어요.

'다르다'에는 두 종류가 있습니다

표에서 눈에 걸리는 건 문의 분류의 57.1%입니다. 기본값에서 8회 중 절반쯤만 같았다는 뜻이니 "역시 답이 매번 다르구나" 싶죠. 이 인턴이 낸 답안지 원본을 열어 보면 얘기가 달라집니다.

8개 출력은 딱 두 종류였습니다. 6번은 이렇게,

[
  {"번호": 1, "분류": "배송"},
  {"번호": 2, "분류": "교환"},

2번은 이렇게 나왔습니다.

[
  {
    "번호": 1,
    "분류": "배송"
  },

줄바꿈 방식만 다릅니다. 분류 라벨 10개는 8회 전부 똑같았어요. 갈릴 거라고 미리 지목해 둔 4개 문항까지 포함해서 하나도 안 흔들렸습니다.

겉모습(문자열)과 결론(내용)의 일치율을 비교한 막대 차트 — 문의 분류는 57.1% 대 100%

이 구분이 실무에서는 전부입니다. 답을 눈으로 읽는 사람에게는 서식 차이가 "다른 답"으로 보이지만, 그 값을 받아 쓰는 프로그램 입장에서는 아무 일도 안 일어난 겁니다. 반대로 JSON을 문자열로 캐싱하거나 해시로 비교하는 코드를 짜 뒀다면, 내용이 같은데도 매번 캐시가 빗나갑니다. 답이 다르다고 느낄 때 먼저 볼 것은 결론이 달라졌는지, 껍데기가 달라졌는지입니다.

교차확인용으로 굴린 qwen3-vl:8b은 기본값에서도 8회 전부 완전일치였습니다. 두 일꾼이 매긴 분류 10개도 서로 10/10 일치했고요. 다만 8번 문항("박스가 찌그러져서 왔는데 새 걸로 보내주세요")을 둘 다 '배송'으로 분류했는데, 사람이라면 '교환'에 가깝다고 볼 문장입니다. 흔들리지 않는 것과 잘 고르는 것은 별개라는 얘기고, 이건 다음 절의 예고편입니다.

정작 흔들린 건 창작 쪽이었습니다

기본값에서 진짜로 무너진 건 대조군이었습니다. 제목 5개 짓기는 완전일치 0%, 8회에 걸쳐 나온 제목 40개 중 38개가 서로 다른 제목이었습니다. 겹침 정도를 수치로 재면 1.2% 수준이니 이 녀석은 사실상 매번 새로 쓴 셈입니다.

그런데 같은 작업도 온도를 0으로 내리자 8회가 통째로 같은 다섯 줄로 굳었습니다.

1. AI 도구, 당신의 사업을 어떻게 바꿀까?
2. 자영업자를 위한 AI 활용 가이드: 초보자도 쉽게!
...

분류·추출처럼 정답 형태가 좁은 일은 기본값에서도 웬만해선 안 흔들리고, 카피·제목·초안처럼 답이 열려 있는 일에서 무작위성이 터집니다. 그러니 "AI 답변이 매번 달라서 못 굴리겠다"는 불만은 대체로 창작형 작업에서 나온 것이고, 그 경우엔 온도를 내리는 게 답이 아니라 다양성을 원해서 온도를 켜 둔 상태라는 걸 먼저 알아야 합니다. 후보를 여러 개 받고 싶으면 그대로 두는 게 맞고, 매번 같은 카피를 원하면 온도를 내리면 됩니다. 어느 쪽이든 프롬프트에서 원하는 조건을 명시적으로 말해 주는 쪽이 온도를 만지는 것보다 효과가 큽니다.

가장 위험한 조합 — 8회 다 똑같이 틀렸습니다

발주 메일 추출은 세 조건 전부 100% 재현이었습니다. 24번 모두 글자까지 같은 답. 월급값 하는 인턴처럼 보이죠.

그 답의 내용은 이랬습니다.

항목 메일 원문 이 일꾼이 뽑은 값
품목 1 수량 × 단가 1,200개 × 7,200원 1200 · 7200 (정확)
품목 1 총금액 8,640,000원이어야 함 864,000 ← 틀림
품목 2 수량 × 단가 450개 × 15,400원 450 · 15400 (정확)
품목 2 총금액 6,930,000원이어야 함 681,000 ← 틀림

베껴야 하는 값은 전부 맞았고, 곱해야 하는 값은 전부 틀렸습니다. 그것도 8회 내내 똑같은 틀린 숫자로요. 총금액 검산 정답률은 세 조건 모두 0/8입니다.

이게 재현성 이야기에서 제일 자주 빠지는 대목입니다. 재현성과 정확성은 다른 축입니다. 매번 똑같이 틀리는 일꾼도 재현성은 100%예요. 오히려 답이 흔들릴 때는 사람이 "어? 아까랑 다른데?" 하고 한 번 더 들여다보는데, 완벽하게 고정된 오답은 그 경보음마저 꺼 버립니다. 온도를 0으로 내리는 조치가 틀린 답을 안정적으로 틀리게 만드는 데도 똑같이 잘 듣는다는 뜻입니다.

그래서 대응은 단순합니다. 검산할 수 있는 값은 AI에게 시키지 마세요. 수량과 단가는 뽑게 하고 곱셈은 코드가 합니다. 확인 절차 전반은 AI 답변에서 지어낸 부분 거르는 법에 정리해 뒀습니다.

그럼 "온도 0이어도 다르다"는 말은 왜 도는가

여기까지 읽고 갸웃할 분이 있을 겁니다. 온도 0이어도 결과가 달라진다는 얘기를 분명히 봤는데 왜 우리 측정에서는 100%가 나왔느냐고요.

둘 다 맞습니다. 조건이 다릅니다.

우리 측정은 내 PC, 요청 하나씩, 같은 그래픽카드, 같은 빌드였습니다. 우리 집 인턴은 책상에 혼자 앉아 내 일감만 처리한 겁니다. 반면 클라우드 챗봇은 내 요청이 그 순간 접속한 남의 요청들과 한 묶음(배치)으로 GPU에 올라갑니다. 같은 일꾼을 수천 명이 동시에 굴리는 셈이고, 한 번에 몇 명분이 얹히느냐가 매번 달라지죠. 배치 크기가 달라지면 내부 계산의 덧셈 순서가 달라지고, 마지막 자릿수가 미세하게 흔들립니다. 그 미세한 차이가 한 토큰의 순위를 뒤집는 순간부터 답이 갈라집니다.

Thinking Machines Lab이 이 문제를 정면으로 다룬 글에 구체적인 수치가 있습니다. 온도 0으로 1,000번을 생성했더니 서로 다른 결과가 80종 나왔고, 가장 흔한 것이 78번이었습니다. 갈라지기 시작한 지점은 103번째 토큰. 이들이 지목한 원인이 바로 배치 크기에 따라 계산 결과가 달라지는 것이었고, 커널을 배치 크기와 무관하게 고쳐 넣자 1,000번이 전부 같아졌습니다.

OpenAI도 seed 파라미터를 안내하면서 "결정적으로 샘플링하도록 최선을 다한다(best effort)", "결정성은 보장되지 않는다"고 명시하고, 백엔드 구성이 바뀌었는지 system_fingerprint로 확인하라고 안내합니다. 즉 클라우드에서 재현성은 보장이 아니라 노력 목표입니다.

로컬(우리 측정 조건) 클라우드 챗봇
배치에 남의 요청이 섞이나 아니오 예(혼잡도에 따라 변동)
모델·빌드가 바뀌나 내가 바꾸기 전엔 아니오 공지 없이 갱신될 수 있음
온도 0의 효과 우리 측정 96회에서 100% 최선의 노력, 보장 아님

다른 글들이 흔히 드는 나머지 이유들 — 모델 버전 교체, 이전 대화 맥락, 사용자 지정 지침(Custom Instructions) — 도 실제 원인이 맞습니다. 다만 이건 우리가 이번에 측정한 축이 아니라 API가 아닌 채팅창 환경에서 생기는 변수라, 여기서는 원인 목록으로만 적고 숫자를 붙이지 않겠습니다.

덤 — 답은 같은데 야근 시간이 2.6배 갈렸습니다

qwen3-vl:8b은 답을 내기 전에 속으로 한참 궁리하는 녀석입니다. 이쪽에서 재미있는 게 나왔습니다.

조건 생성 토큰 수 순수 생성 시간
A 기본값 1,352 ~ 3,396개 (평균 2,273) 12.7 ~ 32.7초
B temp0 1,478개 (8회 고정) 13.9 ~ 14.4초
C temp0+seed 1,478개 (8회 고정) 14.2초

최종 답은 8회 전부 같았는데, 거기 도달하기까지 쓴 토큰이 2.5배까지 요동쳤습니다. 처리 시간으로는 2.6배 차이. 토큰 단위로 과금되는 API였다면 같은 답에 요금이 2.5배 갈렸다는 뜻이에요. 온도를 0으로 두자 이 야근이 사라졌습니다.

첫 시도 때는 이 녀석이 4번째 회차에서 눈에 보이는 답을 아예 비워서 돌려보내 측정이 중단됐습니다. 이때 남은 3회분은 버리고 이 모델 몫 24회를 통째로 다시 돌렸습니다(재실행에서는 24회 모두 정상). 위에 적은 96회는 gemma3:4b 72회와 이 재실행분 24회이고, 중단된 시도의 부분 데이터는 한 건도 섞지 않았습니다. 속으로 길게 생각하는 모델을 자동화에 넣을 거라면 빈 응답을 정상 경로로 처리하는 코드가 있어야 한다는 뜻이기도 합니다.

속도 얘기가 나온 김에 덧붙이면, 위 표의 '순수 생성 시간'은 모델을 메모리에 올리는 시간을 뺀 값입니다. 이번 측정은 매 호출마다 모델을 내렸다 올리도록 설정해서 콜드 로딩이 회차마다 붙었습니다. 로딩까지 포함한 총소요는 이렇게 갈립니다.

일꾼 콜드 로딩 순수 생성 총소요
gemma3:4b 3.56 ~ 3.70초 0.55 ~ 1.44초 4.23 ~ 5.19초
qwen3-vl:8b 2.92 ~ 2.98초 14.02 ~ 21.61초 17.06 ~ 24.64초

세 칸은 작업별 평균이고, 앞의 둘을 더해도 총소요와 정확히 안 맞습니다. 매 회차 0.06~0.11초가 남는데 프롬프트를 읽어 들이는 시간과 요청이 오가는 시간이에요. 굳이 적는 이유는, 이런 잔차를 숨기고 딱 떨어지게 반올림해 놓은 표가 나중에 남을 속이기 때문입니다.

여기서 눈에 띄는 건 4B짜리입니다. 일하는 시간보다 출근하는 시간이 더 깁니다. 반대로 8B 추론형은 로딩이 전체의 12~17%죠. 로딩과 생성을 한 칸에 섞어 놓은 표로는 두 일꾼을 비교할 수 없습니다. 모델별 메모리 사용량은 그래픽카드별로 몇 B까지 굴러가는지 잰 글에 정리돼 있습니다.

이 숫자를 어디까지 믿어도 되나

이번 측정의 한계입니다.

  • 클라우드 챗봇은 측정하지 않았습니다. ChatGPT·Claude·Gemini의 재현율이 몇 %인지는 이 글에 없습니다. 위의 100%를 그쪽으로 옮겨 읽으면 안 됩니다.
  • 동시 요청 조건을 재현하지 않았습니다. 우리는 일꾼에게 일감을 하나씩 넘겼습니다. 인턴 하나를 여럿이 동시에 굴릴 때 결과가 달라지는지는 확인이 필요하고, 그게 바로 클라우드와 갈리는 핵심 변수입니다.
  • 출력이 짧습니다. 세 작업 모두 300자 안팎이었습니다. 앞서 인용한 실험에서 갈라짐이 시작된 지점이 103번째 토큰이었던 걸 생각하면, 수천 토큰짜리 긴 글에서는 같은 조건이라도 어긋날 여지가 더 큽니다.
  • 모델 2종, 4B와 8B급입니다. 조건당 8회, 총 96회. 더 큰 모델이나 다른 계열에서 같은 그림이 나올지는 이 데이터로 말할 수 없습니다.
  • 분류 정답표를 따로 두지 않았습니다. 문의 분류에서 잰 것은 같은 답이 나오는가이지 옳은 답인가가 아닙니다. 8번 문항 사례가 그 차이를 보여 줍니다.

그래서 어떻게 굴리면 되나

작업 성격에 따라 갈립니다.

① 분류·추출·태깅처럼 파이프라인에 넣는 일 — API를 쓴다면 temperature: 0을 명시하세요. 로컬이라면 우리 측정 범위에서는 이것만으로 완전히 고정됐습니다. seed는 넣어도 되고 안 넣어도 결과가 같았습니다. 클라우드라면 seed까지 넣고 system_fingerprint가 바뀌는지 함께 기록해 두세요. 그래도 보장은 아닙니다.

② 답에 계산이 섞이는 일 — 뽑기와 계산을 분리하세요. 숫자는 인턴이 옮겨 적게 하고, 사칙연산은 코드로 검산합니다. 이번 발주 추출이 그 이유를 8번 연속으로 보여 줬습니다.

③ 카피·제목·초안 같은 창작 — 온도를 굳이 내리지 마세요. 이 녀석한테는 매번 다른 게 값입니다. 다만 마음에 든 그 결과를 다시 얻고 싶다면 결과물 자체를 저장해 두는 편이 낫습니다. 온도를 내려 굳혀 버리면 그 다섯 줄만 계속 나오는, 상상력 없는 일꾼이 됩니다.

④ 채팅창에서 쓰는 경우 — 온도 슬라이더가 없습니다. 대신 새 대화에서 시작하고, 조건을 프롬프트에 전부 적고, 결과가 바뀌면 모델 버전이 바뀌지 않았는지부터 확인하는 게 현실적인 대응입니다.

마지막으로 하나만 더. 이 글에서 잰 96번은 답이 같은지만 봤습니다. 재현율 100%는 그 답이 맞다는 뜻이 아니고, 발주 추출에서 확인한 대로 8회 내내 똑같이 틀린 답은 사람 눈에 더 안 띕니다. 온도를 0으로 고정했다면 검산은 그만큼 더 촘촘히 해야 합니다.


참고자료

  • ollama 공식 API 문서 — optionsseed·temperature, keep_alive 기본값: <https://github.com/ollama/ollama/blob/main/docs/api.md>
  • Thinking Machines Lab, "Defeating Nondeterminism in LLM Inference" — 배치 비불변성 원인 규명, 온도 0에서 1,000회 중 80종: <https://thinkingmachines.ai/blog/defeating-nondeterminism-in-llm-inference/>
  • OpenAI Cookbook, seed 파라미터로 재현 가능한 출력 만들기 — best effort, 결정성 미보장, system_fingerprint: <https://developers.openai.com/cookbook/examples/reproducible_outputs_with_the_seed_parameter>

측정 시점: 2026년 7월 29일. 모델은 gemma3:4b, qwen3-vl:8b, 구동은 ollama 로컬, 그래픽카드는 RTX 4070 Ti SUPER 16GB. 조건당 8회, 총 96회. 모델은 언제든 갱신되므로 이후 시점에는 값이 달라질 수 있습니다.

이 글은 cinevyze 운영자가 해당 도구를 직접 테스트하고 결과를 비교·검수해 정리·편집했습니다. 판단·사실확인은 모두 사람이 했고, 글 다듬는 일부 과정에 AI 도구의 도움을 받았습니다.

댓글

이 블로그의 인기 게시물

ChatGPT 글쓰기, 무료로 어디까지 뽑아먹나 — 돈 새는 지점이랑 Go $8 함정까지

AI한테 일 제대로 시키는 법 — 프롬프트 4칸 공식(같은 모델에 18번 넣어 재봤습니다)

챗GPT·클로드·제미나이 요금 비교 — '셋 다 20달러'가 아니었습니다 (2026.07)