ansir 님의 블로그

[ SK 네트웍스 Family AI 캠프 수업 내용 복습 ] 프롬프트 엔지니어링 응용 - CoT( Chan of Thought ) 2025-05-16 본문

SK 네트웍스 family AI 캠프/수업 내용 복습

[ SK 네트웍스 Family AI 캠프 수업 내용 복습 ] 프롬프트 엔지니어링 응용 - CoT( Chan of Thought ) 2025-05-16

ansir 2025. 5. 19. 13:44

CoT의 진화 (Chain of Thought Prompting)

1. 개요

  • CoT( Chain of Thought )는 LLM( Large Language Model )이 복잡한 문제를 단계적으로 논리적으로 해결할 수 있도록 유도하는 프롬프트 기법입니다.

핵심 개념

  • 일반적인 LLM은 문제의 최종 답을 바로 예측하려 하지만, CoT는 문제 해결 과정을 명시적으로 서술하도록 유도합니다.
  • 대표적인 문구:이는 모델이 추론 과정을 서술하도록 유도하여 정답률을 높이는 효과가 있습니다.
  • "Let's think step by step."

예시

질문: 2 + 2 × 3 = ?

  • 일반 모델 출력 (CoT 없음): 12 또는 8 (랜덤하게 오류 가능)
  • CoT 사용:
  • Let's think step by step. 먼저 곱셈을 합니다: 2 × 3 = 6 그런 다음 덧셈을 합니다: 2 + 6 = 8 따라서 정답은 8입니다.

효과

  • CoT는 수학, 논리, 지식 기반 문제, 추론 문제 등 단계적 사고가 필요한 작업에서 특히 효과적입니다.
  • CoT가 없을 경우 GPT-4 같은 모델도 연산 순서 오류, 개념적 오해 등을 일으킬 수 있음

2. CoT의 진화 방향 ( 보충 설명 )

Chain of Thought 기법은 최근 다양한 형태로 확장되고 있으며, 주요 진화 방향은 다음과 같습니다:

기법 특징
Standard CoT 단순한 단계별 사고 유도 (Let's think step by step.)
Few-shot CoT 여러 개의 예시를 함께 제시하여 학습 효과 강화
Auto-CoT LLM이 스스로 CoT 예시를 생성하고, 그 예시를 활용하여 문제 해결
Self-consistency 다양한 CoT 경로를 생성하고, 그 중 가장 자주 등장하는 답을 선택
Tree of Thought (ToT) 하나의 해답 경로가 아닌 여러 사고 경로를 분기시켜 탐색, 더 정교한 의사결정
Program-Aided CoT (PACT) 모델이 논리적 추론 중 실제 프로그램 코드(예: 파이썬)를 이용하여 계산 수행

3. 결론

CoT는 단순히 출력 양식을 바꾸는 것이 아니라, 모델의 사고 방식 자체를 유도하는 강력한 기법입니다.

이를 통해 LLM의 잠재력을 더 깊이 끌어낼 수 있으며, 특히 추론, 계산, 다중 선택 문제 등 복잡한 작업에서 큰 성능 향상을 가져올 수 있습니다.

 


import openai  # OpenAI API 라이브러리 임포트
import os      # 환경 변수 관리를 위한 os 모듈 임포트

# OpenAI API 키를 환경 변수로 설정 (실제 코드에서는 보안을 위해 노출되면 안 됨)
os.environ["OPENAI_API_KEY"] = "private-api-key"

# OpenAI API 클라이언트 생성
client = openai.OpenAI(api_key=os.environ["OPENAI_API_KEY"])

# CoT 방식의 프롬프트를 구성하고 응답을 받아오는 함수
def cot_prompt(query):
  # 입력된 질의를 기반으로 단계별 풀이를 요구하는 프롬프트 작성
  prompt = f'''다음 문제를 단계별로 풀어주세요. 각 단계를 번호로 구분하고 최종 답변을 명확하게 제시하세요
  {query}
  1. 문제 분석
  2. 계산
  3. 답변 확인
  '''
  
  # OpenAI GPT 모델에 요청
  response = client.chat.completions.create(
    model="gpt-3.5-turbo",  # 사용할 모델 지정
    messages=[
      {"role": "system", "content": "당신은 단계별로 문제를 해결하는 논리적인 시스템입니다."},
      {"role": "user", "content": prompt}
    ],
    max_tokens=200,        # 응답의 최대 길이 제한
    temperature=0.7        # 창의성 정도 (0에 가까울수록 보수적, 1에 가까울수록 다양성 높음)
  )

  # 모델의 응답 텍스트 반환
  return response.choices[0].message.content

# 테스트 질의 실행
query = "2 + 2 x 3 = ?"
print(cot_prompt(query))
1. 문제 분석
- 주어진 수식은 "2 + 2 x 3"으로, 곱셈과 덧셈이 혼합되어 있습니다. 이때 연산 순서를 고려하여 정확한 답을 도출해야 합니다.

2. 계산
- 주어진 수식에 따라 우선 곱셈을 먼저 계산합니다.
- 2 x 3 = 6
- 따라서, 2 + 2 x 3 = 2 + 6 = 8

3. 답변 확인
- 따라서, 2 + 2 x 3 = 8 입니다.

코드 설명

1. 목적

  • 이 코드는 Chain of Thought (CoT) 방식으로 수학 문제를 단계적으로 해결하도록 LLM(GPT-3.5-turbo)에 요청하는 예제입니다.

2. 주요 구성

  • cot_prompt(query) 함수: 주어진 문제(query)를 문제 분석 → 계산 → 답 확인의 단계로 유도하는 프롬프트를 생성하고, 그 결과를 반환합니다.
  • openai.OpenAI(...): 최신 OpenAI SDK에서 사용하는 방식으로, 이전의 openai.ChatCompletion.create 방식과 달리 클라이언트를 생성해 사용합니다.
  • temperature: 0.7로 설정되어 있어 너무 획일적인 응답이 아닌, 적절한 다양성을 가진 응답을 기대할 수 있습니다.

 


Tree-of-Thoughts (ToT)

개념 요약

  • CoT(Chain-of-Thought) 방식의 확장으로, 단일한 추론 경로가 아닌 트리 형태의 다중 추론 경로를 따라 문제를 해결함.
  • 각 단계에서 가능한 여러 사고 분기점(branch) 를 고려하고, 그 결과를 탐색하여 최적의 해결 경로를 찾음.
  • 대표 사례: 체스 수 예측처럼 한 선택이 이후 선택에 영향을 주는 문제에 적합.
  • 다중 시나리오 분석비결정적/불확실한 문제 탐색에 효과적.
  • 단일한 논리 흐름만 따르는 CoT보다 훨씬 더 탐색적이고 유연한 문제 해결이 가능함.

주요 특징

요소 설명
구조 사고 과정이 트리 형태로 확장됨 (여러 경로 탐색)
적용 예시 체스, 법률 시뮬레이션, 전략적 선택 문제
CoT와의 차이점 CoT는 선형 사고, ToT는 비선형(분기적 사고)
장점 다양한 경로의 결과를 비교해 최적의 해결안 도출 가능
단점 계산량 증가, 경로 선택 기준이 명확하지 않으면 탐색 효율이 낮을 수 있음

예시 문제: 몬티홀 문제

"3개의 상자 중 하나에만 상품이 있다. 한 상자를 선택한 후, 나머지 두 상자 중 하나가 열리고 빈 상자가 공개된다. 이때 선택을 바꾸면 정답일 확률은?"

CoT 방식:

  1. 처음에 상자를 하나 선택할 확률은 1/3
  2. 진행자가 빈 상자를 공개
  3. 선택을 바꾸면 남은 두 상자 중 처음 고르지 않은 것 → 확률 2/3로 당첨 가능

ToT 방식:

  • 트리 구조로 시나리오를 전개:
    • 루트 노드: 초기 선택
    • 자식 노드: 진행자가 빈 상자 공개
    • 다음 노드들: 선택 유지 vs. 변경
    • 각 경로의 성공 확률을 비교하여 전략 도출

활용 사례

  • 게임 전략: 체스, 바둑 등에서 수를 여러 수 앞까지 전개하여 판단
  • 법률 시뮬레이션: 여러 시나리오별 결과를 예측하여 변호 전략 수립
  • 계획 수립: 여행 계획, 프로젝트 분기 등에서 조건 따라 다양한 결과 분석

보충 설명: ToT가 왜 중요한가?

기존 LLM은 추론 시 하나의 답을 선택하고 그 흐름을 따라가며 응답합니다. 이는 많은 문제에서 효과적이지만, 복잡하고 불확실성이 높은 문제(예: 심리 전략, 정책 결정, 법률 등)에서는 여러 가능성을 고려한 탐색적 사고가 더 유용합니다.

ToT는 이런 상황에서 다양한 사고 시나리오를 병렬적으로 생성하고, 비교/선택하는 방식으로 인간의 고차 사고와 유사한 문제 해결 전략을 구현할 수 있게 합니다.

 


Graph-of-Thoughts (GoT)

개념 요약

  • Graph-of-Thoughts(GoT) 는 사고 과정을 그래프 구조로 확장한 프롬프트 방식입니다.
  • 노드(node) 는 개별 개념(예: 조항, 조건, 사건 등), 엣지(edge) 는 개념 간의 논리적, 인과적, 시간적 관계를 표현합니다.
  • CoT가 선형 추론, ToT가 트리형 다중 추론이라면, GoT는 비선형 연결망 기반의 추론 체계입니다.
  • 복잡한 도메인(법률, 의료, 정책, 학술 분석 등)에서 사용 시, 서로 얽힌 개념들을 시맨틱 그래프 형태로 명시적으로 모델링할 수 있어 유리합니다.

주요 특징

요소 설명
구조 개념 간 관계를 그래프로 구성 (비순차적 사고)
노드(Node) 주요 개념, 조항, 사건, 명제 등
엣지(Edge) 의존 관계, 인과 관계, 상호작용 등
활용 분야 법률 조항 간 해석, 의료 진단 인과 구조, 학술 논문 간 개념 연결
장점 복잡한 시스템 내 개념들의 상호작용을 분석 가능
단점 그래프 구성 기준이 주관적일 수 있고, 시각화 필요성이 큼

예시

질문

임대차 계약에서 임차인의 계약 해지 통지 의무와 임대인의 보증금 반환 의무는 어떻게 연결되나요?

GoT 방식 프롬프트

다음 문제를 Graph-of-Thoughts 방식으로 풀어주세요. 관련 개념(예: 조항, 의무)을 노드로, 그 관계를 엣지로 구성하여 단계별로 분석하세요.

1. 개념 노드 식별
2. 관계 엣지 분석
3. 최종 연결 설명

응답 예시

1. 개념 노드 식별

  • N1: 임차인의 계약 해지 통지 의무
  • N2: 계약 해지 효력 발생
  • N3: 임대인의 보증금 반환 의무
  • N4: 임대인의 확인 의무
  • N5: 반환 시기 조건

2. 관계 엣지 분석

  • E1: N1 → N2 : 통지가 있어야 해지 효력이 발생함
  • E2: N2 → N3 : 계약이 해지되어야 반환 의무가 발생함
  • E3: N3 ↔ N5 : 반환 시기는 조건(계약 만료 후 일정 기간 등)에 따라 다름
  • E4: N3 ← N4 : 임대인은 임차인으로부터의 통지 내용 확인 후 의무가 발생함

3. 최종 연결 설명

  • 임차인이 계약 해지 의사를 통지(N1) 해야만 해지 효력이 발생(N2)하고,반환 의무는 특정 조건(N5) 하에 이행되며, 이 의무는 임대인의 확인(N4)을 통해 활성화됩니다.
  • 해지 효력이 발생해야 임대인은 보증금 반환 의무(N3) 를 가지며,

왜 GoT가 필요한가?

  • CoT/ToT는 순차 또는 분기 사고에 적합하지만, 실세계 문제는 선형이 아닌 다중 관계 기반으로 작동하는 경우가 많습니다.
  • GoT는 개념들 간의 구조적 관계와 의존성을 추론에 포함시킴으로써 더 정밀하고 깊이 있는 reasoning을 가능하게 합니다.
  • 특히 법률, 의료, 정책, 금융 계약 등 고차원적 복합 reasoning이 요구되는 분야에서 LLM의 reasoning 능력을 질적으로 향상시킵니다.

비교 요약

프롬프트 방식 구조 적용 예시
CoT 선형 (단일 경로) 단순 수학, 논리 문제
ToT 트리 (분기 경로) 전략 게임, 다중 시나리오
GoT 그래프 (비선형 관계망) 법률 해석, 의료 진단, 정책 시뮬레이션

 


Tool-augmented Chain of Thought (Tool-augmented CoT)

개요

  • Tool-augmented CoT는 기존의 Chain of Thought 방식에 **외부 도구(external tools)**를 연동하여 LLM의 계산 능력, 정보 검색 능력 등의 한계를 보완하는 방식입니다.
  • 인간이 문제를 풀 때 계산기나 사전, 웹검색을 활용하듯, LLM도 필요한 작업을 적절한 도구에게 위임하여 보다 정확한 reasoning을 수행할 수 있게 합니다.

핵심 요소

구성 요소 설명
LLM 추론 과정을 구성하고, 도구 사용의 시점과 목적을 결정
도구 계산기, 웹 검색, API, 데이터베이스, 코드 실행기 등
연결 방식 내장 함수 호출, 플러그인, API 연동, Toolformer 방식

예시 문제

√(16) + 3² = ?

일반 CoT 방식 (LLM만 사용)

1. 루트 16은 4
2. 3의 제곱은 9
3. 4 + 9 = 13
→ 답: 13

→ 간단한 문제는 가능하나, 복잡한 계산 또는 최신 정보 검색이 필요한 경우 한계 존재

Tool-augmented CoT 방식

1. 루트 16 계산 → 계산기 호출: sqrt(16) = 4
2. 3의 제곱 계산 → 계산기 호출: 3^2 = 9
3. 덧셈 수행: 4 + 9 = 13
→ 정확한 계산 기반으로 답 도출

활용 예시

도구 종류  활용 예시
계산기 수학 문제, 재무 계산 등
웹 검색 시사 문제, 최신 데이터, 트렌드 정보
API 날씨, 번역, 환율, 주식 정보 등
코드 실행기 코드 분석, 시뮬레이션, 수치 계산
DB 질의 도구 고객 정보 조회, 대규모 테이블 분석 등

대표 기술

  • Toolformer
    • Meta AI에서 개발한 LLM + 도구 조합 모델
    • 모델이 도구가 필요한 지점을 스스로 인식하고, API 호출을 삽입하는 방식으로 fine-tuning함
    • 학습 시 도구 사용 여부와 타이밍을 스스로 결정할 수 있게 함
  • ReAct (Reasoning + Acting)
    • 추론을 하면서 중간에 필요한 도구를 호출함 (예: 검색→추론→계산 반복)
    • OpenAI의 Plugin 기반 프롬프트 등에도 활용됨

장점

  • LLM의 내재적 한계(계산, 최신 정보 부족 등)를 보완
  • 보다 정확하고 신뢰도 높은 reasoning 가능
  • 추론 과정이 도구 호출과 결합되어 명확하게 드러남

단점

  • 도구 호출의 정확성에 의존 → 오작동, 오류 처리 필요
  • 도구 호출 비용 발생
  • 복잡한 구성: API 인증, 호출 시점 판단, 에러 처리 등 설계 필요

관련 기술 비교

방식  설명
CoT 내부 추론만으로 문제 해결
Tool-augmented CoT 추론 중 도구를 호출하여 보완
ReAct 추론과 행동(도구 사용)을 번갈아 반복
Toolformer 도구 사용이 포함된 데이터로 사전 학습된 모델

 


def tool_augmented_cot(query):
    # 계산기 함수: 제한된 eval 환경에서 sqrt() 함수만 허용하여 계산 수행
    def calculator(expression):
        try:
            return eval(expression, {'__builtins__': None}, {'sqrt': lambda x: x**0.5})
        except Exception as e:
            return None

    # 수식 정규화 함수:
    # - ^ 연산자는 Python의 거듭제곱 연산자 **로 변경
    # - √(x)는 sqrt(x)로 변경하여 eval에서 계산 가능하게 함
    def normalize_expr(expr):
        expr = expr.replace('^', '**')
        expr = re.sub(r'√\\((.*?)\\)', r'sqrt(\\1)', expr)
        return expr

    # OpenAI LLM 호출: CoT 방식으로 문제를 해결하되, 계산식은 [CALC: ...] 형태로 출력 요청
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "당신은 단계별로 문제를 해결하는 논리적인 시스템입니다."},
            {"role": "user", "content": f"""
문제를 단계별로 풀어주세요. 계산이 필요하면 '[CALC: 식]'으로 표기하고, 계산기 도구를 사용하세요.
{query}
1. 문제 분석
2. 계산
3. 답변 확인
"""}
        ],
        max_tokens=200,
        temperature=0.7
    )

    # LLM 응답 메시지 가져오기
    result = response.choices[0].message.content

    # 응답 내에서 [CALC: ...] 패턴의 수식을 모두 추출
    calc_pattern = r'\\[CALC: (.*?)\\]'
    for calc in re.findall(calc_pattern, result):
        # 수식을 eval에서 계산 가능한 형태로 정규화
        normalized = normalize_expr(calc)
        # 계산 수행
        calc_result = calculator(normalized)
        if calc_result is not None:
            # 계산 결과를 응답 메시지에 덧붙이기
            result += f"\\n계산 결과: {calc} = {calc_result}"
    return result

# 테스트할 질의 입력
query = "√(16) + 3^2 = ?"

# 실행
print(tool_augmented_cot(query))

함수 설명

함수 목적

  • Tool-augmented Chain-of-Thought (CoT) 기법을 구현합니다.
  • LLM이 문제 해결 흐름을 단계별로 출력하고, 계산이 필요한 부분은 [CALC: ...]로 명시하게 합니다.
  • 그런 후 외부 도구(여기선 eval)를 사용해 계산 결과를 보완합니다.

작동 흐름 요약

  1. 질문 입력: query = "√(16) + 3^2 = ?"
  2. LLM 응답 생성: 문제를 Chain-of-Thought 형식으로 해결하고, 계산이 필요한 부분에 [CALC: ...] 형식으로 표시.
  3. 정규식 추출: [CALC: ...] 수식들을 모두 추출.
  4. 정규화: ^ → *, √(x) → sqrt(x) 형태로 변경.
  5. 계산: eval()을 사용해 실제 계산 수행.
  6. 결과 덧붙이기: 계산 결과를 원래 LLM 응답에 추가.
query = "√(16) + 3^2 = ?"
print(tool_augumented_coat(query))
1. 문제 분석:
주어진 수식을 계산해야 합니다. 수식은 다음과 같습니다.
√(16) + 3^2

2. 계산:
√(16) = 4
3^2 = 9

따라서, 수식을 계산하면 다음과 같습니다.
4 + 9

[CALC: 4 + 9]

3. 답변 확인:
4 + 9 = 13

따라서, 주어진 수식을 계산하면 13이 됩니다.
계산 결과: 4 + 9 = 13

 


1. Self-Refinement

  • 정의: LLM이 자신의 초기 응답을 스스로 점검하고 개선하는 능력
  • 핵심 아이디어:② 자기 검토(Self-critique)
  • 수정 및 개선된 응답 생성
  • 초기 응답 생성
  • 적용 예:
    • 요약 결과를 다시 보고 부족한 점(정보 누락, 논리 불일치 등)을 수정
    • 수학 풀이에서 계산 오류를 스스로 찾아 재계산
  • 예시 흐름:
  • Q: AI는 인간을 대체할 수 있는가? A1: AI는 많은 직무에서 인간을 대체할 수 있다. 특히 반복적인 업무에서 그렇다. Self-Check: 윤리적 문제와 창의성에 대한 고려가 빠졌다. A2 (Refined): AI는 반복 업무를 대체할 수 있으나, 윤리적 고려 및 창의적 판단 영역에서는 인간의 역할이 여전히 중요하다.

2. CoT + Toolformer

  • 정의: CoT(Chain-of-Thought)에 도구 자동 삽입 훈련을 결합한 방식
  • Toolformer는 LLM이 어떤 도구를 어느 시점에 호출할지 스스로 학습하게 하여, 계산기/검색/API 등 외부 도구를 자동 호출
  • 기능 요약:
    • LLM이 프롬프트 내에 [TOOL: ...]을 자동 생성
    • 훈련 없이 기존 LLM만으로 도구 호출 시점 예측 가능
  • 예시:
  • 입력: √(121) + 5^2 = ? 출력: 1. √(121)을 계산해야 함 → [TOOL: sqrt(121)] 2. 5^2는 → [TOOL: pow(5, 2)] 3. 두 값을 더함 최종 결과: 11 + 25 = 36

3. ReAct 2.0 (Reasoning + Acting)

  • 정의: **추론(Reasoning)**과 **행동(Acting)**을 교차하며 문제 해결을 수행하는 프레임워크의 발전된 버전
  • ReAct 1.0에서 발전:
    • 더 강력한 메모리 구조
    • 불확실성 추적, 자기 피드백 루프 포함
  • 핵심 흐름:
  • Thought: 우편번호를 찾기 위해 검색이 필요해요. Action: [SEARCH: "서울시 강남구 우편번호"] Observation: "06000" Thought: 우편번호는 06000입니다. Final Answer: 06000
  • 활용:
    • 웹 검색 기반 Q&A
    • 계산, 문서 요약, 웹탐색 등을 순차적으로 처리

세 방식 비교 요약

방법  목적  핵심 구성 장점
Self-Refinement 스스로 검토 및 개선 응답 → 자기평가 → 재작성 정확도와 논리성 향상
CoT + Toolformer 추론 도중 도구 자동 호출 CoT + 도구 삽입 학습 계산기, 검색기 등 유연한 활용 가능
ReAct 2.0 행동과 추론의 결합 Thought-Action-Obs 순환 복잡한 문제 해결, 외부 정보 조합

 

import os
import openai

# OpenAI API 클라이언트 초기화 (환경변수에서 API 키를 불러옴)
client = openai.OpenAI(api_key=os.environ["OPENAI_API_KEY"])

# Self-Refinement 기반 Chain-of-Thought 실행 함수
def self_refinement_cot(query):
    # GPT 모델에 요청 보내기
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",  # 사용할 OpenAI 모델
        messages=[
            # 시스템 역할: 자기개선 시스템이라고 정의
            {"role": "system", "content": "당신은 자기개선을 통해 문제를 해결하는 시스템입니다."},
            # 사용자 질문과 단계별 지시 포함
            {"role": "user", "content": f"""
            다음 문제를 단계별로 풀어주세요, 답변 후 스스로 검토해 오류를 수정하세요, 
            최종 답변에 오류가 있다면 2번 순서부터 다시 실행하세요.
            {query}
            1. 문제 분석
            2. 계산
            3. 검토 및 수정
            4. 최종 답변
            """}
        ],
        max_tokens=400,     # 출력 최대 토큰 수
        temperature=0.7     # 창의성 조절 (0.7은 중간 정도의 무작위성)
    )

    # 생성된 응답 중 첫 번째 메시지의 content(본문) 반환
    return response.choices[0].message.content
query = "한 농부가 닭과 소를 합쳐서 20마리를 기르고 있습니다. 농부가 기르는 동물의 다리 수는 총 50개일 때, 닭과 소의 수는 각각 몇 마리인가요?"
print(self_refinement_cot(query))
1. 문제 분석
- 닭과 소의 수를 각각 x와 y라고 가정합니다.
- 문제에서 주어진 조건에 따라 방정식을 세워야 합니다.
- 닭과 소를 합쳐서 20마리를 기르고 있으므로 x + y = 20
- 농부가 기르는 동물의 다리 수는 총 50개이므로 2x + 4y = 50

2. 계산
- 위의 두 방정식을 풀어 x와 y 값을 구합니다.
- x + y = 20 → x = 20 - y
- 2(20 - y) + 4y = 50
- 40 - 2y + 4y = 50
- 2y = 10
- y = 5
- x = 20 - 5 = 15

3. 검토 및 수정
- 닭과 소의 수를 각각 15마리와 5마리로 계산하였습니다.
- 다리 수를 확인해보겠습니다. 닭은 2개의 다리, 소는 4개의 다리를 가지므로 전체 다리 수는 15*2 + 5*4 = 50으로 맞는 것을 확인할 수 있습니다.

4. 최종 답변
- 농부가 기르는 닭은 15마리, 소는 5마리입니다.

동작 구조 설명 (Self-Refinement CoT)

  1. 입력
    • query: 예를 들어 "√(16) + 3^2 = ?" 같은 질문을 받음
  2. 단계별 출력 요청
    • 모델에게 아래 4단계로 작업을 수행하도록 프롬프트를 구성함:
      1. 문제 분석: 질문의 구조 및 요소 파악
      2. 계산: 필요한 수식이나 논리 수행
      3. 검토 및 수정: 계산 또는 논리 오류 여부 판단
      4. 최종 답변: 오류가 있다면 2번부터 다시 반복하여 재계산 후 최종 답변
  3. 자기검토
    • GPT는 자체적으로 응답 결과를 분석하여, 오류 여부를 판단하고 자동으로 수정 루프를 수행
    • 예: √(16) + 3^2 → 처음에 계산을 잘못하면 검토 후 다시 계산해서 바르게 고침
  4. 출력
    • 최종적으로 검토/수정이 완료된 정답을 반환함

 


CoT Prompt Template 고도화

개념 정리

고도화된 Chain-of-Thought(CoT) Prompt Template이란, 단순히 “step-by-step”이라는 지시어만 사용하는 것이 아니라 문제 해결 단계, 출력 형식, reasoning 방식더 구체적이고 체계적으로 명시하는 프롬프트 설계 방식입니다. 이를 통해 LLM의 일관된 추론 경로 유도 및 오류 감소를 도모할 수 있습니다.

핵심 요소

  1. 단계 수 명시예: 수학 문제 → "변수 정의 → 계산 → 검증"
  2. 문제 유형에 따라 해결 단계의 수와 흐름을 명확히 지정
  3. 명시적 지시어 사용예: "모든 숫자를 변수로 치환한 후 연산 순서를 설명하세요."
  4. 각 단계에서 LLM이 해야 할 사고 절차 또는 판단 기준을 구체적으로 지시
  5. 출력 형식 정의예:
  6. 1. 변수 정의: ... 2. 계산: ... 3. 검증: ... 4. 최종 답변: ...
  7. 응답이 일관되게 구성되도록 결과 형식(template)을 명확히 요구

예시 (수학 문제에 대한 고도화된 CoT Prompt)

프롬프트

다음 수학 문제를 아래 단계에 따라 체계적으로 해결하세요. 각 단계를 번호로 구분하고, 명확한 출력 형식을 따르세요.

문제: (4 + 2) × (10 ÷ 2) = ?

1. 변수 정의: 수식에 포함된 주요 수치와 연산자의 의미를 정의하세요.
2. 계산: 연산 순서에 따라 각 단계를 계산하세요.
3. 검증: 계산 결과가 논리적으로 타당한지 검토하세요.
4. 최종 답변: 최종 정답을 한 문장으로 요약하여 제시하세요.

효과

  • LLM이 혼동 없이 일관된 논리 전개 가능
  • 문제에 특화된 reasoning 전략 적용 가능 (예: 수학, 법률, 코딩 등)
  • 평가와 디버깅이 쉬운 구조적 응답 확보

보충 설명

이러한 방식은 특히 다음 상황에서 효과를 발휘합니다:

  • 고난도 문제: 단순한 “step-by-step” 프롬프트로는 reasoning depth가 부족할 수 있음
  • 문제별 편차가 큰 응답 방지: 구조화된 형식이 정답의 신뢰도를 높여 줌
  • 툴 결합 방식 (Tool-augmented CoT) 또는 Self-Refinement와의 병행에 적합

 


# utils.py
import math  # 수학 관련 함수 및 상수 사용을 위한 모듈
import re    # 정규 표현식 처리를 위한 모듈

# 고도화된 Chain-of-Thought(CoT) 템플릿을 사용하여 문제를 단계적으로 해결하는 함수
def advanced_cot_template(client, query):
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",  # 사용하는 언어 모델
        messages=[
            # 시스템 역할: 자기개선을 수행하는 문제 해결 시스템
            {"role": "system", "content": "당신은 자기개선을 통해 문제를 해결하는 시스템입니다."},
            # 사용자 입력: 문제를 단계적으로 풀고 검토 및 수정 절차까지 거칠 것
            {"role": "user", "content": f"""
            다음 문제를 단계별로 풀어주세요, 답변 후 스스로 검토해 오류를 수정하세요.
            {query}
            1. 문제 분석
            2. 계산
            3. 검토 및 수정
            4. 최종 답변
            """}
        ],
        max_tokens=800,     # 출력 토큰 수 제한
        temperature=0.7     # 출력의 창의성(무작위성) 조절
    )
    # 최종 응답 텍스트 반환
    return response.choices[0].message.content

# Few-shot 예제를 포함한 Chain-of-Thought 방식으로 문제를 해결하는 함수
def few_shot_cot(client, query):
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "당신은 자기개선을 통해 문제를 해결하는 시스템입니다."},
            {"role": "user", "content": f"""
            다음 문제를 few shot으로 단계별로 풀어주세요. 아래 예제를 참고하여 단계별로 답변하세요. 답변 후 스스로 검토해 오류를 수정하세요.
            
            예제 1: 
             1. 문제 분석
            - 닭과 소의 수를 각각 x와 y라고 가정합니다.
            - 문제에서 주어진 조건에 따라 방정식을 세워야 합니다.
            - 닭과 소를 합쳐서 20마리를 기르고 있으므로 x + y = 20
            - 농부가 기르는 동물의 다리 수는 총 50개이므로 2x + 4y = 50

            2. 계산
            - 위의 두 방정식을 풀어 x와 y 값을 구합니다.
            - x + y = 20 → x = 20 - y
            - 2(20 - y) + 4y = 50
            - 40 - 2y + 4y = 50
            - 2y = 10
            - y = 5
            - x = 20 - 5 = 15

            3. 검토 및 수정
            - 닭과 소의 수를 각각 15마리와 5마리로 계산하였습니다.
            - 다리 수를 확인해보겠습니다. 닭은 2개의 다리, 소는 4개의 다리를 가지므로 전체 다리 수는 15*2 + 5*4 = 50으로 맞는 것을 확인할 수 있습니다.

            4. 최종 답변
            - 농부가 기르는 닭은 15마리, 소는 5마리입니다.
             
            예제 2:
             1. 문제 분석:
            - 사과를 A원, 오렌지를 O원이라고 가정하겠습니다.
            - 첫 번째 방정식: 3A + 2O = 13000
            - 두 번째 방정식: 2A + 3O = 12000

            2. 계산:
            - 두 방정식을 활용하여 연립방정식을 풀어보겠습니다.
            - 먼저 두 번째 방정식에 2를 곱하여 새로운 방정식을 만듭니다.
            4A + 6O = 24000
            - 이제 첫 번째 방정식에서 두 번째 방정식을 빼줍니다.
            (3A + 2O) - (4A + 6O) = 13000 - 24000
            -A - 4O = -11000
            A = 11000 - 4O

            - A = 11000 - 4O를 첫 번째 방정식에 대입하여 O를 구합니다.
            3(11000 - 4O) + 2O = 13000
            33000 - 12O + 2O = 13000
            -10O = -20000
            O = 2000

            - O = 2000을 A = 11000 - 4O에 대입하여 A를 구합니다.
            A = 11000 - 4(2000)
            A = 11000 - 8000
            A = 3000
            ...
            - 계산 결과, 사과의 가격은 3,000원, 오렌지의 가격은 2,000원으로 계산되었습니다.

            4. 최종 답변:
            - 사과는 3,000원, 오렌지는 2,000원입니다.

            문제:
            {query}
            1. 변수 정의.
            2. 방정식 설정.
            3. 계산 과정.
            4. 검토.
            5. 최종 답변.
            """}
        ],
        max_tokens=1000,
        temperature=0.7
    )
    return response.choices[0].message.content

코드 설명

  • 이 코드는 LLM 기반 문제 해결 파이프라인 중 CoT 방식으로 구성된 템플릿 2종을 제공합니다.
  • 두 함수 모두 OpenAI의 Chat API를 사용하며, 각각의 방식은 다음과 같습니다:
함수명 주요 목적 특징
advanced_cot_template 일반 CoT + Self-Refinement 4단계 구조(문제 분석 ~ 최종 답변)로 구성
few_shot_cot 예시 기반 Few-shot CoT 2개의 수학 예시 제공 후 5단계 구조(변수 정의 ~ 최종 답변)로 유도
  • 이들은 주로 수학/논리 문제 해결 시 유용하며, 다음과 같은 방식으로 사용할 수 있습니다:
result = advanced_cot_template(client, "어떤 수에 5를 더했더니 12가 되었다. 그 수는?") 
print(result) 
result = few_shot_cot(client, "3개의 펜과 2개의 연필이 8000원, 2개의 펜과 3개의 연필이 7000원일 때 각각의 가격은?") 
print(result)

 

# 사과 3개와 오렌지 2개는 13,000원이고, 사과 2개와 오렌지 3개는 12,000원입니다. 사과와 오렌지는 각각 얼마인가요?
import openai
import os
from dotenv import load_dotenv
load_dotenv()
query = "사과 3개와 오렌지 2개는 13,000원이고, 사과 2개와 오렌지 3개는 12,000원입니다. 사과와 오렌지는 각각 얼마인가요?"

# advanced_cot_template은 utils.py에 정의된 함수입니다.
from utils import advanced_cot_template

client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
print(advanced_cot_template(client, query))
1. 문제 분석:
- 사과를 A원, 오렌지를 O원이라고 가정하겠습니다.
- 첫 번째 방정식: 3A + 2O = 13000
- 두 번째 방정식: 2A + 3O = 12000

2. 계산:
- 두 방정식을 활용하여 연립방정식을 풀어보겠습니다.
- 먼저 두 번째 방정식에 2를 곱하여 새로운 방정식을 만듭니다.
   4A + 6O = 24000
- 이제 첫 번째 방정식에서 두 번째 방정식을 빼줍니다.
   (3A + 2O) - (4A + 6O) = 13000 - 24000
   -A - 4O = -11000
   A = 11000 - 4O

- A = 11000 - 4O를 첫 번째 방정식에 대입하여 O를 구합니다.
   3(11000 - 4O) + 2O = 13000
   33000 - 12O + 2O = 13000
   -10O = -20000
   O = 2000

- O = 2000을 A = 11000 - 4O에 대입하여 A를 구합니다.
   A = 11000 - 4(2000)
   A = 11000 - 8000
   A = 3000
...
- 계산 결과, 사과의 가격은 3,000원, 오렌지의 가격은 2,000원으로 계산되었습니다.

4. 최종 답변:
- 사과는 3,000원, 오렌지는 2,000원입니다.
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

 


암호화

# XOR 연산자를 이용한 암호화 샘플
original = "이건 비밀인데 너만 알고 있어야 해."
key = 64

encoded = [ord(c) ^ key for c in original]
print(f"Encoded: {encoded}")
decoded = "".join([chr(c ^ key) for c in encoded])
print(f"Decoded: {decoded}")
Encoded: [50996, 44084, 96, 48644, 48192, 51000, 45872, 96, 45384, 47500, 96, 50444, 44192, 96, 51144, 50676, 50492, 96, 54580, 110]
Decoded: 이건 비밀인데 너만 알고 있어야 해.

cryptography

!pip install cryptography

from cryptography.fernet import Fernet
# 키 생성( 한 번만 )
public_key = Fernet.generate_key()
print(f"public_key: {public_key.decode()}")
# 암호화
original = "이건 비밀인데 너만 알고 있어야 해."
fernet = Fernet(public_key) # 객체 생성
encrypted = fernet.encrypt(original.encode())
print(f"Encrypted: {encrypted.decode()}")
# 복호화
decrypted = fernet.decrypt(encrypted).decode()
print(f"Decrypted: {decrypted}")
public_key: efCH-8oSrcGKOeyofamWroXxAxyoM74f6gXinAw4-Es=
Encrypted: gAAAAABoJtwu97kdcfdniW4IrLvssE252VuFHojq5e7z6o4e57dqP9jsfztcdG3b8StzAESRFCL1FRvwYa-_RnoY9S-ftWu4shgjg6d93bLyU_nVqPWHfYwvZvDiMFMpzL4Dnr-R1x9f2SfqozoOizXZFv4CqdBR1A==
Decrypted: 이건 비밀인데 너만 알고 있어야 해.

 


Few_Shot

# 사과 3개와 오렌지 2개는 13,000원이고, 사과 2개와 오렌지 3개는 12,000원입니다. 사과와 오렌지는 각각 얼마인가요?
import openai
import os
from dotenv import load_dotenv
load_dotenv()
query = "닭과 소를 합쳐서 20마리를 기르고 있습니다. 농부가 기르는 동물의 다리 수는 총 56개일 때, 닭과 소의 수는 각각 몇 마리인가요?"

# advanced_cot_template은 utils.py에 정의된 함수입니다.
from utils import few_shot_cot

client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
print(few_shot_cot(client, query))
1. 변수 정의:
- 닭의 수를 x, 소의 수를 y로 정의합니다.

2. 방정식 설정:
- 닭과 소를 합쳐서 20마리를 기르고 있으므로 x + y = 20
- 농부가 기르는 동물의 다리 수는 총 56개이므로 2x + 4y = 56

3. 계산 과정:
- 위의 두 방정식을 활용하여 x와 y 값을 구합니다.
- x + y = 20 → x = 20 - y
- 2(20 - y) + 4y = 56
- 40 - 2y + 4y = 56
- 2y = 16
- y = 8
- x = 20 - 8 = 12

4. 검토:
- 닭과 소의 수를 각각 12마리와 8마리로 계산하였습니다.
- 다리 수를 확인해보겠습니다. 닭은 2개의 다리, 소는 4개의 다리를 가지므로 전체 다리 수는 12*2 + 8*4 = 56으로 맞는 것을 확인할 수 있습니다.

5. 최종 답변:
- 농부가 기르는 닭은 12마리, 소는 8마리입니다.
반응형