0Pricing
AI Prompt Engineering · 강의

사고 트리 탐색

사고를 분기하고 평가하기

사고 트리 탐색은(는) CoddyKit의 무료 AI Prompt Engineering 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Prompt Engineering 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Prompt Engineering 강의에는 총 4개의 강의가 포함되어 있습니다.

연쇄에서 트리로

사고 트리(ToT, Yao et al., 2023)는 사고 연쇄를 하나의 선형 경로에서 부분 해답으로 이루어진 탐색 트리로 일반화합니다. 각 노드는 일관된 중간 사고이며, 가지는 서로 다른 후속 과정을 탐색합니다.

이를 통해 모델은 숙고할 수 있습니다. 여러 다음 단계를 생성하고, 이를 평가하며, 가능성이 높은 단계는 유지하고, 막다른 길에서는 되돌아옵니다. 즉, 첫 번째 아이디어를 바로 선택하는 대신 체계적인 문제 해결을 모방합니다.

class ThoughtNode:
    def __init__(self, state, parent=None):
        self.state = state      # partial solution / reasoning so far
        self.parent = parent
        self.children = []
        self.value = None       # evaluator score

ToT의 네 가지 구성 요소

ToT 시스템에는 네 가지 설계 선택이 있습니다. 사고 분해(단계란 무엇인가), 사고 생성기(다음 단계를 제안하는 방법), 상태 평가기(부분 해답을 평가하는 방법), 탐색 알고리즘(BFS, DFS 또는 최우선 탐색)입니다.

각 요소는 별도의 프롬프트나 정책입니다. ToT를 설계한다는 것은 작업에 맞게 네 가지를 모두 지정한다는 뜻입니다.

tot = {
    'decompose': step_definition,   # e.g. one equation, one move
    'generate':  propose_thoughts,  # sampling or proposal prompt
    'evaluate':  score_state,        # value/vote prompt
    'search':    bfs_with_beam,      # BFS | DFS | best-first
}

후보 사고 생성하기

생성 전략은 두 가지입니다. 적당한 온도에서 서로 독립적인 사고를 여러 개 샘플링하거나(탐색 공간이 풍부할 때 적합), 하나의 프롬프트에서 서로 다른 다음 단계를 여러 개 제안할 수 있습니다(명시적으로 다른 선택지를 원할 때 적합).

분기 수는 작게 유지하십시오(대개 3~5개). 후보가 너무 많으면 탐색량과 비용이 폭발적으로 증가합니다.

def propose_thoughts(state, k=4):
    prompt = (
        'Given the partial solution below, propose ' + str(k) +
        ' DISTINCT possible next steps.\n' + state
    )
    return parse_list(llm(prompt, temperature=0.7))

상태 평가하기

상태 평가기가 ToT를 무작위 샘플링 이상의 방법으로 만들어 줍니다. 상태 평가기는 부분 해답이 얼마나 가능성 높은지 점수로 나타냅니다. 값 프롬프트(문제 해결에 얼마나 가까운지 이 상태를 1~10으로 평가)나 투표 프롬프트(이 상태들 중 어느 것이 가장 가능성이 높은지)를 사용할 수 있습니다.

후보 간 투표는 절대적인 점수 매기기보다 더 견고한 경우가 많습니다. 모델은 상대적인 판단을 더 쉽게 내리기 때문입니다.

def score_state(state):
    prompt = (
        'Rate how likely this partial solution leads to a correct '
        'final answer. Reply sure / likely / impossible.\n' + state
    )
    label = llm(prompt, temperature=0).strip().lower()
    return {'sure': 1.0, 'likely': 0.5, 'impossible': 0.0}.get(label, 0.3)

빔 탐색을 사용하는 BFS

너비 우선 ToT는 경계에 있는 모든 노드를 한 번에 한 수준씩 확장한 다음, 평가기 점수가 가장 높은 상위 b개만 빔으로 유지합니다. 이렇게 하면 여러 경로를 병렬로 탐색하면서 탐색량의 폭발을 제한할 수 있습니다.

빔 너비 b는 탐색 범위와 비용을 맞바꿉니다. 구조화된 퍼즐에서는 너비 5, 깊이 3부터 시작하는 것이 일반적입니다.

def bfs_with_beam(root, depth, branch, beam):
    frontier = [root]
    for _ in range(depth):
        nxt = []
        for node in frontier:
            for t in propose_thoughts(node.state, branch):
                child = ThoughtNode(node.state + '\n' + t, node)
                child.value = score_state(child.state)
                nxt.append(child)
        frontier = sorted(nxt, key=lambda n: -n.value)[:beam]
    return max(frontier, key=lambda n: n.value)

백트래킹을 사용하는 DFS

깊이 우선 ToT는 가능성이 가장 높은 가지를 따라 깊이 들어가며, 평가기가 상태를 가망 없다고 판단하면 백트래킹합니다. 제약 퍼즐처럼 실행 불가능한 부분 상태를 명확히 판단할 수 있는 문제에 적합합니다.

불가능한 가지를 조기에 가지치기하는 것이 가장 큰 효율 개선 효과를 냅니다. 실패할 하위 트리를 확장하는 데 드는 낭비를 피할 수 있기 때문입니다.

def dfs(node, depth, branch, prune=0.2):
    if depth == 0 or is_solution(node.state):
        return node
    for t in propose_thoughts(node.state, branch):
        child = ThoughtNode(node.state + '\n' + t, node)
        child.value = score_state(child.state)
        if child.value < prune:
            continue                      # backtrack: prune dead end
        res = dfs(child, depth - 1, branch, prune)
        if res and is_solution(res.state):
            return res
    return None

ToT와 자기 일관성 비교

자기 일관성은 독립적인 완성된 연쇄를 샘플링하고 투표합니다. ToT는 중간 평가와 백트래킹을 사용해 탐색을 적극적으로 유도하고, 가능성이 높은 곳에 계산량을 투자합니다.

ToT는 계획 수립이나 탐색이 필요한 문제, 또는 초기 실수가 치명적인 문제(24 게임, 십자말풀이, 계획 수립)에서 뛰어난 성능을 보입니다. 다양성이 높은 연쇄를 저렴하게 생성할 수 있고 답변이 이산적인 작업이라면 자기 일관성이 더 간단하며 대개 충분합니다.

# Rule of thumb
# - reachable by diverse single passes  -> self-consistency
# - needs lookahead / pruning / backtrack -> tree-of-thought
# ToT cost ~ branch * depth * beam * (gen + eval) LLM calls

비용 폭증과 예산

ToT는 비용이 많이 듭니다. 각 노드에서 생성 및 평가 호출이 발생하기 때문입니다. 전체 비용은 대략 분기 수 × 깊이 × 빔 너비에 평가 호출 비용을 더한 만큼 증가합니다. 엄격한 예산이 없으면 비용이 걷잡을 수 없이 커질 수 있습니다.

전체 LLM 호출 수에 상한을 두고, 최우선 탐색으로 가치가 가장 높은 경계에 예산을 사용하며, 예산이 소진되면 가장 좋은 부분 해답으로 대체하십시오.

import heapq

def best_first(root, max_calls):
    heap = [(-root.value, root)]
    best, calls = root, 0
    while heap and calls < max_calls:
        _, node = heapq.heappop(heap)
        for t in propose_thoughts(node.state, 3):
            calls += 1
            child = ThoughtNode(node.state + '\n' + t, node)
            child.value = score_state(child.state); calls += 1
            if child.value > best.value:
                best = child
            heapq.heappush(heap, (-child.value, child))
    return best

평가기의 신뢰성

ToT의 성능은 평가기의 성능을 넘을 수 없습니다. 보정되지 않은 평가기는 올바른 가지를 잘라 내거나 막다른 길을 따라갈 수 있습니다. 상태마다 여러 번 평가하여 투표하게 하거나, 좋은 상태와 나쁜 상태의 퓨샷 예시를 제공하거나, 외부 검증기(단위 테스트, 해답 도구, 검사기)를 사용하여 평가기를 개선하십시오.

객관적인 검사가 가능한 경우(방정식이 성립하는지, 코드가 통과하는지)에는 LLM의 판단보다 그 검사를 우선하십시오.

def robust_eval(state, votes=3):
    scores = [score_state(state) for _ in range(votes)]
    return sum(scores) / votes        # average to reduce judge noise
# Even better: replace with a deterministic verifier when available

실제 적용 가능성

ToT는 범위는 좁지만 가치가 높은 문제 유형에서 효과가 있습니다. 여러 단계의 계획 수립, 조합적 퍼즐, 전체를 해결하는 것보다 한 단계를 검증하는 비용이 저렴한 작업이 이에 해당합니다. 대부분의 일상적인 프롬프트에서는 ToT가 과도합니다.

검색 기능이 강력하게 내장된 추론 특화 모델에서는 명시적인 ToT 구조가 큰 이득 없이 비용만 추가하는 경우가 많습니다. 도입하기 전에 벤치마크하십시오.

def choose_strategy(task):
    if task.requires_search and task.step_verifiable:
        return 'tree-of-thought'
    if task.discrete_answer:
        return 'self-consistency'
    return 'single chain-of-thought'

최소한의 ToT 해결기

처음부터 끝까지 다음과 같이 수행합니다. 단계를 정의하고, 작은 사고 분기를 제안하며, 각각을 평가하고(투표 또는 검증기 사용), 호출 예산 내에서 BFS-빔 또는 DFS-백트래킹으로 탐색한 뒤, 가장 좋은 종단 상태를 반환합니다.

작업별로 분기 수, 깊이, 빔을 경험적으로 조정할 수 있도록 노드 수와 평가기 점수를 기록하십시오.

def solve(problem, branch=4, depth=3, beam=5, budget=200):
    root = ThoughtNode(problem)
    root.value = score_state(root.state)
    node = bfs_with_beam(root, depth, branch, beam)
    return extract_solution(node.state)

빠른 확인

알맞은 숙고 전략을 선택해 보십시오.

복습

핵심 요점:

  • ToT는 CoT를 사고 생성, 상태 평가, 탐색 알고리즘을 갖춘 탐색 트리로 일반화합니다.
  • 빔을 사용하는 BFS 또는 백트래킹을 사용하는 DFS를 사용하고, 탐색량 폭발을 제어할 수 있도록 분기 수를 작게 유지하십시오.
  • 상태 평가기가 핵심입니다. 투표나 외부 검증기로 평가기를 강화하십시오.
  • 비용은 분기 수 × 깊이 × 빔 너비에 따라 증가하므로, 대개 최우선 탐색을 사용하여 호출 예산을 강제하십시오.
  • ToT는 계획 수립이나 조합적이며 단계를 검증할 수 있는 문제에 한정하십시오. 일상적인 프롬프트에는 과도합니다.

자주 묻는 질문

“사고 트리 탐색” 강의는 무료인가요?

네 — “사고 트리 탐색” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Prompt Engineering 강의 전체를 잠금 해제할 수 있습니다. AI Prompt Engineering 강의에는 총 4개의 강의가 포함되어 있습니다.

“사고 트리 탐색”에서 뭘 배우나요?

사고를 분기하고 평가하기 브라우저에서 직접 실행하는 실습 코드로 AI Prompt Engineering을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

AI Prompt Engineering을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 AI Prompt Engineering은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“사고 트리 탐색” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 AI Prompt Engineering 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 AI Prompt Engineering 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 사고 연쇄 프롬프트
  2. 자기 일관성 샘플링
  3. 사고 트리 탐색
  4. 추론 프롬프트가 도움이 되는 경우
← AI Prompt Engineering(으)로 돌아가기