Prompt Engineering 완벽 가이드 | 구조화된 프롬프트 설계 기법
이 글의 핵심
LLM의 성능을 극대화하는 Prompt Engineering 기법. Zero-shot, Few-shot, Chain-of-Thought, ReAct 패턴부터 시스템 프롬프트 설계, 실전 최적화까지 단계별로 설명합니다.
들어가며
Prompt Engineering은 LLM(대규모 언어 모델)에서 원하는 결과를 얻기 위해 입력(프롬프트)을 체계적으로 설계하는 기술입니다. 같은 GPT-4 모델이라도 프롬프트에 따라 정확도가 20%에서 80%까지 차이 날 수 있습니다. 단순히 “질문을 잘 쓴다”를 넘어, 구조화된 지시, 예제 제공, 사고 과정 유도 등의 기법을 활용합니다.
이 글은 Zero-shot, Few-shot, Chain-of-Thought, ReAct 등 핵심 패턴과, 시스템 프롬프트 설계, 실전 최적화 기법을 코드 예제와 함께 설명합니다.
목차
- Prompt Engineering이란?
- 기본 패턴: Zero-shot vs Few-shot
- Chain-of-Thought (CoT)
- ReAct: 추론 + 행동
- 시스템 프롬프트 설계
- 실전 패턴
- 최적화 기법
- 평가 및 개선
- 실무 사례
- 트러블슈팅
- 마무리
Prompt Engineering이란?
기본 개념
프롬프트 구조:
[시스템 프롬프트] (역할, 제약사항, 출력 형식)
+
[사용자 프롬프트] (작업, 입력 데이터, 예제)
→
[모델 응답]
왜 중요한가?
나쁜 프롬프트:
사용자: 이 텍스트를 분석해줘.
모델: 어떤 관점에서 분석할까요? 감정 분석? 주제 분류?
좋은 프롬프트:
사용자: 다음 고객 리뷰를 긍정/부정/중립로 분류하고,
주요 키워드 3개를 추출하세요.
리뷰: "배송은 빨랐지만 제품 품질이 기대에 못 미쳤습니다."
출력 형식:
- 감정: [긍정/부정/중립]
- 키워드: [키워드1, 키워드2, 키워드3]
모델:
- 감정: 부정
- 키워드: [배송, 품질, 기대]
프롬프트 구성 요소
1. 역할 (Role)
당신은 20년 경력의 C++ 전문가입니다.
2. 작업 (Task)
다음 코드의 메모리 누수를 찾아 수정하세요.
3. 맥락 (Context)
이 코드는 멀티스레드 서버 환경에서 실행됩니다.
4. 제약사항 (Constraints)
- C++17 표준만 사용
- 외부 라이브러리 사용 금지
- 성능 저하 최소화
5. 출력 형식 (Format)
다음 형식으로 답변하세요:
1. 문제점
2. 수정된 코드
3. 설명
기본 패턴: Zero-shot vs Few-shot
Zero-shot Learning
정의: 예제 없이 지시만으로 작업 수행
예제: 감정 분석
from openai import OpenAI
client = OpenAI(api_key="your-api-key")
prompt = """다음 리뷰의 감정을 긍정/부정/중립로 분류하세요.
리뷰: "배송이 너무 느렸어요. 2주나 걸렸습니다."
감정:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
print(response.choices[0].message.content) # "부정"
장점: 간단, 빠름 단점: 복잡한 작업이나 특정 포맷에는 부정확
Few-shot Learning
정의: 몇 개의 예제를 제공하여 패턴 학습
예제: 코드 주석 생성
prompt = """다음 예제를 참고하여 코드에 주석을 추가하세요.
예제 1:
입력:
def add(a, b):
return a + b
출력:
def add(a, b):
\"\"\"두 숫자를 더합니다.\"\"\"
return a + b
예제 2:
입력:
def find_max(arr):
return max(arr)
출력:
def find_max(arr):
\"\"\"배열에서 최댓값을 찾습니다.\"\"\"
return max(arr)
이제 다음 코드에 주석을 추가하세요:
입력:
def calculate_average(numbers):
return sum(numbers) / len(numbers)
출력:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
print(response.choices[0].message.content)
# def calculate_average(numbers):
# \"\"\"숫자 리스트의 평균을 계산합니다.\"\"\"
# return sum(numbers) / len(numbers)
장점: 높은 정확도, 특정 포맷 학습 단점: 토큰 사용량 증가, 예제 선정 필요
Few-shot 예제 선정 전략
1. 다양성 확보
# ❌ 비슷한 예제만
예제 1: "좋아요" → 긍정
예제 2: "훌륭해요" → 긍정
예제 3: "최고예요" → 긍정
# ✅ 다양한 예제
예제 1: "좋아요" → 긍정
예제 2: "별로예요" → 부정
예제 3: "그냥 그래요" → 중립
2. 엣지 케이스 포함
prompt = """다음 예제를 참고하여 이메일 주소를 추출하세요.
예제 1:
입력: "연락처: [email protected]"
출력: [email protected]
예제 2:
입력: "이메일이 없습니다."
출력: (없음)
예제 3:
입력: "[email protected]과 [email protected]에게 보내세요."
출력: [email protected], [email protected]
입력: "{user_input}"
출력:"""
Chain-of-Thought (CoT)
기본 CoT
정의: 모델이 단계적으로 사고하도록 유도
예제: 수학 문제
# ❌ Zero-shot (정확도 낮음)
prompt = """문제: 사과 3개에 1000원, 5개 사면 얼마인가요?
답:"""
# ✅ Chain-of-Thought
prompt = """문제: 사과 3개에 1000원, 5개 사면 얼마인가요?
단계별로 풀어보세요:
1. 사과 1개 가격 계산
2. 5개 가격 계산
3. 최종 답변
풀이:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
print(response.choices[0].message.content)
# 1. 사과 1개 가격: 1000원 ÷ 3 = 약 333.33원
# 2. 5개 가격: 333.33원 × 5 = 1666.65원
# 3. 최종 답변: 약 1667원
Few-shot CoT
예제: 논리 추론
prompt = """다음 예제를 참고하여 논리적으로 추론하세요.
예제:
질문: 모든 고양이는 동물이다. 톰은 고양이다. 톰은 동물인가?
추론:
1. 전제 1: 모든 고양이는 동물이다
2. 전제 2: 톰은 고양이다
3. 결론: 톰은 고양이이므로, 톰은 동물이다
답: 예
이제 다음 질문에 답하세요:
질문: 모든 프로그래머는 컴퓨터를 사용한다. 앨리스는 컴퓨터를 사용한다. 앨리스는 프로그래머인가?
추론:"""
# 모델 응답:
# 1. 전제 1: 모든 프로그래머는 컴퓨터를 사용한다
# 2. 전제 2: 앨리스는 컴퓨터를 사용한다
# 3. 분석: 전제 1은 "프로그래머 → 컴퓨터 사용"이지만,
# "컴퓨터 사용 → 프로그래머"는 아니다 (역은 성립 안 함)
# 답: 알 수 없음 (디자이너, 작가 등도 컴퓨터 사용 가능)
Self-Consistency
정의: 같은 질문을 여러 번 실행하여 다수결로 답 선택
def self_consistency(prompt: str, n: int = 5) -> str:
"""같은 프롬프트를 n번 실행하여 가장 많은 답 반환"""
from collections import Counter
answers = []
for _ in range(n):
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.7 # 다양성을 위해 temperature 증가
)
answer = response.choices[0].message.content.strip()
answers.append(answer)
# 가장 많이 나온 답 반환
most_common = Counter(answers).most_common(1)[0][0]
return most_common
# 사용
prompt = """문제: 52장의 카드에서 2장을 뽑을 때, 둘 다 하트일 확률은?
단계별로 계산하세요."""
answer = self_consistency(prompt, n=5)
print(answer)
ReAct: 추론 + 행동
ReAct 패턴
정의: Reasoning (추론) + Acting (행동)을 반복
구조:
Thought: 무엇을 해야 하는지 생각
Action: 도구 실행 (검색, 계산, API 호출 등)
Observation: 결과 관찰
... (반복)
Answer: 최종 답변
예제: 정보 검색 + 추론
prompt = """다음 형식으로 질문에 답하세요:
Thought: 무엇을 해야 하는지 생각
Action: [Search/Calculate/Finish]
Action Input: 실행할 내용
Observation: 결과
... (필요시 반복)
Answer: 최종 답변
질문: C++26의 Static Reflection은 언제 표준화되었나요?
Thought:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
print(response.choices[0].message.content)
# Thought: C++26 표준화 시점을 검색해야 합니다.
# Action: Search
# Action Input: "C++26 standardization date"
# Observation: C++26은 2026년 3월 ISO 회의에서 feature complete 되었습니다.
# Thought: 정보를 찾았으므로 답변할 수 있습니다.
# Action: Finish
# Answer: C++26은 2026년 3월에 feature complete 되었습니다.
도구 통합 ReAct
import json
def react_agent(question: str, max_iterations: int = 5):
"""ReAct 패턴으로 질문 답변"""
conversation = []
system_prompt = """당신은 도구를 사용할 수 있는 AI 어시스턴트입니다.
사용 가능한 도구:
- Search: 웹 검색
- Calculate: 수학 계산
- PythonREPL: Python 코드 실행
다음 형식으로 응답하세요:
Thought: 다음에 무엇을 해야 하는지
Action: [Search/Calculate/PythonREPL/Finish]
Action Input: 실행할 내용"""
conversation.append({"role": "system", "content": system_prompt})
conversation.append({"role": "user", "content": f"질문: {question}\n\nThought:"})
for i in range(max_iterations):
# LLM 호출
response = client.chat.completions.create(
model="gpt-4",
messages=conversation,
temperature=0
)
output = response.choices[0].message.content
conversation.append({"role": "assistant", "content": output})
# Action 파싱
if "Action: Finish" in output:
# 최종 답변 추출
answer = output.split("Answer:")[-1].strip()
return answer
# Action 실행
if "Action: Search" in output:
query = output.split("Action Input:")[-1].strip()
result = web_search(query) # 실제 검색 함수
conversation.append({
"role": "user",
"content": f"Observation: {result}\n\nThought:"
})
elif "Action: Calculate" in output:
expr = output.split("Action Input:")[-1].strip()
result = eval(expr) # 주의: 실제로는 안전한 계산기 사용
conversation.append({
"role": "user",
"content": f"Observation: {result}\n\nThought:"
})
return "최대 반복 횟수 초과"
# 사용
answer = react_agent("52장 카드에서 2장을 뽑을 때 둘 다 하트일 확률은?")
시스템 프롬프트 설계
기본 구조
system_prompt = """당신은 [역할]입니다.
[핵심 원칙]
- 원칙 1
- 원칙 2
- 원칙 3
[제약사항]
- 제약 1
- 제약 2
[출력 형식]
- 형식 설명
[예제]
입력: ...
출력: ..."""
실전 예제: 코드 리뷰 봇
system_prompt = """당신은 시니어 소프트웨어 엔지니어로, 코드 리뷰를 수행합니다.
핵심 원칙:
- 가독성, 유지보수성, 성능, 보안 관점에서 검토
- 구체적인 개선 제안 제공
- 긍정적이고 건설적인 톤 유지
제약사항:
- 사소한 스타일 지적은 피하기
- 실제 문제가 있을 때만 지적
- 대안 코드 제시
출력 형식:
## 주요 이슈
- [심각도] 문제 설명
## 개선 제안
```제안된 코드```
## 긍정적 측면
- 잘된 부분 언급"""
user_prompt = """다음 코드를 리뷰하세요:
```python
def process_users(users):
result = []
for user in users:
if user['age'] > 18:
result.append(user)
return result
```"""
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
temperature=0.3
)
실전 예제: 고객 지원 봇
system_prompt = """당신은 [회사명] 고객 지원 AI입니다.
역할:
- 제품 문의, 기술 지원, 주문 관련 질문 답변
- 친절하고 전문적인 톤 유지
- 확실하지 않은 정보는 전문 상담사 연결 안내
제약사항:
- 개인정보 요청 금지 (주민번호, 카드번호 등)
- 환불/교환은 정책 범위 내에서만 안내
- 의료/법률 조언 금지
답변 형식:
1. 질문 이해 확인
2. 해결 방법 제시
3. 추가 도움 필요 여부 확인
예제:
고객: 제품이 작동하지 않아요.
답변:
제품이 작동하지 않는다니 불편을 드려 죄송합니다.
다음 단계를 시도해 보시겠어요?
1. 전원 버튼을 5초간 눌러 재시작
2. 최신 펌웨어 업데이트 확인
3. 초기화 후 재설정
위 방법으로 해결되지 않으면, 전문 상담사와 연결해 드리겠습니다.
추가로 도움이 필요하신가요?"""
실전 패턴
1. 구조화된 출력 (JSON)
prompt = """다음 텍스트에서 정보를 추출하여 JSON 형식으로 출력하세요.
텍스트: "홍길동 고객님의 주문 번호는 A12345이며, 배송지는 서울시 강남구입니다. 연락처는 010-1234-5678입니다."
출력 형식:
{
"name": "고객명",
"order_id": "주문번호",
"address": "배송지",
"phone": "연락처"
}
JSON:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0,
response_format={"type": "json_object"} # JSON 모드 강제
)
data = json.loads(response.choices[0].message.content)
print(data)
# {
# "name": "홍길동",
# "order_id": "A12345",
# "address": "서울시 강남구",
# "phone": "010-1234-5678"
# }
2. 다단계 프롬프트 체인
def multi_step_analysis(text: str) -> dict:
"""다단계 분석 파이프라인"""
# 1단계: 주제 추출
prompt1 = f"다음 텍스트의 주요 주제 3개를 추출하세요:\n\n{text}\n\n주제:"
topics = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt1}],
temperature=0
).choices[0].message.content
# 2단계: 감정 분석
prompt2 = f"다음 텍스트의 감정을 분석하세요 (긍정/부정/중립):\n\n{text}\n\n감정:"
sentiment = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt2}],
temperature=0
).choices[0].message.content
# 3단계: 요약 (이전 결과 활용)
prompt3 = f"""다음 텍스트를 요약하세요.
텍스트: {text}
주제: {topics}
감정: {sentiment}
위 정보를 바탕으로 한 문장 요약:"""
summary = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt3}],
temperature=0
).choices[0].message.content
return {
"topics": topics,
"sentiment": sentiment,
"summary": summary
}
3. 템플릿 기반 프롬프트
from string import Template
code_review_template = Template("""다음 $language 코드를 리뷰하세요.
초점:
$focus_areas
코드:
```$language
$code
리뷰:""")
사용
prompt = code_review_template.substitute( language=“Python”, focus_areas=”- 성능\n- 보안\n- 가독성”, code=“def process(data):\n return [x*2 for x in data]” )
response = client.chat.completions.create( model=“gpt-4”, messages=[{“role”: “user”, “content”: prompt}], temperature=0.3 )
### 4. 역할 기반 프롬프트
```python
def get_expert_opinion(topic: str, question: str, expert_role: str) -> str:
"""특정 전문가 역할로 답변"""
system_prompt = f"""당신은 {expert_role}입니다.
해당 분야의 깊은 전문 지식을 바탕으로 답변하세요.
- 전문 용어 사용 가능
- 실무 경험 기반 조언
- 구체적인 예제 제공"""
user_prompt = f"주제: {topic}\n\n질문: {question}"
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
temperature=0.7
)
return response.choices[0].message.content
# 사용
answer = get_expert_opinion(
topic="C++ 메모리 관리",
question="스마트 포인터를 언제 사용해야 하나요?",
expert_role="20년 경력의 C++ 시스템 프로그래머"
)
최적화 기법
1. 명확한 지시
❌ 모호한 프롬프트:
이 코드를 개선해줘.
✅ 명확한 프롬프트:
다음 Python 코드를 개선하세요:
개선 목표:
1. 시간 복잡도를 O(n²)에서 O(n)으로 개선
2. 변수명을 더 명확하게 변경
3. 타입 힌트 추가
코드:
[코드 입력]
개선된 코드:
2. 구분자 사용
prompt = """다음 세 개의 텍스트를 각각 요약하세요.
###텍스트 1###
{text1}
###텍스트 2###
{text2}
###텍스트 3###
{text3}
각 텍스트를 한 문장으로 요약:
1. 텍스트 1:
2. 텍스트 2:
3. 텍스트 3:"""
3. 단계별 지시
prompt = """다음 작업을 순서대로 수행하세요:
1단계: 텍스트에서 모든 이메일 주소 추출
2단계: 각 이메일의 도메인 추출
3단계: 도메인별로 그룹화
4단계: JSON 형식으로 출력
텍스트:
[email protected]과 [email protected], [email protected]에게 이메일을 보냈습니다.
1단계 결과:"""
4. 제약사항 명시
prompt = """다음 제약사항을 준수하여 코드를 작성하세요:
제약사항:
- Python 3.10+ 표준 라이브러리만 사용
- 외부 패키지 금지
- 함수는 50줄 이하
- 타입 힌트 필수
- docstring 포함
작업: 파일에서 중복 줄을 제거하는 함수 작성
코드:"""
5. 출력 길이 제어
# 짧은 답변
prompt = "C++ 스마트 포인터를 한 문장으로 설명하세요."
# 상세한 답변
prompt = """C++ 스마트 포인터를 다음 형식으로 설명하세요:
1. 개념 (2-3 문장)
2. 종류 (unique_ptr, shared_ptr, weak_ptr)
3. 각각의 사용 예제 (코드 포함)
4. 선택 기준 (표로 정리)
최소 500단어 이상 작성하세요."""
평가 및 개선
프롬프트 평가 지표
1. 정확도 (Accuracy)
def evaluate_accuracy(test_cases: list) -> float:
"""프롬프트 정확도 측정"""
correct = 0
for case in test_cases:
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": case["prompt"]}],
temperature=0
)
prediction = response.choices[0].message.content.strip()
if prediction == case["expected"]:
correct += 1
return correct / len(test_cases)
# 사용
test_cases = [
{"prompt": "감정 분석: 최고예요!", "expected": "긍정"},
{"prompt": "감정 분석: 별로예요.", "expected": "부정"},
{"prompt": "감정 분석: 그냥 그래요.", "expected": "중립"},
]
accuracy = evaluate_accuracy(test_cases)
print(f"정확도: {accuracy * 100:.1f}%")
2. 일관성 (Consistency)
def evaluate_consistency(prompt: str, n: int = 10) -> float:
"""같은 프롬프트의 일관성 측정"""
from collections import Counter
responses = []
for _ in range(n):
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
responses.append(response.choices[0].message.content.strip())
# 가장 많은 답변의 비율
most_common_count = Counter(responses).most_common(1)[0][1]
return most_common_count / n
# 사용
consistency = evaluate_consistency("2 + 2 = ?", n=10)
print(f"일관성: {consistency * 100:.1f}%") # 100% (항상 같은 답)
A/B 테스트
def ab_test_prompts(prompt_a: str, prompt_b: str, test_cases: list):
"""두 프롬프트 비교"""
results_a = []
results_b = []
for case in test_cases:
# 프롬프트 A
response_a = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt_a.format(**case)}],
temperature=0
)
results_a.append(response_a.choices[0].message.content)
# 프롬프트 B
response_b = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt_b.format(**case)}],
temperature=0
)
results_b.append(response_b.choices[0].message.content)
# 사람이 평가하거나 자동 평가
return results_a, results_b
# 사용
prompt_a = "이 리뷰의 감정은? {review}"
prompt_b = "다음 리뷰를 긍정/부정/중립로 분류하세요: {review}"
test_cases = [
{"review": "정말 좋아요!"},
{"review": "별로였어요."},
]
results_a, results_b = ab_test_prompts(prompt_a, prompt_b, test_cases)
실무 사례
1. 코드 생성
system_prompt = """당신은 Python 전문가입니다.
요구사항:
- PEP 8 스타일 준수
- 타입 힌트 포함
- docstring 작성 (Google 스타일)
- 에러 처리 포함
- 테스트 코드 함께 제공"""
user_prompt = """다음 기능을 구현하세요:
기능: 파일에서 중복 줄을 제거하고 정렬하여 저장
입력: 파일 경로
출력: 처리된 줄 수
요구사항:
- 빈 줄 제거
- 대소문자 구분 없이 중복 제거
- 알파벳 순 정렬
코드:"""
2. 문서 요약
def summarize_document(text: str, style: str = "technical") -> str:
"""문서 요약 (스타일별)"""
styles = {
"technical": "전문 용어 사용, 핵심 개념 중심, 불릿 포인트",
"executive": "비즈니스 영향 중심, 의사결정 포인트, 간결",
"beginner": "쉬운 언어, 비유 사용, 단계별 설명"
}
prompt = f"""다음 문서를 {styles[style]} 스타일로 요약하세요.
문서:
{text}
요약 ({style} 스타일):"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.3
)
return response.choices[0].message.content
3. 번역 (컨텍스트 포함)
def translate_with_context(text: str, source: str, target: str, domain: str) -> str:
"""도메인 특화 번역"""
prompt = f"""다음 {source} 텍스트를 {target}로 번역하세요.
도메인: {domain}
- 해당 분야의 전문 용어 사용
- 자연스러운 표현
- 원문의 뉘앙스 유지
원문:
{text}
번역:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.3
)
return response.choices[0].message.content
# 사용
translation = translate_with_context(
text="Memory leak can cause performance degradation.",
source="영어",
target="한국어",
domain="소프트웨어 엔지니어링"
)
# "메모리 누수는 성능 저하를 유발할 수 있습니다."
4. 데이터 검증
def validate_data(data: str, schema: dict) -> dict:
"""데이터 검증 및 수정 제안"""
prompt = f"""다음 데이터가 스키마를 만족하는지 검증하세요.
스키마:
{json.dumps(schema, indent=2)}
데이터:
{data}
검증 결과를 JSON으로 출력:
{{
"valid": true/false,
"errors": ["에러 목록"],
"corrected": "수정된 데이터 (가능한 경우)"
}}
결과:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0,
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
트러블슈팅
문제 1: 일관성 없는 출력
원인: temperature가 너무 높음
해결:
# ❌ 창의적이지만 일관성 낮음
response = client.chat.completions.create(
model="gpt-4",
messages=[...],
temperature=1.0
)
# ✅ 일관성 높음
response = client.chat.completions.create(
model="gpt-4",
messages=[...],
temperature=0 # 결정적 출력
)
문제 2: 지시를 무시함
원인: 프롬프트가 모호하거나 제약사항이 약함
해결:
# ❌ 약한 지시
prompt = "JSON으로 출력해줘."
# ✅ 강한 지시
prompt = """다음 형식의 JSON만 출력하세요. 다른 텍스트는 포함하지 마세요.
{
"name": "...",
"age": 숫자
}
JSON:"""
# 또는 JSON 모드 강제
response = client.chat.completions.create(
model="gpt-4",
messages=[...],
response_format={"type": "json_object"}
)
문제 3: 토큰 한도 초과
원인: 프롬프트 + 응답이 컨텍스트 윈도우 초과
해결:
# 1. 프롬프트 압축
prompt = """다음 코드의 버그를 찾으세요.
핵심 로직만 보고하세요. (최대 100단어)
코드:
[...]"""
# 2. max_tokens 제한
response = client.chat.completions.create(
model="gpt-4",
messages=[...],
max_tokens=500 # 응답 길이 제한
)
# 3. 긴 문서는 청크로 분할
def process_long_document(text: str, chunk_size: int = 2000):
chunks = [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]
summaries = []
for chunk in chunks:
summary = summarize(chunk)
summaries.append(summary)
# 요약의 요약
final_summary = summarize("\n".join(summaries))
return final_summary
문제 4: 환각 (Hallucination)
원인: 모델이 사실이 아닌 정보 생성
해결:
# 1. 출처 요구
prompt = """다음 질문에 답하되, 반드시 출처를 명시하세요.
출처가 불확실하면 "확인 필요"라고 답하세요.
질문: C++26은 언제 표준화되었나요?
답변 형식:
답변: ...
출처: ..."""
# 2. 검증 단계 추가
prompt = """다음 답변이 사실인지 검증하세요.
주장: "C++26은 2025년에 표준화되었다"
검증 단계:
1. 공식 발표 확인
2. 타임라인 검증
3. 최종 판단
검증 결과:"""
# 3. RAG 사용 (외부 지식 제공)
# [RAG 가이드 참고](/blog/rag-retrieval-augmented-generation-guide/)
마무리
Prompt Engineering은 LLM을 효과적으로 사용하는 핵심 기술입니다:
핵심 원칙:
- 명확성: 모호하지 않은 지시
- 구조화: 단계별, 형식화된 출력
- 예제: Few-shot으로 패턴 학습
- 검증: 출처, 제약사항 명시
주요 패턴:
- Zero-shot: 간단한 작업
- Few-shot: 특정 포맷, 복잡한 작업
- Chain-of-Thought: 추론, 수학 문제
- ReAct: 도구 사용, 다단계 작업
실전 팁:
- 간단한 프롬프트부터 시작
- 테스트 케이스로 평가
- 반복적으로 개선
- 버전 관리 (프롬프트도 코드처럼)
다음 학습:
- RAG 가이드로 외부 지식 통합
- Python 시리즈에서 구현 기초
- 알고리즘 시리즈에서 문제 해결 패턴
참고 자료: