LLMSlim 구축하기: 결정론적 프롬프트 압축(Deterministic Prompt Compression) 아키텍처 심층 분석
요약
LLMSlim은 시스템 지침이나 JSON 스키마를 보존하면서 프롬프트 토큰을 효율적으로 압축하는 Python 라이브러리입니다. TF-IDF와 LexRank 알고리즘을 활용하여 모델 호출 없이 30ms 이내에 정보 밀도가 높은 문장을 선별하는 6단계 파이프라인을 제공합니다.
핵심 포인트
- 시스템 지침, JSON 스키마, 코드 펜스 등 구조적 데이터의 손실 방지
- 임베딩 대신 TF-IDF를 사용하여 지연 시간(Latency) 최소화
- Regex 기반의 보호된 문장 분할로 코드 및 URL 무결성 유지
- LexRank 알고리즘을 통한 결정론적 프롬프트 압축 아키텍처
대부분의 프롬프트 압축(Prompt Compression) 논의는 순조로운 상황에만 집중합니다. 즉, 긴 RAG 컨텍스트를 가지고 있고, 이를 토큰의 50%로 줄이면 API 비용이 절반으로 줄어든다는 식입니다. 하지만 잘 논의되지 않는 실패 사례들이 있습니다. 시스템 지침(System Instructions)의 누락, 잘려나간 JSON 스키마(JSON Schemas), 깨진 코드 펜스(Code Fences), 그리고 어떤 유사도 지표에서 낮은 점수를 받아 조용히 삭제되어 버린 엔티티(Entity) 이름 등이 그것입니다.
LLMSlim (https://www.llmslim.app)은 이러한 예외 케이스들을 적절히 처리하기 위해 제가 지난 몇 달 동안 구축해 온 Python 라이브러리입니다. 이 포스트에서는 LLMSlim을 작동하게 만드는 아키텍처 결정 사항들에 대해 심층적으로 다룹니다.
핵심 문제: 정보(Information) vs 채우기용 텍스트(Filler)
LLM 입력 프롬프트에는 구조적인 문제가 있습니다. 모델의 동작을 제어하는 지침(시스템 역할, JSON 스키마, MUST/NEVER 지시 사항)은 일반적으로 전체 토큰 수에서 아주 작은 부분만을 차지합니다. 나머지는 컨텍스트(Context)입니다: 검색된 문서, 대화 기록, 배경 정보 등입니다. 그리고 그 컨텍스트 내에서 상당 부분은 정보 밀도가 아닌 인간의 가독성을 위해 존재하는 산문(Prose)입니다.
과제는 모델 호출(Model Call) 없이, 임베딩(Embeddings) 없이, 그리고 30ms 이내에 가치가 높은 정보 문장과 가치가 낮은 채우기용 텍스트를 구분해내는 것입니다.
6단계 파이프라인
LLMSlim은 6개 단계로 구성된 결정론적 DAG (Directed Acyclic Graph, 유향 비순환 그래프)를 통해 프롬프트를 처리합니다:
1. 보호된 문장 분할 (Protected Sentence Splitting)
마침표를 기준으로 하는 단순한 문장 분할은 코드 블록과 URL을 깨뜨립니다. 첫 번째 단계는 다음 사항들을 존중하는 정규 표현식(Regex) 기반 분할을 사용합니다:
- AST 코드 펜스 (Triple backticks, ```) - 원자적 단위(Atomic units)로 취급
- Markdown 헤딩 마커
- URL (URL 내의 마침표에서는 분할하지 않음)
- 일반적인 약어 (예: U.S., etc.)
# 의사 코드: 핵심 분할 로직
sentences = regex_split(text)
for i, sent in enumerate(sentences):
...
2. TF-IDF 벡터 그래프 구축 (TF-IDF Vector Graph Construction)
각 문장은 TF-IDF 벡터가 됩니다. 우리는 이 벡터들에 대해 전체 쌍별 코사인 유사도 행렬 (pairwise cosine similarity matrix)을 계산하여, 에지 가중치(edge weight)가 $weight(i,j) = cosine_similarity(v_i, v_j)$인 가중치 부여된 무방향 그래프 (weighted undirected graph)를 구축합니다.
신경망 임베딩 (neural embeddings) 대신 TF-IDF를 선택한 것은 의도적인 결정이었습니다. TF-IDF는 문장당 마이크로초 단위로 실행됩니다. 이는 어휘 중복 (vocabulary overlap)을 잘 포착하며, 이는 중복된 산문 (redundant prose)을 식별하는 데 있어 정확히 중요한 요소입니다. 신경망 임베딩은 이 작업에 정당화될 수 없는 50-100ms의 지연 시간 (latency)과 모델 로딩 오버헤드를 추가합니다.
3. LexRank 중심성 점수 산정 (LexRank Centrality Scoring)
우리는 LexRank 알고리즘을 적용합니다: 유사도 그래프를 확률적 전이 행렬 (stochastic transition matrix) $M$으로 변환한 다음, 거듭제곱 반복법 (power iteration)을 통해 정상 분포 (stationary distribution)를 찾습니다:
p_{t+1} = d * M * p_t + (1-d) / n
여기서 $d$는 감쇠 계수 (damping factor, 일반적으로 0.85)이고 $n$은 문장 수입니다. 수렴은 보통 20-30회 반복 내에 이루어집니다. 결과로 나오는 정상 확률 벡터 (stationary probability vector)는 각 문장에 대해 해당 문장이 문서 내에서 정보적으로 얼마나 중심적인지를 나타내는 중심성 점수 (centrality score)를 부여합니다.
4. 우선순위 티어 하드 락킹 (Priority Tier Hard Locking)
이 단계는 LLMSlim을 단순한 추출 방식과 차별화하는 단계입니다. 어떤 문장도 제거(pruning)되기 전에, 결정론적 규칙 패스 (deterministic rule pass)를 통해 모든 문장을 네 가지 티어 중 하나로 분류합니다:
Tier 4 (침해 불가 - Inviolable): 다음을 포함하는 문장:
- 역할 마커 (Role markers):
system:,developer:,user: - 명령형 키워드 (Imperative keywords):
MUST,NEVER,ALWAYS,REQUIRED,DO NOT - JSON/XML 스키마 구분자 (schema delimiters)
Tier 3 (보호됨 - Protected): 다음을 포함하는 문장:
- 수치 엔티티 (Numerical entities) (통화, 백분율, 측정값)
- 고유 명사 및 개체명 (Proper nouns and named entities)
- URL 참조
- 코드 식별자 (Code identifiers)
Tier 2 (표준 - Standard): 일반적인 내용 문장
Tier 1 (제거 후보 - Candidate for removal): 채우기 문구 (Filler phrases), 전환 문장 (transition sentences)
Tier 4 문장들은 LexRank 점수와 관계없이 압축 과정에서 살아남도록 하드코딩(hardcoded)되어 있습니다. 예를 들어, 산문 형태의 단락들로 가득 찬 문서에서 "반드시 JSON으로만 응답해야 합니다"라고 말하는 문장은 낮은 점수를 받겠지만, 프롬프트 내에서는 가장 중요한 문장입니다.
5. 2단계 예산 할당 (Two-Pass Budget Allocation)
1단계(Pass 1)는 문서를 의미론적 청크(semantic chunks)로 나누고 토큰 예산을 비례적으로 할당합니다:
chunk_budget_i = target_tokens * (chunk_tokens_i / total_tokens)
2단계(Pass 2)는 전역 재균형(global rebalancing) 단계를 적용합니다. 각 청크에는 선택된 문장들을 합쳤을 때 할당된 예산을 약간 초과하거나 미달하는 경우가 발생할 수 있습니다. 두 번째 단계에서는 모든 청크에 걸친 잉여분/부족분을 수집하고, 우선순위 기반의 탐욕적 배낭 문제 알고리즘(priority-aware greedy knapsack)을 사용하여 토큰을 재분배합니다:
- 선택되지 않은 나머지 문장들을 (계층(tier), lexrank_score) 기준으로 내림차순 정렬
- 전역 토큰 목표치에 도달할 때까지 탐욕적(greedily)으로 문장을 포함
이러한 2단계 접근 방식 덕분에 이 라이브러리는 문서 구조의 변동성이 매우 큰 경우에도 목표 비율의 2~3% 이내로 일관되게 도달할 수 있습니다.
6. 순서 기반 재조립 (Ordered Reassembly)
선택된 문장들은 원래 문서의 위치에 따라 정렬되고 연결됩니다. 문서의 인과적 추론(causal reasoning)과 논리적 흐름은 단순히 내용뿐만 아니라 순서에 의존하기 때문에 원래의 순서가 보존됩니다.
하이브리드 전략 (The Hybrid Strategy, v0.3.0)
v0.3.0은 추출형 파이프라인(extractive pipeline) 위에 생성형 압축 계층(generative compression layer)을 추가합니다. 흐름은 다음과 같습니다:
- 추출형 사전 가지치기(Extractive pre-pruning)를 통해 컨텍스트를 목표치의 약 130%로 줄임 (의도적으로 약간 초과하게 설정)
- RewriteRequest가 플러그형 CallableProvider로 전달됨
- LLM이 최종 비율을 목표로 사전 가지치기된 컨텍스트를 재작성(rewrite)
- 검증 단계(validation pass)를 통해 모든 Tier 4 문장이 살아남았는지 확인
- 검증에 실패할 경우, 추출형 결과물을 폴백(fallback)으로 반환
플러그형 프로바이더(pluggable provider) 모델을 사용하므로 특정 LLM API 키가 반드시 필요하지는 않습니다:
from llmslim import compress, CallableProvider, RewriteRequest
def my_provider(req: RewriteRequest) -> str:
...
벤치마크 (Benchmarks)
모든 벤치마크 (Benchmarks) 결과는 재현 가능합니다. 하드웨어 사양: AMD EPYC 7763, 64GB RAM, Ubuntu 24.04, Python 3.12.3, tiktoken cl100k_base. 데이터셋당 N=500개의 프롬프트, 샘플당 100회의 반복 수행을 거쳤습니다.
| 데이터셋 (Dataset) | 토큰 감소율 (Token Reduction) | 지연 시간 (Latency, 평균) | 지시문 유지율 (Directive Retention) | 엔티티 보존율 (Entity Preservation) |
|---|---|---|---|---|
| 시스템 지시문 (System Directives) | 51.4% ± 1.2% | 24.8ms ± 2.1ms | 100.0% | 95.1% ± 1.1% |
| ... |
작동하지 않았던 것들 (What Didn't Work)
시도 1: 순수 TF-IDF 컷오프 (Pure TF-IDF cutoff). 유사도 임계값 (similarity threshold)을 설정하고 그보다 낮은 문장을 삭제하는 방식은 단순해 보입니다. 하지만 실제로는 전문 용어 (specialized vocabulary)가 포함된 문서 섹션의 경우, 중요한 정보를 포함하고 있음에도 불구하고 전반적으로 낮은 점수를 기록했습니다. 임계값 튜닝 (Threshold tuning)이 문서마다 개별적으로 이루어져야 하는 문제가 발생했습니다.
시도 2: 압축을 위한 요약 (Summarization for compression). 더 작은 모델을 실행하여 청크 (chunks)를 요약하는 방식은 매력적으로 보입니다. 그러나 이는 전체 모델 추론 (model inference) 호출(50-500ms)을 추가하고, API 의존성을 요구하며, 요약 과정에서 다운스트림 모델 (downstream model)의 성능에 중요한 엔티티 (entity)의 구체적인 정보가 누락되는 경향이 있습니다.
시도 3: 단일 패스 예산 할당 (Single-pass budget allocation). 균일한 문서에는 잘 작동합니다. 하지만 기술 사양 (technical specs)과 배경 서사 (background narrative)가 혼합된 것처럼 밀도가 혼재된 문서에서는 심각하게 실패합니다. 이러한 실패 사례들을 디버깅하는 과정에서 2-패스 (two-pass) 접근 방식이 도출되었습니다.
설치 및 링크 (Installation and Links)
pip install llmslim
- 전체 문서가 포함된 웹사이트: https://www.llmslim.app
- 재현 가능한 벤치마크가 포함된 GitHub: https://github.com/Thanatos9404/llmslim
벤치마크 스크립트, 원본 JSON 페이로드 (raw JSON payloads), 그리고 전체 방법론 (methodology)은 공개되어 있습니다. 수치에 오류를 발견하신다면 이슈 (issue)를 생성해 주세요. 진심으로 확인하고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기