LLM 프롬프트 엔지니어링 고급 기법: 실전에서 바로 쓰는 프롬프트 패턴
Chain of Thought, Few-Shot Learning, Self-Consistency 등 실무에서 즉시 활용 가능한 고급 프롬프트 엔지니어링 기법을 코드 예제와 함께 소개합니다.
“처음엔 $100/월이었는데, 갑자기 $10,000/월이 나왔어요!”
이것은 많은 AI 스타트업이 겪는 현실입니다. 작은 프로토타입에서는 괜찮았던 비용이, 사용자가 늘면서 기하급수적으로 증가합니다.
GPT-4 Turbo 기준:
- 입력: $10 / 1M 토큰
- 출력: $30 / 1M 토큰
1일 10,000 대화 × 평균 2,000 토큰 = 20M 토큰
월간 비용: 20M × $30 = $600 × 30일 = $18,000
하지만 최적화하면:
동일한 서비스를 $1,800/월로 운영 가능 (90% 절감!)
같은 의미의 질문을 캐싱합니다.
import hashlib
from langchain.cache import SQLiteCache
import langchain
# 캐시 설정
langchain.llm_cache = SQLiteCache(database_path=".langchain.db")
# 의미 기반 캐싱
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
embeddings = OpenAIEmbeddings()
semantic_cache = {}
def get_cached_response(query):
# 쿼리 임베딩
query_embedding = embeddings.embed_query(query)
# 유사한 쿼리 검색
similar = search_similar(query_embedding, threshold=0.95)
if similar:
return semantic_cache[similar]
# 캐시 미스 - LLM 호출
response = llm(query)
semantic_cache[query] = response
return response
# 절감 효과
# "AI가 뭐야?" → 캐시 저장
# "인공지능이 뭔가요?" → 캐시 히트 (동일 의미)
# 비용: $0.001 → $0.000 (100% 절감)
시간 민감도에 따라 캐시 전략을 다르게 합니다.
from datetime import datetime, timedelta
class SmartCache:
def __init__(self):
self.cache = {}
def get(self, key, ttl_minutes=60):
if key in self.cache:
cached_time, value = self.cache[key]
if datetime.now() - cached_time < timedelta(minutes=ttl_minutes):
return value
return None
def set(self, key, value):
self.cache[key] = (datetime.now(), value)
# 사용
cache = SmartCache()
# 정적 콘텐츠 - 긴 TTL
response = cache.get("what_is_ai", ttl_minutes=1440) # 24시간
# 동적 콘텐츠 - 짧은 TTL
weather = cache.get("seoul_weather", ttl_minutes=30) # 30분
절감 효과: 캐시 히트율 50% 달성 시 → 50% 비용 절감
# ❌ 비효율적 (150 토큰)
prompt = """
안녕하세요! 저는 당신에게 부탁하고 싶은 것이 있습니다.
혹시 시간이 되신다면, 다음의 텍스트를 정말 친절하게
요약해주실 수 있으신지 궁금합니다. 물론 바쁘시다면
나중에 해주셔도 전혀 문제없습니다.
텍스트: {text}
정말 감사드립니다!
"""
# ✅ 효율적 (20 토큰)
prompt = """
다음 텍스트를 요약하세요:
{text}
"""
# 절감: 130 토큰 × $0.00001 × 10,000회/일 = $13/일 = $390/월
Few-shot은 강력하지만 비쌉니다.
# ❌ Few-shot (500 토큰)
prompt = f"""
예제 1: 입력 - "좋아요" → 출력 - "긍정"
예제 2: 입력 - "싫어요" → 출력 - "부정"
예제 3: 입력 - "그냥 그래요" → 출력 - "중립"
...
(10개 예제)
입력: {text}
출력:
"""
# ✅ Fine-tuned 모델 (50 토큰)
# 예제를 모델에 학습시켜 프롬프트에서 제거
prompt = f"감정 분류: {text}"
# 절감: 450 토큰 × $0.00001 × 100,000회/일 = $450/일!
전략: 반복적인 작업은 Fine-tuning 고려
작업 복잡도에 따라 모델을 선택합니다.
def route_to_model(query, complexity):
# 복잡도 분류기 (저렴한 모델 사용)
complexity_score = classify_complexity(query) # GPT-3.5
if complexity_score < 0.3:
# 간단한 질문 → GPT-3.5 Turbo
model = "gpt-3.5-turbo"
cost_multiplier = 1
elif complexity_score < 0.7:
# 중간 질문 → GPT-4o mini
model = "gpt-4o-mini"
cost_multiplier = 3
else:
# 복잡한 질문 → GPT-4 Turbo
model = "gpt-4-turbo"
cost_multiplier = 20
return call_llm(model, query)
# 효과
# 70% 간단한 질문 × 1
# 20% 중간 질문 × 3
# 10% 복잡한 질문 × 20
# 평균 비용 = 0.7×1 + 0.2×3 + 0.1×20 = 3.3
# 모두 GPT-4 사용 시 = 20
# 절감율 = 83.5%!
from openai import OpenAI
client = OpenAI()
class CostOptimizedLLM:
def __init__(self):
self.cheap_model = "gpt-3.5-turbo"
self.expensive_model = "gpt-4-turbo"
def classify_complexity(self, query):
# 간단한 규칙 기반 또는 저렴한 분류기
keywords_complex = ["explain", "analyze", "compare", "详细"]
keywords_simple = ["what", "when", "who"]
query_lower = query.lower()
if any(kw in query_lower for kw in keywords_complex):
return 0.8
elif any(kw in query_lower for kw in keywords_simple):
return 0.2
else:
return 0.5
def call(self, query):
complexity = self.classify_complexity(query)
if complexity < 0.6:
model = self.cheap_model
else:
model = self.expensive_model
return client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": query}]
)
def smart_context_management(messages, max_tokens=4000):
"""중요한 메시지만 유지"""
# 1. 시스템 메시지는 항상 유지
system_messages = [m for m in messages if m['role'] == 'system']
# 2. 최근 N개 메시지만 유지
recent_messages = messages[-10:]
# 3. 토큰 수 계산
total_tokens = count_tokens(system_messages + recent_messages)
# 4. 초과 시 요약
if total_tokens > max_tokens:
# 오래된 대화를 요약
old_messages = messages[:-10]
summary = summarize(old_messages) # 저렴한 모델 사용
return system_messages + [
{"role": "system", "content": f"이전 대화 요약: {summary}"}
] + recent_messages
return system_messages + recent_messages
# ❌ 무제한 출력
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=messages
)
# 최악의 경우 4096 토큰 출력 = $0.12
# ✅ 출력 제한
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=messages,
max_tokens=500 # 충분한 답변을 위한 최소한의 토큰
)
# 최대 500 토큰 = $0.015 (87.5% 절감)
def stream_with_early_stop(query, stop_condition):
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[{"role": "user", "content": query}],
stream=True
)
collected = []
for chunk in response:
content = chunk.choices[0].delta.content
if content:
collected.append(content)
# 조건 충족 시 중단
if stop_condition("".join(collected)):
break
return "".join(collected)
# 예: JSON 완성되면 중단
def json_complete(text):
return text.count('{') == text.count('}') and text.count('{') > 0
result = stream_with_early_stop(query, json_complete)
# ❌ 큰 청크 (2000 토큰)
# 검색된 문서 5개 = 10,000 토큰
# 비용 = $0.10
# ✅ 작은 청크 (500 토큰) + 정확한 검색
# 검색된 문서 3개 = 1,500 토큰
# 비용 = $0.015 (85% 절감)
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 작게
chunk_overlap=50
)
# ❌ 무조건 K개 검색
retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
# 10개 × 500 토큰 = 5000 토큰
# ✅ 유사도 점수 기반
retriever = vectorstore.as_retriever(
search_type="similarity_score_threshold",
search_kwargs={"score_threshold": 0.8, "k": 10}
)
# 관련성 높은 것만 → 평균 3개 × 500 토큰 = 1500 토큰
# 절감: 70%
더 적은 문서로 더 나은 결과를 얻습니다.
# 일반 RAG: 질문으로 직접 검색
query = "RAG가 뭐야?"
docs = retriever.get_relevant_documents(query) # 5개 필요
# HyDE: 가상의 답변 생성 후 검색
hypothetical_answer = cheap_llm.predict(query) # GPT-3.5 사용
docs = retriever.get_relevant_documents(hypothetical_answer) # 3개면 충분
# 비용: GPT-3.5 호출 + 적은 문서 → 더 저렴
비실시간 작업은 배치로 처리합니다.
from openai import OpenAI
import asyncio
client = OpenAI()
async def process_batch(queries):
"""비동기 배치 처리"""
tasks = [
client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": q}]
)
for q in queries
]
# 한 번에 실행
results = await asyncio.gather(*tasks)
return results
# 사용
queries = ["질문1", "질문2", ..., "질문100"]
results = asyncio.run(process_batch(queries))
# 효과: 연결 오버헤드 감소, 처리 속도 향상
OpenAI Batch API 사용 (50% 할인!):
# 24시간 이내 결과 필요 시
batch_file = client.files.create(
file=open("requests.jsonl", "rb"),
purpose="batch"
)
batch = client.batches.create(
input_file_id=batch_file.id,
endpoint="/v1/chat/completions",
completion_window="24h"
)
# 50% 저렴한 가격으로 처리
비용 폭발을 방지합니다.
from openai import OpenAI
client = OpenAI()
class CostMonitor:
def __init__(self, daily_limit=100):
self.daily_limit = daily_limit
self.daily_cost = 0
def track_request(self, model, input_tokens, output_tokens):
# 가격표
prices = {
"gpt-4-turbo": {"input": 0.01, "output": 0.03},
"gpt-3.5-turbo": {"input": 0.0005, "output": 0.0015}
}
cost = (
input_tokens / 1000 * prices[model]["input"] +
output_tokens / 1000 * prices[model]["output"]
)
self.daily_cost += cost
# 임계값 확인
if self.daily_cost > self.daily_limit * 0.8:
send_alert(f"일일 비용의 80% 도달: ${self.daily_cost}")
if self.daily_cost > self.daily_limit:
raise Exception("일일 비용 한도 초과!")
return cost
# 사용
monitor = CostMonitor(daily_limit=100)
response = client.chat.completions.create(...)
cost = monitor.track_request(
model="gpt-4-turbo",
input_tokens=response.usage.prompt_tokens,
output_tokens=response.usage.completion_tokens
)
# Llama 3를 로컬에서 실행
from langchain.llms import Ollama
llm = Ollama(model="llama3:70b")
# 비용: $0
# 단, 서버 비용 고려 필요
# GPU 서버: $500-1000/월
# vs OpenAI GPT-4: $2000/월
# 절감: 50-75%
# OpenRouter - 여러 모델 중 가장 저렴한 것 자동 선택
import openai
openai.api_base = "https://openrouter.ai/api/v1"
openai.api_key = "your-key"
response = openai.ChatCompletion.create(
model="openai/gpt-4-turbo", # 또는 다른 저렴한 모델
messages=[...]
)
# 할인율: 10-30%
Before:
After:
개선 사항:
# 1. FAQ 캐싱
# 2. 의도 분류 후 라우팅
# 3. 컨텍스트 윈도우 관리
# 4. 출력 토큰 제한
Before:
After:
AI 비용 최적화는 일회성이 아닌 지속적인 과정입니다.
핵심 원칙:
목표:
월 $10,000 → $1,000으로 가는 여정, 지금 시작하세요!