챗GPT 계산 오류 해결법: CoT 대신 Program of Thoughts(PoT)
복잡한 계산에서만 자꾸 틀리는 AI, 이제 그 이유를 압니다.
챗GPT에게 “피보나치 50번째 숫자를 구해줄래?”라고 물어봤다가, 완전히 엉뚱한 답을 받은 적 있나요? 아니면 “복리 계산 공식”을 물어봤는데, 처음 설명은 완벽하지만 막상 숫자를 넣으라고 하면 산술 오류를 내던 경험이요.
이것이 바로 LLM(Large Language Model)의 치명적 약점입니다. “다음에 올 단어를 예측”하는 기계가, 반복적인 계산이나 큰 자릿수의 수학에서 ‘그럴듯한 거짓’, 즉 환각(Hallucination)을 내놓는 거죠.
문제는 단순했습니다. “AI에게 계산은 AI에게 맞기지 않는 일이다.”
2023년 Waterloo 대학과 구글 리서치의 연구자들은 이 문제를 근본적으로 해결할 한 가지 전략을 제시했습니다. 바로 Program of Thoughts (PoT)입니다. 오늘은 이 아이디어가 왜 혁신적인지, 그리고 실제로 어떻게 적용하는지 명쾌하게 설명해드리겠습니다.
1. 문제의 근원: 왜 똑똑한 AI가 계산을 틀릴까?
이 질문에 답하려면, LLM이 어떻게 작동하는지 이해해야 합니다.
언어 모델의 기본 원리
LLM은 훈련 데이터의 확률 패턴을 학습합니다. “문맥 A 다음에 문맥 B가 올 확률이 높다”는 식으로요. 이렇게 학습된 모델은 엄청난 언어 이해력을 가집니다. 복잡한 철학 개념도 설명하고, 셰익스피어처럼 시도 쓸 수 있습니다.
하지만 여기엔 근본적인 한계가 숨어있습니다:
LLM은 ‘단어의 다음 단어’를 예측하는 것이지, ‘수학을 계산’하는 것이 아닙니다.
CoT (Chain of Thoughts)의 한계
그동안 이 문제를 해결하기 위해 사람들은 CoT (Chain of Thoughts)라는 기법을 사용해왔습니다. 즉, “단계별로 풀어서 설명해봐”라는 프롬프트를 던지는 방식이죠.
예를 들어:
Q: "50번째 피보나치 숫자는?"
CoT 방식: "첫 번째는 0, 두 번째는 1...
세 번째는 0+1=1, 네 번째는 1+1=2...
(중략)
50번째는 [텍스트로 직접 계산]"
문제는 뭘까요? 50번을 반복 계산하는 동안, 단 한 번의 산술 실수만 있어도 그 이후 모든 값은 틀려집니다. 마치 종이에 손으로 50개의 숫자를 써내려가다가 중간에 하나 헷갈려서 지우는 것처럼요.
연구에 따르면, CoT를 써도 여전히 이런 오류가 발생합니다. 특히:
- 반복 연산이 길면: 루프(Loop)가 많을수록 실수 확률이 높아집니다.
- 큰 자릿수 계산: 천문학적인 숫자들을 다룰 때 AI는 ‘그럴듯한’ 숫자를 만들어냅니다. (정확도가 떨어지기 때문)
- 복합 공식: 여러 단계의 계산이 섞여 있으면, 어느 부분에서 틀렸는지 찾기 어렵습니다.
2. 해결책: PoT의 핵심 철학
이 문제를 해결하는 PoT의 아이디어는 매우 간단하면서도 강력합니다:
“추론(Reasoning)은 AI에게 맡기고, 계산(Computation)은 컴퓨터에게 맡기자.”
즉, AI가 할 일과 컴퓨터가 할 일을 명확하게 분업화하는 것입니다.
PoT의 3단계 워크플로우
| 단계 | 담당자 | 역할 |
|---|---|---|
| 1단계: 문제 이해 | LLM (AI) | 사용자 질문을 파악하고 풀 방법의 논리를 설계합니다 |
| 2단계: 코드 작성 | LLM (AI) | 논리를 실행 가능한 코드(Python 등)로 변환합니다 |
| 3단계: 코드 실행 | 컴퓨터 (Interpreter) | 작성된 코드를 정확하게 실행하여 답을 도출합니다 |
사용자 입장에서는 AI에게 질문을 던지면, 내부적으로 이 세 단계가 자동으로 수행되고, 최종 답만 돌려받는 형태입니다.
왜 이게 더 효과적할까?
세 가지 이유가 있습니다:
- AI는 자신이 잘하는 일에만 집중: 논리 설계와 코딩은 AI의 강점입니다. 언어 모델이 코드 작성에 탁월하다는 것은 이미 증명되었습니다. (GPT-4가 소프트웨어 엔지니어 시험에 합격하는 이유)
- 계산 오류가 원천 차단: Python 인터프리터나 JavaScript 엔진 같은 전용 도구는 수학 연산에서 실수하지 않습니다. 50번을 반복하든 1억 번을 반복하든, 결과는 정확합니다.
- 디버깅이 쉬워집니다: 코드 형태이므로, 만약 잘못된 결과가 나왔다면 ‘어느 부분의 로직이 잘못됐는지’ 명확하게 추적할 수 있습니다.
3. 실제 비교: CoT vs PoT
예시: 50번째 피보나치 수열 계산
❌ CoT 방식
프롬프트: "50번째 피보나치 수를 단계별로 풀어서 구해줄래?
첫 번째부터 차례대로 계산하면서 과정을 보여줘."
응답 예시:
"첫 번째: 0
두 번째: 1
세 번째: 0+1=1
네 번째: 1+1=2
다섯 번째: 1+2=3
...
(중략)
50번째: [부정확한 숫자]"
결과: 정확도 약 30~50%. 특히 제로샷(시범 없이) 환경에서는 더 떨어집니다.
✅ PoT 방식
프롬프트: "50번째 피보나치 수를 구하는 Python 코드를 작성해줄래?
그 코드를 실행해서 정확한 답을 구해줄 거야."
응답 예시:
"알겠습니다. 여기 50번째 피보나치 수를 구하는 코드입니다:
fib = [0, 1]
for i in range(2, 50):
fib.append(fib[i-1] + fib[i-2])
ans = fib[49] # 50번째 (인덱스는 0부터)
print(ans)"
실행 결과: 12,586,269,025"
결과: 정확도 99% 이상. 논리만 올바르면, 계산은 항상 정확합니다.
복잡한 금융 계산 예시
더 복잡한 예시를 보겠습니다. “월 10만원씩 20년을 연 8% 복리로 저축하면, 최종 금액은?”이라는 질문이요.
❌ CoT 방식
텍스트로 공식을 설명하고, 대략적인 숫자를 적용하지만,
소수점 이하 자릿수에서 오류 발생.
특히 "복리 복리" 부분에서 단계마다 미세한 실수가 쌓입니다.
✅ PoT 방식
monthly_deposit = 100000
annual_rate = 0.08
monthly_rate = annual_rate / 12
months = 240 # 20년 × 12개월
future_value = 0
for month in range(months):
future_value = future_value * (1 + monthly_rate) + monthly_deposit
print(f"최종 금액: {future_value:,.0f}원")
결과: 정확한 금액이 나옵니다. 금융 데이터셋(FinQA)에서 PoT는 CoT 대비 20% 이상의 성능 향상을 보였습니다.
4. 연구 데이터로 본 성능 비교
실제 논문의 실험 결과는 어땠을까요?
GSM8K 데이터셋 (수학 문제)
초등학교 ~ 중학교 수준의 문제 1,319개를 테스트한 결과:
| 방식 | 정확도 | 개선도 |
|---|---|---|
| 기본 모델 | ~40% | — |
| CoT (Chain of Thoughts) | ~72% | +32% |
| PoT (Program of Thoughts) | ~84% | +12% (vs CoT) |
FinQA 데이터셋 (금융 계산)
금융 뉴스와 표에서 숫자를 추출하여 계산하는 테스트:
| 방식 | 정확도 |
|---|---|
| CoT | ~62% |
| PoT | ~88% |
해석: 특히 금융처럼 정확한 수치가 중요한 분야에서 PoT의 우위가 압도적입니다.
제로샷(Zero-shot) 환경에서의 차이
흥미로운 지점은, 시범 예제를 주지 않은 ‘제로샷’ 환경에서도 PoT가 더 강하다는 것입니다.
- CoT 제로샷: ~55% (시범이 없으면 ‘단계별 풀이’ 패턴이 약해집니다)
- PoT 제로샷: ~80% (코드 문법만 맞으면, 논리가 더 명확합니다)
이는 “‘말로 푸는 것’보다 ‘코드로 설계하는 것’이 문제 해결의 본질에 더 가깝다”는 뜻입니다.
5. 실전: PoT를 직접 사용해보기
프롬프트 공식
PoT를 효과적으로 사용하려면, 프롬프트 구조가 중요합니다. 다음과 같이 작성하세요:
"다음 문제를 Python 코드로 풀어줄래?
[문제 설명]
코드를 작성한 뒤, 그 코드가 정확하게 실행되는지 확인해서 최종 답을 알려줄래?"
핵심: “코드를 작성해달라”는 요청과 “그 코드를 실행해서 답을 알려달라”는 요청을 명확하게 분리합니다.
실전 예시 1: 이자 계산
프롬프트:
"초기 자본 10만원으로 매년 8% 복리로 10년간 저축하면 최종 금액은?
Python 코드로 계산해주고, 그 코드를 실행해서 정확한 답을 알려줄래?"
ChatGPT 응답:
principal = 100000
rate = 0.08
years = 10
final_amount = principal * (1 + rate) ** years
print(f"최종 금액: {final_amount:,.0f}원")
# 실행 결과: 최종 금액: 215,892원
실전 예시 2: 복잡한 조건 계산
프롬프트:
"A 회사 제품 구매: 5만원
- 첫 1개 구매 시 20% 할인
- 5개 이상 구매 시 추가 10% 할인 (누적)
- 배송료 2천원 (5만원 이상 무료)
12개를 샀을 때 총 결제액은? Python 코드로 계산해줄래?"
응답:
unit_price = 50000
quantity = 12
discount1 = 0.20 # 첫 구매 할인
discount2 = 0.10 # 대량 할인
shipping = 2000
price_after_discount1 = unit_price * (1 - discount1) * quantity
final_price = price_after_discount1 * (1 - discount2)
if final_price >= 50000:
final_price += 0
else:
final_price += shipping
print(f"총 결제액: {final_price:,}원")
# 결과: 총 결제액: 432,000원
주의사항
- 코드 문법이 100% 정확해야 합니다. AI가 문법 오류를 내면, 그 코드는 실행할 수 없습니다.
- 로직 검증이 필요합니다. 코드 문법이 맞아도 논리가 잘못되면 답은 틀립니다. “이 코드가 맞는지 한번 더 확인해줄래?”라고 물어보세요.
- 간단한 질문에는 과할 수 있습니다. “미국의 수도는?”같은 상식 질문에 코드는 불필요합니다. PoT는 계산과 반복 논리가 필요한 문제에 효과적합니다.
6. 한계와 미래 전망
PoT도 완벽한 해결책은 아닙니다.
현재의 한계
- 코드 생성 오류: AI가 프로그래밍 문법을 모두 완벽하게 구현하지는 못합니다. 특히 복잡한 알고리즘은 여전히 실수가 있을 수 있습니다.
- 외부 데이터베이스 접근 불가: 실시간 주식 데이터, 날씨 정보 등 외부 API를 호출해야 하는 경우, 현재 LLM만으로는 어렵습니다.
- 모든 도구를 갖춰야 합니다: 코드를 실행할 Python 인터프리터나 JavaScript 엔진이 필요합니다. (하지만 이는 클라우드 환경에서 쉽게 해결됩니다)
앞으로의 방향
현재 OpenAI의 ChatGPT-4o나 Google의 Gemini 같은 최신 모델들은 이미 ‘코드 인터프리터’ 기능을 내장하고 있습니다. 즉, AI가 코드를 작성하기만 하면 자동으로 실행하고 결과를 반영하는 형태로 진화하고 있습니다.
미래에는 사용자가 “이걸 코드로 풀어줄래?”라고 명시하지 않아도, AI 자체가 “이 문제는 논리적 설계가 필요하니 코드로 접근하자”고 자동으로 판단할 수 있을 겁니다.
7. 결론: AI의 미래는 ‘역할 분담’
PoT의 핵심은 매우 간단합니다:
“AI는 논리 설계를 담당하고, 컴퓨터는 계산을 담당하자.”
이것은 단순한 기술의 개선이 아닙니다. 인간과 기계의 협력 방식을 다시 정의하는 것입니다.
인간이 손으로 직접 글자를 쓰지 않고 타이핑 기계를 쓰듯이, 우리도 이제 LLM이 추론만 하고 계산은 외부 도구에 맡기는 방식으로 일하게 될 겁니다.
다음번에 ChatGPT에게 복잡한 계산을 물을 때, 다음과 같이 프롬프트를 조정해보세요:
"이걸 단계별로 설명해줄래?" (❌ 구식)
vs
"이걸 Python 코드로 풀어주고,
그 코드를 실행해서 정확한 답을 알려줄래?" (✅ 신식)
그 차이를 직접 경험하게 될 겁니다.
