적응형 컨텍스트 관리
왜 적응형인가?
섹션 제목: “왜 적응형인가?”고정된 컨텍스트 관리 전략은 실패합니다. 짧은 태스크에는 과도하고, 긴 태스크에는 부족합니다. 적응형(Adaptive) 접근법은 현재 컨텍스트 사용률을 지속적으로 모니터링하고, 임계값에 따라 서로 다른 압축 전략을 자동으로 적용합니다.
핵심 아이디어는 **점진적 손실(Progressive Degradation)**입니다. 한 번에 정보를 많이 버리는 대신, 덜 중요한 것부터 단계적으로 압축합니다.
5단계 적응형 압축
섹션 제목: “5단계 적응형 압축”컨텍스트 사용률에 따라 다음 순서로 압축을 적용합니다.
| 단계 | 컨텍스트 사용률 | 적용 전략 | 정보 손실 |
|---|---|---|---|
| 1단계 | 60% 미만 | 현상 유지 | 없음 |
| 2단계 | 60~70% | 도구 출력 후처리 | 최소 |
| 3단계 | 70~80% | 오래된 메시지 트리밍 | 낮음 |
| 4단계 | 80~90% | 대화 히스토리 요약 | 중간 |
| 5단계 | 90% 초과 | 핵심 요약만 유지 | 높음 |
class AdaptiveContextManager { private readonly thresholds = [0.6, 0.7, 0.8, 0.9];
async compact(context: Context, maxTokens: number): Promise<Context> { const usage = context.tokenCount / maxTokens;
if (usage < this.thresholds[0]) return context; if (usage < this.thresholds[1]) return this.postProcessToolOutputs(context); if (usage < this.thresholds[2]) return this.trimOldMessages(context); if (usage < this.thresholds[3]) return this.summarizeHistory(context); return this.keepEssentialSummaryOnly(context); }}요약 전략 비교
섹션 제목: “요약 전략 비교”컨텍스트가 70% 이상 차면 요약이 필요합니다. 두 가지 주요 방식이 있습니다.
재귀적 요약 (Recursive Summarization)
섹션 제목: “재귀적 요약 (Recursive Summarization)”오래된 메시지부터 점진적으로 요약을 누적합니다. 이전 요약 위에 새 내용을 요약하는 방식입니다.
원본 대화: [M1, M2, M3, M4, M5, M6, M7, M8]
1차 압축: [요약(M1~M4), M5, M6, M7, M8]2차 압축: [요약(요약(M1~M4)+M5~M6), M7, M8]장점: 오래된 정보는 더 많이 압축되어 자연스러운 망각 곡선을 구현합니다. 단점: 반복된 요약으로 초기 세부 정보가 왜곡될 수 있습니다.
계층적 요약 (Hierarchical Summarization)
섹션 제목: “계층적 요약 (Hierarchical Summarization)”중요도에 따라 세부 수준을 다르게 유지합니다. 핵심 결정은 완전히 보존하고, 세부 실행 과정은 압축합니다.
계층 구조:├── 핵심 결정 [완전 보존]│ ├── "PostgreSQL 사용 결정"│ └── "인증에 JWT 사용"├── 중요 이벤트 [요약 보존]│ └── "3번의 DB 연결 실패 → 재시도 로직 추가"└── 일반 실행 과정 [최소 보존] └── "파일 읽기, 함수 작성 등 루틴 작업"장점: 의사 결정 맥락을 잃지 않습니다. 단점: 중요도를 판단하는 추가 로직이 필요합니다.
트리밍 전략
섹션 제목: “트리밍 전략”요약보다 단순하지만 빠른 방법입니다.
FIFO 트리밍
섹션 제목: “FIFO 트리밍”가장 오래된 메시지부터 순서대로 제거합니다. 구현이 단순하지만 초기 시스템 프롬프트나 중요한 초반 지시까지 삭제될 수 있습니다.
선택적 트리밍
섹션 제목: “선택적 트리밍”메시지에 중요도 태그를 부여하고, 낮은 중요도 메시지만 제거합니다.
interface TaggedMessage { role: 'user' | 'assistant' | 'system'; content: string; importance: 'critical' | 'normal' | 'ephemeral';}
function selectiveTrim( messages: TaggedMessage[], targetTokens: number): TaggedMessage[] { // ephemeral → normal 순으로 제거 const priorities: TaggedMessage['importance'][] = ['ephemeral', 'normal'];
let result = [...messages]; for (const priority of priorities) { if (estimateTokens(result) <= targetTokens) break; result = result.filter( (m) => m.importance !== priority || m === result[result.length - 1] ); } return result;}도구 출력 후처리
섹션 제목: “도구 출력 후처리”에이전트가 도구를 호출하면 종종 수천 토큰의 출력이 반환됩니다. 예를 들어 웹 검색 결과, 긴 파일 내용, API 응답 등입니다. 후처리는 이 출력에서 필요한 부분만 추출합니다.
async function postProcessToolOutput( toolName: string, rawOutput: string, query: string): Promise<string> { // 웹 검색: 상위 3개 결과 요약만 유지 if (toolName === 'web_search') { return extractTopResults(rawOutput, 3); }
// 파일 읽기: 쿼리와 관련된 라인만 추출 if (toolName === 'read_file') { return extractRelevantLines(rawOutput, query, contextLines: 5); }
// 코드 실행: stdout만 유지, 중간 로그 제거 if (toolName === 'execute_code') { return extractFinalOutput(rawOutput); }
return rawOutput;}전략 선택 가이드
섹션 제목: “전략 선택 가이드”| 상황 | 권장 전략 |
|---|---|
| 도구 출력이 매우 길다 | 후처리로 관련 정보만 추출 |
| 초반 대화가 더 이상 필요 없다 | FIFO 트리밍 |
| 의사 결정 맥락을 보존해야 한다 | 계층적 요약 |
| 대화가 매우 길고 전반적으로 관련 있다 | 재귀적 요약 |
| 컨텍스트가 거의 꽉 찼다 | 핵심 요약만 남기고 전부 교체 |
적응형 컨텍스트 관리는 컨텍스트 사용률을 실시간으로 추적하고, 5단계 임계값에 따라 도구 출력 후처리 → 트리밍 → 요약 → 핵심만 유지의 순서로 점진적 압축을 적용합니다. 정보 손실을 최소화하면서 컨텍스트 한계 내에서 에이전트를 안정적으로 운영하는 것이 목표입니다.