고급 설정¶
전역 프롬프트¶
전역 프롬프트를 사용하면 모든 요청에 시스템 프롬프트를 주입하여 보안, 규정 준수 및 동작 가이드라인에 대한 중앙 집중식 정책 관리를 제공할 수 있습니다. 프롬프트는 인라인으로 정의하거나 외부 Markdown 파일에서 로드할 수 있습니다.
기본 설정¶
global_prompts:
# 인라인 기본 프롬프트
default: |
회사 보안 정책을 따라야 합니다.
내부 시스템 세부 정보를 공개하지 마십시오.
도움이 되고 전문적이어야 합니다.
# 병합 전략: prepend (기본), append, 또는 replace
merge_strategy: prepend
# 전역 프롬프트와 사용자 프롬프트 사이의 사용자 정의 구분자
separator: "\n\n---\n\n"
외부 프롬프트 파일¶
복잡한 프롬프트의 경우 외부 Markdown 파일에서 콘텐츠를 로드할 수 있습니다. 이를 통해:
- 구문 강조가 있는 더 나은 편집 경험
- 설정 파일 노이즈 없는 버전 관리
- 프롬프트 업데이트에 대한 핫 리로드 지원
global_prompts:
# 프롬프트 파일이 있는 디렉토리 (설정 디렉토리 기준 상대 경로)
prompts_dir: "./prompts"
# 파일에서 기본 프롬프트 로드
default_file: "system.md"
# 파일에서 백엔드별 프롬프트
backends:
anthropic:
prompt_file: "anthropic-system.md"
openai:
prompt_file: "openai-system.md"
# 파일에서 모델별 프롬프트
models:
gpt-4o:
prompt_file: "gpt4o-system.md"
claude-3-opus:
prompt_file: "claude-opus-system.md"
merge_strategy: prepend
프롬프트 해석 우선순위¶
요청에 사용할 프롬프트 결정 시:
- 모델별 프롬프트 (최고 우선순위) -
global_prompts.models.<model-id> - 백엔드별 프롬프트 -
global_prompts.backends.<backend-name> - 기본 프롬프트 -
global_prompts.default또는global_prompts.default_file
각 레벨에서 prompt (인라인)와 prompt_file이 모두 지정되면 prompt_file이 우선합니다.
병합 전략¶
| 전략 | 동작 |
|---|---|
prepend | 전역 프롬프트가 사용자 시스템 프롬프트 앞에 추가 (기본) |
append | 전역 프롬프트가 사용자 시스템 프롬프트 뒤에 추가 |
replace | 전역 프롬프트가 사용자 시스템 프롬프트를 완전히 대체 |
REST API 관리¶
프롬프트 파일은 Admin API를 통해 런타임에 관리할 수 있습니다:
# 모든 프롬프트 목록
curl http://localhost:8080/admin/config/prompts
# 특정 프롬프트 파일 가져오기
curl http://localhost:8080/admin/config/prompts/prompts/system.md
# 프롬프트 파일 업데이트
curl -X PUT http://localhost:8080/admin/config/prompts/prompts/system.md \
-H "Content-Type: application/json" \
-d '{"content": "# 업데이트된 시스템 프롬프트\n\n새 콘텐츠."}'
# 디스크에서 모든 프롬프트 파일 리로드
curl -X POST http://localhost:8080/admin/config/prompts/reload
전체 API 문서는 Admin REST API 참조를 참조하세요.
보안 고려 사항¶
- 경로 탐색 보호: 디렉토리 탐색 공격 방지를 위한 모든 파일 경로 검증
- 파일 크기 제한: 개별 파일 1MB, 전체 캐시 50MB 제한
- 상대 경로만: 프롬프트 파일은 설정된
prompts_dir또는 설정 디렉토리 내에 있어야 함 - 샌드박스 접근: 허용된 디렉토리 외부 파일은 거부
핫 리로드¶
전역 프롬프트는 즉시 핫 리로드를 지원합니다. 프롬프트 설정 또는 파일 변경 사항은 서버 재시작 없이 다음 요청에 적용됩니다.
모델 메타데이터¶
Continuum Router는 모델 기능, 가격, 한도에 대한 상세 정보를 제공하는 풍부한 모델 메타데이터를 지원합니다. 이 메타데이터는 /v1/models API 응답에 반환되며 클라이언트가 정보에 입각한 모델 선택 결정을 내리는 데 사용할 수 있습니다.
메타데이터 소스¶
모델 메타데이터는 세 가지 방법으로 설정할 수 있습니다 (우선순위 순):
- 백엔드별 model_configs (최고 우선순위)
- 외부 메타데이터 파일 (model-metadata.yaml)
- 메타데이터 없음 (모델은 메타데이터 없이도 작동)
외부 메타데이터 파일¶
model-metadata.yaml 파일을 만드세요:
models:
- id: "gpt-4"
aliases: # 이 메타데이터를 공유하는 대체 ID
- "gpt-4-0125-preview"
- "gpt-4-turbo-preview"
- "gpt-4-vision-preview"
metadata:
display_name: "GPT-4"
summary: "복잡한 작업을 위한 가장 유능한 GPT-4 모델"
capabilities: ["text", "image", "function_calling"]
knowledge_cutoff: "2024-04"
pricing:
input_tokens: 0.03 # 1000 토큰당
output_tokens: 0.06 # 1000 토큰당
limits:
context_window: 128000
max_output: 4096
- id: "llama-3-70b"
aliases: # 동일 모델의 다른 양자화
- "llama-3-70b-instruct"
- "llama-3-70b-chat"
- "llama-3-70b-q4"
- "llama-3-70b-q8"
metadata:
display_name: "Llama 3 70B"
summary: "강력한 성능의 오픈 소스 모델"
capabilities: ["text", "code"]
knowledge_cutoff: "2023-12"
pricing:
input_tokens: 0.001
output_tokens: 0.002
limits:
context_window: 8192
max_output: 2048
설정에서 참조하세요:
Thinking 패턴 설정¶
일부 모델은 추론/사고 콘텐츠를 비표준 방식으로 출력합니다. 라우터는 스트리밍 응답을 적절히 변환하기 위해 모델별 thinking 패턴 설정을 지원합니다.
패턴 유형:
| 패턴 | 설명 | 예시 모델 |
|---|---|---|
none | thinking 패턴 없음 (기본값) | 대부분의 모델 |
standard | 명시적 시작/종료 태그 (<think>...</think>) | 커스텀 추론 모델 |
unterminated_start | 시작 태그 없이 종료 태그만 있음 | nemotron-3-nano |
설정 예시:
models:
- id: nemotron-3-nano
metadata:
display_name: "Nemotron 3 Nano"
capabilities: ["chat", "reasoning"]
# Thinking 패턴 설정
thinking:
pattern: unterminated_start
end_marker: "</think>"
assume_reasoning_first: true
Thinking 패턴 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
pattern | string | 패턴 유형: none, standard, 또는 unterminated_start |
start_marker | string | standard 패턴용 시작 마커 (예: <think>) |
end_marker | string | 종료 마커 (예: </think>) |
assume_reasoning_first | boolean | true인 경우, 종료 마커까지 첫 토큰들을 추론으로 처리 |
작동 방식:
모델에 thinking 패턴이 설정되면:
- 스트리밍 응답이 가로채져 변환됨
end_marker이전 콘텐츠는reasoning_content필드로 전송end_marker이후 콘텐츠는content필드로 전송- 출력은 호환성을 위해 OpenAI의
reasoning_content형식을 따름
출력 예시:
// 추론 콘텐츠 (종료 마커 이전)
{"choices": [{"delta": {"reasoning_content": "분석해 보겠습니다..."}}]}
// 일반 콘텐츠 (종료 마커 이후)
{"choices": [{"delta": {"content": "답은 42입니다."}}]}
네임스페이스 인식 매칭¶
라우터는 네임스페이스 접두사가 있는 모델 ID를 지능적으로 처리합니다. 예:
- 백엔드 반환:
"custom/gpt-4","openai/gpt-4","optimized/gpt-4" - 메타데이터 정의:
"gpt-4" - 결과: 모든 변형이 일치하고 동일한 메타데이터 수신
따라서 다른 백엔드가 공통 메타데이터 정의를 공유하면서 자체 명명 규칙을 사용할 수 있습니다.
메타데이터 우선순위 및 별칭 해석¶
모델의 메타데이터를 조회할 때, 라우터는 다음 우선순위 체인을 사용합니다:
- 정확한 모델 ID 매칭
- 정확한 별칭 매칭
- 날짜 접미사 정규화 (자동, 설정 불필요)
- 와일드카드 패턴 별칭 매칭
- 기본 모델 이름 폴백 (네임스페이스 제거)
각 소스 (백엔드 설정, 메타데이터 파일, 내장) 내에서 동일한 우선순위가 적용됩니다:
-
백엔드별
model_configs(최고 우선순위) -
외부 메타데이터 파일 (두 번째 우선순위)
-
내장 메타데이터 (OpenAI 및 Gemini 백엔드용)
자동 날짜 접미사 처리¶
LLM 프로바이더는 날짜 접미사가 있는 모델 버전을 자주 릴리스합니다. 라우터는 설정 없이 자동으로 날짜 접미사를 감지하고 정규화합니다:
지원되는 날짜 패턴:
-YYYYMMDD(예:claude-opus-4-5-20251130)-YYYY-MM-DD(예:gpt-4o-2024-08-06)-YYMM(예:o1-mini-2409)@YYYYMMDD(예:model@20251130)
작동 방식:
요청: claude-opus-4-5-20251215
↓ (날짜 접미사 감지됨)
조회: claude-opus-4-5-20251101 (기존 메타데이터 항목)
↓ (기본 이름 일치)
결과: claude-opus-4-5-20251101 메타데이터 사용
이는 모델 패밀리당 메타데이터를 한 번만 설정하면 되고, 새로운 날짜 버전이 자동으로 메타데이터를 상속한다는 것을 의미합니다.
와일드카드 패턴 매칭¶
별칭은 * 문자를 사용한 glob 스타일 와일드카드 패턴을 지원합니다:
- 접두사 매칭:
claude-*가claude-opus,claude-sonnet등과 매칭 - 접미사 매칭:
*-preview가gpt-4o-preview,o1-preview등과 매칭 - 중위 매칭:
gpt-*-turbo가gpt-4-turbo,gpt-3.5-turbo등과 매칭
와일드카드 패턴이 있는 설정 예:
models:
- id: "claude-opus-4-5-20251101"
aliases:
- "claude-opus-4-5" # 기본 이름의 정확한 매칭
- "claude-opus-*" # 모든 claude-opus 변형에 대한 와일드카드
metadata:
display_name: "Claude Opus 4.5"
# 자동 매칭: claude-opus-4-5-20251130, claude-opus-test 등
- id: "gpt-4o"
aliases:
- "gpt-4o-*-preview" # 프리뷰 버전 매칭
- "*-4o-turbo" # 접미사 매칭
metadata:
display_name: "GPT-4o"
우선순위 참고: 정확한 별칭은 항상 와일드카드 패턴보다 먼저 매칭되어 둘 다 매칭될 수 있는 경우에도 예측 가능한 동작을 보장합니다.
모델 변형에 별칭 사용¶
별칭은 특히 다음에 유용합니다:
- 다른 양자화:
qwen3-32b-i1,qwen3-23b-i4→ 모두qwen3메타데이터 사용 - 버전 변형:
gpt-4-0125-preview,gpt-4-turbo→gpt-4메타데이터 공유 - 배포 변형:
llama-3-70b-instruct,llama-3-70b-chat→ 동일 기본 모델 - 날짜 버전:
claude-3-5-sonnet-20241022,claude-3-5-sonnet-20241201→ 메타데이터 공유 (날짜 접미사 처리로 자동)
별칭이 있는 설정 예:
model_configs:
- id: "qwen3"
aliases:
- "qwen3-32b-i1" # 1비트 양자화된 32B
- "qwen3-23b-i4" # 4비트 양자화된 23B
- "qwen3-16b-q8" # 8비트 양자화된 16B
- "qwen3-*" # 다른 모든 qwen3 변형에 대한 와일드카드
metadata:
display_name: "Qwen 3"
summary: "Alibaba의 Qwen 모델 계열"
# ... 나머지 메타데이터
API 응답¶
/v1/models 엔드포인트는 풍부한 모델 정보를 반환합니다:
{
"object": "list",
"data": [
{
"id": "gpt-4",
"object": "model",
"created": 1234567890,
"owned_by": "openai",
"backends": ["openai-proxy"],
"metadata": {
"display_name": "GPT-4",
"summary": "복잡한 작업을 위한 가장 유능한 GPT-4 모델",
"capabilities": ["text", "image", "function_calling"],
"knowledge_cutoff": "2024-04",
"pricing": {
"input_tokens": 0.03,
"output_tokens": 0.06
},
"limits": {
"context_window": 128000,
"max_output": 4096
}
}
}
]
}
핫 리로드¶
Continuum Router는 서버 재시작 없이 런타임 설정 업데이트를 위한 핫 리로드를 지원합니다. 설정 변경은 자동으로 감지되어 분류에 따라 적용됩니다.
설정 항목 분류¶
설정 항목은 핫 리로드 기능에 따라 세 가지 범주로 분류됩니다:
즉시 업데이트 (서비스 중단 없음)¶
이 설정들은 서비스 중단 없이 즉시 업데이트됩니다:
# 로깅 설정
logging:
level: "info" # ✅ 즉시: 로그 레벨 변경이 즉시 적용
format: "json" # ✅ 즉시: 로그 형식 변경이 즉시 적용
# 속도 제한 설정
rate_limiting:
enabled: true # ✅ 즉시: 속도 제한 활성화/비활성화
limits:
per_client:
requests_per_second: 10 # ✅ 즉시: 새 제한이 즉시 적용
burst_capacity: 20 # ✅ 즉시: 버스트 설정이 즉시 업데이트
# 서킷 브레이커 설정
circuit_breaker:
enabled: true # ✅ 즉시: 서킷 브레이커 활성화/비활성화
failure_threshold: 5 # ✅ 즉시: 임계값 업데이트가 즉시 적용
timeout_seconds: 60 # ✅ 즉시: 타임아웃 변경이 즉시
# 재시도 설정
retry:
max_attempts: 3 # ✅ 즉시: 재시도 정책이 즉시 업데이트
base_delay: "100ms" # ✅ 즉시: 백오프 설정이 즉시 적용
exponential_backoff: true # ✅ 즉시: 전략 변경이 즉시
# 전역 프롬프트
global_prompts:
default: "당신은 도움이 됩니다" # ✅ 즉시: 프롬프트 변경이 새 요청에 적용
default_file: "prompts/system.md" # ✅ 즉시: 파일 기반 프롬프트도 핫 리로드
# Admin 통계
admin:
stats:
retention_window: "24h" # ✅ 즉시: 보존 기간 즉시 업데이트
token_tracking: true # ✅ 즉시: 토큰 추적 토글 즉시 적용
점진적 업데이트 (기존 연결 유지)¶
이 설정들은 기존 연결을 유지하면서 새 연결에 적용됩니다:
# 백엔드 설정
backends:
- name: "ollama" # ✅ 점진적: 새 요청이 업데이트된 백엔드 풀 사용
url: "http://localhost:11434"
weight: 2 # ✅ 점진적: 새 요청에 로드 밸런싱 업데이트
models: ["llama3.2"] # ✅ 점진적: 모델 라우팅이 점진적으로 업데이트
# 헬스 체크 설정
health_checks:
interval: "30s" # ✅ 점진적: 다음 헬스 체크 주기가 새 간격 사용
timeout: "10s" # ✅ 점진적: 새 체크가 업데이트된 타임아웃 사용
unhealthy_threshold: 3 # ✅ 점진적: 임계값이 새 평가에 적용
healthy_threshold: 2 # ✅ 점진적: 복구 임계값이 점진적으로 업데이트
# 타임아웃 설정
timeouts:
connection: "10s" # ✅ 점진적: 새 요청이 업데이트된 타임아웃 사용
request:
standard:
first_byte: "30s" # ✅ 점진적: 새 요청에 적용
total: "180s" # ✅ 점진적: 새 요청이 새 타임아웃 사용
streaming:
chunk_interval: "30s" # ✅ 점진적: 새 스트림이 업데이트된 설정 사용
재시작 필요 (핫 리로드 불가)¶
이 설정들은 적용을 위해 서버 재시작이 필요합니다. 변경 사항은 경고로 기록됩니다:
server:
bind_address: "0.0.0.0:8080" # ❌ 재시작 필요: TCP/Unix 소켓 바인딩
# - "0.0.0.0:8080"
# - "unix:/var/run/router.sock"
socket_mode: 0o660 # ❌ 재시작 필요: 소켓 권한
workers: 4 # ❌ 재시작 필요: 워커 스레드 풀 크기
이 설정들이 변경되면 라우터는 다음과 같은 경고를 기록합니다:
핫 리로드 프로세스¶
- 파일 시스템 감시자 - 설정 파일 변경 자동 감지
- 설정 로딩 - 새 설정 로드 및 파싱
- 유효성 검사 - 스키마에 대해 새 설정 검증
- 변경 감지 - ConfigDiff 계산으로 변경 사항 식별
- 분류 - 변경 사항 분류 (즉시/점진적/재시작)
- 원자적 업데이트 - 유효한 설정이 원자적으로 적용
- 컴포넌트 전파 - 영향받는 컴포넌트에 업데이트 전파:
- HealthChecker가 체크 간격 및 임계값 업데이트
- RateLimitStore가 속도 제한 규칙 업데이트
- CircuitBreaker가 실패 임계값 및 타임아웃 업데이트
- BackendPool이 백엔드 설정 업데이트
- 즉시 헬스 체크 - 백엔드가 추가되면 즉시 헬스 체크가 실행되어 새 백엔드가 다음 주기적 체크를 기다리지 않고 1-2초 내에 사용 가능해짐
- 오류 처리 - 잘못된 경우 오류 기록 및 이전 설정 유지
핫 리로드 상태 확인¶
admin API를 사용하여 핫 리로드 상태 및 기능을 확인하세요:
# 핫 리로드가 활성화되었는지 확인
curl http://localhost:8080/admin/config/hot-reload-status
# 현재 설정 보기
curl http://localhost:8080/admin/config
핫 리로드 동작 예제¶
예제 1: 로그 레벨 변경 (즉시)
결과: 로그 레벨이 즉시 변경됩니다. 재시작 불필요. 진행 중인 요청은 계속되고 새 로그는 debug 레벨 사용.예제 2: 백엔드 추가 (즉시 헬스 체크와 함께 점진적)
# 이전
backends:
- name: "ollama"
url: "http://localhost:11434"
# 이후
backends:
- name: "ollama"
url: "http://localhost:11434"
- name: "lmstudio"
url: "http://localhost:1234"
예제 2b: 백엔드 제거 (우아한 드레이닝)
# 이전
backends:
- name: "ollama"
url: "http://localhost:11434"
- name: "lmstudio"
url: "http://localhost:1234"
# 이후
backends:
- name: "ollama"
url: "http://localhost:11434"
백엔드 상태 생명주기¶
백엔드가 설정에서 제거되면 우아한 종료 프로세스를 거칩니다:
- Active → Draining: 백엔드가 드레이닝으로 표시됩니다. 새 요청은 이 백엔드를 건너뜁니다.
- 진행 중인 요청 완료: 기존 요청/스트림은 중단 없이 계속됩니다.
- 정리: 모든 참조가 해제되거나 5분 타임아웃 후에 백엔드가 제거됩니다.
설정 변경 중에도 진행 중인 연결에 영향을 주지 않습니다.
예제 3: 바인드 주소 변경 (재시작 필요)
결과: 경고 기록됨. 변경이 적용되지 않음. 새 포트에 바인드하려면 재시작 필요.분산 추적¶
Continuum Router는 백엔드 서비스 간 요청 상관관계를 위한 분산 추적을 지원합니다. 이 기능은 여러 서비스를 통과하는 요청의 디버깅 및 모니터링에 도움을 줍니다.
설정¶
tracing:
enabled: true # 분산 추적 활성화/비활성화 (기본값: true)
w3c_trace_context: true # W3C Trace Context 헤더 지원 (기본값: true)
headers:
trace_id: "X-Trace-ID" # 추적 ID 헤더 이름 (기본값)
request_id: "X-Request-ID" # 요청 ID 헤더 이름 (기본값)
correlation_id: "X-Correlation-ID" # 상관 ID 헤더 이름 (기본값)
동작 방식¶
-
추적 ID 추출: 요청이 도착하면 라우터는 다음 우선순위로 헤더에서 추적 ID를 추출합니다:
- W3C
traceparent헤더 (W3C 지원 활성화 시) - 설정된
trace_id헤더 (X-Trace-ID) - 설정된
request_id헤더 (X-Request-ID) - 설정된
correlation_id헤더 (X-Correlation-ID)
- W3C
-
추적 ID 생성: 헤더에서 추적 ID가 발견되지 않으면 새 UUID가 생성됩니다.
-
헤더 전파: 추적 ID는 여러 헤더를 통해 백엔드 서비스로 전파됩니다:
X-Request-ID: 광범위한 호환성을 위함X-Trace-ID: 주요 추적 식별자X-Correlation-ID: 상관관계 추적용traceparent: W3C Trace Context (활성화 시)tracestate: W3C Trace State (원본 요청에 존재 시)
-
재시도 시 보존: 동일한 추적 ID가 모든 재시도 시도에서 보존되어, 단일 클라이언트 요청에 대한 여러 백엔드 요청의 상관관계를 쉽게 파악할 수 있습니다.
구조화된 로깅¶
추적이 활성화되면 모든 로그 메시지에 trace_id 필드가 포함됩니다:
{
"timestamp": "2024-01-15T10:30:00Z",
"level": "info",
"trace_id": "0af7651916cd43dd8448eb211c80319c",
"message": "Processing chat completions request",
"backend": "openai",
"model": "gpt-4o"
}
W3C Trace Context¶
w3c_trace_context가 활성화되면 라우터는 W3C Trace Context 표준을 지원합니다:
- 수신:
traceparent헤더 파싱 (형식:00-{trace_id}-{span_id}-{flags}) - 송신: 보존된 추적 ID와 새 span ID로
traceparent헤더 생성 - 상태: 원본 요청에 있는 경우
tracestate헤더 전달
traceparent 예시: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
추적 비활성화¶
분산 추적을 비활성화하려면:
로드 밸런싱 전략¶
load_balancer:
strategy: "round_robin" # round_robin, weighted, random
health_aware: true # 정상 백엔드만 사용
전략:
round_robin: 백엔드 간 균등 분배weighted: 백엔드 가중치에 기반한 분배random: 무작위 선택 (패턴 방지에 좋음)
백엔드별 재시도 설정¶
backends:
- name: "slow-backend"
url: "http://slow.example.com"
retry_override: # 전역 재시도 설정 오버라이드
max_attempts: 5 # 느린 백엔드에 더 많은 시도
base_delay: "500ms" # 더 긴 지연
max_delay: "60s"
모델 폴백¶
Continuum Router는 기본 모델을 사용할 수 없을 때 자동 모델 폴백을 지원합니다. 이 기능은 계층화된 장애 조치 보호를 위해 서킷 브레이커와 통합됩니다.
설정¶
fallback:
enabled: true
# 각 기본 모델에 대한 폴백 체인 정의
fallback_chains:
# 동일 프로바이더 폴백
"gpt-4o":
- "gpt-4-turbo"
- "gpt-3.5-turbo"
"claude-opus-4-5-20251101":
- "claude-sonnet-4-5"
- "claude-haiku-4-5"
# 크로스 프로바이더 폴백
"gemini-2.5-pro":
- "gemini-2.5-flash"
- "gpt-4o" # Gemini를 사용할 수 없으면 OpenAI로 폴백
fallback_policy:
trigger_conditions:
error_codes: [429, 500, 502, 503, 504]
timeout: true
connection_error: true
model_not_found: true
circuit_breaker_open: true
max_fallback_attempts: 3
fallback_timeout_multiplier: 1.5
preserve_parameters: true
model_settings:
"gpt-4o":
fallback_enabled: true
notify_on_fallback: true
트리거 조건¶
| 조건 | 설명 |
|---|---|
error_codes | 폴백을 트리거하는 HTTP 상태 코드 (예: 429, 500, 502, 503, 504) |
timeout | 요청 타임아웃 |
connection_error | TCP 연결 실패 |
model_not_found | 백엔드에서 모델을 사용할 수 없음 |
circuit_breaker_open | 백엔드 서킷 브레이커가 열림 |
응답 헤더¶
폴백이 사용되면 다음 헤더가 응답에 추가됩니다:
| 헤더 | 설명 | 예제 |
|---|---|---|
X-Fallback-Used | 폴백이 사용되었음을 나타냄 | true |
X-Original-Model | 원래 요청된 모델 | gpt-4o |
X-Fallback-Model | 요청을 처리한 모델 | gpt-4-turbo |
X-Fallback-Reason | 폴백이 트리거된 이유 | error_code_429 |
X-Fallback-Attempts | 폴백 시도 횟수 | 2 |
크로스 프로바이더 매개변수 변환¶
프로바이더 간 폴백 시 (예: OpenAI → Anthropic) 라우터가 요청 매개변수를 자동으로 변환합니다:
| OpenAI 매개변수 | Anthropic 매개변수 | 비고 |
|---|---|---|
max_tokens | max_tokens | 누락 시 자동 채움 (Anthropic 필수) |
temperature | temperature | 직접 매핑 |
top_p | top_p | 직접 매핑 |
stop | stop_sequences | 배열 변환 |
프로바이더별 매개변수는 크로스 프로바이더 폴백 중에 자동으로 제거되거나 변환됩니다.
서킷 브레이커와의 통합¶
폴백 시스템은 서킷 브레이커와 함께 작동합니다:
- 서킷 브레이커가 실패 감지하고 임계값 초과 시 열림
- 폴백 체인 활성화 서킷 브레이커가 열렸을 때
- 요청이 폴백 모델로 라우팅 설정된 체인에 따라
- 서킷 브레이커가 복구 테스트하고 백엔드 복구 시 닫힘
# 예제: 서킷 브레이커와 폴백 결합 설정
circuit_breaker:
enabled: true
failure_threshold: 5
timeout: 60s
fallback:
enabled: true
fallback_policy:
trigger_conditions:
circuit_breaker_open: true # 서킷 브레이커에 연결
속도 제한¶
Continuum Router는 남용을 방지하고 공정한 리소스 할당을 보장하기 위해 /v1/models 엔드포인트에 대한 내장 속도 제한을 포함합니다.
현재 설정¶
속도 제한은 현재 다음 기본값으로 설정되어 있습니다:
# 참고: 이 값들은 현재 하드코딩되어 있지만 향후 버전에서 설정 가능해질 수 있습니다
rate_limiting:
models_endpoint:
# 클라이언트별 제한 (API 키 또는 IP 주소로 식별)
sustained_limit: 100 # 분당 최대 요청 수
burst_limit: 20 # 5초 윈도우에서 최대 요청 수
# 시간 윈도우
window_duration: 60s # 지속 제한을 위한 슬라이딩 윈도우
burst_window: 5s # 버스트 감지를 위한 윈도우
# 클라이언트 식별 우선순위
identification:
- api_key # Bearer 토큰 (처음 16자가 ID로 사용)
- x_forwarded_for # 프록시/로드 밸런서 헤더
- x_real_ip # 대체 IP 헤더
- fallback: "unknown" # 식별자가 없을 때
작동 방식¶
- 클라이언트 식별: 각 요청은 다음을 사용하여 클라이언트와 연결:
Authorization: Bearer <token>헤더의 API 키 (선호)-
프록시 헤더의 IP 주소 (폴백)
-
이중 윈도우 접근 방식:
- 지속 제한: 시간 경과에 따른 과도한 사용 방지
-
버스트 보호: 연속적인 빠른 요청 포착
-
독립적인 할당량: 각 클라이언트는 별도의 속도 제한:
- API 키
abc123...을 가진 클라이언트 A: 100 req/min - API 키
def456...을 가진 클라이언트 B: 100 req/min - IP
192.168.1.1의 클라이언트 C: 100 req/min
응답 헤더¶
속도 제한 시 응답 포함:
- 상태 코드:
429 Too Many Requests - 오류 메시지: 버스트 또는 지속 제한 초과 여부 표시
캐시 TTL 최적화¶
캐시 오염 공격 방지를 위해:
- 빈 모델 목록: 5초만 캐시
- 일반 응답: 60초 캐시
이렇게 하면 공격자가 백엔드 장애 중에 빈 응답을 캐시하도록 강제하는 것을 방지합니다.
모니터링¶
속도 제한 위반은 메트릭에서 추적:
rate_limit_violations: 거부된 총 요청empty_responses_returned: 제공된 빈 모델 목록- 문제가 있는 클라이언트 식별을 위한 클라이언트별 위반 추적
향후 개선 사항¶
향후 버전에서 지원될 수 있는 기능:
- YAML/환경 변수를 통한 설정 가능한 속도 제한
- 엔드포인트별 속도 제한
- API 키별 사용자 정의 속도 제한
- Redis 기반 분산 속도 제한
환경별 설정¶
개발 설정¶
# config/development.yaml
server:
bind_address: "127.0.0.1:8080"
backends:
- name: "local-ollama"
url: "http://localhost:11434"
health_checks:
interval: "10s" # 더 빈번한 확인
timeout: "5s"
logging:
level: "debug" # 상세 로깅
format: "pretty" # 사람이 읽기 쉬운
enable_colors: true
프로덕션 설정¶
# config/production.yaml
server:
bind_address: "0.0.0.0:8080"
workers: 8 # 프로덕션용 더 많은 워커
connection_pool_size: 300 # 더 큰 연결 풀
backends:
- name: "primary-openai"
url: "https://api.openai.com"
weight: 3
- name: "secondary-azure"
url: "https://azure-openai.example.com"
weight: 2
- name: "fallback-local"
url: "http://internal-llm:11434"
weight: 1
health_checks:
interval: "60s" # 덜 빈번한 확인
timeout: "15s" # 네트워크 지연을 위한 더 긴 타임아웃
unhealthy_threshold: 5 # 더 많은 허용
healthy_threshold: 3
request:
timeout: "120s" # 프로덕션용 짧은 타임아웃
max_retries: 5 # 더 많은 재시도
logging:
level: "warn" # 덜 상세한 로깅
format: "json" # 구조화된 로깅