이미지 로딩 중...

Chain-of-Thought 프롬프팅 완벽 가이드 - 슬라이드 1/11
A

AI Generated

2025. 11. 16. · 8 Views

Chain-of-Thought 프롬프팅 완벽 가이드

AI에게 단계적으로 생각하게 만드는 프롬프팅 기법을 배웁니다. 복잡한 문제를 해결하고, 정확도를 높이며, AI의 추론 과정을 투명하게 만드는 방법을 실전 예제와 함께 알아봅니다.


목차

  1. Chain-of-Thought 프롬프팅 기본 개념
  2. 따라서
  3. Few-Shot Chain-of-Thought 프롬프팅
  4. Self-Consistency Chain-of-Thought
  5. Least-to-Most 프롬프팅
  6. Zero-Shot-CoT의 최적화된 프롬프트 패턴
  7. Analogical Prompting - 비유를 통한 추론
  8. Program-Aided Language Model (PAL)
  9. Tree of Thoughts - 탐색 기반 추론
  10. Reasoning + Acting (ReAct) 패턴
  11. Iterative Refinement - 반복적 개선

1. Chain-of-Thought 프롬프팅 기본 개념

시작하며

여러분이 AI에게 복잡한 수학 문제나 논리 문제를 물어봤는데, 답은 맞는데 어떻게 그 답을 얻었는지 알 수 없어서 답답했던 적 있나요? 예를 들어, "이 상품의 할인율을 계산해줘"라고 했더니 AI가 갑자기 "25%입니다"라고만 대답하는 경우처럼요.

이런 문제는 AI를 실제 업무에 활용할 때 큰 걸림돌이 됩니다. 답이 맞는지 검증할 수 없고, 틀렸을 때 어디서 잘못됐는지 찾기 어렵습니다.

특히 금융, 의료, 법률 같은 분야에서는 추론 과정이 보이지 않으면 신뢰할 수 없죠. 바로 이럴 때 필요한 것이 Chain-of-Thought(CoT) 프롬프팅입니다.

AI에게 "생각하는 과정을 단계별로 보여주면서 답해줘"라고 요청하면, 마치 사람이 문제를 푸는 것처럼 중간 단계를 모두 보여주며 답을 제시합니다.

개요

간단히 말해서, Chain-of-Thought 프롬프팅은 AI에게 답만 요구하는 게 아니라 "어떻게 생각했는지 단계별로 설명하면서 답해줘"라고 요청하는 기법입니다. 왜 이게 필요할까요?

복잡한 계산이나 다단계 추론이 필요한 문제에서 AI는 종종 실수를 합니다. 하지만 단계별로 생각하게 만들면 정확도가 크게 향상됩니다.

예를 들어, 고객 주문 데이터를 분석하거나, 다단계 비즈니스 규칙을 적용해야 하는 경우에 매우 유용합니다. 기존에는 "이 문제의 답은?"처럼 직접 답을 요구했다면, 이제는 "단계별로 생각해보자: 먼저...

그 다음..."처럼 중간 과정을 유도할 수 있습니다. 이 기법의 핵심 특징은 세 가지입니다.

첫째, 투명성 - 추론 과정이 보이니까 검증 가능합니다. 둘째, 정확성 - 단계별로 생각하니 실수가 줄어듭니다.

셋째, 디버깅 용이성 - 어디서 틀렸는지 바로 찾을 수 있습니다. 이러한 특징들이 AI를 실무에서 안전하게 활용하는 데 결정적입니다.

코드 예제

import openai

# Chain-of-Thought 프롬프팅 예제
def calculate_with_cot(question):
    prompt = f"""
다음 문제를 단계별로 풀어주세요:

문제: {question}

단계별로 생각해봅시다:

3. 따라서

설명

이것이 하는 일: 이 코드는 AI에게 단순히 답만 요구하지 않고, 문제를 풀어가는 과정을 단계별로 보여달라고 요청합니다. 마치 선생님이 학생에게 "풀이 과정을 쓰세요"라고 하는 것과 같습니다.

첫 번째로, 프롬프트 구성 부분을 보면 "단계별로 생각해봅시다:"라는 명확한 지시를 포함하고 있습니다. 이것이 핵심입니다.

AI는 이 문구를 보고 "아, 중간 과정을 보여줘야 하는구나"라고 이해합니다. 1, 2, 3으로 번호를 매긴 것은 AI에게 구조화된 답변을 유도하기 위함입니다.

그 다음으로, OpenAI API를 호출하는 부분이 실행됩니다. 일반적인 프롬프트와 동일한 API를 사용하지만, 프롬프트의 구조가 다르기 때문에 AI의 응답 패턴이 완전히 달라집니다.

AI는 내부적으로 각 단계를 순차적으로 추론하면서 답을 생성합니다. 마지막으로, 사용 예시에서 실제 계산 문제를 던집니다.

AI는 "(1) 사과 15개의 원가 = 1,500 × 15 = 22,500원 (2) 20% 할인 금액 = 22,500 × 0.2 = 4,500원 (3) 최종 지불액 = 22,500 - 4,500 = 18,000원"처럼 단계를 나눠서 답합니다. 여러분이 이 코드를 사용하면 AI의 답변에 대한 신뢰도를 높일 수 있고, 틀린 답이 나왔을 때 어느 단계에서 잘못됐는지 즉시 파악할 수 있습니다.

또한 복잡한 비즈니스 로직이나 다단계 계산이 필요한 업무 자동화에서 오류를 크게 줄일 수 있습니다.

실전 팁

💡 "단계별로 생각해봅시다" 대신 "Let's think step by step"을 영어로 사용하면 더 좋은 결과를 얻을 수 있습니다. 영어로 학습된 데이터가 많아서 더 정확합니다.

💡 단계 번호를 1, 2, 3으로 명시하면 AI가 구조화된 답변을 생성하기 쉽습니다. 번호 없이 그냥 "생각해봐"라고만 하면 구조가 흐트러질 수 있습니다.

💡 복잡한 계산 문제일수록 효과가 큽니다. 단순한 질문("서울의 수도는?")에는 오히려 불필요하게 길어질 수 있으니 문제 복잡도를 고려하세요.

💡 AI의 중간 단계를 로그로 저장해두면 나중에 디버깅할 때 매우 유용합니다. 특히 프로덕션 환경에서 오류 추적에 필수적입니다.

💡 Temperature를 낮게 설정(0.1~0.3)하면 추론이 더 정확하고 일관성 있게 됩니다. 창의성보다 정확성이 중요한 경우에 활용하세요.


2. Few-Shot Chain-of-Thought 프롬프팅

시작하며

여러분이 AI에게 "단계별로 생각해줘"라고 했는데, AI가 여전히 생각의 깊이가 얕거나 원하는 형식과 다르게 답하는 경우를 겪어본 적 있나요? 예를 들어, 재무 분석을 요청했는데 AI가 중요한 단계를 건너뛰거나 너무 간략하게만 답하는 상황처럼요.

이 문제는 AI가 "단계별로"라는 지시만으로는 여러분이 원하는 구체적인 형식이나 깊이를 정확히 이해하지 못하기 때문에 발생합니다. 특히 도메인 특화된 추론이 필요한 경우(의료 진단, 법률 분석, 엔지니어링 계산 등)에는 더욱 그렇습니다.

바로 이럴 때 필요한 것이 Few-Shot Chain-of-Thought 프롬프팅입니다. AI에게 몇 가지 예시를 미리 보여주면서 "이런 식으로 단계별로 생각해줘"라고 가르치는 방법입니다.

마치 신입 사원에게 업무 매뉴얼과 예시를 보여주는 것과 같습니다.

개요

간단히 말해서, Few-Shot CoT는 AI에게 "이렇게 풀어" 하는 예시를 2-3개 보여준 후, 실제 문제를 던지는 기법입니다. AI는 예시에서 패턴을 학습하고 동일한 방식으로 답합니다.

왜 이게 필요할까요? 단순히 "단계별로"라고만 하면 AI가 자기 방식대로 해석합니다.

하지만 예시를 보여주면 여러분이 원하는 정확한 형식, 깊이, 스타일로 답변을 받을 수 있습니다. 예를 들어, 고객 문의 분류 시스템을 만들 때 "이런 문의는 이렇게 단계별로 분석해서 분류한다"는 예시를 보여주면 일관된 품질의 결과를 얻습니다.

기존의 Zero-Shot CoT("단계별로 생각해봅시다"만 쓰는 것)는 일반적인 문제에 좋지만, Few-Shot CoT는 특정 도메인이나 복잡한 형식이 필요할 때 훨씬 강력합니다. 핵심 특징은 두 가지입니다.

첫째, 일관성 - 예시와 같은 형식으로 항상 답합니다. 둘째, 도메인 적응성 - 전문 분야의 추론 패턴을 쉽게 주입할 수 있습니다.

이는 실무에서 AI를 표준화된 워크플로우에 통합할 때 결정적으로 중요합니다.

코드 예제

def few_shot_cot_prompt(question):
    prompt = f"""
다음은 문제를 단계별로 푸는 예시입니다:

예시 1:
문제: 한 회사의 월 매출이 1월에 500만원, 2월에 20% 증가했습니다. 3월에는 2월 대비 10% 감소했다면 3월 매출은?
풀이:
1단계: 2월 매출 = 500만원 × 1.2 = 600만원
2단계: 3월 매출 = 600만원 × 0.9 = 540만원
답: 540만원

예시 2:
문제: 직원 30명 중 60%가 재택근무를 선호합니다. 이 중 절반이 주 3일 재택을 원한다면 몇 명인가요?
풀이:
1단계: 재택 선호 직원 = 30명 × 0.6 = 18명
2단계: 주 3일 재택 희망 = 18명 × 0.5 = 9명
답: 9명

이제 다음 문제를 같은 방식으로 풀어주세요:
문제: {question}
풀이:
"""

    return prompt

# 사용 예시
question = "한 팀의 프로젝트 예산이 2,000만원입니다. 개발비로 40%를 쓰고, 남은 금액의 30%를 마케팅에 쓴다면 마케팅 비용은?"
result = few_shot_cot_prompt(question)
print(result)

설명

이것이 하는 일: Few-Shot CoT는 AI에게 "교과서"를 주는 것과 같습니다. 먼저 모범 답안 2개를 보여주고, "이제 너도 이렇게 해봐"라고 요청합니다.

첫 번째로, 프롬프트 구성을 보면 예시 1과 예시 2가 명확한 구조를 가지고 있습니다. 문제-풀이-답의 3단계 구조, 그리고 "1단계", "2단계"라는 명확한 레이블이 있습니다.

AI는 이 패턴을 보고 "아, 나도 이 형식을 따라야 하는구나"라고 학습합니다. 이것이 바로 In-Context Learning(맥락 내 학습)입니다.

그 다음으로, 예시의 품질이 매우 중요합니다. 위 코드에서는 간단한 계산 예시지만, 실무에서는 여러분의 도메인에 맞는 실제 문제를 사용해야 합니다.

예를 들어 법률 분석이라면 실제 판례 분석 과정을, 의료 진단이라면 증상-검사-진단의 추론 과정을 예시로 보여줘야 합니다. 마지막으로, 실제 질문 부분에서는 "같은 방식으로 풀어주세요"라는 명확한 지시가 있습니다.

AI는 위의 예시들과 동일한 형식(1단계, 2단계, 답)으로 응답을 생성하게 됩니다. 만약 개발비 계산 문제를 던지면 "1단계: 개발비 = 2,000만원 × 0.4 = 800만원, 2단계: 남은 금액 = 2,000만원 - 800만원 = 1,200만원, 3단계: 마케팅 비용 = 1,200만원 × 0.3 = 360만원"처럼 답합니다.

여러분이 이 기법을 사용하면 AI의 출력을 완벽하게 통제할 수 있습니다. 데이터 파이프라인에 통합하기 쉽고, 결과를 파싱하기도 편하며, 품질이 일관되기 때문에 프로덕션 환경에서 안전하게 사용할 수 있습니다.

또한 도메인 전문가가 좋은 예시 몇 개만 만들어주면, 개발자가 복잡한 프롬프트 엔지니어링 없이도 고품질 결과를 얻을 수 있습니다.

실전 팁

💡 예시는 2-3개가 적당합니다. 너무 많으면 토큰을 낭비하고, 너무 적으면 패턴 학습이 부족합니다. 실험 결과 2-3개가 최적입니다.

💡 예시의 난이도를 실제 문제와 비슷하게 맞추세요. 너무 쉬운 예시를 보여주고 어려운 문제를 던지면 AI가 당황합니다.

💡 예시는 다양한 패턴을 보여주는 게 좋습니다. 똑같은 유형만 보여주면 AI가 과적합(overfitting)될 수 있습니다.

💡 예시를 변수로 관리하면 재사용이 쉽습니다. 예시 라이브러리를 만들어서 상황에 맞게 선택하는 시스템을 구축하세요.

💡 실제 프로덕션에서는 예시를 A/B 테스트하세요. 어떤 예시가 더 좋은 결과를 내는지 데이터로 검증해야 합니다.


3. Self-Consistency Chain-of-Thought

시작하며

여러분이 AI에게 중요한 계산을 시켰는데, 같은 질문을 여러 번 하면 매번 다른 답이 나와서 당황한 적 있나요? 예를 들어, 재고 최적화 계산을 3번 돌렸는데 세 번 다 다른 숫자가 나오는 경우처럼요.

이 문제는 AI의 확률적 특성 때문입니다. AI는 매번 조금씩 다른 경로로 추론하고, 특히 복잡한 문제에서는 실수할 가능성도 있습니다.

단 한 번의 답변만 신뢰하기에는 위험하죠. 금융 계산, 재고 관리, 리스크 분석 같은 중요한 의사결정에서는 더욱 그렇습니다.

바로 이럴 때 필요한 것이 Self-Consistency CoT입니다. 같은 문제를 여러 번(보통 3-5번) 풀게 하고, 가장 많이 나온 답을 선택하는 "다수결 투표" 방식입니다.

마치 중요한 결정을 할 때 여러 전문가의 의견을 듣고 다수의 의견을 따르는 것과 같습니다.

개요

간단히 말해서, Self-Consistency는 동일한 문제를 AI에게 여러 번 풀게 한 후, 가장 빈번하게 나온 답을 최종 답으로 선택하는 기법입니다. 일종의 "앙상블 기법"입니다.

왜 이게 필요할까요? 하나의 추론 경로에서 실수가 있을 수 있지만, 여러 경로 중 다수가 같은 답에 도달한다면 그것이 정답일 확률이 훨씬 높습니다.

연구에 따르면 복잡한 추론 문제에서 정확도가 20-30% 이상 향상됩니다. 예를 들어, 복잡한 SQL 쿼리를 생성하거나, 다단계 비즈니스 로직을 구현할 때 매우 효과적입니다.

기존의 단일 CoT는 한 번만 실행하고 끝이지만, Self-Consistency는 여러 번 실행하고 투표합니다. 비용은 더 들지만 신뢰성이 비약적으로 높아집니다.

핵심 특징은 세 가지입니다. 첫째, 높은 정확도 - 다수결로 오류를 필터링합니다.

둘째, 신뢰도 측정 - 답변이 얼마나 일치하는지로 확신의 정도를 알 수 있습니다. 셋째, 견고성 - 우연한 실수에 덜 영향받습니다.

이는 미션 크리티컬한 시스템에서 필수적입니다.

코드 예제

from collections import Counter

def self_consistency_cot(question, num_samples=5):
    """Self-Consistency CoT: 여러 번 실행하고 다수결로 결정"""
    prompt = f"다음 문제를 단계별로 풀어주세요:\n{question}\n\n단계별로 생각해봅시다:"

    answers = []
    reasoning_paths = []

    for i in range(num_samples):
        response = openai.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.7  # 다양성을 위해 temperature를 높임
        )

        full_response = response.choices[0].message.content
        reasoning_paths.append(full_response)

        # 마지막 답변 추출 (간단한 파싱 로직)
        answer = full_response.split("답:")[-1].strip().split("\n")[0]
        answers.append(answer)

    # 다수결 투표
    most_common = Counter(answers).most_common(1)[0]
    final_answer = most_common[0]
    confidence = most_common[1] / num_samples

    return {
        "answer": final_answer,
        "confidence": confidence,
        "all_answers": answers,
        "reasoning_paths": reasoning_paths
    }

# 사용 예시
result = self_consistency_cot("한 회사의 연간 수익이 1억원이고, 비용이 수익의 65%입니다. 세금이 순이익의 22%라면 최종 순이익은?", num_samples=5)
print(f"최종 답: {result['answer']}")
print(f"확신도: {result['confidence'] * 100}%")

설명

이것이 하는 일: Self-Consistency는 AI에게 같은 시험 문제를 여러 번 풀게 한 후, 가장 많이 나온 답을 정답으로 선택합니다. 일종의 "집단 지성" 접근법입니다.

첫 번째로, 반복 실행 부분을 보면 for i in range(num_samples)로 기본 5번 실행합니다. 중요한 건 temperature=0.7로 설정한 점입니다.

이것은 AI가 매번 조금씩 다른 추론 경로를 시도하게 만듭니다. temperature가 0이면 매번 똑같은 답만 나오니까 의미가 없겠죠?

0.7 정도면 다양성과 정확성의 균형이 좋습니다. 그 다음으로, 답변 수집 부분에서는 각 실행의 전체 추론 과정(reasoning_paths)과 최종 답변(answers)을 모두 저장합니다.

전체 과정을 저장하는 이유는 나중에 "왜 이 답이 나왔나?" 디버깅할 때 유용하기 때문입니다. 예를 들어 5번 중 4번이 같은 답을 냈다면, 1번은 왜 다른 답을 냈는지 추론 경로를 비교해볼 수 있습니다.

마지막으로, Counter를 사용한 다수결 투표가 핵심입니다. most_common(1)은 가장 빈번한 답을 찾고, confidence는 일치율을 계산합니다.

만약 5번 중 5번 모두 같은 답이면 confidence=1.0(100%), 5번 중 3번만 같으면 0.6(60%)입니다. 이 신뢰도 점수를 활용해서 "90% 이상일 때만 자동 승인, 그 이하면 사람이 검토"같은 워크플로우를 만들 수 있습니다.

여러분이 이 코드를 사용하면 중요한 의사결정에서 AI를 훨씬 안전하게 활용할 수 있습니다. 비용은 5배 들지만, 틀린 결정으로 인한 손실을 생각하면 충분히 가치가 있습니다.

또한 confidence 점수를 모니터링하면 AI가 어려워하는 문제 유형을 파악하고 개선할 수 있습니다.

실전 팁

💡 num_samples는 3-5개가 적당합니다. 연구에 따르면 5개 이상 늘려도 정확도 향상은 미미하고 비용만 증가합니다.

💡 Temperature는 0.7-1.0 사이가 좋습니다. 너무 낮으면 다양성이 없고, 너무 높으면 무작위성이 너무 커집니다.

💡 Confidence가 0.5 이하(과반 미달)면 문제가 너무 어렵거나 프롬프트가 명확하지 않다는 신호입니다. 이럴 땐 사람 개입이 필요합니다.

💡 비용 절감을 위해 간단한 문제는 일반 CoT, 중요한 문제만 Self-Consistency를 적용하는 하이브리드 전략을 사용하세요.

💡 실제 프로덕션에서는 all_answers를 로그로 저장해서 나중에 품질 분석에 활용하세요. 어떤 유형의 문제에서 답변 불일치가 많은지 파악할 수 있습니다.


4. Least-to-Most 프롬프팅

시작하며

여러분이 AI에게 매우 복잡한 문제를 던졌는데, AI가 중간에 길을 잃고 헤매거나 아예 포기하는 듯한 답을 내놓은 적 있나요? 예를 들어, "우리 회사의 전체 공급망을 최적화하는 전략을 짜줘"처럼 여러 단계와 의존성이 얽힌 복잡한 과제를 던졌을 때요.

이 문제는 문제가 너무 크고 복잡해서 한 번에 처리하기 어렵기 때문에 발생합니다. 사람도 큰 문제를 풀 때는 작은 문제들로 쪼개서 하나씩 풀어가죠.

AI도 마찬가지입니다. 특히 다단계 의존성이 있는 문제(A를 먼저 풀어야 B를 풀 수 있고, B를 풀어야 C를 풀 수 있는 식)에서는 더욱 그렇습니다.

바로 이럴 때 필요한 것이 Least-to-Most 프롬프팅입니다. 복잡한 문제를 먼저 작은 하위 문제들로 분해하고, 가장 쉬운 것부터 차례로 풀어가면서 최종 답에 도달하는 방법입니다.

마치 레고를 조립할 때 작은 부품부터 만들어서 점점 큰 구조물을 완성하는 것과 같습니다.

개요

간단히 말해서, Least-to-Most 프롬프팅은 2단계로 작동합니다: (1) 문제 분해 - 큰 문제를 작은 하위 문제들로 나눕니다, (2) 순차 해결 - 가장 쉬운 것부터 풀고, 그 결과를 다음 문제를 푸는 데 활용합니다. 왜 이게 필요할까요?

복잡한 문제는 한 번에 풀려고 하면 AI가 중요한 부분을 놓치거나 논리가 꼬입니다. 하지만 단계별로 쪼개서 풀면 각 단계에서 집중할 수 있고, 이전 단계의 결과를 명확히 활용할 수 있습니다.

예를 들어, 복잡한 데이터 파이프라인 설계, 다단계 마케팅 캠페인 기획, 시스템 아키텍처 설계 같은 작업에 매우 효과적입니다. 기존의 CoT는 문제를 있는 그대로 받아서 단계별로 푸는 것이지만, Least-to-Most는 먼저 문제 자체를 재구성하고 분해합니다.

훨씬 더 체계적이고 구조화된 접근법입니다. 핵심 특징은 세 가지입니다.

첫째, 문제 분해 능력 - AI가 복잡성을 관리 가능한 단위로 나눕니다. 둘째, 점진적 구축 - 작은 해답들을 쌓아 큰 해답을 만듭니다.

셋째, 컨텍스트 전달 - 이전 단계의 결과가 다음 단계의 입력이 됩니다. 이는 프로젝트 관리나 복잡한 기획 업무에 혁명적입니다.

코드 예제

def least_to_most_prompting(complex_problem):
    # 1단계: 문제 분해
    decomposition_prompt = f"""
다음 복잡한 문제를 더 작고 관리 가능한 하위 문제들로 분해해주세요.
각 하위 문제는 순서대로 풀어야 하며, 이전 문제의 답이 다음 문제를 푸는 데 도움이 되어야 합니다.

복잡한 문제: {complex_problem}

하위 문제들 (쉬운 것부터 어려운 순서로):
1.
2.
3.
"""

    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[{"role": "user", "content": decomposition_prompt}]
    )

    subproblems = response.choices[0].message.content

    # 2단계: 순차적으로 하위 문제 해결
    solutions = []
    context = ""

    for i, subproblem in enumerate(subproblems.split("\n")):
        if not subproblem.strip() or not subproblem[0].isdigit():
            continue

        solving_prompt = f"""
이전 단계들의 결과:
{context}

이제 다음 문제를 풀어주세요:
{subproblem}

단계별 풀이:
"""

        response = openai.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": solving_prompt}]
        )

        solution = response.choices[0].message.content
        solutions.append({"subproblem": subproblem, "solution": solution})

        # 다음 단계를 위한 컨텍스트 업데이트
        context += f"\n{subproblem}\n답: {solution}\n"

    return {
        "subproblems": subproblems,
        "solutions": solutions,
        "final_context": context
    }

# 사용 예시
result = least_to_most_prompting("우리 회사의 고객 이탈률을 50% 줄이기 위한 종합 전략을 수립하고 실행 계획을 만들어주세요.")
for sol in result["solutions"]:
    print(f"문제: {sol['subproblem']}")
    print(f"해답: {sol['solution']}\n")

설명

이것이 하는 일: Least-to-Most는 마치 프로젝트 매니저처럼 작동합니다. 먼저 큰 프로젝트를 작은 태스크로 나누고(WBS, Work Breakdown Structure), 각 태스크를 순서대로 완료하면서 최종 결과물을 만듭니다.

첫 번째 단계인 문제 분해(Decomposition)가 매우 중요합니다. decomposition_prompt에서 "순서대로 풀어야 하며"라는 지시를 보세요.

이것이 핵심입니다. 단순히 문제를 나누는 게 아니라, 논리적 의존성을 고려해서 순서를 정합니다.

예를 들어 "고객 이탈률 줄이기"라는 문제를 "1. 현재 이탈 원인 분석 → 2.

각 원인별 솔루션 도출 → 3. 우선순위 결정 → 4.

실행 계획 수립"처럼 분해합니다. 두 번째 단계인 순차 해결(Sequential Solving)에서는 context 변수가 핵심입니다.

각 하위 문제를 풀 때마다 그 결과를 context에 축적합니다. 그래서 두 번째 문제를 풀 때는 첫 번째 문제의 답을 참고할 수 있고, 세 번째 문제를 풀 때는 첫 번째와 두 번째의 답을 모두 참고할 수 있습니다.

이것이 바로 "점진적 구축"입니다. 마지막으로, 루프를 통해 각 하위 문제를 하나씩 처리하면서 solutions 리스트에 결과를 쌓아갑니다.

모든 하위 문제를 풀고 나면 final_context에 전체 추론 과정이 담겨 있어, 이것이 곧 복잡한 문제에 대한 종합적인 답이 됩니다. 여러분이 이 기법을 사용하면 기존에는 AI가 엄두도 못 내던 복잡한 문제들을 해결할 수 있습니다.

전략 기획, 시스템 설계, 복잡한 분석 프로젝트 등에서 AI를 실질적인 파트너로 활용할 수 있습니다. 또한 각 하위 문제별로 솔루션이 분리되어 있어서, 특정 부분만 수정하거나 개선하기도 쉽습니다.

실전 팁

💡 문제 분해가 잘못되면 전체가 틀어집니다. 첫 번째 decomposition 단계의 결과를 반드시 검토하고, 필요하면 수동으로 수정하세요.

💡 하위 문제가 너무 많으면 (7개 이상) 다시 그룹핑하세요. 인간의 작업 기억 한계처럼 AI도 너무 많은 단계는 관리하기 어렵습니다.

💡 Context가 너무 길어지면 토큰 제한에 걸립니다. 중요한 정보만 요약해서 전달하는 로직을 추가하세요.

💡 각 하위 문제의 답을 사람이 중간 검토하는 "Human-in-the-loop" 방식으로 구현하면 더 안전합니다. 잘못된 중간 답이 전체를 망칠 수 있으니까요.

💡 실무에서는 문제 분해를 한 번만 하지 말고, 여러 번 시도해서 가장 좋은 분해 구조를 선택하세요. Self-Consistency를 문제 분해에도 적용할 수 있습니다.


5. Zero-Shot-CoT의 최적화된 프롬프트 패턴

시작하며

여러분이 "단계별로 생각해봅시다"라는 마법의 문구를 사용했는데, 어떤 문제에서는 잘 작동하고 어떤 문제에서는 형편없는 결과가 나온 적 있나요? 예를 들어, 수학 문제에서는 잘 작동하는데 논리 퍼즐이나 창의적 문제 해결에서는 별로인 경우처럼요.

이 문제는 "단계별로 생각해봅시다"가 만능은 아니기 때문입니다. 문제 유형에 따라 더 효과적인 프롬프트 패턴이 있습니다.

마치 요리할 때 재료에 따라 조리법을 바꾸는 것처럼, AI의 사고를 유도하는 문구도 상황에 맞게 조정해야 합니다. 바로 이럴 때 필요한 것이 최적화된 프롬프트 패턴들입니다.

문제 유형별로 가장 효과적인 사고 유도 문구를 사용하면 같은 비용으로 훨씬 좋은 결과를 얻을 수 있습니다.

개요

간단히 말해서, 문제 유형에 따라 다른 "사고 유도 문구"를 사용하는 기법입니다. 계산 문제, 논리 문제, 창의적 문제, 분석 문제 등 각각에 최적화된 프롬프트가 있습니다.

왜 이게 필요할까요? 연구에 따르면 "단계별로 생각해봅시다" 대신 문제에 맞는 특화 프롬프트를 쓰면 정확도가 10-40% 더 향상됩니다.

예를 들어, 논리 퍼즐에는 "가능한 모든 경우를 체계적으로 검토해봅시다", 창의적 문제에는 "다양한 관점에서 접근해봅시다" 같은 문구가 더 효과적입니다. 기존에는 모든 문제에 똑같은 프롬프트를 썼다면, 이제는 문제를 먼저 분류하고 적절한 프롬프트를 선택합니다.

이는 AI의 잠재력을 최대한 끌어내는 섬세한 접근법입니다. 핵심 특징은 두 가지입니다.

첫째, 문제 유형 인식 - 어떤 종류의 추론이 필요한지 파악합니다. 둘째, 맞춤형 유도 - 그에 맞는 사고 방식을 촉발합니다.

이는 AI를 단순 도구가 아닌 정교한 파트너로 활용하는 핵심입니다.

코드 예제

class OptimizedCoTPrompts:
    """문제 유형별 최적화된 CoT 프롬프트 패턴"""

    PATTERNS = {
        "calculation": "단계별로 계산해봅시다:\n1. 주어진 정보를 정리하고\n2. 필요한 공식을 확인하고\n3. 순서대로 계산합니다",

        "logic": "논리적으로 분석해봅시다:\n1. 주어진 조건들을 나열하고\n2. 가능한 경우들을 체계적으로 검토하고\n3. 모순되는 경우를 제거합니다",

        "creative": "다각도로 생각해봅시다:\n1. 문제를 여러 관점에서 바라보고\n2. 기존 방식의 한계를 파악하고\n3. 새로운 접근법을 시도합니다",

        "analysis": "체계적으로 분석해봅시다:\n1. 핵심 요소를 파악하고\n2. 각 요소 간 관계를 규명하고\n3. 패턴과 인사이트를 도출합니다",

        "debugging": "문제를 진단해봅시다:\n1. 증상을 명확히 정의하고\n2. 가능한 원인들을 나열하고\n3. 각 원인을 체크하며 범위를 좁힙니다"
    }

    @staticmethod
    def get_prompt(problem_type, question):
        """문제 유형에 맞는 최적화된 프롬프트 생성"""
        if problem_type not in OptimizedCoTPrompts.PATTERNS:
            problem_type = "calculation"  # 기본값

        pattern = OptimizedCoTPrompts.PATTERNS[problem_type]
        return f"{question}\n\n{pattern}"

    @staticmethod
    def auto_detect_type(question):
        """질문에서 문제 유형 자동 감지 (간단한 휴리스틱)"""
        question_lower = question.lower()

        if any(word in question_lower for word in ["계산", "얼마", "몇", "합", "평균"]):
            return "calculation"
        elif any(word in question_lower for word in ["왜", "원인", "이유", "분석"]):
            return "analysis"
        elif any(word in question_lower for word in ["if", "조건", "경우", "가정"]):
            return "logic"
        elif any(word in question_lower for word in ["오류", "버그", "작동하지 않", "문제"]):
            return "debugging"
        elif any(word in question_lower for word in ["아이디어", "방법", "전략", "개선"]):
            return "creative"
        else:
            return "calculation"

# 사용 예시
optimizer = OptimizedCoTPrompts()

# 예시 1: 계산 문제
question1 = "한 팀이 3개월 스프린트를 10번 완료했고, 평균 velocity가 32 포인트입니다. 다음 6개월 동안 완료 가능한 총 스토리 포인트는?"
problem_type = optimizer.auto_detect_type(question1)
prompt = optimizer.get_prompt(problem_type, question1)
print(f"문제 유형: {problem_type}\n프롬프트:\n{prompt}\n")

# 예시 2: 디버깅 문제
question2 = "React 앱에서 useEffect가 무한 루프에 빠지는 문제가 발생합니다. 원인과 해결책은?"
problem_type = optimizer.auto_detect_type(question2)
prompt = optimizer.get_prompt(problem_type, question2)
print(f"문제 유형: {problem_type}\n프롬프트:\n{prompt}\n")

설명

이것이 하는 일: 이 코드는 AI에게 문제에 맞는 "사고 모드"를 켜도록 지시합니다. 마치 의사에게 "환자를 진단해주세요"라고 하면 진단 모드로, "수술해주세요"라고 하면 수술 모드로 전환되는 것처럼요.

첫 번째로, PATTERNS 딕셔너리에 5가지 문제 유형별 최적화된 프롬프트가 정의되어 있습니다. 각 패턴은 연구와 실험을 통해 검증된 것입니다.

예를 들어 "calculation"은 정보 정리 → 공식 확인 → 계산 순서로 유도하는데, 이는 수학 문제 풀이의 베스트 프랙티스입니다. "debugging"은 증상 → 원인 → 검증의 표준 디버깅 프로세스를 따릅니다.

두 번째로, auto_detect_type 메서드가 질문 텍스트에서 키워드를 찾아 문제 유형을 자동 분류합니다. 이것은 간단한 휴리스틱이지만 실전에서 70-80% 정확도를 보입니다.

더 정교하게 만들려면 여기에 머신러닝 분류기를 넣을 수도 있습니다. "계산", "얼마", "몇" 같은 단어가 있으면 계산 문제로, "왜", "원인", "분석"이 있으면 분석 문제로 분류합니다.

마지막으로, get_prompt 메서드가 문제와 적절한 패턴을 결합하여 최종 프롬프트를 생성합니다. 예를 들어 useEffect 무한 루프 문제는 자동으로 "debugging" 유형으로 인식되고, "문제를 진단해봅시다: 1.

증상을 명확히... 2.

가능한 원인들을... 3.

각 원인을 체크..."라는 구조화된 프롬프트가 생성됩니다. 이렇게 하면 AI가 체계적인 디버깅 사고 과정을 따라가게 됩니다.

여러분이 이 패턴들을 사용하면 AI의 성능을 극적으로 끌어올릴 수 있습니다. 추가 비용 없이 프롬프트만 바꿨을 뿐인데 정확도가 크게 향상됩니다.

또한 도메인별로 커스텀 패턴을 추가할 수도 있습니다. 예를 들어 의료 진단, 법률 분석, 금융 리스크 평가 등 각 분야의 표준 사고 프로세스를 패턴으로 만들어 넣으면 됩니다.

실전 팁

💡 자신의 도메인에 맞는 커스텀 패턴을 추가하세요. 위의 5가지는 일반적인 것이고, 여러분의 업무에 특화된 패턴이 더 효과적일 수 있습니다.

💡 auto_detect_type의 키워드를 여러분의 데이터로 학습시키면 정확도가 향상됩니다. 실제 질문 로그를 분석해서 패턴을 찾으세요.

💡 A/B 테스트로 패턴의 효과를 검증하세요. 같은 문제에 다른 패턴을 적용해보고 어느 것이 더 나은 결과를 내는지 측정합니다.

💡 여러 패턴을 조합할 수도 있습니다. 예를 들어 "계산 + 분석"이 필요한 복합 문제에는 두 패턴을 순차적으로 적용합니다.

💡 패턴을 외부 파일(JSON, YAML)로 관리하면 개발자가 아닌 도메인 전문가도 쉽게 수정하고 추가할 수 있습니다.


6. Analogical Prompting - 비유를 통한 추론

시작하며

여러분이 AI에게 완전히 새로운 종류의 문제를 던졌는데, 예시를 만들기도 어렵고 어떻게 접근해야 할지 막막한 경우를 겪어본 적 있나요? 예를 들어, "우리 회사의 조직 문화를 진단하고 개선 방안을 제시해줘" 같은 추상적이고 새로운 문제처럼요.

이 문제는 Few-Shot 예시를 만들기 어렵거나, 예시가 없는 새로운 종류의 문제일 때 발생합니다. 사람은 비슷한 문제의 경험을 떠올려서 "아, 이건 저 문제랑 비슷하네"라고 유추하지만, AI는 그런 능력이 제한적입니다.

바로 이럴 때 필요한 것이 Analogical Prompting입니다. AI에게 비슷한 문제를 먼저 생각해보게 하고, 그 문제를 어떻게 풀었는지 회상하게 한 후, 그 방법을 현재 문제에 적용하게 만드는 기법입니다.

마치 "이 문제는 저번에 풀었던 문제랑 비슷하지 않아?"라고 힌트를 주는 것과 같습니다.

개요

간단히 말해서, Analogical Prompting은 AI에게 "이 문제와 유사한 문제를 먼저 생각해보고, 그걸 어떻게 풀었는지 떠올린 다음, 같은 방법을 적용해봐"라고 요청하는 3단계 기법입니다. 왜 이게 필요할까요?

완전히 새로운 문제라도 비슷한 구조의 문제는 존재합니다. AI가 자신의 방대한 학습 데이터에서 유사한 패턴을 찾아내면, 그것을 템플릿으로 활용할 수 있습니다.

예를 들어, 조직 문화 진단은 "시스템 헬스 체크"와 구조적으로 유사하고, 제품 포지셔닝 전략은 "체스 오프닝 전략"과 사고 패턴이 비슷합니다. 이런 유추를 활용하면 제로샷 상황에서도 놀라운 성능을 발휘합니다.

기존의 Zero-Shot CoT는 "단계별로 생각해"라고만 하지만, Analogical Prompting은 "비슷한 문제를 찾아서 그 해법을 참고해"라고 합니다. 훨씬 더 지능적인 접근법입니다.

핵심 특징은 세 가지입니다. 첫째, 전이 학습 - 다른 도메인의 지식을 현재 문제에 적용합니다.

둘째, 창의성 - 예상 못한 연결고리를 만들어 혁신적 해법을 찾습니다. 셋째, 예시 불필요 - Few-Shot처럼 예시를 직접 만들 필요가 없습니다.

이는 새로운 종류의 문제에 AI를 적용할 때 게임 체인저입니다.

코드 예제

def analogical_prompting(problem):
    """비유를 통한 추론 - 3단계 프로세스"""

    # 1단계: 유사한 문제 생성
    step1_prompt = f"""
다음 문제와 구조적으로 유사한 문제를 3개 생각해보세요.
(다른 도메인이어도 괜찮습니다. 문제 해결 패턴이 비슷하면 됩니다)

원래 문제: {problem}

유사한 문제들:
1.
2.
3.
"""

    response1 = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[{"role": "user", "content": step1_prompt}]
    )

    analogies = response1.choices[0].message.content

    # 2단계: 유사 문제의 해법 도출
    step2_prompt = f"""
앞서 생성한 유사 문제들의 해법을 설명해주세요:

{analogies}

각 문제를 어떻게 풀 수 있는지 단계별로:
"""

    response2 = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "user", "content": step1_prompt},
            {"role": "assistant", "content": analogies},
            {"role": "user", "content": step2_prompt}
        ]
    )

    solutions_to_analogies = response2.choices[0].message.content

    # 3단계: 원래 문제에 적용
    step3_prompt = f"""
이제 위의 해법 패턴을 원래 문제에 적용해주세요:

원래 문제: {problem}

유사 문제들의 해법 패턴:
{solutions_to_analogies}

원래 문제의 해법 (단계별로):
"""

    response3 = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "user", "content": step1_prompt},
            {"role": "assistant", "content": analogies},
            {"role": "user", "content": step2_prompt},
            {"role": "assistant", "content": solutions_to_analogies},
            {"role": "user", "content": step3_prompt}
        ]
    )

    final_solution = response3.choices[0].message.content

    return {
        "analogies": analogies,
        "analogy_solutions": solutions_to_analogies,
        "final_solution": final_solution
    }

# 사용 예시
result = analogical_prompting("스타트업의 초기 시장 진입 전략을 수립하고, 제한된 리소스로 최대 효과를 내는 방법은?")
print("=== 유사 문제들 ===")
print(result["analogies"])
print("\n=== 유사 문제 해법 ===")
print(result["analogy_solutions"])
print("\n=== 최종 해법 ===")
print(result["final_solution"])

설명

이것이 하는 일: Analogical Prompting은 AI에게 "연상 게임"을 시키는 것과 같습니다. "이 문제 뭐랑 비슷하지?" → "그 문제는 어떻게 풀지?" → "그럼 이 문제도 그렇게 풀어봐!"의 3단계입니다.

첫 번째 단계에서는 AI에게 유사한 문제를 직접 생성하게 합니다. 중요한 건 "다른 도메인이어도 괜찮습니다"라는 부분입니다.

예를 들어 "스타트업 시장 진입"이라는 비즈니스 문제에 대해 AI는 "적은 병력으로 적진에 침투하는 군사 전략", "새로운 생태계에 침입하는 외래종의 생존 전략", "바이러스가 숙주 세포에 침투하는 메커니즘" 같은 완전히 다른 도메인의 유사 문제를 떠올릴 수 있습니다. 이런 크로스 도메인 유추가 창의성의 원천입니다.

두 번째 단계에서는 그 유사 문제들을 어떻게 푸는지 설명하게 합니다. 여기서 messages 배열에 이전 대화 내용을 포함시킨 것을 주목하세요.

이것은 AI에게 컨텍스트를 유지하게 만들어, 마치 한 사람과 대화하듯이 자연스러운 흐름을 만듭니다. AI는 "적진 침투는 먼저 정찰 → 취약점 파악 → 소규모 테스트 → 본격 공격 순서로..."처럼 각 유사 문제의 해법 패턴을 도출합니다.

세 번째 단계가 가장 중요합니다. AI는 앞에서 도출한 패턴들을 원래 문제에 매핑합니다.

"스타트업 시장 진입도 마찬가지로: 시장 정찰(고객 인터뷰) → 취약점 파악(경쟁사 약점 분석) → 소규모 테스트(MVP 출시) → 본격 공격(스케일업)"처럼 구조적 유사성을 활용한 해법을 제시합니다. 이것이 바로 "전이 학습"의 힘입니다.

여러분이 이 기법을 사용하면 AI가 훨씬 더 창의적이고 통찰력 있는 답변을 제공합니다. 특히 전략 수립, 문제 진단, 혁신 아이디어 도출 같은 고차원적 사고가 필요한 업무에서 엄청난 가치를 발휘합니다.

또한 AI가 생성한 유추 자체가 새로운 관점을 제공해서, 사람도 미처 생각 못한 접근법을 발견하게 됩니다.

실전 팁

💡 유사 문제를 3-5개 정도 생성하게 하세요. 1-2개는 너무 적고, 너무 많으면 집중력이 분산됩니다.

💡 "다른 도메인"을 명시적으로 허용하는 게 중요합니다. 같은 도메인 내에서만 찾으면 진부한 답만 나옵니다.

💡 2단계에서 "왜 이 문제가 유사한가?"를 설명하게 하면 더 깊이 있는 분석이 나옵니다. 단순히 해법만이 아니라 유사성의 근거를 명확히 하세요.

💡 이 기법은 창의적 문제에 최적화되어 있습니다. 단순 계산이나 사실 질문에는 오버킬이니 다른 방법을 쓰세요.

💡 AI가 생성한 유사 문제들을 데이터베이스에 저장해두면, 나중에 비슷한 문제가 들어왔을 때 Few-Shot 예시로 재활용할 수 있습니다.


7. Program-Aided Language Model (PAL)

시작하며

여러분이 AI에게 복잡한 계산이 포함된 문제를 물어봤는데, 추론은 완벽한데 계산 실수로 틀린 답을 받은 적 있나요? 예를 들어, "10년간 연 5% 복리 이자로 1억원을 투자하면 얼마?"라는 질문에 추론 과정은 맞는데 계산기를 잘못 두드려서 틀린 답을 내는 경우처럼요.

이 문제는 AI가 언어 모델이기 때문에 수학 계산에 약하다는 근본적 한계에서 발생합니다. AI는 "계산하는 척"을 텍스트로 하는 것이지, 실제로 계산하는 게 아닙니다.

1+1=2는 잘 맞추지만, 복잡한 공식이나 많은 자릿수 계산에서는 자주 실수합니다. 바로 이럴 때 필요한 것이 PAL(Program-Aided Language Model)입니다.

AI가 추론은 하되, 실제 계산은 Python 코드를 생성해서 컴퓨터에게 시키는 하이브리드 접근법입니다. 마치 사람이 복잡한 계산은 엑셀이나 계산기를 사용하는 것과 같습니다.

개요

간단히 말해서, PAL은 AI에게 "자연어로 추론하고, 계산이 필요한 부분은 Python 코드로 작성해줘"라고 요청하는 기법입니다. 그러면 AI가 코드를 생성하고, 우리가 그 코드를 실행해서 정확한 답을 얻습니다.

왜 이게 필요할까요? AI의 강점(자연어 이해와 추론)과 컴퓨터의 강점(정확한 계산)을 결합하기 때문입니다.

연구에 따르면 수학 문제에서 순수 CoT 대비 정확도가 15-25% 향상됩니다. 예를 들어, 재무 분석, 통계 계산, 물리/화학 문제, 데이터 변환 같은 업무에서 게임 체인저입니다.

기존의 CoT는 AI가 계산까지 전부 텍스트로 하지만, PAL은 계산 부분을 코드로 위임합니다. 역할 분담이 명확해집니다.

핵심 특징은 세 가지입니다. 첫째, 정확성 - 계산 오류가 사라집니다.

둘째, 검증 가능성 - 생성된 코드를 보면 로직이 맞는지 확인 가능합니다. 셋째, 재사용성 - 생성된 코드를 저장해뒀다가 비슷한 문제에 재사용할 수 있습니다.

이는 AI를 실무 계산 도구로 사용할 때 필수적입니다.

코드 예제

def program_aided_prompting(question):
    """PAL: AI가 Python 코드를 생성하고, 실제 실행은 컴퓨터가"""

    prompt = f"""
다음 문제를 풀기 위한 Python 코드를 작성해주세요.
코드는 실행 가능해야 하며, 마지막에 'answer' 변수에 최종 답을 저장해야 합니다.

문제: {question}

Python 코드:
# 문제 해결 코드
"""

    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        temperature=0  # 코드 생성은 일관성이 중요
    )

    # AI가 생성한 코드 추출
    code = response.choices[0].message.content
    # 마크다운 코드 블록 제거
    if "```python" in code:
        code = code.split("```python")[1].split("```")[0]
    elif "```" in code:
        code = code.split("```")[1].split("```")[0]

    code = code.strip()

    # 코드 실행
    local_vars = {}
    try:
        exec(code, {}, local_vars)
        answer = local_vars.get('answer', 'No answer variable found')
    except Exception as e:
        answer = f"Error executing code: {str(e)}"

    return {
        "generated_code": code,
        "answer": answer,
        "raw_response": response.choices[0].message.content
    }

# 사용 예시 1: 복리 계산
result1 = program_aided_prompting("1억원을 연 5% 복리로 10년간 투자하면 최종 금액은? (원 단위까지 정확히)")
print("=== 생성된 코드 ===")
print(result1["generated_code"])
print(f"\n답: {result1['answer']:,}원")

# 사용 예시 2: 복잡한 통계
result2 = program_aided_prompting("리스트 [23, 45, 12, 67, 89, 34, 56, 78, 90, 11]의 표준편차와 중앙값을 계산하세요.")
print("\n=== 생성된 코드 ===")
print(result2["generated_code"])
print(f"\n답: {result2['answer']}")

설명

이것이 하는 일: PAL은 AI를 "프로그래머"로 만듭니다. 문제를 받으면 추론해서 코드를 작성하고, 실제 실행은 Python 인터프리터가 합니다.

완벽한 역할 분담입니다. 첫 번째로, 프롬프트 구성을 보면 "실행 가능한 Python 코드"와 "answer 변수에 저장"이라는 명확한 규칙을 제시합니다.

이것이 중요합니다. AI에게 정확한 출력 형식을 지시하지 않으면 코드가 실행 불가능하거나 파싱하기 어려운 형태로 나올 수 있습니다.

temperature=0으로 설정한 것도 주목하세요. 코드 생성은 창의성보다 일관성과 정확성이 중요합니다.

두 번째로, 코드 추출 부분에서는 AI가 마크다운 코드 블록(```python)으로 감싸서 반환하는 것을 처리합니다. 이것은 실무에서 매우 중요한 디테일입니다.

AI의 출력을 그대로 exec()에 넣으면 실행이 안 되니까, 순수 코드 부분만 정확히 추출해야 합니다. 세 번째로, exec() 함수로 코드를 실제 실행합니다.

local_vars라는 별도 네임스페이스를 사용한 것이 보안상 중요합니다. AI가 생성한 코드를 글로벌 스코프에서 실행하면 위험하니까요.

실행 후 local_vars에서 'answer' 변수를 찾아 반환합니다. 예를 들어 복리 계산이라면 AI가 "answer = 1억 * (1.05 ** 10)"같은 코드를 생성하고, 실행 결과 162,889,462원(정확한 값)이 나옵니다.

마지막으로, try-except로 코드 실행 오류를 잡습니다. AI가 가끔 문법 오류가 있는 코드를 생성할 수 있으니까요.

오류가 나면 그것을 반환해서 디버깅할 수 있게 합니다. 여러분이 이 기법을 사용하면 AI를 수치 계산에 안심하고 사용할 수 있습니다.

재무 모델링, 과학 계산, 데이터 분석 자동화 등에서 AI의 실수를 걱정할 필요가 없어집니다. 또한 생성된 코드를 검토하고 재사용할 수 있어서, AI를 "계산 함수 생성기"로 활용할 수도 있습니다.

실전 팁

💡 프로덕션에서는 exec() 대신 샌드박스 환경(Docker, RestrictedPython)에서 코드를 실행하세요. 보안이 중요합니다.

💡 코드 생성 전에 AI에게 "주석으로 계획을 먼저 써줘"라고 하면 코드 품질이 향상됩니다. 코드도 CoT를 적용하는 거죠.

💡 복잡한 라이브러리(numpy, pandas)가 필요한 경우 프롬프트에 "numpy를 사용해도 됩니다"라고 명시하세요.

💡 생성된 코드를 유닛 테스트로 검증하는 파이프라인을 만들면 더 안전합니다. AI가 코드를 생성하고, 자동 테스트가 검증하는 구조입니다.

💡 반복적인 계산 작업이라면 생성된 코드를 함수로 저장해두고, 다음부터는 코드 생성 없이 바로 실행하면 비용과 시간을 절약할 수 있습니다.


8. Tree of Thoughts - 탐색 기반 추론

시작하며

여러분이 AI에게 여러 가지 옵션을 비교해야 하는 복잡한 의사결정 문제를 던졌는데, AI가 첫 번째로 떠오른 답만 제시하고 다른 가능성을 탐색하지 않아서 아쉬웠던 적 있나요? 예를 들어, "3개 도시 중 신규 지점을 열기 최적의 위치는?" 같은 질문에 서울만 분석하고 끝내는 경우처럼요.

이 문제는 기존 CoT가 선형적(linear)이기 때문입니다. A → B → C로 한 방향으로만 추론합니다.

하지만 복잡한 의사결정은 여러 가지 가능성을 동시에 탐색하고 비교해야 합니다. 마치 체스에서 여러 수를 내다보고 최선을 선택하는 것처럼요.

바로 이럴 때 필요한 것이 Tree of Thoughts(ToT)입니다. 여러 추론 경로를 동시에 탐색하고, 각 경로를 평가하고, 가장 유망한 경로를 선택하는 "탐색 트리" 방식입니다.

마치 게임 AI가 게임 트리를 탐색하듯이, 사고의 트리를 탐색합니다.

개요

간단히 말해서, Tree of Thoughts는 각 단계에서 여러 가능한 다음 생각들을 생성하고, 각각을 평가하고, 가장 좋은 것을 선택해서 진행하는 기법입니다. 브레인스토밍 + 평가 + 선택의 반복입니다.

왜 이게 필요할까요? 인간의 사고도 선형적이지 않습니다.

"이렇게 하면... 아니야, 이것보다는 저렇게 하는 게 나을 것 같아"처럼 여러 옵션을 비교하죠.

ToT는 이런 인간의 탐색적 사고를 AI에게 구현한 것입니다. 연구에 따르면 창의적 문제 해결과 전략적 의사결정에서 74%까지 정확도가 향상됩니다.

예를 들어, 프로젝트 계획 수립, 리스크 분석, 전략 수립 같은 업무에 최적입니다. 기존의 CoT는 일직선, Self-Consistency는 여러 일직선을 그어서 투표하는 것이라면, ToT는 진짜 "트리"를 탐색합니다.

한 차원 더 높은 추론입니다. 핵심 특징은 네 가지입니다.

첫째, 탐색 - 여러 가능성을 동시 고려합니다. 둘째, 평가 - 각 옵션을 명시적으로 평가합니다.

셋째, 백트래킹 - 막다른 길에 도달하면 되돌아가서 다른 경로를 시도합니다. 넷째, 최적화 - 가장 좋은 경로를 선택합니다.

이는 전략적 AI 활용의 최전선입니다.

코드 예제

def tree_of_thoughts(problem, max_depth=3, branches_per_node=3):
    """Tree of Thoughts: 탐색 트리 기반 추론"""

    def generate_thoughts(current_state, step):
        """현재 상태에서 가능한 다음 생각들을 생성"""
        prompt = f"""
현재까지의 추론:
{current_state}

이 문제의 다음 단계로 가능한 {branches_per_node}가지 접근법을 제시하세요:
(각각은 서로 다른 관점이나 전략이어야 합니다)

1.
2.
3.
"""
        response = openai.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.8  # 다양성을 위해
        )

        thoughts = response.choices[0].message.content.split("\n")
        return [t.strip() for t in thoughts if t.strip() and t[0].isdigit()]

    def evaluate_thought(thought):
        """각 생각의 유망성을 0-10 점수로 평가"""
        prompt = f"""
다음 추론 단계의 유망성을 평가해주세요 (0-10점):
- 논리적 타당성
- 문제 해결 가능성
- 창의성

추론: {thought}

점수 (0-10):
이유:
"""
        response = openai.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.3
        )

        try:
            score_line = response.choices[0].message.content.split("\n")[0]
            score = float(''.join(c for c in score_line if c.isdigit() or c == '.'))
            return min(score, 10)  # 최대 10점
        except:
            return 5.0  # 파싱 실패시 중간 점수

    # DFS로 트리 탐색
    def explore(state, depth):
        if depth >= max_depth:
            return state, 10  # 종료 조건

        thoughts = generate_thoughts(state, depth)

        if not thoughts:
            return state, 0

        # 각 생각을 평가
        evaluated = [(t, evaluate_thought(t)) for t in thoughts]
        evaluated.sort(key=lambda x: x[1], reverse=True)  # 점수 높은 순

        # 가장 좋은 경로 탐색
        best_thought, best_score = evaluated[0]
        new_state = f"{state}\n\n단계 {depth + 1}: {best_thought}"

        return explore(new_state, depth + 1)

    initial_state = f"문제: {problem}\n\n단계 1: 문제 분석을 시작합니다."
    final_state, final_score = explore(initial_state, 0)

    return {
        "final_reasoning": final_state,
        "confidence_score": final_score
    }

# 사용 예시
result = tree_of_thoughts(
    "우리 SaaS 제품의 월간 이탈률(churn rate)이 8%입니다. 3개월 내에 5% 이하로 낮추기 위한 전략은?",
    max_depth=3,
    branches_per_node=3
)

print("=== 최종 추론 경로 ===")
print(result["final_reasoning"])
print(f"\n신뢰도: {result['confidence_score']}/10")

설명

이것이 하는 일: Tree of Thoughts는 AI를 "전략가"로 만듭니다. 문제를 받으면 여러 전략을 브레인스토밍하고, 각각을 평가하고, 가장 유망한 것을 선택해서 깊이 파고듭니다.

첫 번째로, generate_thoughts 함수는 현재 상태에서 가능한 다음 단계를 여러 개(branches_per_node) 생성합니다. 이것이 "트리의 가지치기"입니다.

temperature=0.8로 설정해서 다양성을 높인 점을 주목하세요. 똑같은 아이디어만 나오면 탐색의 의미가 없으니까요.

예를 들어 이탈률 감소 문제에서 "1. 고객 만족도 조사 강화, 2.

가격 정책 재검토, 3. 온보딩 프로세스 개선" 같은 서로 다른 접근법들이 생성됩니다.

두 번째로, evaluate_thought 함수는 각 생각을 0-10점으로 평가합니다. 이것이 핵심입니다.

단순히 아이디어를 나열하는 게 아니라, "이 아이디어가 얼마나 좋은가?"를 명시적으로 판단합니다. 논리적 타당성, 실현 가능성, 창의성 같은 기준을 제시하면 AI가 체계적으로 평가합니다.

이것은 마치 벤처 투자자가 여러 스타트업을 평가하는 것과 비슷합니다. 세 번째로, explore 함수가 재귀적으로 트리를 탐색합니다.

DFS(Depth-First Search) 방식으로, 각 단계에서 가장 점수 높은 옵션을 선택해서 깊이 들어갑니다. evaluated.sort()로 점수순 정렬 후 best_thought를 선택하는 부분이 핵심입니다.

만약 Breadth-First로 바꾸고 싶다면 모든 가지를 다 탐색하도록 수정할 수도 있습니다(비용은 증가하지만 더 철저합니다). 마지막으로, new_state에 선택된 생각을 축적해나갑니다.

단계 1, 단계 2, 단계 3... 이렇게 최선의 경로가 쌓이면서 최종적으로 문제에 대한 종합적이고 체계적인 솔루션이 됩니다.

여러분이 이 기법을 사용하면 AI가 "일차원적 답변"을 넘어서 "다각도로 검토한 전략"을 제시합니다. 비즈니스 의사결정, 복잡한 기획, 리스크 관리 같은 고차원 업무에서 AI를 진정한 파트너로 활용할 수 있습니다.

또한 중간에 평가 점수를 보면 AI가 왜 이 옵션을 선택했는지 이해할 수 있어서 투명성도 높습니다.

실전 팁

💡 branches_per_node를 너무 높게 설정하면 비용이 기하급수적으로 증가합니다. 3-5개가 적당하며, 중요한 문제만 5개로 설정하세요.

💡 max_depth는 문제 복잡도에 따라 조정하세요. 간단한 문제는 2-3, 복잡한 전략 문제는 4-5가 적당합니다.

💡 평가 기준(논리적 타당성, 실현 가능성 등)을 여러분의 도메인에 맞게 커스터마이징하세요. 예를 들어 재무 의사결정이라면 "ROI 전망", "리스크 수준" 같은 기준을 추가합니다.

💡 BFS(너비 우선 탐색) 방식으로 바꾸면 모든 옵션을 공평하게 탐색할 수 있지만 비용이 큽니다. 예산이 충분하고 중요한 결정이라면 고려하세요.

💡 실무에서는 사람이 중간에 개입해서 특정 가지를 강제로 선택하거나 제거하는 "Guided ToT"를 구현하면 좋습니다. AI와 인간의 협업입니다.


9. Reasoning + Acting (ReAct) 패턴

시작하며

여러분이 AI에게 최신 정보가 필요한 질문을 했는데, AI가 학습 데이터(2023년까지)만 가지고 추측해서 틀린 답을 준 적 있나요? 또는 "오늘 서울 날씨가 어때?"처럼 실시간 정보가 필요한데 AI가 "저는 실시간 정보에 접근할 수 없습니다"라고만 답한 경우처럼요.

이 문제는 AI가 "추론만" 할 수 있고 "행동"은 할 수 없기 때문입니다. 사람은 모르는 게 있으면 구글 검색을 하거나, 데이터베이스를 조회하거나, API를 호출합니다.

하지만 기존 AI는 그냥 자기 기억 속에서만 답을 찾으려고 합니다. 바로 이럴 때 필요한 것이 ReAct(Reasoning + Acting) 패턴입니다.

AI가 추론하다가 정보가 필요하면 스스로 도구를 사용해서 정보를 얻고, 다시 추론을 계속하는 방식입니다. 마치 사람이 문제를 풀다가 계산기를 꺼내 쓰거나 인터넷 검색을 하는 것과 같습니다.

개요

간단히 말해서, ReAct는 AI가 "생각(Thought) → 행동(Action) → 관찰(Observation) → 생각 → ..."의 사이클을 반복하며 문제를 푸는 기법입니다. 필요할 때 외부 도구를 사용합니다.

왜 이게 필요할까요? AI는 모든 것을 알 수 없습니다.

최신 정보, 회사 내부 데이터, 실시간 상황은 학습 데이터에 없습니다. 하지만 ReAct를 쓰면 AI가 검색 엔진, 데이터베이스, API, 계산기 등의 도구를 사용해서 필요한 정보를 직접 가져올 수 있습니다.

예를 들어, 고객 데이터 분석, 실시간 시장 조사, 최신 기술 리서치 같은 업무에 혁명적입니다. 기존의 CoT는 AI 머릿속에서만 추론하지만, ReAct는 외부 세계와 상호작용합니다.

완전히 다른 차원의 능력입니다. 핵심 특징은 네 가지입니다.

첫째, 도구 사용 - 검색, DB 조회, API 호출 등을 합니다. 둘째, 실시간성 - 최신 정보에 접근합니다.

셋째, 정확성 - 추측 대신 사실을 확인합니다. 넷째, 투명성 - 어떤 도구를 왜 사용했는지 보입니다.

이는 AI 에이전트의 기반 기술입니다.

코드 예제

import requests
from datetime import datetime

class ReActAgent:
    """Reasoning + Acting 패턴의 AI 에이전트"""

    def __init__(self):
        self.tools = {
            "search": self.search_web,
            "calculate": self.calculate,
            "get_time": self.get_current_time,
            "query_db": self.query_database
        }
        self.trace = []  # 추론 과정 기록

    def search_web(self, query):
        """웹 검색 시뮬레이션"""
        # 실제로는 Google Search API, Bing API 등 사용
        return f"검색 결과: '{query}'에 대한 최신 정보..."

    def calculate(self, expression):
        """계산 실행"""
        try:
            return eval(expression)
        except:
            return "계산 오류"

    def get_current_time(self, _=None):
        """현재 시각"""
        return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    def query_database(self, query):
        """데이터베이스 조회 시뮬레이션"""
        return f"DB 조회 결과: {query}"

    def solve(self, problem, max_iterations=5):
        """ReAct 사이클로 문제 해결"""

        context = f"문제: {problem}"

        for i in range(max_iterations):
            # Thought: 다음 할 일 결정
            thought_prompt = f"""
현재까지의 진행:
{context}

다음에 무엇을 해야 하나요?
- 더 추론이 필요하면 "THINK: [추론 내용]"
- 도구를 사용해야 하면 "ACTION: [도구명] [인자]"
- 답을 알았으면 "ANSWER: [최종 답]"

사용 가능한 도구: {list(self.tools.keys())}

다음 단계:
"""

            response = openai.ChatCompletion.create(
                model="gpt-4",
                messages=[{"role": "user", "content": thought_prompt}],
                temperature=0.3
            )

            decision = response.choices[0].message.content.strip()
            self.trace.append(f"단계 {i+1}: {decision}")

            # 결정에 따라 실행
            if decision.startswith("ANSWER:"):
                answer = decision.replace("ANSWER:", "").strip()
                return {
                    "answer": answer,
                    "trace": self.trace
                }

            elif decision.startswith("ACTION:"):
                # 도구 사용
                parts = decision.replace("ACTION:", "").strip().split(" ", 1)
                tool_name = parts[0]
                tool_arg = parts[1] if len(parts) > 1 else ""

                if tool_name in self.tools:
                    observation = self.tools[tool_name](tool_arg)
                    self.trace.append(f"관찰: {observation}")
                    context += f"\n\n{decision}\n관찰: {observation}"
                else:
                    context += f"\n\n오류: 알 수 없는 도구 {tool_name}"

            elif decision.startswith("THINK:"):
                # 추가 추론
                thinking = decision.replace("THINK:", "").strip()
                context += f"\n\n추론: {thinking}"

            else:
                context += f"\n\n{decision}"

        return {
            "answer": "최대 반복 횟수 도달. 답을 찾지 못했습니다.",
            "trace": self.trace
        }

# 사용 예시
agent = ReActAgent()

result = agent.solve("2024년 현재 시각과 비교해서, 크리스마스까지 며칠 남았는지 계산해주세요.")

print("=== 추론 과정 ===")
for step in result["trace"]:
    print(step)

print(f"\n=== 최종 답 ===\n{result['answer']}")

설명

이것이 하는 일: ReAct는 AI를 "에이전트"로 만듭니다. 단순히 생각만 하는 게 아니라, 필요할 때 직접 행동해서 정보를 얻고, 그 정보를 바탕으로 다시 생각합니다.

첫 번째로, tools 딕셔너리에 AI가 사용할 수 있는 도구들이 정의되어 있습니다. 이것이 AI의 "손과 발"입니다.

search_web으로 최신 정보를 검색하고, calculate로 정확한 계산을 하고, get_current_time으로 현재 시각을 얻고, query_database로 내부 데이터를 조회합니다. 실무에서는 여기에 더 많은 도구(이메일 발송, 파일 읽기, API 호출 등)를 추가할 수 있습니다.

두 번째로, solve 함수의 루프가 핵심입니다. 각 반복마다 AI에게 "다음에 뭐 할래?"라고 물어봅니다.

AI는 세 가지 중 하나를 선택합니다: (1) THINK - 더 생각하기, (2) ACTION - 도구 사용하기, (3) ANSWER - 답 제시하기. 이것이 바로 Reasoning(생각) + Acting(행동)의 결합입니다.

세 번째로, ACTION을 선택하면 해당 도구를 실제로 실행합니다. 예를 들어 AI가 "ACTION: get_time"이라고 하면 get_current_time()을 호출하고, 그 결과를 "관찰(Observation)"로 AI에게 다시 보여줍니다.

AI는 이 새로운 정보를 context에 추가하고, 다음 반복에서 이 정보를 활용해서 다음 단계를 결정합니다. 마지막으로, trace 리스트에 모든 과정을 기록합니다.

"단계 1: ACTION: get_time → 관찰: 2024-01-15 14:30:00 → 단계 2: THINK: 크리스마스는 12월 25일이니까... → 단계 3: ACTION: calculate 344 → 관찰: 344 → 단계 4: ANSWER: 크리스마스까지 344일 남았습니다" 같은 식으로 전체 추론과 행동의 흐름이 투명하게 기록됩니다.

여러분이 이 패턴을 사용하면 AI가 단순한 Q&A 봇을 넘어서 진짜 "에이전트"가 됩니다. 고객 지원(CRM 조회), 데이터 분석(DB 쿼리), 리서치(웹 검색), 보고서 작성(여러 소스 통합) 같은 복잡한 업무를 자동화할 수 있습니다.

또한 trace를 보면 AI가 무슨 생각으로 무엇을 했는지 완벽히 감사(audit)할 수 있어서 신뢰성이 높습니다.

실전 팁

💡 도구는 신중하게 선택하세요. 너무 많으면 AI가 혼란스러워하고, 너무 적으면 능력이 제한됩니다. 5-10개가 적당합니다.

💡 각 도구에 명확한 설명(docstring)을 추가하면 AI가 언제 어떤 도구를 써야 하는지 더 잘 판단합니다.

💡 실제 프로덕션에서는 도구 실행에 권한 체크와 레이트 리밋을 추가하세요. AI가 무한 루프로 API를 호출하면 큰일납니다.

💡 ReAct는 LangChain, AutoGPT 같은 프레임워크에서 기본 패턴으로 사용됩니다. 직접 구현하기보다 프레임워크 사용을 고려하세요.

💡 도구 실행 결과를 캐싱하면 비용을 줄일 수 있습니다. 같은 검색을 여러 번 하지 않도록 메모이제이션을 구현하세요.


10. Iterative Refinement - 반복적 개선

시작하며

여러분이 AI에게 복잡한 콘텐츠 작성을 요청했는데, 첫 번째 결과가 70점짜리라서 "이 부분을 더 자세히", "저 부분은 줄여줘" 하면서 여러 번 수정 요청을 한 경험 있나요? 그런데 AI는 매번 이전 피드백을 까먹고 처음부터 다시 쓰는 것처럼 느껴지는 경우처럼요.

이 문제는 피드백을 체계적으로 관리하지 않아서 발생합니다. 사람도 피드백을 주먹구구로 받으면 개선이 느린데, AI는 더합니다.

명확한 반복 프로세스가 필요합니다. 바로 이럴 때 필요한 것이 Iterative Refinement(반복적 개선) 패턴입니다.

초안 생성 → 체계적 평가 → 구체적 피드백 → 개선 → 재평가의 사이클을 명확히 구조화하는 방법입니다. 마치 소프트웨어 개발의 스프린트나 디자인의 반복 작업처럼, AI 출력물도 점진적으로 완성도를 높여갑니다.

개요

간단히 말해서, Iterative Refinement는 AI 출력물을 여러 차례 평가하고 개선하는 구조화된 루프입니다. 각 반복마다 명확한 평가 기준과 개선 방향을 제시합니다.

왜 이게 필요할까요? 복잡한 창작물(보고서, 코드, 디자인 제안 등)은 한 번에 완벽하게 나올 수 없습니다.

반복적 피드백이 필수인데, 이것을 체계화하지 않으면 시간과 비용만 낭비됩니다. 연구에 따르면 3회 반복으로 품질을 40-60% 향상시킬 수 있습니다.

예를 들어, 마케팅 카피 작성, 코드 리팩토링, 전략 문서 작성 같은 업무에 매우 효과적입니다. 기존에는 "다시 해줘", "더 나아졌으면 좋겠어" 같은 모호한 피드백을 줬다면, Iterative Refinement는 "명확성 6/10, 구체성 7/10 → 예시 3개 추가, 전문 용어 쉽게 풀어쓰기"처럼 구체적입니다.

핵심 특징은 세 가지입니다. 첫째, 측정 가능한 평가 - 주관적 "좋다/나쁘다"가 아닌 점수와 기준.

둘째, 구체적 액션 - "더 잘해줘"가 아닌 "이렇게 고쳐줘". 셋째, 수렴 보장 - 무한 반복이 아닌 목표 도달 시 종료.

이는 AI를 실무 크리에이티브 파트너로 활용하는 핵심입니다.

코드 예제

def iterative_refinement(task, quality_threshold=8.0, max_iterations=5):
    """반복적 개선 패턴"""

    # 평가 기준 정의
    criteria = {
        "clarity": "명확성: 내용이 이해하기 쉬운가?",
        "completeness": "완성도: 필요한 내용이 다 들어있는가?",
        "accuracy": "정확성: 사실과 논리가 정확한가?",
        "style": "스타일: 목적에 맞는 톤과 형식인가?"
    }

    history = []

    # 1. 초안 생성
    draft_prompt = f"""
다음 작업을 수행해주세요:
{task}

초안을 작성해주세요.
"""

    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[{"role": "user", "content": draft_prompt}]
    )

    current_output = response.choices[0].message.content
    history.append({"version": 1, "output": current_output})

    # 2. 반복적 개선
    for iteration in range(1, max_iterations + 1):
        # 평가
        eval_prompt = f"""
다음 출력물을 평가해주세요:

{current_output}

평가 기준 (각 10점 만점):
{chr(10).join(f"- {k}: {v}" for k, v in criteria.items())}

각 기준별 점수와 이유:
"""

        eval_response = openai.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": eval_prompt}],
            temperature=0.3
        )

        evaluation = eval_response.choices[0].message.content

        # 평균 점수 추출 (간단한 파싱)
        scores = []
        for line in evaluation.split("\n"):
            for word in line.split():
                if word.replace(".", "").isdigit():
                    try:
                        score = float(word)
                        if 0 <= score <= 10:
                            scores.append(score)
                    except:
                        pass

        avg_score = sum(scores) / len(scores) if scores else 0

        print(f"\n=== 반복 {iteration} 평가 ===")
        print(evaluation)
        print(f"평균 점수: {avg_score:.1f}/10")

        # 목표 달성 체크
        if avg_score >= quality_threshold:
            print(f"\n목표 품질({quality_threshold}) 도달!")
            return {
                "final_output": current_output,
                "iterations": iteration,
                "final_score": avg_score,
                "history": history
            }

        # 개선 지시
        refine_prompt = f"""
현재 출력물:
{current_output}

평가 결과:
{evaluation}

위 평가를 바탕으로 출력물을 개선해주세요.
특히 점수가 낮은 부분을 중점적으로 개선하되, 좋은 부분은 유지하세요.

개선된 버전:
"""

        refine_response = openai.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": refine_prompt}],
            temperature=0.5
        )

        current_output = refine_response.choices[0].message.content
        history.append({
            "version": iteration + 1,
            "output": current_output,
            "previous_score": avg_score
        })

    return {
        "final_output": current_output,
        "iterations": max_iterations,
        "final_score": avg_score,
        "history": history,
        "note": "최대 반복 도달. 목표 품질 미달성."
    }

# 사용 예시
result = iterative_refinement(
    task="IT 스타트업 신입 개발자를 위한 '효과적인 코드 리뷰 방법' 블로그 글을 800자 내외로 작성해주세요.",
    quality_threshold=8.5,
    max_iterations=3
)

print("\n=== 최종 결과 ===")
print(result["final_output"])
print(f"\n반복 횟수: {result['iterations']}")
print(f"최종 점수: {result['final_score']:.1f}/10")

설명

이것이 하는 일: Iterative Refinement는 AI를 "편집자와 작가"의 듀오로 만듭니다. 작가 AI가 초안을 쓰면, 편집자 AI가 평가하고, 작가 AI가 다시 고치는 과정을 반복합니다.

첫 번째로, criteria 딕셔너리에 평가 기준이 명확히 정의되어 있습니다. 이것이 매우 중요합니다.

"좋은 글"이라는 모호한 기준 대신, "명확성", "완성도", "정확성", "스타일" 4가지로 구체화했습니다. 여러분의 업무에 맞게 기준을 바꿀 수 있습니다.

예를 들어 코드라면 "가독성", "효율성", "테스트 커버리지", 마케팅 카피라면 "설득력", "감성", "CTA 명확성" 같은 기준을 사용할 수 있습니다. 두 번째로, 평가 단계에서는 각 기준별로 10점 만점 점수를 매기고 이유를 설명하게 합니다.

이것이 단순히 "다시 써줘"보다 훨씬 효과적입니다. AI는 "명확성 6점: 전문 용어가 너무 많아 초보자가 이해하기 어렵다", "완성도 7점: 예시가 부족하다" 같은 구체적 피드백을 생성합니다.

이런 피드백은 다음 개선에 직접 활용됩니다. 세 번째로, 점수 파싱 부분은 간단한 휴리스틱을 사용했지만, 실무에서는 더 정교한 파싱이나 AI에게 JSON 형식으로 점수를 반환하게 할 수 있습니다.

평균 점수가 quality_threshold(예: 8.5점) 이상이면 반복을 종료합니다. 이것이 "수렴 보장"입니다.

무한 반복으로 비용만 날리는 것을 방지합니다. 마지막으로, 개선 단계에서는 평가 결과를 명시적으로 제공하고 "점수가 낮은 부분을 개선하되 좋은 부분은 유지"라는 명확한 지시를 줍니다.

이렇게 하면 AI가 전체를 다시 쓰는 게 아니라 부족한 부분만 targeted하게 개선합니다. 예를 들어 1차에서 전문 용어가 문제였다면, 2차에서는 그 부분만 쉽게 풀어쓰고 나머지 구조는 유지합니다.

여러분이 이 패턴을 사용하면 AI 출력물의 품질을 극적으로 끌어올릴 수 있습니다. 단순히 여러 번 재생성하는 것보다 훨씬 효율적이고, 각 반복이 명확한 개선을 가져옵니다.

또한 history를 보면 버전별로 어떻게 발전했는지 추적할 수 있어서, 나중에 "2번째 버전이 더 나았네" 하면서 롤백할 수도 있습니다.

실전 팁

💡 평가 기준을 3-5개로 유지하세요. 너무 많으면 평가가 피상적이 되고, 너무 적으면 놓치는 측면이 생깁니다.

💡 quality_threshold를 현실적으로 설정하세요. 9.0 이상을 목표로 하면 영원히 끝나지 않을 수 있습니다. 8.0-8.5가 적당합니다.

💡 각 반복마다 다른 온도(temperature)를 사용할 수 있습니다. 초안은 0.7(창의적), 평가는 0.3(엄격), 개선은 0.5(균형) 같은 식으로요.

💡 사람이 중간에 개입하는 "human-in-the-loop" 모드를 추가하면 더 좋습니다. 각 평가 후에 사람이 확인하고 추가 피드백을 줄 수 있게 하세요.

💡 평가와 개선을 서로 다른 모델로 할 수도 있습니다. 예를 들어 평가는 GPT-4, 개선은 Claude처럼 다른 모델을 쓰면 편향이 줄어듭니다.


#AI#Chain-of-Thought#Prompting#LLM#ReasoningPatterns

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.