서버 & 백엔드¶
서버 섹션¶
HTTP 서버 동작을 제어합니다:
server:
bind_address: "0.0.0.0:8080" # 바인드할 호스트와 포트
workers: 4 # 워커 스레드 (0 = 자동)
connection_pool_size: 100 # HTTP 연결 풀 크기
다중 바인드 주소 및 Unix 소켓¶
서버는 Unix 도메인 소켓(Unix 계열 시스템)을 포함하여 여러 주소에 동시에 바인딩하는 것을 지원합니다. 이를 통해 다음과 같은 유연한 배포 시나리오가 가능합니다:
- IPv4와 IPv6 주소 모두에서 수신
- 외부 클라이언트용 TCP 포트 노출과 로컬 서비스용 Unix 소켓 동시 사용
- 보안 강화를 위한 Unix 소켓을 통한 리버스 프록시 운영
단일 주소 (하위 호환):
다중 주소:
server:
bind_address:
- "127.0.0.1:8080" # IPv4 localhost
- "[::1]:8080" # IPv6 localhost
- "0.0.0.0:9090" # 포트 9090의 모든 인터페이스
Unix 소켓 바인딩 (Linux, macOS, Windows 10 1809+ 지원):
server:
bind_address:
- "0.0.0.0:8080" # 외부 액세스용 TCP
- "unix:/var/run/continuum-router.sock" # 로컬 서비스용 Unix 소켓
socket_mode: 0o660 # 선택 사항: Unix 소켓의 파일 권한 (8진수)
설정 옵션:
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
bind_address | 문자열 또는 배열 | "0.0.0.0:8080" | 바인드할 주소. TCP 형식: host:port. Unix 소켓 형식: unix:/path/to/socket |
socket_mode | 정수 (8진수) | null | Unix 소켓의 파일 권한 (예: 0o660은 소유자/그룹 읽기-쓰기) |
Unix 소켓 참고사항:
- Unix 소켓 주소는
unix:접두사로 시작해야 합니다 - 기존 소켓 파일은 바인딩 전에 자동으로 삭제됩니다
- 소켓 파일은 정상적인 종료 시 정리됩니다
- Windows 10 1809+ (Build 17063+)에서는
socket2크레이트를 통해 Unix 소켓이 완전히 지원됩니다 - 기타 비Unix 플랫폼에서는
unix:주소가 경고를 기록하고 건너뜁니다 - Windows는 Unix 파일 권한 모드를 지원하지 않습니다.
socket_mode옵션은 허용되지만 무시됩니다 - Unix 소켓 연결은 IP 기반 인증 검사를 우회합니다 (클라이언트 IP는 "unix"로 보고됨)
Nginx 리버스 프록시 예제:
upstream continuum {
server unix:/var/run/continuum-router.sock;
}
server {
listen 443 ssl;
location /v1/ {
proxy_pass http://continuum;
}
}
성능 튜닝:
workers: 자동 감지를 위해 0으로 설정하거나 CPU 코어 수와 일치connection_pool_size: 고부하 시나리오에서는 증가 (200-500)
CORS 설정¶
CORS (Cross-Origin Resource Sharing)는 라우터가 다른 출처에서 실행되는 웹 브라우저의 요청을 수락할 수 있게 합니다. 다음 환경에 continuum-router를 임베딩할 때 필수적입니다:
- Tauri 앱:
tauri://localhost와 같은 출처를 사용하는 WebView - Electron 앱: 사용자 정의 프로토콜
- 별도의 웹 프론트엔드: 다른 포트의 개발 서버
server:
bind_address: "0.0.0.0:8080"
cors:
enabled: true
allow_origins:
- "tauri://localhost"
- "http://localhost:*" # 와일드카드 포트 매칭
- "https://example.com"
allow_methods:
- "GET"
- "POST"
- "PUT"
- "DELETE"
- "OPTIONS"
- "PATCH"
allow_headers:
- "Content-Type"
- "Authorization"
- "X-Request-ID"
- "X-Trace-ID"
expose_headers:
- "X-Request-ID"
- "X-Fallback-Used"
allow_credentials: false
max_age: 3600 # 프리플라이트 캐시 기간 (초)
CORS 설정 옵션:
| 옵션 | 유형 | 기본값 | 설명 |
|---|---|---|---|
enabled | boolean | false | CORS 미들웨어 활성화/비활성화 |
allow_origins | array | [] | 허용된 출처 (*로 모든 출처 허용, http://localhost:*와 같은 포트 와일드카드 지원) |
allow_methods | array | ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"] | 허용된 HTTP 메서드 |
allow_headers | array | ["Content-Type", "Authorization", "X-Request-ID", "X-Trace-ID"] | 허용된 요청 헤더 |
expose_headers | array | [] | 클라이언트 JavaScript에 노출되는 헤더 |
allow_credentials | boolean | false | 쿠키와 인증 헤더 허용 |
max_age | integer | 3600 | 프리플라이트 응답 캐시 기간 (초) |
출처 패턴 매칭:
| 패턴 | 예시 | 설명 |
|---|---|---|
* | * | 모든 출처 매칭 (allow_credentials: true와 호환되지 않음) |
| 정확한 URL | https://example.com | 정확히 일치 |
| 사용자 정의 스킴 | tauri://localhost | 사용자 정의 프로토콜 (Tauri, Electron) |
| 포트 와일드카드 | http://localhost:* | localhost의 모든 포트 매칭 |
보안 고려사항:
- 출처에
*를 사용하면 모든 웹사이트에서 요청할 수 있습니다 - 공개 API에만 사용하세요 allow_credentials가true일 때 출처에*를 사용할 수 없습니다 - 정확한 출처를 지정하세요- 개발 시에는 유연성을 위해
http://localhost:*와 같은 포트 와일드카드를 사용하세요 - 프로덕션에서는 보안을 위해 항상 정확한 출처를 지정하세요
핫 리로드: CORS 설정은 즉시 핫 리로드를 지원합니다 - 서버 재시작 없이 새 요청에 변경 사항이 즉시 적용됩니다.
백엔드 섹션¶
요청을 라우팅할 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"
백엔드 없이 시작하기¶
라우터는 빈 백엔드 목록(backends: [])으로 시작할 수 있으며, 다음과 같은 경우에 유용합니다:
- 인프라 부트스트래핑: 라우터를 먼저 시작한 다음 Admin API를 통해 동적으로 백엔드 추가
- 컨테이너 오케스트레이션: 백엔드 서비스보다 라우터 컨테이너가 먼저 준비될 수 있음
- 개발 워크플로우: 백엔드가 프로비저닝되기 전에 관리자 엔드포인트 테스트
- 점진적 롤아웃: 백엔드 없이 시작하여 점진적으로 추가
백엔드 없이 실행할 때:
/v1/models는{"object": "list", "data": []}를 반환/v1/chat/completions및 기타 라우팅 엔드포인트는 503 "No backends available" 반환/health는 정상 상태 반환 (라우터 자체는 작동 중)POST /admin/backends를 통해 백엔드 추가 가능
동적 백엔드 관리를 위한 최소 구성 예제:
server:
bind_address: "0.0.0.0:8080"
backends: [] # 백엔드 없이 시작 - 나중에 Admin API로 추가
admin:
auth:
method: bearer
token: "${ADMIN_TOKEN}"
지원되는 백엔드 유형:
| 유형 | 설명 | 기본 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 |
llamacpp | llama.cpp llama-server (GGUF 모델) | http://localhost:8080 |
mlxcel | MLxcel 서버 (MLX 기반, llama-server 호환, macOS 전용) | http://localhost:8080 |
lmstudio | LM Studio 로컬 서버 | http://localhost:1234 |
anthropic | Anthropic Claude API (요청/응답 변환 포함 네이티브) | https://api.anthropic.com |
continuum-router | 원격 Continuum Router 또는 Backend.AI GO 인스턴스 (연합 라우팅) | 지정 필수 |
네이티브 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 검색 메커니즘 사용 |
llamacpp | ✅ 예 | /v1/models 엔드포인트에서 자동 검색 |
mlxcel | ✅ 예 | /v1/models 엔드포인트에서 자동 검색 |
lmstudio | ✅ 예 | /v1/models 엔드포인트에서 자동 검색 |
continuum-router | ✅ 예 | 원격 /v1/models 엔드포인트에서 자동 검색 |
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
API 키를 사용한 전체 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 인증 방법¶
Gemini 백엔드는 두 가지 인증 방법을 지원합니다:
API 키 인증 (기본)¶
Google AI Studio API 키를 사용하는 가장 간단한 인증 방법:
backends:
- name: "gemini"
type: gemini
api_key: "${CONTINUUM_GEMINI_API_KEY}"
models:
- gemini-2.5-pro
서비스 계정 인증¶
엔터프라이즈 환경 및 Google Cloud Platform (GCP) 배포의 경우, 자동 OAuth2 토큰 관리와 함께 서비스 계정 인증을 사용할 수 있습니다:
backends:
- name: "gemini"
type: gemini
auth:
type: service_account
key_file: "/path/to/service-account.json"
models:
- gemini-2.5-pro
- gemini-2.5-flash
키 파일 경로에 환경 변수 사용:
backends:
- name: "gemini"
type: gemini
auth:
type: service_account
key_file: "${GOOGLE_APPLICATION_CREDENTIALS}"
models:
- gemini-2.5-pro
서비스 계정 인증 기능:
| 기능 | 설명 |
|---|---|
| 자동 토큰 갱신 | OAuth2 토큰이 만료 5분 전에 자동으로 갱신됩니다 |
| 토큰 캐싱 | 인증 오버헤드를 최소화하기 위해 토큰이 메모리에 캐시됩니다 |
| 스레드 안전 | 동시 요청이 토큰 갱신 작업을 안전하게 공유합니다 |
| 환경 변수 확장 | 키 파일 경로가 ${VAR} 및 ~ 확장을 지원합니다 |
서비스 계정 키 생성:
- Google Cloud Console로 이동
- IAM & Admin > Service Accounts로 이동
- 새 서비스 계정을 만들거나 기존 계정 선택
- Keys > Add Key > Create new key 클릭
- JSON 형식을 선택하고 키 파일 다운로드
- 키 파일을 안전하게 저장하고 설정에서 참조
필요한 권한:
Gemini API 접근을 위해 서비스 계정에 다음 역할이 필요합니다:
roles/aiplatform.user- Vertex AI Gemini 엔드포인트용- 또는 generativelanguage.googleapis.com용 적절한 Google AI Studio 권한
인증 우선순위¶
여러 인증 방법이 설정된 경우:
| 우선순위 | 방법 | 조건 |
|---|---|---|
| 1 (최고) | auth 블록 | auth.type이 지정된 경우 |
| 2 | api_key 필드 | auth 블록이 없는 경우 |
| 3 | 환경 변수 | CONTINUUM_GEMINI_API_KEY로 폴백 |
api_key와 auth가 모두 지정된 경우, auth 블록이 우선되며 경고가 기록됩니다.
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 백엔드용으로 자동 로드) |
GOOGLE_APPLICATION_CREDENTIALS | 서비스 계정 JSON 키 파일 경로 (표준 GCP 환경 변수) |
네이티브 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 네이티브 API 엔드포인트¶
OpenAI 형식 요청을 Anthropic 백엔드로 라우팅하는 것 외에도, 라우터는 네이티브 Anthropic API 엔드포인트도 제공합니다:
| 엔드포인트 | 설명 |
|---|---|
POST /anthropic/v1/messages | 네이티브 Anthropic Messages API |
POST /anthropic/v1/messages/count_tokens | 계층적 백엔드 지원을 통한 토큰 카운팅 |
GET /anthropic/v1/models | Anthropic 형식의 모델 목록 |
이 엔드포인트를 통해 Anthropic의 네이티브 API 형식을 사용하는 클라이언트(예: Claude Code)가 요청/응답 변환 오버헤드 없이 직접 연결할 수 있습니다.
Claude Code 호환성¶
Anthropic 네이티브 API 엔드포인트는 Claude Code 및 기타 고급 Anthropic API 클라이언트와의 완전한 호환성을 포함합니다:
프롬프트 캐싱 지원:
라우터는 요청/응답 파이프라인 전체에서 cache_control 필드를 유지합니다:
- 시스템 프롬프트 텍스트 블록
- 사용자 메시지 콘텐츠 블록 (텍스트, 이미지, 문서)
- 도구 정의
- 도구 사용 및 도구 결과 블록
헤더 전달:
| 헤더 | 동작 |
|---|---|
anthropic-version | 네이티브 Anthropic 백엔드로 전달됨 |
anthropic-beta | 베타 기능 활성화를 위해 전달됨 (예: prompt-caching-2024-07-31, interleaved-thinking-2025-05-14) |
x-request-id | 요청 추적을 위해 전달됨 |
캐시 사용량 보고:
네이티브 Anthropic 백엔드의 스트리밍 응답에는 캐시 사용량 정보가 포함됩니다:
{
"usage": {
"input_tokens": 2159,
"cache_creation_input_tokens": 2048,
"cache_read_input_tokens": 0
}
}
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 백엔드용으로 자동 로드) |
네이티브 llama.cpp 백엔드¶
type: llamacpp를 사용하면 라우터는 llama.cpp llama-server에 대한 네이티브 지원을 제공합니다:
- 기본 URL:
http://localhost:8080(llama-server 기본 포트) - 헬스 체크:
/health엔드포인트 사용 (/v1/models로 폴백) - 모델 검색: llama-server의 하이브리드
/v1/models응답 형식 파싱 - 풍부한 메타데이터: 응답에서 컨텍스트 윈도우, 파라미터 수, 모델 크기 추출
최소 llama.cpp 설정:
backends:
- name: "local-llama"
type: llamacpp
# 기본 http://localhost:8080 사용 시 URL 불필요
# 로컬 서버에는 API 키 불필요
전체 llama.cpp 설정:
backends:
- name: "local-llama"
type: llamacpp
url: "http://192.168.1.100:8080" # 필요시 커스텀 URL
weight: 2
# 모델은 /v1/models 엔드포인트에서 자동 검색
llama.cpp 기능¶
| 기능 | 설명 |
|---|---|
| GGUF 모델 | GGUF 양자화 모델 네이티브 지원 |
| 로컬 추론 | 클라우드 API 의존성 없음 |
| 하드웨어 지원 | CPU, NVIDIA, AMD, Apple Silicon |
| 스트리밍 | 완전한 SSE 스트리밍 지원 |
| 임베딩 | /v1/embeddings 엔드포인트 지원 |
| 도구 호출 감지 | /props 엔드포인트를 통한 도구 호출 지원 자동 감지 |
도구 호출 자동 감지¶
라우터는 모델 검색 중 /props 엔드포인트를 쿼리하여 llama.cpp 백엔드의 도구 호출 기능을 자동으로 감지합니다. 수동 설정 없이 자동으로 함수 호출 지원이 가능해집니다.
작동 방식:
- llama.cpp 백엔드가 검색되면 라우터가
/props엔드포인트를 조회합니다 chat_template필드를 정밀한 Jinja2 패턴 매칭으로 분석하여 도구 관련 구문을 감지합니다- 도구 호출 패턴이 감지되면 모델의
function_calling기능이 자동으로 활성화됩니다 - 감지 결과가 참조용으로 저장됩니다 (채팅 템플릿의 해시 포함)
감지 패턴:
라우터는 오탐을 줄이기 위해 정밀한 패턴 매칭을 사용합니다:
- 역할 기반 패턴:
message['role'] == 'tool',message.role == "tool" - 도구 반복:
for tool in tools,for function in functions - 도구 호출 접근:
.tool_calls,['tool_calls'],message.tool_call - 도구 키워드가 포함된 Jinja2 블록:
{% if tools %},{% for tool_call in ... %}
분석되는 /props 응답 예제:
{
"chat_template": "{% for message in messages %}{% if message['role'] == 'tool' %}...",
"default_generation_settings": { ... },
"total_slots": 1
}
폴백 동작:
/props를 사용할 수 없는 경우: 도구 호출이 지원되는 것으로 가정 (최신 llama.cpp 버전에 대한 낙관적 폴백)/props가 오류를 반환하는 경우: 도구 호출이 지원되는 것으로 가정 (새로운 모델과의 호환성 보장)- 채팅 템플릿이 64KB를 초과하는 경우: 감지가 건너뛰어지고 지원되는 것으로 기본 설정
- 최대 호환성을 위해 대소문자 구분 없음
- 결과는
model-metadata.yaml의 기존 모델 메타데이터와 병합됩니다 - 감지된 기능은
/v1/models/{model_id}응답의features필드에 나타납니다
모델 메타데이터 추출¶
라우터는 llama-server 응답에서 풍부한 메타데이터를 추출합니다:
| 필드 | 소스 | 설명 |
|---|---|---|
| 컨텍스트 윈도우 | meta.n_ctx_train | 학습 컨텍스트 윈도우 크기 |
| 파라미터 수 | meta.n_params | 모델 파라미터 (예: "4B") |
| 모델 크기 | meta.size | 파일 크기 (바이트) |
| 기능 | models[].capabilities | 모델 기능 배열 |
llama-server 시작하기¶
# 기본 시작
./llama-server -m model.gguf --port 8080
# GPU 레이어 사용
./llama-server -m model.gguf --port 8080 -ngl 35
# 커스텀 컨텍스트 크기 사용
./llama-server -m model.gguf --port 8080 --ctx-size 8192
llama.cpp 백엔드 자동 감지¶
타입이 지정되지 않은 백엔드가 추가되면 (기본값 generic), 라우터는 자동으로 /v1/models 엔드포인트를 탐색하여 백엔드 타입을 감지합니다. llama.cpp 백엔드는 다음으로 식별됩니다:
- 응답의
owned_by: "llamacpp" - llama.cpp 전용 메타데이터 필드 존재 (
n_ctx_train,n_params,vocab_type) models[]와data[]배열이 모두 있는 하이브리드 응답 형식
이 자동 감지는 다음에 적용됩니다:
- 핫 리로드 설정 변경
- 명시적 타입 없이 Admin API를 통해 추가된 백엔드
type: generic또는 타입이 지정되지 않은 설정 파일
예제: Admin API를 통한 자동 감지 백엔드:
# 타입 지정 없이 백엔드 추가 - llama.cpp 자동 감지
curl -X POST http://localhost:8080/admin/backends \
-H "Content-Type: application/json" \
-d '{
"name": "local-llm",
"url": "http://localhost:8080"
}'
네이티브 MLxcel 백엔드¶
type: mlxcel을 사용하면 라우터는 Apple Silicon을 사용하는 macOS용 MLX 기반 모델 서빙 백엔드인 MLxcel에 대한 네이티브 지원을 제공합니다:
- 기본 URL:
http://localhost:8080(llama-server와 동일) - API 호환성: llama-server (llama.cpp) API와 완전 호환
- 모델 형식: Apple의 MLX 프레임워크를 통해 SafeTensor 형식 모델 제공
- 헬스 체크:
/health를 기본으로 사용하고,/v1/models를 폴백으로 사용 - 플랫폼: Apple Silicon이 탑재된 macOS 전용
최소 MLxcel 설정:
전체 MLxcel 설정:
backends:
- name: "mlxcel-local"
type: mlxcel
url: "http://192.168.1.100:8080" # 필요시 커스텀 URL
weight: 2
models:
- mlx-community/Qwen3-4B-4bit
자동 감지 미지원
MLxcel은 llama.cpp와 동일한 응답 형식(owned_by: "llamacpp" 포함)을 반환하므로 /v1/models 응답에서 자동 감지할 수 없습니다. 설정에서 type: mlxcel을 명시적으로 설정해야 합니다. 이렇게 하면 모델 식별에 적절한 owned_by 메타데이터(mlxcel)가 사용됩니다.
네이티브 LM Studio 백엔드¶
type: lmstudio를 사용하면 라우터는 LM Studio 로컬 서버에 대한 네이티브 지원을 제공합니다:
- 기본 URL:
http://localhost:1234(LM Studio 기본 포트) - 헬스 체크:
/v1/models(OpenAI 호환)를 기본으로 사용하고,/api/v1/models(네이티브 API)를 폴백으로 사용 - 모델 검색:
/v1/models엔드포인트에서 모델 자동 검색 owned_by속성: 적절한 모델 속성을 위해"lmstudio"보고
최소 LM Studio 설정:
backends:
- name: "lmstudio"
type: lmstudio
# 기본 http://localhost:1234 사용 시 URL 불필요
# 로컬 서버에는 API 키 불필요
전체 LM Studio 설정:
backends:
- name: "lmstudio"
type: lmstudio
url: "http://192.168.1.100:1234" # 필요시 커스텀 URL
weight: 2
api_key: "${LM_API_TOKEN}" # 선택: LM Studio API 토큰 (v0.4.0+)
# 모델은 /v1/models 엔드포인트에서 자동 검색
LM Studio 기능¶
| 기능 | 설명 |
|---|---|
| OpenAI 호환 API | /v1/chat/completions, /v1/completions, /v1/embeddings 완전 지원 |
| 네이티브 REST API | 모델 관리를 위한 추가 /api/v1/* 엔드포인트 |
| 로컬 추론 | 클라우드 API 의존성 없음 |
| 자동 검색 | /v1/models에서 모델 자동 감지 |
| 선택적 인증 | Authorization: Bearer 헤더를 통한 API 토큰 지원 (v0.4.0+) |
네이티브 Continuum Router / Backend.AI GO 백엔드¶
type: continuum-router를 사용하면 라우터는 연합 LLM 라우팅을 위해 원격 Continuum Router 인스턴스 또는 Backend.AI GO 배포에 연결합니다. 지원 별칭: continuum-router, continuum_router, ContinuumRouter, backendai, backend-ai, backend_ai.
- 헬스 체크: 기본
/health, 폴백/v1/models - 모델 검색: 원격 인스턴스의
/v1/models엔드포인트에서 자동 검색 - 인증:
Authorization: Bearer <key>헤더를 통한 Bearer 토큰 - 요청 패스스루: 변환 없이 요청 전달 (두 시스템 모두 OpenAI 호환 API 사용)
owned_by속성: 검색된 모델에 대해"continuum-router"보고- 전송: HTTP 및 Unix Domain Socket 전송 모두 지원
최소 설정:
backends:
- name: "remote-cr"
type: continuum-router
url: "https://remote.example.com"
api_key: "${REMOTE_API_KEY}"
# 모델은 원격 /v1/models 엔드포인트에서 자동 검색됨
명시적 모델이 있는 전체 설정:
backends:
- name: "remote-backendai"
type: continuum-router
url: "https://remote-backend-ai.example.com"
api_key: "${REMOTE_BACKEND_AI_API_KEY}"
weight: 2
models:
- gpt-4o
- claude-sonnet-4-20250514
사용 사례:
- 다중 지역 배포: Continuum Router 인스턴스 간 지역 기반 요청 라우팅
- 연합 라우팅: 독립적인 CR 또는 Backend.AI GO 배포 연결
- 계층적 접근: 할당량 관리를 위해 중앙 Backend.AI GO 인스턴스를 통한 라우팅
- 고가용성: 장애 조치를 위한 여러 Backend.AI GO 인스턴스 구성
Continuum Router 백엔드 기능¶
| 기능 | 설명 |
|---|---|
| 연합 라우팅 | 원격 Continuum Router 또는 Backend.AI GO 인스턴스로 요청 전달 |
| 자동 검색 | 원격 /v1/models에서 모델 자동 검색 |
| Bearer 인증 | API 키를 Authorization: Bearer 헤더로 전달 |
| SSE 스트리밍 | 채팅 완성에 대한 완전한 스트리밍 지원 |
| 변환 없음 | 요청을 그대로 패스스루 (양쪽 모두 OpenAI 호환) |
| Unix 소켓 지원 | unix:///path/to/socket.sock 전송 URL 지원 |
Unix Domain Socket 백엔드¶
Continuum Router는 로컬 LLM 백엔드를 위해 TCP 대신 Unix Domain Socket(UDS)을 전송 수단으로 지원합니다. Unix 소켓은 다음을 제공합니다:
- 향상된 보안: TCP 포트 노출 없음 - 파일 시스템을 통한 통신
- 낮은 레이턴시: 로컬 통신에서 네트워크 스택 오버헤드 없음
- 더 나은 성능: 컨텍스트 스위칭 및 메모리 복사 감소
- 간단한 접근 제어: 표준 Unix 파일 권한 사용
URL 형식:
플랫폼 지원:
| 플랫폼 | 지원 |
|---|---|
| Linux | 네이티브 AF_UNIX를 통한 완전 지원 |
| macOS | 네이티브 AF_UNIX를 통한 완전 지원 |
| Windows | socket2 크레이트를 통한 완전 지원 (Windows 10 1809+ / Build 17063+) |
| 기타 | 미지원; 주소가 경고와 함께 건너뜀 |
설정 예제:
Windows에서는 드라이브 문자 경로를 사용합니다 (예: unix://C:/temp/llama.sock). Linux/macOS에서는 표준 절대 경로를 사용합니다 (예: unix:///var/run/llama.sock).
backends:
# Unix 소켓을 사용하는 llama-server
- name: "llama-socket"
type: llamacpp
url: "unix:///var/run/llama-server.sock"
weight: 2
models:
- llama-3.2-3b
- qwen3-4b
# Unix 소켓을 사용하는 Ollama
- name: "ollama-socket"
type: ollama
url: "unix:///var/run/ollama.sock"
weight: 1
models:
- llama3.2
- mistral
# Unix 소켓을 사용하는 vLLM
- name: "vllm-socket"
type: vllm
url: "unix:///tmp/vllm.sock"
weight: 3
models:
- meta-llama/Llama-3.1-8B-Instruct
Unix 소켓으로 백엔드 시작하기:
# llama-server
./llama-server -m model.gguf --unix /var/run/llama.sock
# Ollama
OLLAMA_HOST="unix:///var/run/ollama.sock" ollama serve
# vLLM
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B \
--unix-socket /tmp/vllm.sock
소켓 경로 규칙:
| 경로 | 사용 사례 |
|---|---|
/var/run/*.sock | 시스템 서비스 (root 권한 필요) |
/tmp/*.sock | 임시, 사용자 접근 가능 |
~/.local/share/continuum/*.sock | 사용자별 영구 소켓 |
~/Library/Application Support/*.sock | macOS 애플리케이션 데이터 (공백이 포함된 경로 지원) |
헬스 체크: 라우터는 TCP 백엔드와 동일한 엔드포인트(/health, /v1/models)를 사용하여 Unix 소켓 백엔드에 대해 자동으로 헬스 체크를 수행합니다.
현재 제한 사항:
- 스트리밍(SSE) 미지원: Unix 소켓 백엔드는 현재 Server-Sent Events(SSE) 스트리밍을 지원하지 않습니다. 스트리밍 채팅 완성에는 TCP 백엔드를 사용하세요.
- Windows 플랫폼: Unix 소켓은 현재 Windows에서 지원되지 않습니다 (향후 릴리스에서 지원 예정).
- 최대 응답 크기: 메모리 고갈을 방지하기 위해 응답 본문은 기본적으로 100MB로 제한됩니다.
문제 해결:
| 오류 | 원인 | 해결 방법 |
|---|---|---|
| "Socket file not found" | 서버가 실행되지 않음 | 백엔드 서버 시작 |
| "Permission denied" | 파일 권한 | chmod 660 socket.sock |
| "Connection timeout" | 서버가 연결을 수락하지 않음 | 서버가 리스닝 중인지 확인 |
| "Response body exceeds maximum size" | 응답이 너무 큼 | maxresponsesize 증가 또는 TCP 백엔드로 스트리밍 사용 |