시간 제한 예산과 우아한 성능 저하
파이프라인의 각 계층에 엄격한 시간 제한 예산을 설정하고, LLM이 예산을 초과하면 캐시된 응답이나 단순화된 응답을 제공하는 우아한 성능 저하를 구현합니다.
시간 제한 예산과 우아한 성능 저하은(는) CoddyKit의 무료 AI Engineering Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Engineering Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
시간 제한 예산이란 무엇인가요
시간 제한 예산은 요청이 파이프라인의 모든 단계를 거쳐 완료되는 데 할당되는 총 시간의 최댓값입니다. 각 API 호출마다 임의의 시간 제한을 설정하는 대신, 사용자에게 결과를 제공하는 작업의 처음부터 끝까지 사용할 예산을 정의하고 검색, LLM 생성, 후처리 단계에 나누어 할당합니다. 이렇게 하면 일부 단계가 느리더라도 항상 허용 가능한 시간 안에 응답할 수 있습니다.
파이프라인 단계 간 예산 분배
일반적인 RAG 대화 파이프라인에는 검색, LLM 생성, 응답 형식 지정이라는 세 단계가 있습니다. 각 단계가 보통 얼마나 걸리는지와 사용자가 어느 정도의 지연을 감수할 수 있는지를 기준으로 시간 일부를 할당하십시오. 남은 여유 시간은 성능 저하 버퍼입니다. 어떤 단계가 할당된 시간을 모두 사용하면 전체 예산을 지키기 위해 이후 단계에서 일부 처리를 생략하기 시작합니다.
# Total user-facing SLA: 8000ms
BUDGET_TOTAL_MS = 8000
BUDGET_STAGES = {
'retrieval': 1500, # vector search + rerank
'llm_call': 5500, # token streaming
'formatting': 500, # post-processing
'slack': 500, # buffer for overhead
}
assert sum(BUDGET_STAGES.values()) == BUDGET_TOTAL_MS예산 사용량 추적
시작 시간을 기록하고 각 단계 전환 시 남은 예산을 확인하는 BudgetTracker를 사용하십시오. 단계를 시작하기 전에 예산이 충분히 남아 있는지 확인하십시오. 이렇게 하면 이후 단계가 상황에 맞게 조정할 수 있습니다. 예를 들어 검색 단계가 1500ms의 예산 중 1200ms를 사용하면 여유 시간은 300ms뿐이므로, 더 단순한 LLM 프롬프트를 사용하거나 재순위화 단계를 건너뛰어야 합니다.
import time
class BudgetTracker:
def __init__(self, total_ms: float):
self.start = time.perf_counter()
self.total_ms = total_ms
def elapsed_ms(self) -> float:
return (time.perf_counter() - self.start) * 1000
def remaining_ms(self) -> float:
return self.total_ms - self.elapsed_ms()
def check(self, stage: str, required_ms: float = 0) -> bool:
remaining = self.remaining_ms()
if remaining < required_ms:
print(f'Budget exhausted before {stage}: {remaining:.0f}ms left, need {required_ms}ms')
return False
return True정상적인 성능 저하의 정의
정상적인 성능 저하란 전체 파이프라인을 예산 안에 완료할 수 없을 때 오류를 반환하는 대신, 품질은 낮지만 여전히 유용한 응답을 제공하는 것을 의미합니다. 예를 들면 캐시된 응답 반환, 재순위화 생략, 문맥 창 잘라내기, 더 빠르지만 정확도가 낮은 모델 사용, 미리 작성한 대체 메시지 반환 등이 있습니다. 목표는 사용자에게 아무것도 주지 않는 대신 항상 무언가를 제공하는 것입니다.
# Degradation ladder for a RAG chat endpoint:
# Level 0 (normal): retrieve 10 chunks + rerank + GPT-4o -- 8000ms budget
# Level 1 (fast): retrieve 5 chunks + skip rerank + GPT-4o -- 5000ms budget
# Level 2 (minimal): retrieve 3 chunks + GPT-4o-mini -- 3000ms budget
# Level 3 (cached): return semantic cache hit -- 100ms
# Level 4 (sorry): return static 'Try again in a moment' -- 1ms성능 저하 단계 사다리 구현
각 파이프라인 의사 결정 지점에서 남은 예산을 확인하고 적절한 품질 수준을 선택하십시오. 아래 코드는 남은 예산에 따라 검색 깊이와 모델을 선택합니다. 따라서 일반적인 부하에서는 사용자가 최상의 품질을 얻고, 지연 시간이 긴 상황에서도 시간 제한 오류 대신 유용한 응답을 받을 수 있습니다.
async def smart_rag_query(question: str, budget_ms: float = 8000) -> str:
tracker = BudgetTracker(budget_ms)
# Retrieval stage
if tracker.remaining_ms() > 5000:
chunks = await retrieve_and_rerank(question, top_k=10)
elif tracker.remaining_ms() > 3000:
chunks = await retrieve(question, top_k=5) # skip rerank
elif tracker.remaining_ms() > 1500:
chunks = await retrieve(question, top_k=3) # minimal retrieval
else:
return await get_cached_or_static(question)
# LLM stage
if tracker.remaining_ms() > 4000:
model = 'gpt-4o'
else:
model = 'gpt-4o-mini' # faster fallback
timeout = tracker.remaining_ms() / 1000 - 0.5
return await generate_answer(question, chunks, model, timeout)API 호출 수준에서 시간 제한 설정
모든 외부 API 호출에 항상 명시적인 시간 제한을 설정하십시오. OpenAI Python SDK는 초 단위의 timeout 매개변수를 지원합니다. 예외를 처리하고 전체 응답 기한 전에 정상적인 성능 저하 처리를 수행할 수 있도록, 남은 예산보다 약간 짧게 설정하십시오. SDK의 기본 시간 제한에 의존하지 마십시오. 사용자에게 직접 제공하는 요청에는 너무 길 수 있습니다.
async def generate_answer(question: str, chunks: list, model: str, timeout_sec: float) -> str:
context = '\n\n'.join(chunks)
prompt = f'Answer using this context:\n{context}\n\nQuestion: {question}'
try:
resp = await client.chat.completions.create(
model=model,
messages=[{'role': 'user', 'content': prompt}],
max_tokens=500,
timeout=max(timeout_sec, 1.0) # minimum 1 second
)
return resp.choices[0].message.content
except openai.APITimeoutError:
return 'I was unable to generate a response in time. Please try again.'부분 스트리밍 응답 반환
스트리밍을 사용하면 예산이 만료되기 전에 생성된 부분 응답을 반환할 수 있습니다. 스트리밍 중 시간 제한이 발생하면 새 토큰 읽기를 중지하고 줄임표나 짧은 이어쓰기 프롬프트를 추가한 다음 스트림을 닫으십시오. 사용자는 빈 오류 대신 자연스럽게 끝나는 응답을 보게 됩니다. 이는 스트리밍에서만 가능합니다. 스트리밍하지 않는 호출은 전부 성공하거나 전부 실패합니다.
async def stream_with_budget(question: str, budget_ms: float):
tracker = BudgetTracker(budget_ms)
collected = []
stream = await client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': question}],
stream=True
)
async for chunk in stream:
if tracker.remaining_ms() < 200: # 200ms safety margin
collected.append(' [response truncated]')
break
delta = chunk.choices[0].delta.content or ''
collected.append(delta)
yield delta
# Ensure stream is closed even if budget exceeded
await stream.close()성능 저하 계층으로서의 의미 기반 캐시
의미 기반 캐시는 지연 시간이 거의 없기 때문에 훌륭한 성능 저하 계층입니다. LLM을 호출하기 전에 의미 기반 캐시에서 이전의 유사한 질문을 조회하십시오. 유사도가 높은 캐시 적중 결과(코사인 유사도 0.92 초과)가 있으면 캐시된 답변을 즉시 반환하십시오. 이렇게 하면 응답 속도를 높이는 동시에 LLM이 느리거나 사용할 수 없을 때 즉시 대체 응답을 제공할 수 있습니다.
async def query_with_cache_fallback(question: str, budget_ms: float = 8000) -> str:
# Try semantic cache first (fast)
cached = await semantic_cache.lookup(question, threshold=0.92)
if cached:
return cached.response
tracker = BudgetTracker(budget_ms)
# Try full pipeline
if tracker.remaining_ms() > 3000:
try:
return await smart_rag_query(question, tracker.remaining_ms())
except Exception:
pass # fall through to static response
# Last resort
return 'I am experiencing high load right now. Please try again in a moment.'성능 저하 이벤트 기록
파이프라인이 더 낮은 품질 수준으로 성능 저하될 때마다 구조화된 이벤트로 기록하십시오. 도달한 성능 저하 수준, 각 단계에서 남은 예산, 최종 지연 시간을 포함하십시오. 이러한 기록을 분석하면 각 성능 저하 수준이 얼마나 자주 발생하는지 알 수 있으며, 이를 통해 예산을 조정하고 지속적으로 예산을 초과하는 단계를 식별하며 인프라 투자를 정당화할 수 있습니다.
import structlog
log = structlog.get_logger()
def log_degradation(level: int, stage: str, remaining_ms: float, total_ms: float):
log.warning(
'pipeline_degradation',
degradation_level=level,
triggered_at_stage=stage,
remaining_budget_ms=round(remaining_ms),
total_budget_ms=total_ms,
budget_consumed_pct=round((total_ms - remaining_ms) / total_ms * 100)
)UI 신호로 사용자 기대치 설정
성능이 저하된 응답을 제공할 때는 평소보다 품질이 낮을 수 있음을 사용자에게 알리십시오. 대화형 인터페이스에는 '빠른 응답 모드 — 일부 세부 정보가 제한될 수 있습니다.'와 같은 은은한 표시를 보여 주십시오. 데이터 추출 API에는 JSON 응답에 degraded: true 필드를 포함하여 이후 사용자가 성능이 저하된 결과를 다르게 처리할 수 있도록 하십시오. 투명성은 장애 상황에서도 사용자의 신뢰를 지켜 줍니다.
from pydantic import BaseModel
from typing import Optional
class ChatResponse(BaseModel):
content: str
degraded: bool = False
degradation_level: Optional[int] = None # 0=full, 1=fast, 2=minimal, 3=cached
latency_ms: int
# API response when degraded:
# {
# 'content': 'Here is a brief answer...',
# 'degraded': true,
# 'degradation_level': 2,
# 'latency_ms': 2800
# }시간에 따른 예산 할당 조정
초기 예산 할당은 추정치입니다. 운영 환경에서 일주일간 실행한 후 추적 데이터로 각 단계에 소요된 시간의 분포를 분석하십시오. 검색에 예산으로 할당한 1500ms가 아니라 지속적으로 800ms만 걸린다면, 남는 시간을 LLM 단계에 재할당하여 더 많은 출력 토큰이나 더 큰 문맥 창을 사용할 수 있도록 하십시오. 예산 조정은 한 번만 수행하는 설정이 아니라 지속적으로 수행하는 운영 작업입니다.
# Budget tuning based on production p95 data:
ACTUAL_P95 = {
'retrieval': 780, # vs budget 1500ms -> 720ms headroom
'llm_call': 4200, # vs budget 5500ms -> 1300ms headroom
'formatting': 120, # vs budget 500ms -> 380ms headroom
}
TOTAL_HEADROOM = sum(
BUDGET_STAGES[k] - ACTUAL_P95[k] for k in ACTUAL_P95
)
print(f'Total headroom: {TOTAL_HEADROOM}ms')
# Reallocate headroom to allow longer LLM responses빠른 확인
시간 제한 예산과 정상적인 성능 저하에 대한 이해도를 확인해 보십시오.
단원 요약
이 단원에서는 다음을 배웠습니다. 시간 제한 예산은 파이프라인 단계 전체에 시간을 할당하여 항상 허용 가능한 기한 안에 응답하도록 하고, 성능 저하 단계 사다리는 시간이 소진되었을 때 오류 대신 점진적으로 낮은 품질의 응답을 제공하며, 성능 저하 이벤트 기록은 만성적인 병목을 식별하고 해결하는 데 도움을 줍니다. 다음 단원에서는 자동화된 품질 평가를 위한 LLM 심사자 패턴을 살펴봅니다.
AI 튜터와 함께 Python을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 30
- 레슨
- 120
자주 묻는 질문
“시간 제한 예산과 우아한 성능 저하” 강의는 무료인가요?
네 — “시간 제한 예산과 우아한 성능 저하” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Engineering Academy 강의 전체를 잠금 해제할 수 있습니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“시간 제한 예산과 우아한 성능 저하”에서 뭘 배우나요?
파이프라인의 각 계층에 엄격한 시간 제한 예산을 설정하고, LLM이 예산을 초과하면 캐시된 응답이나 단순화된 응답을 제공하는 우아한 성능 저하를 구현합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Engineering Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Engineering Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Engineering Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“시간 제한 예산과 우아한 성능 저하” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Engineering Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Engineering Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- LLM 지연 시간 측정: TTFT와 TPOT
- 부하 분산과 다중 키 전략
- 대체 제공업체와 회로 차단기
- 시간 제한 예산과 우아한 성능 저하