설정 가이드¶
이 가이드는 Continuum Router 설정에 대한 종합적인 문서를 제공합니다. 라우터는 다양한 배포 시나리오에 최대한의 유연성을 제공하기 위해 명확한 우선순위 시스템과 함께 여러 설정 방법을 지원합니다.
설정 방법¶
Continuum Router는 세 가지 설정 방법을 지원합니다:
- 설정 파일 (YAML) - 프로덕션 환경에 권장
- 환경 변수 - 컨테이너화된 배포에 적합
- 명령줄 인수 - 테스트 및 오버라이드에 유용
설정 파일 검색¶
라우터는 다음 위치에서 설정 파일을 자동으로 검색합니다 (순서대로):
--config플래그로 지정된 경로./config.yaml(현재 디렉토리)./config.yml/etc/continuum-router/config.yaml/etc/continuum-router/config.yml~/.config/continuum-router/config.yaml~/.config/continuum-router/config.yml
설정 우선순위¶
설정은 다음 우선순위로 적용됩니다 (높은 것부터 낮은 순):
- 명령줄 인수 (최고 우선순위)
- 환경 변수
- 설정 파일
- 기본값 (최저 우선순위)
이를 통해 다음이 가능합니다:
- 파일에 기본 설정 지정
- 컨테이너에서 환경 변수로 특정 설정 오버라이드
- 명령줄 인수로 임시 조정
설정 파일 형식¶
전체 설정 예제¶
# Continuum Router 설정
# 이 예제는 모든 사용 가능한 설정 옵션과 기본값을 보여줍니다
# 서버 설정
server:
bind_address: "0.0.0.0:8080" # 서버 바인드 주소
workers: 4 # 워커 스레드 수 (0 = 자동 감지)
connection_pool_size: 100 # 백엔드당 최대 유휴 연결 수
# 모델 메타데이터 설정 (선택 사항)
model_metadata_file: "model-metadata.yaml" # 외부 모델 메타데이터 파일 경로
# 백엔드 설정
backends:
# 내장 설정이 있는 네이티브 OpenAI API
- name: "openai"
type: openai # 네이티브 OpenAI 백엔드 사용
api_key: "${CONTINUUM_OPENAI_API_KEY}" # 환경 변수에서 로드
org_id: "${CONTINUUM_OPENAI_ORG_ID}" # 선택적 조직 ID
weight: 3
models: # 사용할 모델 지정
- gpt-4o
- gpt-4o-mini
- o3-mini
- text-embedding-3-large
retry_override: # 백엔드별 재시도 설정 (선택 사항)
max_attempts: 5
base_delay: "200ms"
max_delay: "30s"
exponential_backoff: true
jitter: true
# 사용자 정의 메타데이터가 있는 일반 OpenAI 호환 백엔드
- name: "openai-compatible"
url: "https://custom-llm.example.com"
weight: 1
models:
- "gpt-4"
- "gpt-3.5-turbo"
model_configs: # 메타데이터가 포함된 향상된 모델 설정
- id: "gpt-4"
aliases: # 이 메타데이터를 공유하는 대체 ID (선택 사항)
- "gpt-4-0125-preview"
- "gpt-4-turbo-preview"
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
# 자동 URL 감지가 있는 Ollama 로컬 서버
- name: "local-ollama"
type: ollama # 기본값 http://localhost:11434
weight: 2
models:
- "llama2"
- "mistral"
- "codellama"
# vLLM 서버
- name: "vllm-server"
type: vllm
url: "http://localhost:8000"
weight: 1
# 지정하지 않으면 모델이 자동으로 검색됩니다
# 네임스페이스 접두사가 있는 모델 (예: "custom/gpt-4")은
# 자동으로 기본 이름의 메타데이터와 일치합니다 (예: "gpt-4")
# Google Gemini API (네이티브 백엔드)
- name: "gemini"
type: gemini # 네이티브 Gemini 백엔드 사용
api_key: "${CONTINUUM_GEMINI_API_KEY}" # 환경 변수에서 로드
weight: 2
models:
- gemini-2.5-pro
- gemini-2.5-flash
- gemini-2.0-flash
# 헬스 모니터링 설정
health_checks:
enabled: true # 헬스 체크 활성화/비활성화
interval: "30s" # 백엔드 상태 확인 주기
timeout: "10s" # 헬스 체크 요청 타임아웃
unhealthy_threshold: 3 # 비정상으로 표시되기 전 실패 횟수
healthy_threshold: 2 # 정상으로 표시되기 전 성공 횟수
endpoint: "/v1/models" # 헬스 체크에 사용되는 엔드포인트
# 요청 처리 및 타임아웃 설정
timeouts:
connection: "10s" # TCP 연결 설정 타임아웃
request:
standard: # 비스트리밍 요청
first_byte: "30s" # 첫 바이트 수신까지의 시간
total: "180s" # 전체 요청 타임아웃 (3분)
streaming: # 스트리밍 (SSE) 요청
first_byte: "60s" # 첫 SSE 청크까지의 시간
chunk_interval: "30s" # 청크 간 최대 시간
total: "600s" # 전체 스트리밍 타임아웃 (10분)
image_generation: # 이미지 생성 요청 (DALL-E 등)
first_byte: "60s" # 첫 바이트 수신까지의 시간
total: "180s" # 전체 타임아웃 (기본 3분)
model_overrides: # 모델별 타임아웃 오버라이드
gpt-5-latest:
streaming:
total: "1200s" # GPT-5용 20분
gpt-4o:
streaming:
total: "900s" # GPT-4o용 15분
health_check:
timeout: "5s" # 헬스 체크 타임아웃
interval: "30s" # 헬스 체크 간격
request:
max_retries: 3 # 요청 최대 재시도 횟수
retry_delay: "1s" # 재시도 간 초기 지연
# 전역 재시도 및 복원력 설정
retry:
max_attempts: 3 # 최대 재시도 횟수
base_delay: "100ms" # 재시도 간 기본 지연
max_delay: "30s" # 재시도 간 최대 지연
exponential_backoff: true # 지수 백오프 사용
jitter: true # 지연에 무작위 지터 추가
# 캐싱 및 최적화 설정
cache:
model_cache_ttl: "300s" # 모델 목록 캐시 5분
deduplication_ttl: "60s" # 요청 중복 제거 1분
enable_deduplication: true # 요청 중복 제거 활성화
# 로깅 설정
logging:
level: "info" # 로그 레벨: trace, debug, info, warn, error
format: "json" # 로그 형식: json, pretty
enable_colors: false # 컬러 출력 활성화 (pretty 형식용)
# Files API 설정
files:
enabled: true # Files API 엔드포인트 활성화/비활성화
max_file_size: 536870912 # 최대 파일 크기 (바이트, 기본: 512MB)
storage_path: "./data/files" # 업로드된 파일 저장 경로 (~지원)
retention_days: 0 # 파일 보존 기간 (일, 0 = 영구 보존)
metadata_storage: persistent # 메타데이터 백엔드: "memory" 또는 "persistent" (기본)
cleanup_orphans_on_startup: false # 시작 시 고아 파일 자동 정리
# 인증 및 권한
auth:
method: api_key # "none" 또는 "api_key" (기본)
required_scope: files # 접근에 필요한 API 키 스코프
enforce_ownership: true # 사용자가 자신의 파일만 접근 가능
admin_can_access_all: true # admin 스코프는 모든 파일 접근 가능
# 로드 밸런싱 설정
load_balancer:
strategy: "round_robin" # 전략: round_robin, weighted, random
health_aware: true # 정상 백엔드로만 라우팅
# 서킷 브레이커 설정
circuit_breaker:
enabled: false # 서킷 브레이커 활성화
failure_threshold: 5 # 회로 개방까지의 실패 횟수
recovery_timeout: "60s" # 복구 시도까지의 시간
half_open_retries: 3 # 반개방 상태에서의 재시도 횟수
# 속도 제한 설정
rate_limiting:
enabled: false # 속도 제한 활성화
requests_per_second: 100 # 전역 초당 요청 수
burst_size: 200 # 버스트 용량
# 메트릭 및 모니터링 설정
metrics:
enabled: false # 메트릭 수집 활성화
endpoint: "/metrics" # 메트릭 엔드포인트 경로
include_labels: true # 상세 레이블 포함
최소 설정¶
# 최소 설정 - 나머지 설정은 기본값 사용
server:
bind_address: "0.0.0.0:8080"
backends:
- name: "ollama"
url: "http://localhost:11434"
- name: "lm-studio"
url: "http://localhost:1234"
환경 변수¶
모든 설정 옵션은 CONTINUUM_ 접두사가 붙은 환경 변수로 오버라이드할 수 있습니다:
서버 설정¶
| 변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
CONTINUUM_BIND_ADDRESS | string | "0.0.0.0:8080" | 서버 바인드 주소 |
CONTINUUM_WORKERS | integer | 4 | 워커 스레드 수 |
CONTINUUM_CONNECTION_POOL_SIZE | integer | 100 | HTTP 연결 풀 크기 |
백엔드 설정¶
| 변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
CONTINUUM_BACKEND_URLS | string | 쉼표로 구분된 백엔드 URL | |
CONTINUUM_BACKEND_WEIGHTS | string | 쉼표로 구분된 가중치 (URL과 일치해야 함) |
헬스 체크 설정¶
| 변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
CONTINUUM_HEALTH_CHECKS_ENABLED | boolean | true | 헬스 체크 활성화 |
CONTINUUM_HEALTH_CHECK_INTERVAL | string | "30s" | 헬스 체크 간격 |
CONTINUUM_HEALTH_CHECK_TIMEOUT | string | "10s" | 헬스 체크 타임아웃 |
CONTINUUM_UNHEALTHY_THRESHOLD | integer | 3 | 비정상 판정까지의 실패 횟수 |
CONTINUUM_HEALTHY_THRESHOLD | integer | 2 | 정상 판정까지의 성공 횟수 |
요청 설정¶
| 변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
CONTINUUM_REQUEST_TIMEOUT | string | "300s" | 최대 요청 타임아웃 |
CONTINUUM_MAX_RETRIES | integer | 3 | 최대 재시도 횟수 |
CONTINUUM_RETRY_DELAY | string | "1s" | 초기 재시도 지연 |
로깅 설정¶
| 변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
CONTINUUM_LOG_LEVEL | string | "info" | 로그 레벨 |
CONTINUUM_LOG_FORMAT | string | "json" | 로그 형식 |
CONTINUUM_LOG_COLORS | boolean | false | 컬러 출력 활성화 |
RUST_LOG | string | Rust 전용 로깅 설정 |
캐시 설정¶
| 변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
CONTINUUM_MODEL_CACHE_TTL | string | "300s" | 모델 캐시 TTL |
CONTINUUM_DEDUPLICATION_TTL | string | "60s" | 중복 제거 TTL |
CONTINUUM_ENABLE_DEDUPLICATION | boolean | true | 중복 제거 활성화 |
Files API 설정¶
| 변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
CONTINUUM_FILES_ENABLED | boolean | true | Files API 활성화/비활성화 |
CONTINUUM_FILES_MAX_SIZE | integer | 536870912 | 최대 파일 크기 (바이트, 512MB) |
CONTINUUM_FILES_STORAGE_PATH | string | "./data/files" | 업로드 파일 저장 경로 |
CONTINUUM_FILES_RETENTION_DAYS | integer | 0 | 파일 보존 기간 (일, 0 = 영구) |
CONTINUUM_FILES_METADATA_STORAGE | string | "persistent" | 메타데이터 백엔드: "memory" 또는 "persistent" |
CONTINUUM_FILES_CLEANUP_ORPHANS | boolean | false | 시작 시 고아 파일 자동 정리 |
CONTINUUM_FILES_AUTH_METHOD | string | "api_key" | 인증 방법: "none" 또는 "api_key" |
CONTINUUM_FILES_AUTH_SCOPE | string | "files" | Files API 접근에 필요한 API 키 스코프 |
CONTINUUM_FILES_ENFORCE_OWNERSHIP | boolean | true | 사용자가 자신의 파일만 접근 가능 |
CONTINUUM_FILES_ADMIN_ACCESS_ALL | boolean | true | admin 스코프는 모든 파일 접근 가능 |
CONTINUUM_DEV_MODE | boolean | false | 개발용 API 키 활성화 (프로덕션에서 사용 금지) |
API 키 관리 설정¶
| 변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
CONTINUUM_API_KEY | string | - | 간단한 배포용 단일 API 키 |
CONTINUUM_API_KEY_SCOPES | string | "read,write" | API 키의 쉼표로 구분된 스코프 |
CONTINUUM_API_KEY_USER_ID | string | "admin" | API 키와 연결된 사용자 ID |
CONTINUUM_API_KEY_ORG_ID | string | "default" | API 키와 연결된 조직 ID |
CONTINUUM_DEV_MODE | boolean | false | 개발용 API 키 활성화 (프로덕션에서 사용 금지) |
환경 설정 예제¶
# 기본 설정
export CONTINUUM_BIND_ADDRESS="0.0.0.0:9000"
export CONTINUUM_BACKEND_URLS="http://localhost:11434,http://localhost:1234"
export CONTINUUM_LOG_LEVEL="debug"
# 고급 설정
export CONTINUUM_CONNECTION_POOL_SIZE="200"
export CONTINUUM_HEALTH_CHECK_INTERVAL="60s"
export CONTINUUM_MODEL_CACHE_TTL="600s"
export CONTINUUM_ENABLE_DEDUPLICATION="true"
# 라우터 시작
continuum-router
명령줄 인수¶
명령줄 인수는 최고 우선순위의 설정 방법으로 테스트와 임시 오버라이드에 유용합니다.
핵심 옵션¶
| 인수 | 타입 | 설명 |
|---|---|---|
-c, --config <FILE> | path | 설정 파일 경로 |
--generate-config | flag | 샘플 설정을 생성하고 종료 |
백엔드 설정¶
| 인수 | 타입 | 설명 |
|---|---|---|
--backends <URLs> | string | 쉼표로 구분된 백엔드 URL |
--backend-url <URL> | string | 단일 백엔드 URL (지원 중단) |
서버 설정¶
| 인수 | 타입 | 설명 |
|---|---|---|
--bind <ADDRESS> | string | 서버 바인드 주소 |
--connection-pool-size <SIZE> | integer | HTTP 연결 풀 크기 |
헬스 체크 설정¶
| 인수 | 타입 | 설명 |
|---|---|---|
--disable-health-checks | flag | 헬스 모니터링 비활성화 |
--health-check-interval <SECONDS> | integer | 헬스 체크 간격 |
--health-check-timeout <SECONDS> | integer | 헬스 체크 타임아웃 |
--unhealthy-threshold <COUNT> | integer | 비정상 판정까지의 실패 횟수 |
--healthy-threshold <COUNT> | integer | 정상 판정까지의 성공 횟수 |
CLI 사용 예제¶
# 설정 파일과 오버라이드 사용
continuum-router --config config.yaml --bind "0.0.0.0:9000"
# 백엔드 임시 오버라이드
continuum-router --config config.yaml --backends "http://localhost:11434"
# 테스트용 헬스 체크 설정 조정
continuum-router --config config.yaml --health-check-interval 10
# 샘플 설정 생성
continuum-router --generate-config > my-config.yaml
설정 섹션¶
서버 섹션¶
HTTP 서버 동작을 제어합니다:
server:
bind_address: "0.0.0.0:8080" # 바인드할 호스트와 포트
workers: 4 # 워커 스레드 (0 = 자동)
connection_pool_size: 100 # HTTP 연결 풀 크기
성능 튜닝:
workers: 자동 감지를 위해 0으로 설정하거나 CPU 코어 수와 일치connection_pool_size: 고부하 시나리오에서는 증가 (200-500)
백엔드 섹션¶
요청을 라우팅할 LLM 백엔드를 정의합니다:
backends:
- name: "unique-identifier" # 모든 백엔드에서 고유해야 함
type: "generic" # 백엔드 유형 (선택 사항, 기본값 "generic")
url: "http://backend:port" # 백엔드 기본 URL
weight: 1 # 로드 밸런싱 가중치 (1-100)
api_key: "${API_KEY}" # API 키 (선택 사항, 환경 변수 참조 지원)
org_id: "${ORG_ID}" # 조직 ID (선택 사항, OpenAI용)
models: ["model1", "model2"] # 선택 사항: 명시적 모델 목록
retry_override: # 선택 사항: 백엔드별 재시도 설정
max_attempts: 5
base_delay: "200ms"
지원되는 백엔드 유형:
| 유형 | 설명 | 기본 URL |
|---|---|---|
generic | OpenAI 호환 API (기본) | 지정 필수 |
openai | 내장 설정이 있는 네이티브 OpenAI API | https://api.openai.com/v1 |
gemini | Google Gemini API (OpenAI 호환 엔드포인트) | https://generativelanguage.googleapis.com/v1beta/openai |
azure | Azure OpenAI Service | 지정 필수 |
vllm | vLLM 서버 | 지정 필수 |
ollama | Ollama 로컬 서버 | http://localhost:11434 |
anthropic | Anthropic Claude API (요청/응답 변환 포함 네이티브) | https://api.anthropic.com |
네이티브 OpenAI 백엔드¶
type: openai를 사용하면 라우터는 다음을 제공합니다:
- 기본 URL:
https://api.openai.com/v1(프록시용으로 오버라이드 가능) - 내장 모델 메타데이터: 자동 가격, 컨텍스트 윈도우, 기능
- 환경 변수 지원:
CONTINUUM_OPENAI_API_KEY및CONTINUUM_OPENAI_ORG_ID에서 자동 로드
최소 OpenAI 설정:
명시적 API 키가 있는 전체 OpenAI 설정:
backends:
- name: "openai-primary"
type: openai
api_key: "${CONTINUUM_OPENAI_API_KEY}"
org_id: "${CONTINUUM_OPENAI_ORG_ID}" # 선택 사항
models:
- gpt-4o
- gpt-4o-mini
- o1
- o1-mini
- o3-mini
- text-embedding-3-large
프록시와 함께 OpenAI 사용:
backends:
- name: "openai-proxy"
type: openai
url: "https://my-proxy.example.com/v1" # 기본 URL 오버라이드
api_key: "${PROXY_API_KEY}"
models:
- gpt-4o
OpenAI 환경 변수¶
| 변수 | 설명 |
|---|---|
CONTINUUM_OPENAI_API_KEY | OpenAI API 키 (type: openai 백엔드용으로 자동 로드) |
CONTINUUM_OPENAI_ORG_ID | OpenAI 조직 ID (선택 사항) |
모델 자동 검색:
models가 지정되지 않았거나 비어 있으면, 백엔드는 초기화 중에 /v1/models API 엔드포인트에서 사용 가능한 모델을 자동으로 검색합니다. 이 기능은 설정 유지보수를 줄이고 백엔드에서 보고된 모든 모델이 라우팅 가능하도록 보장합니다.
| 백엔드 유형 | 자동 검색 지원 | 폴백 모델 |
|---|---|---|
openai | ✅ 예 | gpt-4o, gpt-4o-mini, o3-mini |
gemini | ✅ 예 | gemini-2.5-pro, gemini-2.5-flash, gemini-2.0-flash |
vllm | ✅ 예 | vicuna-7b-v1.5, llama-2-7b-chat, mistral-7b-instruct |
ollama | ✅ 예 | vLLM 검색 메커니즘 사용 |
anthropic | ❌ 아니오 (API 없음) | 하드코딩된 Claude 모델 |
generic | ❌ 아니오 | 모든 모델 지원 (supports_model()이 true 반환) |
검색 동작:
- 타임아웃: 10초 타임아웃으로 시작 차단 방지
- 폴백: 검색 실패 시 (타임아웃, 네트워크 오류, 잘못된 응답) 폴백 모델 사용
- 로깅: 검색된 모델은 INFO 레벨로 로깅; 폴백 사용은 WARN 레벨로 로깅
모델 해석 우선순위:
- 설정의 명시적
models목록 (최고 우선순위) model_configs필드의 모델- 백엔드 API에서 자동 검색된 모델
-
하드코딩된 폴백 모델 (최저 우선순위)
-
명시적 모델 목록은 시작 시간을 개선하고 백엔드 쿼리를 줄입니다
네이티브 Gemini 백엔드¶
type: gemini를 사용하면 라우터는 다음을 제공합니다:
- 기본 URL:
https://generativelanguage.googleapis.com/v1beta/openai(OpenAI 호환 엔드포인트) - 내장 모델 메타데이터: Gemini 모델에 대한 자동 컨텍스트 윈도우 및 기능
- 환경 변수 지원:
CONTINUUM_GEMINI_API_KEY에서 자동 로드 - 확장 스트리밍 타임아웃: 사고 모델용 300초 타임아웃 (gemini-2.5-pro, gemini-3-pro)
- 자동 max_tokens 조정: 사고 모델용, 아래 참조
최소 Gemini 설정:
backends:
- name: "gemini"
type: gemini
models:
- gemini-2.5-pro
- gemini-2.5-flash
- gemini-2.0-flash
전체 Gemini 설정:
backends:
- name: "gemini"
type: gemini
api_key: "${CONTINUUM_GEMINI_API_KEY}"
weight: 2
models:
- gemini-2.5-pro
- gemini-2.5-flash
- gemini-2.0-flash
Gemini 사고 모델: 자동 max_tokens 조정¶
Gemini "사고" 모델 (gemini-2.5-pro, gemini-3-pro, -pro-preview 접미사가 있는 모델)은 응답 생성 전에 확장된 추론을 수행합니다. 응답 잘림을 방지하기 위해 라우터가 자동으로 max_tokens를 조정합니다:
| 조건 | 동작 |
|---|---|
max_tokens 미지정 | 자동으로 16384로 설정 |
max_tokens < 4096 | 자동으로 16384로 증가 |
max_tokens >= 4096 | 클라이언트 값 유지 |
이렇게 하면 클라이언트 라이브러리의 낮은 기본값으로 인한 잘림 없이 사고 모델이 완전한 응답을 생성할 수 있습니다.
Gemini 환경 변수¶
| 변수 | 설명 |
|---|---|
CONTINUUM_GEMINI_API_KEY | Google Gemini API 키 (type: gemini 백엔드용으로 자동 로드) |
네이티브 Anthropic 백엔드¶
type: anthropic을 사용하면 라우터는 다음을 제공합니다:
- 기본 URL:
https://api.anthropic.com(프록시용으로 오버라이드 가능) - 네이티브 API 변환: OpenAI 형식 요청을 Anthropic Messages API 형식으로 자동 변환 및 역변환
- Anthropic 전용 헤더:
x-api-key및anthropic-version헤더 자동 추가 - 환경 변수 지원:
CONTINUUM_ANTHROPIC_API_KEY에서 자동 로드 - 확장 스트리밍 타임아웃: 확장 사고 모델용 600초 타임아웃 (Claude Opus, Sonnet 4)
최소 Anthropic 설정:
backends:
- name: "anthropic"
type: anthropic
models:
- claude-sonnet-4-20250514
- claude-haiku-3-5-20241022
전체 Anthropic 설정:
backends:
- name: "anthropic"
type: anthropic
api_key: "${CONTINUUM_ANTHROPIC_API_KEY}"
weight: 2
models:
- claude-opus-4-5-20250514
- claude-sonnet-4-20250514
- claude-haiku-3-5-20241022
Anthropic API 변환¶
라우터는 OpenAI와 Anthropic API 형식 간의 변환을 자동으로 처리합니다:
| OpenAI 형식 | Anthropic 형식 |
|---|---|
role: "system"이 있는 messages 배열 | 별도의 system 매개변수 |
Authorization: Bearer <key> | x-api-key: <key> 헤더 |
선택적 max_tokens | 필수 max_tokens (누락 시 자동 채움) |
choices[0].message.content | content[0].text |
finish_reason: "stop" | stop_reason: "end_turn" |
usage.prompt_tokens | usage.input_tokens |
요청 변환 예제:
OpenAI 형식 (클라이언트에서 들어오는):
{
"model": "claude-sonnet-4-20250514",
"messages": [
{"role": "system", "content": "당신은 도움이 됩니다."},
{"role": "user", "content": "안녕하세요"}
],
"max_tokens": 1024
}
Anthropic 형식 (API로 전송되는):
{
"model": "claude-sonnet-4-20250514",
"system": "당신은 도움이 됩니다.",
"messages": [
{"role": "user", "content": "안녕하세요"}
],
"max_tokens": 1024
}
Anthropic 확장 사고 모델¶
확장 사고를 지원하는 모델 (Claude Opus, Sonnet 4)은 더 긴 응답 시간이 필요할 수 있습니다. 라우터는 자동으로: - 사고 모델에 대해 더 높은 기본 max_tokens (16384) 설정 - 이 모델에 대해 확장 스트리밍 타임아웃 (600초) 사용
OpenAI ↔ Claude 추론 매개변수 변환¶
라우터는 OpenAI의 추론 매개변수와 Claude의 thinking 매개변수 간을 자동으로 변환하여 원활한 크로스 프로바이더 추론 요청을 가능하게 합니다.
지원되는 OpenAI 형식:
| 형식 | API | 예제 |
|---|---|---|
reasoning_effort (플랫) | Chat Completions API | "reasoning_effort": "high" |
reasoning.effort (중첩) | Responses API | "reasoning": {"effort": "high"} |
두 형식이 모두 있으면 reasoning_effort (플랫)가 우선합니다.
Effort 레벨에서 Budget 토큰 매핑:
| Effort 레벨 | Claude thinking.budget_tokens |
|---|---|
none | (사고 비활성화) |
minimal | 1,024 |
low | 4,096 |
medium | 10,240 |
high | 32,768 |
요청 예제 - Chat Completions API (플랫 형식):
// 클라이언트가 OpenAI Chat Completions API 요청을 보냄
{
"model": "claude-sonnet-4-5-20250929",
"reasoning_effort": "high",
"messages": [{"role": "user", "content": "이 복잡한 문제를 풀어주세요"}]
}
// 라우터가 Claude 형식으로 변환
{
"model": "claude-sonnet-4-5-20250929",
"thinking": {"type": "enabled", "budget_tokens": 32768},
"messages": [{"role": "user", "content": "이 복잡한 문제를 풀어주세요"}]
}
요청 예제 - Responses API (중첩 형식):
// 클라이언트가 OpenAI Responses API 요청을 보냄
{
"model": "claude-sonnet-4-5-20250929",
"reasoning": {"effort": "medium"},
"messages": [{"role": "user", "content": "이 데이터를 분석해주세요"}]
}
// 라우터가 Claude 형식으로 변환
{
"model": "claude-sonnet-4-5-20250929",
"thinking": {"type": "enabled", "budget_tokens": 10240},
"messages": [{"role": "user", "content": "이 데이터를 분석해주세요"}]
}
추론 콘텐츠가 있는 응답:
{
"choices": [{
"message": {
"role": "assistant",
"content": "최종 답변은...",
"reasoning_content": "단계별로 분석해 보겠습니다..."
}
}]
}
중요 사항: - thinking 매개변수가 명시적으로 제공되면 reasoning_effort 및 reasoning.effort보다 우선합니다 - reasoning_effort (플랫)가 두 형식이 모두 있을 때 reasoning.effort (중첩)보다 우선합니다 - 확장 사고를 지원하는 모델 (Opus 4.x, Sonnet 4.x)만 추론이 활성화됩니다 - 추론이 활성화되면 temperature 매개변수가 자동으로 제거됩니다 (Claude API 요구 사항) - 스트리밍 응답의 경우 사고 콘텐츠가 reasoning_content delta 이벤트로 반환됩니다
Anthropic 환경 변수¶
| 변수 | 설명 |
|---|---|
CONTINUUM_ANTHROPIC_API_KEY | Anthropic API 키 (type: anthropic 백엔드용으로 자동 로드) |
헬스 체크 섹션¶
백엔드 헬스 모니터링을 설정합니다:
health_checks:
enabled: true # 헬스 모니터링 활성화/비활성화
interval: "30s" # 확인 주기
timeout: "10s" # 요청 타임아웃
unhealthy_threshold: 3 # 비정상 표시까지의 실패 횟수
healthy_threshold: 2 # 정상 표시까지의 성공 횟수
endpoint: "/v1/models" # 확인할 엔드포인트
헬스 체크 프로세스:
- 라우터가 각 백엔드의 헬스 엔드포인트를 쿼리
- 성공적인 응답은 성공 카운터 증가
- 실패한 응답은 실패 카운터 증가
- 실패 임계값에 도달하면 백엔드를 비정상으로 표시
- 성공 임계값에 도달하면 백엔드를 정상으로 표시
- 정상 백엔드만 트래픽 수신
요청 섹션¶
요청 처리 동작을 제어합니다:
request:
timeout: "300s" # 최대 요청 지속 시간
max_retries: 3 # 실패한 요청의 재시도 횟수
retry_delay: "1s" # 재시도 간 초기 지연
타임아웃 고려 사항:
- 긴 타임아웃 (300s)은 느린 모델 추론 수용
- 스트리밍 요청은 비스트리밍보다 오래 걸릴 수 있음
- 사용자 경험과 리소스 사용 간 균형
재시도 섹션¶
복원력을 위한 전역 재시도 설정:
retry:
max_attempts: 3 # 최대 재시도 횟수
base_delay: "100ms" # 재시도 간 기본 지연
max_delay: "30s" # 재시도 지연 상한
exponential_backoff: true # 지수 백오프 사용
jitter: true # 무작위 지터 추가
재시도 전략:
- 지수 백오프: 지연이 지수적으로 증가 (100ms, 200ms, 400ms...)
- 지터: 썬더링 허드 방지를 위한 무작위성 추가
- 최대 지연: 극도로 긴 대기 방지
캐시 섹션¶
캐싱 및 최적화를 제어합니다:
cache:
model_cache_ttl: "300s" # 모델 목록 캐시 기간
deduplication_ttl: "60s" # 동일 요청 캐시 기간
enable_deduplication: true # 요청 중복 제거 활성화
캐시 이점:
- 모델 캐싱은 백엔드 쿼리 감소
- 중복 제거는 중복 처리 방지
- TTL은 오래된 데이터 문제 방지
로깅 섹션¶
로깅 출력을 설정합니다:
logging:
level: "info" # trace, debug, info, warn, error
format: "json" # json, pretty
enable_colors: false # 컬러 출력 (pretty 형식만)
로그 레벨:
trace: 매우 상세, 모든 세부 정보 포함debug: 상세한 디버깅 정보info: 일반적인 운영 정보warn: 경고 메시지 및 잠재적 문제error: 오류 조건만
로그 형식:
json: 구조화된 JSON 로깅 (프로덕션 권장)pretty: 사람이 읽기 쉬운 형식 (개발에 적합)
API 키 섹션¶
API 키는 라우터 엔드포인트에 대한 클라이언트 접근을 제어합니다. 키는 여러 소스를 통해 설정할 수 있습니다.
인증 모드¶
mode 설정은 API 엔드포인트에 API 인증이 필요한지 제어합니다:
| 모드 | 동작 |
|---|---|
permissive (기본) | API 키 없이 요청 허용. 유효한 API 키가 있는 요청은 인증됨. |
blocking | API 키 인증을 통과한 요청만 처리. 인증되지 않은 요청은 401 수신. |
대상 엔드포인트 (mode가 blocking일 때):
/v1/chat/completions/v1/completions/v1/responses/v1/images/generations/v1/images/edits/v1/images/variations/v1/models
참고: Admin, Files, Metrics 엔드포인트는 별도의 인증 메커니즘이 있으며 이 설정의 영향을 받지 않습니다.
섹션 설정 속성:
| 속성 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
mode | string | 아니오 | permissive | 인증 모드: permissive 또는 blocking |
api_keys | array | 아니오 | [] | 인라인 API 키 정의 |
api_keys_file | string | 아니오 | - | 외부 API 키 파일 경로 |
api_keys:
# 인증 모드: "permissive" (기본) 또는 "blocking"
mode: permissive
# 인라인 API 키 정의
api_keys:
- key: "${API_KEY_1}" # 환경 변수 치환
id: "key-production-1" # 고유 식별자
user_id: "user-admin" # 연결된 사용자
organization_id: "org-main" # 연결된 조직
name: "Production Admin Key" # 사람이 읽을 수 있는 이름
scopes: # 권한
- read
- write
- files
- admin
rate_limit: 1000 # 분당 요청 수 (선택 사항)
enabled: true # 활성 상태
expires_at: "2025-12-31T23:59:59Z" # 선택적 만료 (ISO 8601)
- key: "${API_KEY_2}"
id: "key-service-1"
user_id: "service-bot"
organization_id: "org-main"
name: "Service Account"
scopes: [read, write, files]
rate_limit: 500
enabled: true
# 보안 향상을 위한 외부 키 파일
api_keys_file: "/etc/continuum-router/api-keys.yaml"
키 속성:
| 속성 | 타입 | 필수 | 설명 |
|---|---|---|---|
key | string | 예 | API 키 값 (${ENV_VAR} 치환 지원) |
id | string | 예 | admin 작업을 위한 고유 식별자 |
user_id | string | 예 | 이 키와 연결된 사용자 |
organization_id | string | 예 | 사용자가 속한 조직 |
name | string | 아니오 | 사람이 읽을 수 있는 이름 |
description | string | 아니오 | 키에 대한 메모 |
scopes | array | 예 | 권한: read, write, files, admin |
rate_limit | integer | 아니오 | 분당 최대 요청 수 |
enabled | boolean | 아니오 | 활성 상태 (기본값: true) |
expires_at | string | 아니오 | ISO 8601 만료 타임스탬프 |
외부 키 파일 형식:
# /etc/continuum-router/api-keys.yaml
keys:
- key: "sk-prod-xxxxxxxxxxxxxxxxxxxxx"
id: "key-external-1"
user_id: "external-user"
organization_id: "external-org"
scopes: [read, write, files]
enabled: true
보안 기능:
- 키 마스킹: 전체 키는 로깅되지 않음 (
sk-***last4로 표시) - 만료 적용: 만료된 키는 자동으로 거부
- 핫 리로드: 서버 재시작 없이 키 업데이트
- 감사 로깅: 모든 키 관리 작업 로깅
- 상수 시간 검증: 타이밍 공격 방지
- 최대 키 제한: DoS 방지를 위해 최대 10,000개 키
Admin API 엔드포인트 (admin 인증 필요):
| 엔드포인트 | 메서드 | 설명 |
|---|---|---|
/admin/api-keys | GET | 모든 키 목록 (마스킹됨) |
/admin/api-keys/:id | GET | 키 세부 정보 가져오기 |
/admin/api-keys | POST | 새 키 생성 |
/admin/api-keys/:id | PUT | 키 속성 업데이트 |
/admin/api-keys/:id | DELETE | 키 삭제 |
/admin/api-keys/:id/rotate | POST | 새 키 값 생성 |
/admin/api-keys/:id/enable | POST | 키 활성화 |
/admin/api-keys/:id/disable | POST | 키 비활성화 |
고급 설정¶
전역 프롬프트¶
전역 프롬프트를 사용하면 모든 요청에 시스템 프롬프트를 주입하여 보안, 규정 준수 및 동작 가이드라인에 대한 중앙 집중식 정책 관리를 제공할 수 있습니다. 프롬프트는 인라인으로 정의하거나 외부 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
설정에서 참조하세요:
네임스페이스 인식 매칭¶
라우터는 네임스페이스 접두사가 있는 모델 ID를 지능적으로 처리합니다. 예:
- 백엔드 반환:
"custom/gpt-4","openai/gpt-4","optimized/gpt-4" - 메타데이터 정의:
"gpt-4" - 결과: 모든 변형이 일치하고 동일한 메타데이터 수신
이를 통해 다른 백엔드가 공통 메타데이터 정의를 공유하면서 자체 명명 규칙을 사용할 수 있습니다.
메타데이터 우선순위 및 별칭 해석¶
모델에 대해 여러 메타데이터 소스가 있는 경우:
-
백엔드별
model_configs(최고 우선순위) -
외부 메타데이터 파일 (두 번째 우선순위)
-
별칭 매칭 (정확한 ID를 찾을 수 없는 경우)
"gpt-4-turbo"요청 시 별칭으로 나열된 경우-
상위 모델 설정의 메타데이터 반환
-
기본 모델 폴백 (네임스페이스 매칭용)
"custom/gpt-4"에 정확한 일치가 없는 경우"gpt-4"의 메타데이터로 폴백
모델 변형에 별칭 사용¶
별칭은 특히 다음에 유용합니다:
- 다른 양자화:
qwen3-32b-i1,qwen3-23b-i4→ 모두qwen3메타데이터 사용 - 버전 변형:
gpt-4-0125-preview,gpt-4-turbo→gpt-4메타데이터 공유 - 배포 변형:
llama-3-70b-instruct,llama-3-70b-chat→ 동일 기본 모델
별칭이 있는 설정 예:
model_configs:
- id: "qwen3"
aliases:
- "qwen3-32b-i1" # 1비트 양자화된 32B
- "qwen3-23b-i4" # 4비트 양자화된 23B
- "qwen3-16b-q8" # 8비트 양자화된 16B
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" # ✅ 즉시: 파일 기반 프롬프트도 핫 리로드
점진적 업데이트 (기존 연결 유지)¶
이 설정들은 기존 연결을 유지하면서 새 연결에 적용됩니다:
# 백엔드 설정
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" # ✅ 점진적: 새 스트림이 업데이트된 설정 사용
재시작 필요 (핫 리로드 불가)¶
이 설정들은 적용을 위해 서버 재시작이 필요합니다. 변경 사항은 경고로 기록됩니다:
이 설정들이 변경되면 라우터는 다음과 같은 경고를 기록합니다:
핫 리로드 프로세스¶
- 파일 시스템 감시자 - 설정 파일 변경 자동 감지
- 설정 로딩 - 새 설정 로드 및 파싱
- 유효성 검사 - 스키마에 대해 새 설정 검증
- 변경 감지 - ConfigDiff 계산으로 변경 사항 식별
- 분류 - 변경 사항 분류 (즉시/점진적/재시작)
- 원자적 업데이트 - 유효한 설정이 원자적으로 적용
- 컴포넌트 전파 - 영향받는 컴포넌트에 업데이트 전파:
- HealthChecker가 체크 간격 및 임계값 업데이트
- RateLimitStore가 속도 제한 규칙 업데이트
- CircuitBreaker가 실패 임계값 및 타임아웃 업데이트
- BackendPool이 백엔드 설정 업데이트
- 오류 처리 - 잘못된 경우 오류 기록 및 이전 설정 유지
핫 리로드 상태 확인¶
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"
예제 3: 바인드 주소 변경 (재시작 필요)
결과: 경고 기록됨. 변경이 적용되지 않음. 새 포트에 바인드하려면 재시작 필요.로드 밸런싱 전략¶
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" # 구조화된 로깅
컨테이너 설정¶
# config/container.yaml - 컨테이너에 최적화
server:
bind_address: "0.0.0.0:8080"
workers: 0 # 컨테이너 제한에 따라 자동 감지
backends:
- name: "backend-1"
url: "${BACKEND_1_URL}" # 환경 변수 치환
- name: "backend-2"
url: "${BACKEND_2_URL}"
logging:
level: "${LOG_LEVEL}" # 환경을 통해 설정 가능
format: "json" # 컨테이너에서 항상 JSON
예제¶
다중 백엔드 설정¶
# 엔터프라이즈 다중 백엔드 설정
server:
bind_address: "0.0.0.0:8080"
workers: 8
connection_pool_size: 400
backends:
# 기본 OpenAI GPT 모델
- name: "openai-primary"
url: "https://api.openai.com"
weight: 5
models: ["gpt-4", "gpt-3.5-turbo"]
retry_override:
max_attempts: 3
base_delay: "500ms"
# 보조 Azure OpenAI
- name: "azure-openai"
url: "https://your-resource.openai.azure.com"
weight: 3
models: ["gpt-4", "gpt-35-turbo"]
# 오픈 모델을 위한 로컬 Ollama
- name: "local-ollama"
url: "http://ollama:11434"
weight: 2
models: ["llama2", "mistral", "codellama"]
# vLLM 배포
- name: "vllm-cluster"
url: "http://vllm-service:8000"
weight: 4
models: ["meta-llama/Llama-2-7b-chat-hf"]
health_checks:
enabled: true
interval: "45s"
timeout: "15s"
unhealthy_threshold: 3
healthy_threshold: 2
request:
timeout: "180s"
max_retries: 4
cache:
model_cache_ttl: "600s" # 10분 캐시
deduplication_ttl: "120s" # 2분 중복 제거
enable_deduplication: true
logging:
level: "info"
format: "json"
고성능 설정¶
# 높은 처리량 시나리오에 최적화
server:
bind_address: "0.0.0.0:8080"
workers: 16 # 높은 워커 수
connection_pool_size: 1000 # 큰 연결 풀
backends:
- name: "fast-backend-1"
url: "http://backend1:8000"
weight: 1
- name: "fast-backend-2"
url: "http://backend2:8000"
weight: 1
- name: "fast-backend-3"
url: "http://backend3:8000"
weight: 1
health_checks:
enabled: true
interval: "30s"
timeout: "5s" # 빠른 타임아웃
unhealthy_threshold: 2 # 빠른 실패
healthy_threshold: 1 # 빠른 복구
request:
timeout: "60s" # 높은 처리량을 위한 짧은 타임아웃
max_retries: 2 # 적은 재시도
retry:
max_attempts: 2
base_delay: "50ms" # 빠른 재시도
max_delay: "5s"
exponential_backoff: true
jitter: true
cache:
model_cache_ttl: "300s"
deduplication_ttl: "30s" # 짧은 중복 제거 윈도우
enable_deduplication: true
logging:
level: "warn" # 성능을 위한 최소 로깅
format: "json"
개발 설정¶
# 개발자 친화적 설정
server:
bind_address: "127.0.0.1:8080" # localhost만
workers: 2 # 개발용 적은 워커
connection_pool_size: 20 # 작은 풀
backends:
- name: "local-ollama"
url: "http://localhost:11434"
weight: 1
health_checks:
enabled: true
interval: "10s" # 빠른 피드백을 위한 잦은 확인
timeout: "3s"
unhealthy_threshold: 2
healthy_threshold: 1
request:
timeout: "300s" # 디버깅을 위한 긴 타임아웃
max_retries: 1 # 디버깅을 위한 최소 재시도
logging:
level: "debug" # 상세 로깅
format: "pretty" # 사람이 읽기 쉬운 형식
enable_colors: true # 컬러 출력
cache:
model_cache_ttl: "60s" # 빠른 테스트를 위한 짧은 캐시
deduplication_ttl: "10s" # 짧은 중복 제거
enable_deduplication: false # 테스트를 위해 비활성화
마이그레이션 가이드¶
명령줄 인수에서 마이그레이션¶
현재 명령줄 인수를 사용하고 있다면 설정 파일로 마이그레이션하세요:
이전:
이후: 1. 설정 파일 생성:
-
설정 편집:
-
설정 파일 사용:
환경 변수에서 마이그레이션¶
설정 파일과 함께 환경 변수를 오버라이드로 계속 사용할 수 있습니다:
설정 파일 (config.yaml):
환경 오버라이드:
export CONTINUUM_BIND_ADDRESS="0.0.0.0:9000"
export CONTINUUM_BACKEND_URLS="http://localhost:11434,http://localhost:1234"
continuum-router --config config.yaml
설정 유효성 검사¶
서버를 시작하지 않고 설정을 검증하려면:
# 설정 로딩 테스트
continuum-router --config config.yaml --help
# dry-run으로 설정 확인 (향후 기능)
continuum-router --config config.yaml --dry-run
이 설정 가이드는 Continuum Router에서 사용할 수 있는 모든 설정 옵션에 대한 포괄적인 내용을 제공합니다. 유연한 설정 시스템을 통해 명확한 우선순위 규칙과 유효성 검사를 유지하면서 모든 배포 시나리오에 라우터를 적용할 수 있습니다.