🔥 LLM은 공정한 동전을 못 던진다, 그 해법이 웃긴다

#AI#LLM#프롬프트#Sakana AI#논문
1679자
22분

LLM 머릿속에서 던지는 동전과 ASCII 랜덤 문자열

어젯밤에 이 블로그 포스트를 열었다가 한참을 멍하니 있었다. Sakana AIICLR 2026에 발표한 논문 글인데, 제목은 "String Seed of Thought". 문장 하나가 눈에 꽂혔다.

"LLM은 공정한 동전을 던지지 못한다."

그럴 리가. 최신 프론티어 모델이라도 확률 얘기는 끊임없이 해봤을 텐데. 그런데 논문에 실린 실험이 꽤 직설적이다. "Flip a fair coin. Output Heads or Tails." 딱 이 한 줄을 천 번 반복시켰더니, 결과가 50대 50 근처도 못 갔다. 모델에 따라서는 24% Heads / 76% Tails 같은 대놓고 기울어진 분포가 나왔다.

논문은 이 현상을 체계적으로 보여주고, 해법을 하나 제안한다. 그 해법이 좀 웃긴다. "머릿속에서 먼저 랜덤 문자열 하나 만들어라. 그걸로 동전을 던져라." 두 줄. 이걸로 동일한 24/76 편향이 49/51 근처로 돌아온다(Sakana AI 블로그 기준, 각 n=1000 trials). 학습도 없고, 외부 도구도 없다.

LLM은 왜 공정한 동전을 못 던지는가

논문의 오프닝 실험은 단순하다. 프론티어 LLM들한테 "Flip a fair coin"을 천 번씩 시킨다. 기대값은 500/500. 실제로는 그 근처에도 못 간다. Sakana AI가 돌린 DeepSeek-R1 기준 경우에 따라 24% Heads, 76% Tails 같은 편향이 나온다. 다른 프론티어 모델들도 비슷하다(verified 2026-04-22).

왜 이게 말이 안 되냐면, 같은 모델한테 "공정한 동전의 확률은 얼마냐"고 물어보면 P(H) = 0.5, P(T) = 0.5라고 완벽하게 설명한다. 설명은 할 줄 아는데 샘플링은 못 한다는 말이다.

연구자들은 이 현상이 일반적이라는 걸 여러 세팅에서 확인했다. 2지선다, 4지선다, 16지선다, 64지선다. 확률이 균등할 때도, 30/70처럼 치우쳤을 때도. 모양은 달라도 결론은 같다.

Observation: 선택지와 연관 확률이 주어졌을 때, 프론티어 LLM은 직접 프롬프트로는 목표 분포에서 충실히 샘플링하지 못한다.

이게 왜 문제인지 조금 뜯어보자. 에이전트가 포커를 두거나 블러핑을 해야 할 때, Kuhn Poker 같은 단순한 변종조차 내시 균형 전략을 쓰려면 특정 확률로 블러핑해야 한다. 확률 그 자체를 샘플링하지 못하면, 패턴 헌팅하는 상대한테 꾸준히 지게 된다. 인간 행동 시뮬레이션, 에이전트 기반 시뮬레이션, 합성 데이터 생성 같은 영역에서도 같은 문제가 생긴다.

그럼 왜 이럴까. 논문 안팎을 종합해 보면 원인이 몇 가지로 갈린다. 하나는 RLHF로 인한 모드 붕괴다. 인간 피드백으로 튠을 하면 모델이 "안전하게 느껴지는" 답으로 수렴한다. "Heads"가 "Tails"보다 먼저 떠오르는 모델이 있으면, 학습 후엔 그 편향이 더 강해진다. 또 하나는 토큰 단위의 결정적 흐름이다. 트랜스포머는 autoregressive다. 프롬프트 앞부분에 같은 문맥이 깔리면 다음 토큰 확률 분포도 같다. 온도(temperature)를 올리면 다양해지지만, 품질이 깎이는 트레이드오프가 따라온다.

결론: LLM이 "머릿속에서 동전을 던진다"고 할 때, 실제로는 동전을 던지는 게 아니다. "Heads"라는 단어가 이 문맥에서 얼마나 그럴듯한지를 계산하고 있을 뿐이다. 랜덤 같은 '척'만 하고 있다.

SSoT, 두 줄로 푸는 방법

Sakana AI의 해법은 프롬프트 두 줄을 추가하는 것이다.

  1. 머릿속에서 복잡한 랜덤 문자열을 먼저 생성해라.
  2. 그 문자열을 조작해서 원하는 확률 결정을 유도해라.

그게 전부다. 저자들은 이걸 String Seed of Thought(SSoT)라고 부른다. 구체적인 프롬프트 형식은 이렇게 생겼다.

Generate a complex random string between <random_string> and </random_string>,
and manipulate this string to guide any stochastic decisions within <thinking>
and </thinking> tags. Then, provide your final answer, enclosed within <answer>
and </answer> tags.
Generate a complex random string between <random_string> and </random_string>,
and manipulate this string to guide any stochastic decisions within <thinking>
and </thinking> tags. Then, provide your final answer, enclosed within <answer>
and </answer> tags.

User prompt는 원하는 그대로 두면 된다. "Flip a fair coin and output Heads or Tails with equal probability." 그게 다다.

처음에 이걸 보고 "응? 그냥 CoT 아닌가" 싶었다. Chain-of-Thought가 추론 흐름을 글로 풀어내게 만드는 거라면, SSoT는 그 추론 흐름 안에 랜덤 소스를 집어넣는 방식이다. 모델이 '생각'을 글로 풀 때, 그 글 안에 xK9mQ3p 같은 문자열을 먼저 써놓고, 그걸 써서 결정을 내린다. 랜덤이 모델의 내부 확률분포가 아니라, 출력 스트림 위에서 표현된다는 게 핵심이다.

왜 이게 먹히는가. 모델이 xK9mQ3p를 만들 때, 이건 사실 결정적 샘플링이다. 온도가 0이 아니면 매번 다른 문자열이 나오지만, 중요한 건 그게 아니다. 핵심은 이 문자열이 시퀀스이고, 내부 구조가 없다는 점이다. ASCII 합 mod 2가 0인지 1인지는 문자 하나만 바뀌어도 뒤집힌다. 작은 노이즈가 큰 결정을 뒤집는 영역으로 들어가니까, 사실상 난수와 구분이 안 되는 출력이 나온다.

비유하자면 이렇다. 당신이 "공정한 동전 던져!"라고 누구한테 요청했는데, 그 사람이 대답 대신 주머니에서 책을 꺼내고, 아무 페이지나 열고, 세 번째 단어의 글자 수가 짝수면 앞, 홀수면 뒤. 책을 펼치는 행위 자체는 난수가 아닌데도, 최종 결정은 충분히 난수스럽다. 랜덤성을 알고리즘 안에 묶어두는 전략이다.

내부에서 무슨 일이 벌어지는가

논문에서 흥미로운 건, SSoT 프롬프트가 문자열 조작 방법을 구체적으로 지시하지 않는다는 점이다. 그냥 "랜덤 문자열을 만들고 조작해서 결정을 내려라"고만 한다. 그런데 LLM은 스스로 적절한 전략을 찾아낸다.

저자들이 추론 트레이스를 뜯어보니까 두 가지 지배적인 패턴이 보였다.

Sum-Mod — 균등 분포용. 문자열을 만들고, 각 글자의 ASCII 값을 다 더하고, 선택지 개수로 나머지 연산을 한다. 예를 들어 공정한 동전이면 sum(ASCII) mod 2가 0이면 Heads, 1이면 Tails. "xK9mQ3p"의 ASCII 합이 735라고 치면, 735 mod 2 = 1 → Tails.

Rolling Hash — 편향된 분포용. 문자를 하나씩 처리하면서 해시값을 굴린다. hash = (hash × 31 + ASCII) mod M 같은 식으로. 최종 해시값이 0에서 M-1 사이의 큰 정수가 되니까, 30/70 같은 임의의 비율도 임계값 분할로 표현할 수 있다.

둘 다 문자열 해싱에서 교과서적인 기법이다. 놀라운 건 지시받지 않았는데도 모델이 이걸 선택했다는 점이다. 프롬프트에 "ASCII를 써라"라고 안 썼는데 쓴다. "나머지 연산을 써라"라고 안 썼는데 쓴다. 모델 자신이 가진 코딩 지식으로 "이런 상황에서 이게 맞다"를 스스로 판단한 셈이다.

DAG(Diversity-Aware Generation) 쪽에선 전략이 다르다. "짧은 우화를 써 달라" 같은 오픈엔디드 프롬프트를 주면, 모델이 이야기 구성 요소를 템플릿처럼 분해한다. 설정(setting), 등장 캐릭터 특성(traits), 갈등(conflict), 교훈(moral). 그리고 각 카테고리의 후보를 랜덤 문자열의 서로 다른 부분을 써서 Sum-Mod로 뽑는다. 문자열이 바뀌면 조합이 바뀌고, 전혀 다른 이야기가 나온다.

모델이 이걸 자발적으로 한다는 게 제일 흥미로운 부분이다. 논문에선 이걸 "LLM이 자율적으로 과업에 맞는 전략을 채택한다"고 표현하는데, 말하자면 SSoT는 전략을 지시하는 게 아니라, 전략이 돌아갈 수 있는 공간을 열어주는 프롬프트다.

실험 결과: 거의 PRNG 수준까지 간다

구체적인 숫자를 보자. 평가 지표는 Jensen–Shannon divergence. 두 확률 분포의 유사도를 재는 지표인데, 0에 가까울수록 목표 분포에 충실하다.

DeepSeek-R1에서는 SSoT가 PRNG 기준선에 바짝 붙는 수준까지 분포를 돌려놓는다. 논문이 돌린 다양한 프론티어 모델에서도 baseline 대비 편향이 유의미하게 줄어든다. 2지선다에서 64지선다까지 action space를 늘려봐도, SSoT(빨간 선)가 다른 프롬프팅 기법(high-temperature, few-shot, prompt ensembling, sequential sampling)을 전부 제친다.

예외도 있다. QwQ-32B는 공정한 2지선다에서 baseline의 JS divergence가 2.43 × 10⁻³로 이미 PRNG 수준에 가까웠고, SSoT를 쓰면 3.39 × 10⁻³로 오히려 약간 악화된다. 저자들은 논문 본편에서 이 실패 모드를 따로 분석한다. SSoT가 무조건 이기는 건 아니라는 뜻이다.

재미있는 건 가위바위보 실험이다. SSoT, Baseline, Simple 세 가지 프롬프트로 LLM에게 가위바위보를 시켰다. 상대는 Kaggle에 공개된 RPS Dojo 블랙벨트 봇 10종. 이 봇들은 상대의 전체 수 이력을 보지만 LLM은 못 본다. 패턴이 예측 가능하면 털린다.

  • Simple: 그냥 "이기도록 수를 골라라"
  • Baseline: "내시 균형 전략으로 수를 다양하게 골라라". 전략만 말하고 랜덤 메커니즘은 없음
  • SSoT: "랜덤 문자열을 시드로 삼아 내시 균형 혼합 전략을 실행해라"

결과: SSoT는 평균 점수가 0 근처(즉, 봇들과 비긴다). Baseline과 Simple은 명백히 털린다. 이게 중요한 이유는 샘플링 편향이 실제 게임 플레이에서 exploit 가능한 구멍이라는 걸 증명했기 때문이다. 이론상 내시 균형을 안다고 말해봐야, 실제로 그 확률로 움직일 수 없으면 의미가 없다.

DAG 쪽 실험은 NoveltyBench로 돌렸다. 이 벤치는 다양성 평가용으로 만들어진 1,100개 프롬프트 세트로, 창의적 글쓰기, 사실 지식, 주관적 의견, 제품 추천 같은 카테고리를 커버한다. 지표는 두 개다.

  • Distinct: k=8 응답 중 기능적으로 다른 응답의 개수(1~8)
  • Utility: 다양성과 품질을 합친 지표. 새로운 응답만 보상 점수로 합산하되, 순서별 인내심 계수로 할인한다

DeepSeek-R1에서 SSoT는 curated, WildChat 두 스플릿 모두에서 Distinct 점수 최고를 찍었다. Utility도 baseline보다 명확히 올라간다. "다양하지만 질이 떨어지는" 흔한 함정에 빠지지 않았다는 뜻이다. 몇몇 카테고리(제품 추천, 의견)에선 Paraphrase나 high-temperature가 Utility에서 앞서기도 했지만, 전체 경향은 SSoT 쪽이다.

이걸로 해결되지 않는 것들

SSoT가 만능은 아니다. 저자들도 명확히 선을 긋는다.

작은 모델은 못 쓴다. SSoT는 모델이 자율적으로 모듈로 연산이나 해싱 같은 전략을 "고안하고 실행"하는 능력에 의존한다. 추론 능력이 떨어지는 소형 모델에선 이 자율성이 작동하지 않는다. 논문에선 DeepSeek-R1 같은 추론 중심 모델에서 특히 효과가 크다고 보고한다.

정답이 하나인 태스크에는 오히려 방해다. 수학 문제, 사실 검색, 결정적 답을 요구하는 질문 같은 경우 SSoT를 쓰면 모델이 엉뚱하게 산만해진다. 논문도 이 점을 분명히 한다. 결정적 태스크엔 기존 CoT가, 확률적 태스크엔 SSoT가 어울린다.

긴 추론 토큰이 필요하다. 논문의 CoT-scaling 분석에 따르면, 추론 트레이스가 길수록 샘플링 충실도가 올라간다. 토큰 비용을 추가로 지불하는 셈이다. 공짜 점심은 아니다.

비슷한 결의 최신 연구들이 잇따라 나오고 있다는 점도 짚고 가자. Verbalized Sampling은 "응답 여러 개와 각 확률을 말로 뱉어라"는 전략으로 mode collapse를 공략한다. Verbalized Rejection Sampling은 고전적 기각 샘플링을 자연어로 에뮬레이트한다. SSoT와 접근은 다르지만, "프롬프트만으로 외부 도구 없이 분포 충실도를 고친다"는 공통의 목표를 공유한다. 2025~2026년의 프롬프팅 연구가 한쪽에서 또렷한 결로 움직이고 있다.

내 생각

이 논문이 흥미로운 건 결과보다 은유에 있다고 생각한다.

우리는 LLM을 가끔 마법 상자로 취급한다. 온도를 올리면 창의성이 나오고, CoT를 넣으면 추론이 되고, 시스템 프롬프트를 잘 쓰면 행동이 정렬된다. 그런데 랜덤이라는 자원만큼은 모델 내부에서 제대로 공급되지 않는다. 온도 샘플링은 토큰 수준의 노이즈고, 의미 수준에서 "동전을 뒤집는" 진짜 난수는 아니다.

SSoT는 이 간극을 메우는 방식이 거의 우회로 같다. "내부에 난수원이 없다면, 출력에다 난수원을 두자." 모델이 자기 출력 스트림 위에 랜덤 문자열을 적고, 그걸 해시 함수처럼 써서 결정을 내린다. 일종의 자기 참조적 난수기다. 모델의 결정이 모델이 만든 글자에 의존하는 구조.

이건 단순한 프롬프팅 트릭이 아니라, LLM 아키텍처의 한계를 프롬프트 레이어에서 수정하는 패턴 같다. 비슷한 결의 이야기가 요즘 여러 곳에서 나온다. Karpathy의 LLM Wiki가 메모리 부재를 마크다운으로 외재화한 것이나, 하네스 엔지니어링이 에이전트의 상태 관리를 코드 레이어로 끌어올린 것과 같은 흐름이다. 모델을 고치지 않고, 모델 바깥의 구조로 문제를 해결한다.

현실적으로는 어디에 쓸까. 에이전트 시뮬레이션에서 "실제 사람처럼 다양하게 행동하는 에이전트"가 필요할 때. 합성 데이터 생성에서 mode collapse 없이 다양한 샘플을 얻고 싶을 때. 게임 AI에서 exploit 당하지 않게 혼합 전략을 실행하고 싶을 때. Monte Carlo 기반 에이전트 탐색에서 분기 샘플링이 편향되지 않게 하고 싶을 때.

다만 이 논문이 이 흐름의 마침표는 아닐 것 같다. "LLM은 출력을 쌓아서 생각한다"는 전제에 기대는 방법론인데, 그 전제 자체가 맞지 않을 때는 어떻게 할지 열려 있다. 모델이 스스로 랜덤 문자열을 "충분히 랜덤하게" 만들어낸다는 가정도 완전히 안전하진 않다. 관찰 수준에서 그렇게 작동한다는 거지, 이론적 분석은 논문 본편에 더 있긴 하지만 아직 초기라고 본다.

그래도 이번 주말에는 내 에이전트 코드 몇 군데에 SSoT를 꽂아볼 생각이다. 단 세 줄이면 되는 실험이고, 만약 합성 데이터의 다양성이 정말 올라간다면 데이터셋 품질이 실질적으로 개선된다. 결과가 나오면 다시 쓸 것 같다.

LLM은 공정한 동전을 못 던진다. 그런데 동전 이름의 글자 하나하나를 ASCII로 바꾸고 2로 나눈 나머지는 잘 던진다. 2026년에 아직도 이런 놀라운 트릭이 남아 있다는 게, 뭔가 기분이 이상하다.

참고 자료

YouTube 영상

채널 보기
AI를 위한 선형대수학 - 소개 | 선형대수학
투영과 예측, 그리고 선형 결합 | 선형대수학
우리가 매일 쓰는 맞춤법 검사기와 라우터 속에 숨겨진 알고리즘은? | Trie 자료구조 이야기
직교성과 벡터 투영 | 선형대수학
벡터의 정의와 덧셈 연산 | 선형대수학
행렬의 기본 연산 - 행렬 덧셈, 스칼라 곱, 전치 | 선형대수학
트라이(Trie)에서 단어를 삭제하는 방법 | Trie 자료구조 이야기
행렬의 가장 중요한 연산 - 행렬 곱셈 | 선형대수학