AI Sparkup

최신 AI 쉽게 깊게 따라잡기⚡

프롬프트 압축 팁 – 에이전틱 루프의 토큰 비용 줄이기

context-engineering에서 가장 먼저 비용으로 드러나는 문제는 에이전트가 같은 정보를 매 스텝 다시 보내는 것이다. 프롬프트 압축(Prompt Compression)은 시스템 지시사항, 대화 이력, 도구 결과, 중간 작업 상태를 더 짧은 표현으로 바꿔 에이전틱 루프의 입력 토큰과 지연시간을 줄이는 방법이다. 장기 실행 에이전트, 리서치 에이전트, 코딩 에이전트처럼 10회 이상 모델 호출이 반복되는 워크플로에 특히 중요하다.

왜 비용이 선형이 아니라 제곱으로 커지는가

에이전트 루프가 20단계라면 20번 호출하는 비용만 문제가 아니다. 1단계에서 500토큰을 보냈고, 2단계에서 이전 이력과 새 정보를 합쳐 1,000토큰을 보냈고, 3단계에서 1,500토큰을 보낸다면 각 호출의 프롬프트 길이는 선형으로 늘어난다. 하지만 전체 누적 입력 토큰은 같은 이력을 계속 재전송하기 때문에 제곱에 가까운 곡선으로 커진다.

이 문제는 돈만 태우지 않는다.

  • TTFT 증가: 긴 프롬프트는 첫 토큰까지의 대기시간을 늘린다.
  • 컨텍스트 오염: 오래된 실패, 중복 JSON, 낡은 도구 출력이 현재 판단을 흐린다.
  • 배치 효율 저하: 서빙 시스템 입장에서는 긴 입력이 배치 크기와 처리량을 갉아먹는다.

따라서 프롬프트 압축은 미세 최적화가 아니라 멀티 스텝 에이전트의 기본 설계다.

주요 압축 전략

전략방식적합한 상황
지시사항 증류긴 시스템 프롬프트를 짧은 약어·규칙 세트로 변환같은 시스템 프롬프트가 수십 번 반복될 때
재귀 요약오래된 실행 이력을 짧은 상태 요약으로 교체5단계 이상 이어지는 작업
RAG 기반 이력 검색전체 히스토리를 벡터 DB에 저장하고 관련 이력만 주입장기 메모리와 추적성이 모두 필요할 때
LLMLingua류 토큰 압축중요도가 낮은 토큰을 자동 제거긴 문서·도구 출력 압축

지시사항 증류

긴 자연어 지시를 모델이 이해할 수 있는 짧은 스키마로 바꾼다.

Before:
You are a helpful research assistant. Your goal is to find information about X.
Please provide your output in a valid JSON format and do not include any conversational filler.

After:
Act: ResearchBot. Task: Find X. Output: JSON. No fluff.

차이는 작아 보이지만 시스템 프롬프트는 루프 전체에서 반복된다. 30토큰 차이가 100회 반복되면 시스템 프롬프트만으로 3,000토큰이 절약된다. 다만 너무 과하게 줄이면 정책·제약 조건이 모호해지므로, 압축 전후 출력 품질을 회귀 테스트해야 한다.

재귀 요약

일정 단계마다 전체 이력을 “현재 상태 문서”로 접는다. 좋은 요약은 단순 대화 요약이 아니라 다음 필드를 유지한다.

  • 사용자의 원래 목표
  • 이미 완료한 작업
  • 확정된 결정
  • 실패한 시도와 반복하면 안 되는 이유
  • 남은 작업과 다음 액션
def build_context(system_prompt, recent_steps, state_summary=None):
    parts = [system_prompt]
    if state_summary:
        parts.append(f"State summary:\n{state_summary}")
    parts.append("Recent steps:\n" + "\n".join(recent_steps[-3:]))
    return "\n\n".join(parts)

최근 몇 단계는 원문으로 유지하고, 오래된 단계만 요약으로 치환하는 하이브리드 방식이 실전에서 안정적이다. 요약 모델은 큰 모델일 필요가 없다. 저렴한 소형 모델이나 로컬 모델로 “상태 압축”만 맡겨도 비용 대비 효과가 크다.

RAG 기반 이력 검색

모든 이력을 프롬프트에 넣지 말고 외부 메모리에 저장한다. 현재 질문과 관련된 과거 결정, 파일, 도구 결과만 검색해 넣으면 장기 세션에서도 컨텍스트가 일정하게 유지된다.

이 방식은 agentic-memory와 결합하기 좋다. 단, 검색 결과가 틀리면 중요한 이력이 빠질 수 있으므로 “최근 N단계 원문 + 검색된 과거 이력 + 장기 요약”처럼 다층 구조로 구성하는 편이 안전하다.

간단한 구현 패턴

압축은 별도 거대한 시스템이 아니라 루프 안의 정책으로 시작할 수 있다.

MAX_RECENT_STEPS = 4
COMPRESS_EVERY = 5

state_summary = ""
history = []

for step in range(max_steps):
    context = build_context(
        system_prompt=DISTILLED_SYSTEM_PROMPT,
        recent_steps=history[-MAX_RECENT_STEPS:],
        state_summary=state_summary,
    )
    result = call_model(context)
    history.append(result)

    if len(history) % COMPRESS_EVERY == 0:
        state_summary = summarize_state(state_summary, history)
        history = history[-MAX_RECENT_STEPS:]

핵심은 원문 히스토리를 버리는 시점이 아니라 버려도 되는 정보와 보존해야 하는 정보를 구분하는 스키마다. 요약 프롬프트에 “실패한 시도”, “사용자 제약”, “파일 경로”, “열린 질문”을 명시하면 재작업이 줄어든다.

운영 기준

프롬프트 압축을 넣었다면 다음 지표를 함께 본다.

지표의미
압축률원본 대비 입력 토큰 감소율
회상 정확도압축 후에도 중요한 과거 결정을 기억하는지
재작업률이미 수행한 도구 호출·파일 탐색을 반복하는 빈도
비용/성공 작업태스크 성공 1건당 모델 비용
TTFT첫 토큰 대기시간 변화

압축률만 높으면 위험하다. 에이전트가 중요한 제약을 잃고 재작업을 반복하면 토큰 절약분보다 실패 비용이 커진다. 따라서 “얼마나 줄였는가”보다 “줄이고도 같은 작업을 끝내는가”가 더 중요하다.

관련 문서

참고 자료



AI Sparkup 구독하기

최신 게시물 요약과 더 심층적인 정보를 이메일로 받아 보세요! (무료)