Program-Aided Language Models: 모델에게 직접 수학 문제를 풀게 하지 마세요
요약
언어 모델의 취약한 산술 연산 능력을 해결하기 위해 모델이 직접 계산하는 대신 실행 가능한 프로그램을 작성하게 하는 PAL(Program-Aided Language Models) 기법을 소개합니다. 모델은 추론 로직을 코드로 작성하고, 실제 계산은 외부 인터프리터에 위임하여 정확성과 결정론적 결과를 보장합니다.
핵심 포인트
- LLM은 토큰 예측 방식의 한계로 인해 복잡한 산술 연산에서 오류를 범함
- PAL은 추론(방법론)과 계산(수치)을 분리하여 모델의 약점을 보완함
- 모델이 Python 코드를 생성하면 실제 인터프리터가 실행하여 정확한 값을 산출
- 결과가 결정론적이며, 생성된 코드를 통해 논리적 검증이 용이함
언어 모델에게 "strawberry"라는 단어에 알파벳 "r"이 몇 번 나오는지 물어보면, 두 번이라고 답할 가능성이 꽤 높습니다. $2,500를 연이율 7%로 8년 동안 복리로 계산해 달라고 요청하면, 모델은 조용히 단리로 전환하여 $4,295.47 대신 $3,900를 내놓을 수도 있습니다. 추론 과정은 괜찮게 들릴지 모르지만, 숫자는 틀렸습니다. 그리고 모델은 어느 쪽이든 똑같이 자신만만합니다.
이것은 프롬프트(prompt)만으로 해결할 수 있는 버그가 아닙니다. 왜냐하면 이것은 모델의 본질적인 특성에 내재되어 있기 때문입니다. 언어 모델은 다음 **토큰 (token)**을 예측합니다. 모델이 1234 × 5678 =이라고 쓸 때, 모델은 곱셈을 수행하는 것이 아닙니다. 훈련 과정에서 본 모든 데이터를 바탕으로 가장 가능성 높은 숫자 토큰 시퀀스를 추측하는 것입니다. 그 밑바탕에는 올림(carry) 로직도, 자릿수(place value) 개념도, 실제 산술 연산도 없습니다. 그저 그럴듯해 보이는 숫자, 즉 길이는 맞고 앞자리 숫자는 믿음직스럽지만, 결과는 틀린 숫자를 얻게 될 뿐입니다. 정확한 계산, 세심한 장부 기록, 또는 개수 세기가 필요한 모든 작업은 모델의 가장 취약한 지점에 정면으로 맞닥뜨리게 됩니다.
**Program-Aided Language Models (PAL)**는 한 가지 방법으로 이 문제를 해결합니다. 모델에게 정답을 묻지 말고, _프로그램 (program)_을 작성하라고 요청하는 것입니다.
🖩 대화형 데모 (CoT는 산술에서 실수하지만, PAL의 코드는 브라우저에서 실제로 실행됩니다): https://dev48v.infy.uk/prompt/day27-pal.html
코드로 추론하고, 런타임에서 계산하라
일반적인 Chain-of-Thought (CoT)는 모델이라는 하나의 시스템에 매우 다른 두 가지 작업, 즉 _방법 (method)_을 도출하는 것과 _숫자 (numbers)_를 계산하는 것을 동시에 요구합니다. 방법론 부분은 모델이 매우 잘 수행합니다. 하지만 숫자 계산은 모델이 가장 못하는 부분입니다. 따라서 단 한 번의 곱셈 실수만으로도 otherwise(그렇지 않았다면) 건전했을 추론 과정 전체가 오염됩니다.
PAL은 이 두 가지 작업을 분리합니다. 모델은 여전히 추론을 수행합니다. 어떤 수치가 중요한지 결정하고, 이를 변수(variable)로 명명하며, 이들을 결합하는 연산을 작성합니다. 하지만 최종 숫자를 말하는 대신, 짧은 프로그램을 생성하고 멈춥니다. 그런 다음 **실제 인터프리터 (real interpreter)**가 그 프로그램을 실행하여 숫자를 산출합니다.
PAL 방식으로 계산하는 복리:
principal = 2500
rate = 0.07
for y in range(8):
...
모델은 1.07**8을 계산한 적이 없습니다. 모델은 그것을 계산하는 _방법 (how)_을 설명했고, 산술 연산은 Python이 수행하도록 했습니다. 이것이 핵심 비결입니다. 모델이 잘하지 못하는 부분을 구조적으로 정확할 수밖에 없는 시스템에 위임하는 것입니다.
이것이 매우 잘 작동하는 이유
결정론적 (deterministic)입니다. 인터프리터는 매번 동일한 값을 반환합니다. 샘플링(sampling), 온도(temperature), 드리프트(drift)가 없습니다. 한 번을 실행하든 백 번을 실행하든, 결과는 4295.47입니다.
검증 가능 (verifiable)합니다. 잘못된 사고 사슬 (Chain-of-Thought)은 일일이 수동으로 다시 확인해야 하는 긴 산문 덩어리입니다. 반면 잘못된 PAL 프로그램은 특정 라인의 버그입니다. 코드를 읽거나, 단위 테스트 (unit-test)를 하거나, 명세 (spec)와 비교(diff)하거나, 새로운 입력값으로 실행하여 방법론이 일반화되는지 확인할 수 있습니다.
모델이 조금 부주의하더라도 결과는 맞을 수 있습니다. 코드 내의 _방법 (method)_이 타당하기만 하다면, 정확한 산술 연산은 하류 (downstream) 단계에서 처리됩니다. 이는 머릿속으로 모든 곱셈을 정확히 해내는 것보다 훨씬 낮은 문턱입니다.
PAL을 '사슬이 실행 가능한 사고 사슬 (Chain-of-Thought)'이라고 생각하십시오. 추론의 골격(문제를 단계별로 나누는 것)은 동일하지만, 그 단계가 코드이며 실제로 무언가가 그것을 실행합니다.
이것은 사실상 도구 사용 (tool use)입니다
ReAct 패턴이나 함수 호출 (function calling)을 본 적이 있다면, PAL이 친숙하게 느껴질 것입니다. 이는 도구가 코드 인터프리터이고 모델의 "행동 (action)"이 프로그램을 생성하는, 도구 사용의 구체적이고 강력한 사례입니다. 이것은 현대적인 코드 인터프리터 기능이 작동하는 방식과 정확히 일치합니다. 모델이 Python을 작성하면, 샌드박스 (sandbox)가 이를 실행하고, 결과가 돌아옵니다. 이런 관점에서 보면 PAL은 에이전트 (agents)로 바로 연결됩니다. 깔끔하게 계산 가능한 모든 하위 작업(수학, 날짜 산술, 파싱, 집계 등)에 대해, 에이전트는 머릿속으로 계산하는 대신 코드 도구를 사용합니다. 일반화하자면 간단합니다. 계산할 수 있는 것에 대해 추론하지 말고, 그냥 계산하십시오.
주의점: 모델이 작성한 코드를 실행한다는 것
PAL은 모델이 생성한 텍스트를 실행하는 것을 의미하므로, 이를 신뢰할 수 없는 입력(untrusted input)으로 취급해야 합니다. 절대로 완전한 권한을 가진 귀하의 프로세스 내에서 eval을 사용하지 마십시오. 악의적이거나 조작된 프로그램은 비밀 정보를 읽거나, 네트워크에 접속하거나, 파일을 삭제하거나, 무한 루프를 돌 수 있습니다. 파일 시스템이나 네트워크 접근이 차단되고, 메모리 제한(memory cap)과 엄격한 타임아웃(hard timeout)이 설정된 격리된 샌드박스(sandbox) — 즉, 잠금 처리된 서브프로세스(subprocess), 컨테이너(container), 또는 제한된 VM(Virtual Machine) — 에서 실행하십시오. 오직 출력값(output)만을 캡처하십시오.
또한 PAL에는 한계가 있습니다. PAL은 문제가 코드로서 _정형화(formalised)_될 수 있는 경우, 즉 수학, 논리, 변환, 날짜, 계산, 데이터 조작과 같은 경우에만 도움이 됩니다. 취향, 판단력, 또는 진정으로 개방형인 질문(open-ended questions)에는 아무런 도움이 되지 않습니다. 또한 잘못된 계획으로부터 당신을 구해줄 수도 없습니다. 만약 모델이 잘못된 공식을 선택한다면, 인터프리터(interpreter)는 틀린 답을 매우 정확하고 자신 있게 계산할 것입니다. PAL은 산술적 실수(arithmetic slips)를 제거하는 것이지, 추론적 실수(reasoning slips)를 제거하는 것이 아닙니다.
기억하기 쉬운 경험 법칙(rule of thumb)은 다음과 같습니다. 만약 계산기나 다섯 줄짜리 스크립트로 해결할 수 있는 문제라면, 모델이 그 스크립트를 작성하게 하십시오. 그리고 수학에 능숙한 기계가 수학을 계산하게 하십시오.
데모에서 세 가지 문제를 모두 직접 체험해 보세요: https://dev48v.infy.uk/prompt/day27-pal.html
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기