3편. LLM의 성능을 끌어올리는 프롬프트 엔지니어링

·4분 읽기·
목차

지난 글에서는 ChatGPT API를 이용해 실제로 LLM(Large Language Model)을 사용하는 방법을 알아봤습니다. 그런데 같은 모델을 써도, 어떻게 질문을 던지는지(프롬프트 엔지니어링)에 따라 결과의 품질이 완전히 달라질 수 있습니다.

이번 글에서는 대표적인 프롬프팅 기법들(제로샷, 원샷, 퓨샷, CoT, Self-Consistency)을 실제 프롬프트(시스템 프롬프트)와 사용자의 질문(유저 인풋)으로 명확히 나눠서, 코드와 함께 차근차근 살펴보겠습니다.


1. 제로샷(Zero-shot) 프롬프팅

제로샷은 아무 예시 없이 모델에게 바로 원하는 작업을 지시하는 방식입니다. 제일 간단하고 빠르게 결과를 얻을 수 있지만, 가끔 모델이 제대로 이해 못 하면 결과가 정확하지 않을 수도 있습니다.

하지만 모델이 작업을 잘 이해하지 못하면 정확도가 낮습니다.

📌 프롬프트 예시

시스템 프롬프트

markdown
다음 문장을 긍정, 부정 중 하나로 분류하세요.

유저 인풋

python
오늘 날씨가 좋아서 정말 행복해.

💻 코드 예시

python
import openai

system_prompt = "다음 문장을 긍정, 부정 중 하나로 분류하세요."
user_input = "오늘 날씨가 좋아서 정말 행복해."

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role":"system", "content": system_prompt},
        {"role":"user", "content": user_input}
    ]
)

print(response.choices[0].message.content)

2. 원샷(One-shot) 프롬프팅

제로샷이 부족할 때는 모델에게 한 개의 명확한 예시를 미리 보여줍니다. 그러면 모델이 작업의 형식을 더 잘 이해하게 되어, 결과의 정확성을 높일 수 있습니다.

하지만 복잡한 문제에서는 효과가 제한적입니다.

📌 프롬프트 예시

시스템 프롬프트

문장의 감정을 긍정, 부정으로 분류하세요.
예시: '영화가 정말 재밌었어.' → 긍정

유저 인풋

python
오늘 하루 정말 피곤하고 짜증나.

💻 코드 예시

python
import openai

system_prompt = """
문장의 감정을 긍정, 부정으로 분류하세요.
예시: '영화가 정말 재밌었어.' → 긍정
"""
user_input = "오늘 하루 정말 피곤하고 짜증나."

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role":"system", "content": system_prompt},
        {"role":"user", "content": user_input}
    ]
)

print(response.choices[0].message.content)

3. 퓨샷(Few-shot) 프롬프팅

하나의 예시로 부족한 경우, 여러 개의 예시를 제공하는 방식입니다. 모델이 작업의 패턴을 더욱 명확히 이해할 수 있어서 복잡하거나 정확도가 중요한 작업에 적합합니다.

하지만 입력 길이가 늘어나 비용이 증가할 수 있습니다.

📌 프롬프트 예시

시스템 프롬프트

문장의 감정을 긍정, 부정으로 분류하세요.

예시1: '오늘 맛있는 걸 먹어서 너무 좋아.' → 긍정
예시2: '친구랑 싸워서 기분이 안 좋아.' → 부정
예시3: '시험 성적이 좋아서 행복해.' → 긍정

유저 인풋

python
일이 많아서 정말 힘들다.

💻 코드 예시

python
import openai

system_prompt = """
문장의 감정을 긍정, 부정으로 분류하세요.

예시1: '오늘 맛있는 걸 먹어서 너무 좋아.' → 긍정
예시2: '친구랑 싸워서 기분이 안 좋아.' → 부정
예시3: '시험 성적이 좋아서 행복해.' → 긍정
"""

user_input = "일이 많아서 정말 힘들다."

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role":"system", "content": system_prompt},
        {"role":"user", "content": user_input}
    ]
)

print(response.choices[0].message.content)

4. 사고의 연쇄(CoT, Chain-of-Thought) 프롬프팅

사고의 연쇄(CoT) 프롬프팅은 모델이 추론 과정(사고 과정)을 단계별로 자세히 표현하도록 유도하는 방법입니다. 복잡한 문제를 해결할 때 매우 효과적이며, 모델의 논리적인 추론 능력을 높일 수 있습니다. 단순히 답만 제공하는 것이 아니라 답에 이르는 과정을 표현하게 하여, 모델이 올바르게 사고하고 있는지 확인할 수 있습니다.

하지만 응답 길이가 늘어나 처리 비용이 증가할 수 있습니다.

📌 프롬프트 예시

시스템 프롬프트

당신은 문제를 단계별로 설명하며 정답을 구하는 도우미입니다. 질문이 들어오면 각 단계를 명확히 나누어서 최종 답을 제시하세요.

유저 인풋

python
민수는 도서관에서 책 3권을 빌렸고, 친구에게서 2권을 더 받았다. 그 후 자신이 가진 책 중에서 4권을 반납했습니다. 민수에게는 지금 책이 몇 권 남았는지 단계별로 설명하세요.

💻 코드 예시

python
import openai

system_prompt = """
당신은 문제를 단계별로 설명하며 정답을 구하는 도우미입니다. 질문이 들어오면 각 단계를 명확히 나누어서 최종 답을 제시하세요.
"""

user_input = """
민수는 도서관에서 책 3권을 빌렸고, 친구에게서 2권을 더 받았다. 그 후 자신이 가진 책 중에서 4권을 반납했습니다. 민수에게는 지금 책이 몇 권 남았는지 단계별로 설명하세요.
"""

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

print(response.choices[0].message.content

5. 자기 일관성(Self-Consistency) 프롬프팅

자기 일관성 프롬프팅은 모델에게 동일한 질문을 여러 번 던지고, 모델이 가장 일관되게 내놓는 답을 최종 답변으로 선정하는 방식입니다. 모델이 혼란스러워 할 수 있는 질문에서도 신뢰할 수 있는 답을 얻을 수 있습니다.

하지만 반복 호출로 인해 비용이 증가할 수 있습니다.

📌 프롬프트 예시

시스템 프롬프프트

당신은 수학 문제를 단계별로 정확히 풀이하는 도우미입니다.

유저 인풋

python
(8 ÷ 2) × (2 + 2)의 값을 단계별로 풀이해서 알려주세요.

💻 코드 예시

python
import openai
from collections import Counter

system_prompt = """
당신은 수학 문제를 단계별로 정확히 풀이하는 도우미입니다.
"""

user_input = "(8 ÷ 2) × (2 + 2)의 값을 단계별로 풀이해서 알려주세요."

answers = []
for _ in range(3):
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role":"system", "content": system_prompt},
            {"role":"user", "content": user_input}
        ],
        temperature=0.7
    )
    answers.append(response.choices[0].message.content)

most_common_answer = Counter(answers).most_common(1)[0][0]

print(most_common_answer)

마무리

프롬프트 엔지니어링을 제대로 하면 LLM의 성능을 훨씬 더 효과적으로 끌어올릴 수 있습니다. 이번 글에서는 제로샷부터 자기 일관성까지 다양한 프롬프팅 방법들을 실제 예시와 함께 알아봤습니다.

다음 글에서는 LLM 활용의 수준을 한 단계 더 끌어올릴 수 있는 RAG(Retrieval-Augmented Generation) 기법에 대해서 알아보고, 실제로 활용한 프로젝트 사례도 함께 살펴보겠습니다.