생각의 나무(Tree of Thought, ToT) 프롬프팅은 여러분이 종이 위에서 문제를 풀 듯 언어 모델이 문제를 풀게 합니다. 가능한 다음 단계를 몇 개 적고, 어느 것이 유망해 보이는지 판단하고, 그것을 이어 가고, 막다른 가지는 버리는 것입니다. 이 아이디어는 Yao 등의 2023년 논문 "Tree of Thoughts: Deliberate Problem Solving with Large Language Models"에서 나왔습니다. 추론 한 줄기를 따라가는 생각의 사슬(CoT) 프롬프팅을 여러 줄기에 대한 탐색으로 확장한 것입니다.
이 페이지는 원래 방법의 원리를 설명하고, ChatGPT, Claude, Gemini에서 써 볼 수 있는 프롬프트 하나짜리 버전을 주고, 프롬프트 하나로 부족할 때를 위해 코드로 된 반복문을 보여 줍니다.
생각의 나무의 원리
논문은 이 방법을 네 가지 결정으로 나눕니다.
- 무엇을 생각 하나로 볼 것인가. 생각 하나는 중간 단계 하나로, 모델이 잘 만들어 낼 만큼 작고 판단할 수 있을 만큼 큽니다. 수학 퍼즐에서는 식 하나이고, 글쓰기 작업에서는 짧은 계획 하나입니다.
- 생각을 어떻게 만들 것인가. 현재의 부분 해답에서 모델이 다음 단계 후보를 여러 개 제안합니다. 독립적으로 샘플링하거나 답변 하나에 나열하는 방식입니다.
- 어떻게 평가할 것인가. 모델에게 각 부분 해답을 평가하게 합니다. 논문은 두 가지 방식을 썼습니다. 각 상태에 따로 점수를 매기거나(예: "확실함", "가능성 있음", "불가능"), 여러 상태를 보여 주고 가장 좋은 것에 투표하게 하는 방식입니다.
- 어떻게 탐색할 것인가. 프로그램이 단계마다 가장 좋은 상태 몇 개를 남기거나(너비 우선 탐색), 한 가지를 깊이 따라가다가 평가가 가망 없다고 하면 되돌아갑니다(깊이 우선 탐색).
논문의 24 게임 과제를 예로 들어 보겠습니다. 숫자 4, 9, 10, 13을 한 번씩, 사칙연산으로 써서 24를 만드는 문제입니다. 생각의 사슬은 첫 번째 식을 정하면 그것을 안고 가야 합니다. 생각의 나무는 첫 단계로 13 - 9 = 4, 10 - 4 = 6, 4 + 9 = 13을 시도해 보고, 남은 숫자로 여전히 24를 만들 수 있는지 모델에게 묻고, 막다른 길(10, 13, 13으로는 24를 만들 수 없음)을 버리고, (10 - 4) * (13 - 9) = 24에 도달할 수 있습니다.
논문이 보여 준 것
저자들은 GPT-4가 생각의 사슬을 써도 어려워한 과제 세 가지를 골랐습니다. 각각 계획이나 탐색이 필요한 과제로, 24 게임, 마지막 문장이 정해진 창작 글쓰기, 5x5 미니 십자말풀이입니다. GPT-4에서 트리 탐색은 생각의 사슬 프롬프팅이나 사슬 여러 개를 샘플링해 다수결로 고르는 방법보다 24 게임 퍼즐을 훨씬 많이 풀었고, 다른 두 과제에서도 더 좋은 결과를 냈습니다.
대가는 호출 수입니다. 후보 단계 하나하나와 평가 하나하나가 별도의 요청이므로, 생각의 사슬이면 호출 한 번이면 될 문제 하나를 푸는 데 수십 번의 모델 호출이 들 수 있습니다. 이 거래는 어려운 문제에서는 말이 되고, 간단한 문제에서는 전혀 말이 안 됩니다.
프롬프트 하나로 하는 생각의 나무
메시지 하나로 이 아이디어를 근사할 수 있습니다. 서로 다른 접근법 여러 개, 주어진 사실에 비춘 각각의 판정, 그리고 살아남은 것만 발전시키라고 요청하는 것입니다. 아래 탭은 같은 문제를 두 가지 방식으로 보냅니다.
주된 원인은 호주와 프랑크푸르트 서버 사이의 물리적 거리입니다. 모든 요청이 유럽까지 갔다 와야 하고, 페이지를 로드할 때마다 요청이 40개씩 있으니 그 지연이 쌓입니다.
표준적인 해결책은 CDN(콘텐츠 전송 네트워크)입니다. CDN은 전 세계 서버에 사이트 사본을 두어서, 호주 사용자가 프랑크푸르트가 아니라 가까운 곳에서 내려받게 합니다. 대부분의 제공사는 코드를 바꾸지 않고 기존 사이트 앞에 CDN을 둘 수 있게 해 줍니다.
이미지를 압축하고 브라우저 캐싱을 켜면 로딩 시간을 더 줄일 수 있습니다.
바로 한 답이 터무니없지는 않습니다. 요청 40개도 세었지만, 들어맞는 첫 번째 설명("거리")을 골라 그대로 밀고 나갔습니다. 가지를 친 답은 각 설명을 프롬프트의 세부 사항과 대조했고, 그래서 "호주"보다 "하나씩 차례로"가 더 중요하다는 것, CDN으로는 API 호출이 그대로 남는다는 것을 알아챘습니다.
재사용할 수 있는 템플릿
같은 구조가 설계 선택과 계획에도 통합니다. 문제와 중요하게 여기는 기준을 채워 넣으세요. 답변은 기본값을 채운 결과입니다.
PaaS (관리형 앱 호스팅) 비용: 중간, 트래픽에 따라 오름. 설정: Git 저장소로 한 시간 이내. 유지 보수: 낮음, 호스트가 OS 패치를 함. 유지.
직접 운영하는 가상 서버 비용: 가장 낮음. 설정: 서버, TLS, 프로세스 관리자에 하루. 유지 보수: 높음, 업데이트와 재시작을 직접 해야 함. 3명 팀에는 탈락.
서버리스 함수 비용: 소규모에서는 매우 낮음. 설정: 중간, 기존 서버 앱을 재구성해야 할 수 있음. 유지 보수: 낮음, 하지만 콜드 스타트로 지연이 생김. 차선책으로 유지.
최선: PaaS. 첫 단계:
- start 스크립트를 추가하고 포트를 환경 변수에서 읽게 한다.
- 비밀 값을 호스트의 환경 설정으로 옮긴다.
- 저장소를 연결하고 main 브랜치를 배포한다.
- 헬스 체크 엔드포인트를 추가한다.
- 지출 알림을 설정한다.
프롬프트 하나짜리 버전의 한계
프롬프트 하나짜리 버전은 이 방법의 용어는 유지하지만 장치 대부분을 잃습니다.
- 진짜 되돌아가기가 없습니다. 모델은 모든 가지와 판정을 한 번에 씁니다. 선택한 가지의 3단계가 실패해도 1단계로 돌려보내는 것이 없습니다.
- 심판이 곧 작성자입니다. 아이디어를 제안한 바로 그 답변이 채점까지 하므로, 이미 염두에 둔 가지를 편드는 경향이 있습니다. 논문에서 평가는 후보가 만들어진 뒤에 하는 별도의 호출입니다.
- 가지들이 독립적이지 않습니다. 답변 하나에 나열된 아이디어들은 서로 영향을 주고, 결국 한 주제의 변형이 되는 경우가 많습니다. 템플릿처럼 "서로 확실히 다른" 접근법을 요청하면 이를 막는 데 도움이 되지만 완전히 없애지는 못합니다.
- 추론 모델은 이미 가지를 칩니다. 답하기 전에 생각하는 모델은 내부적으로 접근법을 시도하고 버립니다. 이런 모델에서 이 프롬프트가 더하는 정확도는 작고, 남는 가치는 탈락한 선택지를 볼 수 있고 그 추론에 이의를 제기할 수 있다는 것입니다.
코드로 진짜 트리 탐색 실행하기
완전한 방법은 프로그램 안의 반복문입니다. 후보 단계를 만들고, 각 부분 해답에 별도 호출로 점수를 매기고, 가장 좋은 몇 개를 남기고, 반복합니다. 아래는 OpenAI Python SDK로 만든 최소한의 너비 우선 버전이고, 어떤 제공사든 같은 모양으로 동작합니다.
from openai import OpenAI
client = OpenAI()
MODEL = "your-model-id" # e.g. from your provider's model list
def ask(prompt, temperature=0.7):
response = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": prompt}],
temperature=temperature,
)
return response.choices[0].message.content.strip()
def propose(problem, path, k=3):
steps = "\n".join(path) or "(none yet)"
prompt = f"Problem: {problem}\nSteps so far:\n{steps}\nPropose the next step only."
return [ask(prompt) for _ in range(k)]
def score(problem, path):
steps = "\n".join(path)
prompt = (f"Problem: {problem}\nPartial solution:\n{steps}\n"
"How likely is this to lead to a correct solution? Reply with a number from 1 to 10 only.")
try:
return float(ask(prompt, temperature=0))
except ValueError:
return 0.0
def tree_of_thought(problem, depth=3, keep=2):
frontier = [[]]
for _ in range(depth):
candidates = [path + [step] for path in frontier for step in propose(problem, path)]
candidates.sort(key=lambda p: score(problem, p), reverse=True)
frontier = candidates[:keep]
return frontier[0]
depth=3, keep=2, 상태당 제안 세 개로 한 번 실행하면 호출이 30번쯤 일어납니다. 많은 작업에서는 자기 일관성 프롬프팅(완성된 답 여러 개, 다수결)이나 프롬프트 체이닝의 고정된 단계 순서가 더 적은 호출로 이점 대부분을 얻습니다. 작업에 탐색이 필요할 때, 즉 가능한 첫수가 많고 막다른 길을 일찍 알아볼 방법이 있을 때 트리를 쓰세요.
자주 묻는 질문
생각의 나무 프롬프팅이란 무엇인가요?
생각의 나무 프롬프팅은 모델이 가능한 다음 단계를 여러 개 제안하고, 각각이 얼마나 유망한지 평가하고, 가장 좋은 가지만 이어 가며, 가지가 실패하면 되돌아가는 문제 해결 방법입니다. Yao 등의 2023년 논문 "Tree of Thoughts: Deliberate Problem Solving with Large Language Models"에서 나왔습니다. 논문에서는 모델을 여러 번 호출하는 프로그램이 가지치기와 점수 매기기를 실행합니다.
생각의 나무와 생각의 사슬은 어떻게 다른가요?
생각의 사슬은 처음부터 끝까지 추론 한 줄기를 따라가므로 초반의 실수가 답까지 이어집니다. 생각의 나무는 여러 부분 해답을 동시에 살려 두고, 평가하고, 약한 것을 버리므로 잘못된 첫 단계에서 회복할 수 있습니다. 대가는 훨씬 많은 모델 호출입니다.
ChatGPT나 Claude에서 생각의 나무를 쓸 수 있나요?
근사한 버전은 쓸 수 있습니다. 여러 접근법을 나열하고, 여러분의 기준으로 각각을 판단하고, 약한 것을 버리고, 가장 좋은 것을 발전시키라고 요청하는 프롬프트 하나입니다. 어떤 채팅 앱에서든 통합니다. 다만 모든 것이 답변 하나 안에서 일어나고, 아이디어를 쓴 바로 그 과정에서 모델이 자기 아이디어를 채점하므로 완전한 방법은 아닙니다.
추론 모델에서도 생각의 나무 프롬프팅이 쓸모 있나요?
예전보다는 덜합니다. 답하기 전에 생각하는 모델은 이미 내부적으로 접근법을 시도하고 버리므로, 가지를 치라고 요청해도 더해지는 것이 적습니다. 그래도 선택지와 그것이 탈락한 이유를 보고 싶을 때, 그래서 판단을 직접 확인하고 싶을 때는 프롬프트 하나짜리 버전이 여전히 쓸모 있습니다.
생각의 나무 프롬프팅은 언제 써야 하나요?
그럴듯한 접근법이 여러 개이고 첫 아이디어가 틀리는 경우가 많은 문제에 쓰세요. 계획, 설계 선택, 증상으로 문제 진단하기, 탐색이 필요한 퍼즐 같은 것들입니다. 경로가 하나뿐인 뻔한 질문이라면 평범한 생각의 사슬이 더 싸고 결과도 똑같이 좋습니다.