토큰 윈도우
Context Window
LLM이 한 번에 처리할 수 있는 최대 토큰 수. 긴 문맥 이해 능력 결정.
Context Window
LLM이 한 번에 처리할 수 있는 최대 토큰 수. 긴 문맥 이해 능력 결정.
토큰 윈도우(Token Window), 또는 컨텍스트 윈도우(Context Window)는 대규모 언어 모델(LLM)이 한 번의 요청에서 처리할 수 있는 최대 토큰 수입니다. 이 윈도우에는 시스템 프롬프트, 사용자 입력, 대화 기록, 모델 응답이 모두 포함됩니다. 윈도우 크기가 클수록 더 긴 문서를 처리하고, 더 긴 대화 맥락을 유지할 수 있습니다.
초기 GPT-2는 1,024 토큰, GPT-3는 4,096 토큰의 컨텍스트 윈도우를 가졌습니다. 2023-2024년에는 GPT-4 Turbo(128K), Claude 3(200K), Gemini 1.5 Pro(2M) 등 급격하게 확장되었습니다. 이러한 확장은 RoPE(Rotary Position Embedding), ALiBi, Sliding Window Attention 등의 위치 인코딩 기술 발전과 Flash Attention 같은 메모리 효율화 기법 덕분입니다. 2025년에는 100만 토큰 이상의 컨텍스트가 일반화되고 있습니다.
컨텍스트 윈도우의 크기는 기술적으로 어텐션 메커니즘의 O(n²) 복잡도와 관련됩니다. 토큰 수가 늘어날수록 메모리와 연산량이 제곱으로 증가하므로, 효율적인 처리를 위해 다양한 최적화 기법이 필요합니다. 또한 "Lost in the Middle" 현상처럼 컨텍스트 중간 부분의 정보를 놓치는 문제도 있어, 긴 컨텍스트가 항상 좋은 것은 아닙니다.
실무에서 컨텍스트 윈도우 관리는 비용과 성능의 균형입니다. 긴 컨텍스트를 사용하면 더 많은 정보를 제공할 수 있지만, 비용이 증가하고 응답 속도가 느려집니다. RAG(Retrieval-Augmented Generation)로 관련 정보만 선별하거나, 슬라이딩 윈도우로 대화 기록을 관리하는 전략이 일반적입니다. 또한 캐싱을 통해 반복되는 시스템 프롬프트의 처리 비용을 줄일 수 있습니다.
컨텍스트 윈도우 관리 및 토큰 계산 예제입니다.
# 컨텍스트 윈도우 관리
# pip install tiktoken openai
import tiktoken
class ContextWindowManager:
def __init__(self, model="gpt-4", max_tokens=128000, reserve_for_response=4096):
self.encoder = tiktoken.encoding_for_model(model)
self.max_tokens = max_tokens
self.reserve_for_response = reserve_for_response
self.available_tokens = max_tokens - reserve_for_response
def count_tokens(self, text):
"""텍스트의 토큰 수 계산"""
return len(self.encoder.encode(text))
def count_messages_tokens(self, messages):
"""OpenAI 메시지 형식의 토큰 수 계산"""
total = 0
for msg in messages:
total += 4 # 메시지 오버헤드
for key, value in msg.items():
total += self.count_tokens(str(value))
total += 2 # 응답 시작 오버헤드
return total
def fit_messages(self, system_prompt, messages, max_history=10):
"""컨텍스트 윈도우에 맞게 메시지 조정"""
system_tokens = self.count_tokens(system_prompt)
available = self.available_tokens - system_tokens
# 최신 메시지부터 역순으로 추가
fitted_messages = []
current_tokens = 0
for msg in reversed(messages[-max_history:]):
msg_tokens = self.count_tokens(msg.get("content", "")) + 4
if current_tokens + msg_tokens > available:
break
fitted_messages.insert(0, msg)
current_tokens += msg_tokens
return fitted_messages, current_tokens + system_tokens
# 사용 예시
manager = ContextWindowManager(model="gpt-4", max_tokens=128000)
system_prompt = "당신은 친절한 AI 어시스턴트입니다."
messages = [
{"role": "user", "content": "안녕하세요"},
{"role": "assistant", "content": "안녕하세요! 무엇을 도와드릴까요?"},
{"role": "user", "content": "오늘 날씨가 어때요?"},
{"role": "assistant", "content": "죄송합니다, 실시간 날씨 정보는 제공하지 못합니다."},
]
fitted, total_tokens = manager.fit_messages(system_prompt, messages)
print(f"포함된 메시지: {len(fitted)}개")
print(f"총 토큰 수: {total_tokens}")
print(f"남은 토큰: {manager.available_tokens - total_tokens}")
슬라이딩 윈도우 대화 관리 예제입니다.
# 슬라이딩 윈도우 대화 관리
# pip install tiktoken
import tiktoken
from collections import deque
class SlidingWindowChat:
def __init__(self, model="gpt-4", window_size=8000):
self.encoder = tiktoken.encoding_for_model(model)
self.window_size = window_size
self.messages = deque()
self.current_tokens = 0
def add_message(self, role, content):
"""새 메시지 추가 (윈도우 초과 시 오래된 메시지 제거)"""
msg_tokens = len(self.encoder.encode(content)) + 4 # 오버헤드
# 윈도우 초과 시 오래된 메시지 제거
while self.current_tokens + msg_tokens > self.window_size and self.messages:
old_msg = self.messages.popleft()
old_tokens = len(self.encoder.encode(old_msg["content"])) + 4
self.current_tokens -= old_tokens
# 새 메시지 추가
self.messages.append({"role": role, "content": content})
self.current_tokens += msg_tokens
def get_messages(self):
"""현재 윈도우의 메시지 반환"""
return list(self.messages)
def get_stats(self):
"""현재 상태 정보"""
return {
"message_count": len(self.messages),
"current_tokens": self.current_tokens,
"available_tokens": self.window_size - self.current_tokens
}
# 사용 예시
chat = SlidingWindowChat(window_size=1000)
# 대화 시뮬레이션
conversations = [
("user", "인공지능에 대해 설명해주세요."),
("assistant", "인공지능(AI)은 인간의 지능을 모방하여 학습, 추론, 문제 해결 등의 작업을 수행하는 컴퓨터 시스템입니다..."),
("user", "머신러닝과의 차이점은요?"),
("assistant", "머신러닝은 AI의 하위 분야로, 명시적 프로그래밍 없이 데이터로부터 학습하는 방식입니다..."),
]
for role, content in conversations:
chat.add_message(role, content)
stats = chat.get_stats()
print(f"[{role}] 추가 후: {stats['message_count']}개 메시지, {stats['current_tokens']} 토큰")
print("\n최종 메시지:")
for msg in chat.get_messages():
print(f" {msg['role']}: {msg['content'][:50]}...")
2025년 1월 기준 주요 LLM 컨텍스트 윈도우 비교입니다.
| 모델 | 컨텍스트 | 대략 페이지* | 특징 |
|---|---|---|---|
| GPT-4o | 128K | ~300 페이지 | 빠른 속도, 멀티모달 |
| Claude 3.5 Sonnet | 200K | ~500 페이지 | 긴 문서 분석 우수 |
| Gemini 1.5 Pro | 2M | ~5,000 페이지 | 최대 컨텍스트 |
| Llama 3.1 (405B) | 128K | ~300 페이지 | 오픈소스 최대 |
* 페이지 수는 영어 기준 대략적 추정 (1페이지 ≈ 400토큰)
컨텍스트 길이별 비용 및 응답 시간:
| 컨텍스트 사용량 | 입력 비용 (GPT-4o) | 예상 응답 시간 | 권장 사용 |
|---|---|---|---|
| ~4K 토큰 | $0.01 | 1-2초 | 일반 대화 |
| ~32K 토큰 | $0.08 | 3-5초 | 문서 요약 |
| ~128K 토큰 | $0.32 | 10-15초 | 전체 문서 분석 |
128K 토큰을 다 채운다고 성능이 좋아지지 않습니다. 관련 없는 정보는 오히려 노이즈가 되어 정확도를 떨어뜨릴 수 있고, 비용과 응답 시간만 증가합니다.
컨텍스트 윈도우는 입력과 출력을 모두 포함합니다. 128K 전체를 입력으로 채우면 모델이 응답할 공간이 없습니다. 예상 응답 길이만큼 여유를 두세요.
컨텍스트의 70-80%만 사용하고 응답 공간을 확보하세요. 긴 문서는 청킹 + 랭킹으로 관련 부분만 선별하고, 대화 기록은 슬라이딩 윈도우로 최신 N턴만 유지하세요.