4.4K
혹시 학창 시절 수학 선생님께서 “풀이 과정도 점수에 포함된다!”라고 말씀하셨던 기억이 나는가? 답만 맞히는 게 중요한 게 아니고, 정답에 이르는 논리적인 과정을 제대로 이해하는 능력이 중요했기 때문이다.

AI, 즉 LLM의 할루시네이션을 줄일 때도 이런 메커니즘이 필요하다. 생각의 사슬(Chain-of-Thought, CoT) 프롬프팅은 바로 이 원리를 LLM에게 적용하는 것이다. LLM에게 단순히 답을 ‘찍는’ 대신, 문제 해결 과정을 ‘차근차근 생각하고 설명하도록’ 유도하여 복잡한 추론 능력과 정확성을 높이는 기법이다.
인간은 문제가 생기면 ‘주어진 조건이 무엇인지 확인하고, 어떤 공식을 적용할 수 있는지 생각한 뒤, 계산을 수행하고, 결과를 검토한다.’ 같은 단계적인 사고 과정을 거친다. 이는 인간 지성의 중요한 특징이다.
CoT 프롬프팅은 이런 인간이 가진 특성을 LLM에게 강제로 주입하는 것과 같다. 핵심은 LLM에게 “이 문제를 풀기 위해 어떤 단계를 거쳐야 하고, 각 단계의 결과는 무엇이며, 최종 답은 어떻게 도출되는가?”라고 스스로 단계적 사고 과정을 밟을 수 있도록 묻는 것이다.

CoT는 LLM의 사고 과정을 들여다볼 수 있는 이점을 제공한다. 모델이 어떤 논리를 따라 결론에 도달했는지, 중간에 어떤 가정이나 계산을 했는지, 혹시 오류가 있다면 어느 단계에서 발생했는지 추적하고 분석할 수 있기 때문이다. 이는 LLM의 예측 불가능성을 줄이고 신뢰도를 높이며 모델의 작동 방식을 이해하고 개선하는 데 중요한 단서를 제공한다.
그럼 프롬프트 엔지니어의 입장에서, 실제로 어떻게 LLM에게 생각의 사슬을 생성하도록 유도할 수 있을까? 핵심은 모델이 답을 바로 내놓는 것이 아니라, 중간 추론 과정을 단계적으로 드러내도록 유도하는 문구와 구조를 프롬프트에 포함하는 것이다. 가장 단순한 형태는 질문과 함께 “단계별로 생각의 과정을 서술하라.”라는 지시를 추가하는 것이다.
퓨샷(Few-Shot) CoT는 프롬프트 내에 해결하고자 하는 문제와 유사한 여러 개의 완전한 [예시] 세트를 포함시키는 것이다. 단순히 질문과 답만 있는 것이 아니라 질문, 그에 대한 단계별 추론 과정(생각의 사슬), 그리고 최종 답까지 모두 보여주는 것을 의미한다. 마치 학생에게 여러 서술형 문제와 그 모범 풀이 과정을 함께 제공하여 학습시키는 것과 같다.


결과에서 볼 수 있듯 모델은 프롬프트에 제공된 예시의 상세한 절차를 학습하여 새로운 단어 ‘엔지니어링’에 대해서도 동일한 단계(음절 분해, 자모 분해, 목표 모음 식별, 계수)를 거쳐 정확한 답 ‘3’을 도출했다.
제로샷(Zero-Shot) CoT는 목적지만 알려주고 “스스로 길을 찾아보라”라고 격려하는 방식에 가깝다.
질문: ‘엔지니어링’이라는 단어에 ‘ㅣ’ 모음은 총 몇 개가 있나요? 단계별로 생각의 과정을 순차적으로 이어주고, 그 단계들의 서술을 바탕으로 최종적인 결론을 내려주세요. |

놀랍게도 별도의 예시 없이 “단계별로 생각해보자.”라는 문구만 추가했음에도 불구하고 모델이 스스로 필요한 추론 과정(음절 분해, 자모 분해, 목표 모음 식별, 계수)을 생성하며 정확한 답 ‘3’에 도달했다. 이는 LLM이 이미 내부적으로 문제 해결을 위한 다양한 절차적 지식을 갖추고 있으며 적절한 트리거를 통해 이를 활성화할 수 있음을 보여주는 흥미로운 사례다. 하지만 퓨샷만큼 안정적이거나 정확한 결과를 보장할 수는 없다.
직접 코드 예제를 만들어보며 조금 더 난이도 있는 문제를 해결해보자. CoT를 적용했을 때와 그렇지 않았을 때 LLM의 문제 해결 능력이 어떻게 달라지는지 지켜보며 CoT의 효과를 확인할 수 있다. 도전할 문제는 다음과 같은 여러 단계의 논리 구성을 요구하는 문제다.
세 명의 친구, 지아, 민준, 서연이가 각자 다른 종류의 과일 주스를 샀습니다. 주스 종류는 파인애플 주스, 바나나 주스, 딸기 주스 세 가지입니다. 다음 단서들을 이용해 누가 어떤 주스를 샀는지 알아내세요.
1. 서연이 산 주스에 사용한 과일의 한국어 이름은 민준이 산 과일 글자보다 크다. 2. 지아가 산 주스의 과일은 민준이 산 주스의 과일보다 일반적으로 크기가 작다. 3. 민준이 산 주스에 사용한 과일의 영어 이름에서 알파벳 모음 총 개수는 2보다 크다. |
CoT를 사용하지 않는 프롬프팅 방식과 제로샷 CoT 방식을 순차적으로 적용하여 결과를 비교하는 코드를 살펴보자. 우선 코드 예제는 다음과 같다.
(..생략..)
def call_openai_api(messages: list[str], temperature: float = 0.0) -> str:
max_retries = 3
for attempt in range(max_retries):
try:
completion = client.chat.completions.create(
model="gpt-4o",
messages=messages,
temperature=temperature,
)
return completion.choices[0].message.content
except (APIError, RateLimitError) as e:
print(
f"API 오류 발생 (시도 {attempt + 1}/{max_retries}): {e}. 잠시 후 재시도합니다..."
)
if attempt = = max_retries - 1:
return f"오류: API 호출 실패 ({e})"
time.sleep(2**attempt)
except Exception as e:
print(f"알 수 없는 오류 발생: {e}")
return f"오류: {e}"
return "알 수 없는 오류로 응답 생성 실패"
logical_problem = """
세 명의 친구, 지아, 민준, 서연이가 각자 다른 종류의 과일 주스를 샀습니다.
주스 종류는 파인애플 주스, 바나나 주스, 딸기 주스 세 가지입니다.
다음 단서들을 이용해 누가 어떤 주스를 샀는지 알아내세요.
1. 서연이 산 주스에 사용한 과일의 한국어 이름은 민준이 산 과일 글자보다 크다.
2. 지아가 산 주스의 과일은 민준이 산 주스의 과일보다 일반적으로 크기가 작다.
3. 민준이 산 주스에 사용한 과일의 영어 이름에서 알파벳 모음 총 개수는 2보다 크다.
""".strip()
# 정답:
# 지아 딸기
# 민준 바나나
# 서연 파인애플
print("--- 1. CoT가 사용되지 않은 프롬프트 방식 ---")
previous_prompt = f"""
다음 논리 문제를 풀어주세요:
문제:
{logical_problem}
아래 결과를 먼저 설명하고, 그 뒤 그 이유를 단계적으로 설명하세요.
지아: [과일 이름]
민준: [과일 이름]
서연: [과일 이름]
"""
standard_messages = [{"role": "user", "content": previous_prompt}]
result_standard = call_openai_api(standard_messages, temperature=0)
print("[CoT가 사용되지 않은 프롬프팅 결과]")
print(result_standard)
print("-" * 30)
print("--- 2. Zero-Shot CoT 프롬프트 방식 ---")
cot_prompt = f"""
다음 논리 문제를 풀어주세요:
문제:
{logical_problem}
단계별로 생각해서 각 단서를 어떻게 적용했는지 설명하고, 최종 답을 다음 형식으로 제시해
주세요.
지아: [과일 이름]
민준: [과일 이름]
서연: [과일 이름]
"""
cot_messages = [{"role": "user", "content": cot_prompt}]
result_cot = call_openai_api(cot_messages, temperature=0)
print("\n[Zero-Shot CoT 프롬프팅 결과]")
print(result_cot)
print("-" * 30)
이 코드에 대한 실행 결과는 다음과 같다.
[실행 결과]
--- 1. CoT가 사용되지 않은 프롬프트 방식 ---
[CoT가 사용되지 않은 프롬프팅 결과]
결과:
지아: 딸기 주스
민준: 파인애플 주스
서연: 바나나 주스
이유를 단계적으로 설명하겠습니다:
1. **단서 3**을 먼저 살펴보겠습니다. 민준이 산 주스에 사용한 과일의 영어 이름에서 알파
벳 모음의 개수가 2보다 커야 합니다.
- Pineapple (파인애플): 모음 4개 (i, e, a, e)
- Banana (바나나): 모음 3개 (a, a, a)
- Strawberry (딸기): 모음 2개 (a, e)
따라서, 민준은 파인애플 주스나 바나나 주스를 샀을 수 있습니다.
2. **단서 1**을 살펴보겠습니다. 서연이 산 주스에 사용한 과일의 한국어 이름은 민준이 산
과일 이름보다 글자 수가 많아야 합니다.
- 파인애플 (5글자)
- 바나나 (3글자)
- 딸기 (2글자)
민준이 파인애플 주스를 샀다면, 서연은 바나나 주스를 살 수 있습니다. 민준이 바나나 주스
를 샀다면, 서연은 파인애플 주스를 살 수 있습니다.
3. **단서 2**를 살펴보겠습니다. 지아가 산 주스의 과일은 민준이 산 주스의 과일보다 일반
적으로 크기가 작아야 합니다.
- 일반적으로 과일의 크기를 비교하면, 딸기 < 바나나 < 파인애플입니다.
따라서, 민준이 파인애플 주스를 샀다면, 지아는 딸기 주스를 살 수 있습니다. 민준이 바나나
주스를 샀다면, 지아는 딸기 주스를 살 수 있습니다.
4. 모든 단서를 종합해보면:
- 민준이 파인애플 주스를 샀을 때, 서연은 바나나 주스를 사고, 지아는 딸기 주스를 사는 것
이 모든 조건을 만족합니다.
따라서, 최종적으로:
- 지아: 딸기 주스
- 민준: 파인애플 주스
- 서연: 바나나 주스
------------------------------
--- 2. Zero-Shot CoT 프롬프트 방식 ---
[Zero-Shot CoT 프롬프팅 결과]
이 문제를 해결하기 위해 주어진 단서를 단계별로 분석해 보겠습니다.
1. **단서 1**: 서연이 산 주스에 사용한 과일의 한국어 이름은 민준이 산 과일 글자보다 크다.
- 과일 이름의 글자 수를 비교합니다.
- 파인애플(5글자), 바나나(3글자), 딸기(2글자)
- 따라서, 서연이 산 주스는 파인애플 주스일 가능성이 높습니다.
2. **단서 2**: 지아가 산 주스의 과일은 민준이 산 주스의 과일보다 일반적으로 크기가 작다.
- 일반적인 과일 크기를 비교합니다.
- 딸기 < 바나나 < 파인애플
- 따라서, 지아가 산 주스는 딸기 주스일 가능성이 높습니다.
3. **단서 3**: 민준이 산 주스에 사용한 과일의 영어 이름에서 알파벳 모음 총 개수는 2보다
크다.
- 영어 이름의 모음 개수를 세어봅니다.
- Pineapple (4개: i, e, a, e), Banana (3개: a, a, a), Strawberry (2개: a, e)
- 따라서, 민준이 산 주스는 바나나 주스일 가능성이 높습니다.
이제 각 단서를 종합하여 결론을 내리겠습니다.
최종 답:
지아: 딸기
민준: 바나나
서연: 파인애플
------------------------------
CoT를 적용하지 않았을 때 결과를 먼저 살펴보자. 모델은 초기에 별다른 설명 없이 “지아: 딸기 주스, 민준: 파인애플 주스, 서연: 바나나 주스”라는 답을 먼저 제시했다. 하지만 이는 명백한 오답이다. 추론 과정이 투명하지 않아 왜 글자 수 오류가 발생했는지, 어떻게 단서들을 종합하여 그 결론에 도달했는지 정확히 알기 어렵다.
반면, “단계별로 생각해서...”라는 CoT 지시어를 사용한 결과를 보자. 모델은 훨씬 체계적이고 정확한 추론 과정을 보여주었다. 단서 3(영어 알파벳 모음 수)을 올바르게 분석하여 민준이 딸기 주스를 살 수 없음을 먼저 배제하고, 이를 바탕으로 단서 1(글자 수)과 단서 2(과일 크기)를 순차적으로 적용하여 가능한 경우의 수를 좁혀 나갔다. 이 논리적인 과정을 통해 최종적으로 정답을 도출했다. 재밌는 점은 답은 맞았지만 이 결과에서 모델은 파인애플을 5글자라고 오인하고 있다.
만약 우리가 CoT 프롬프트를 사용하지 않았다면 이런 문제가 있음을 감지하지 못했을 것이다. 이렇게 발견된 오류로 인해 이후 “각 과일의 한국어 이름을 글자 단위로 분해하고 그 개수를 정확히 세어 비교하라.”와 같이 더욱 구체적인 지침을 제공하여 잠재적 문제점을 해결할 수 있을 것이다. 이는 CoT가 추론 과정의 세밀한 제어를 통해 특정 유형의 오류를 예방하는 데에도 기여할 수 있음을 보여준다.
*위 콘텐츠는 『할루시네이션을 줄여주는 프롬프트 엔지니어링』내용을 기반으로 작성하였습니다.

댓글