콘텐츠로 이동

서버 & 백엔드

서버 섹션

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: "0.0.0.0:8080"

다중 주소:

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_credentialstrue일 때 출처에 *를 사용할 수 없습니다 - 정확한 출처를 지정하세요
  • 개발 시에는 유연성을 위해 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_KEYCONTINUUM_OPENAI_ORG_ID에서 자동 로드

최소 OpenAI 설정:

backends:
  - name: "openai"
    type: openai
    models:
      - gpt-4o
      - gpt-4o-mini
      - o3-mini

명시적 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 레벨로 로깅

모델 해석 우선순위:

  1. 설정의 명시적 models 목록 (최고 우선순위)
  2. model_configs 필드의 모델
  3. 백엔드 API에서 자동 검색된 모델
  4. 하드코딩된 폴백 모델 (최저 우선순위)

  5. 명시적 모델 목록은 시작 시간을 개선하고 백엔드 쿼리를 줄입니다

네이티브 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}~ 확장을 지원합니다

서비스 계정 키 생성:

  1. Google Cloud Console로 이동
  2. IAM & Admin > Service Accounts로 이동
  3. 새 서비스 계정을 만들거나 기존 계정 선택
  4. Keys > Add Key > Create new key 클릭
  5. JSON 형식을 선택하고 키 파일 다운로드
  6. 키 파일을 안전하게 저장하고 설정에서 참조

필요한 권한:

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_keyauth가 모두 지정된 경우, 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-keyanthropic-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_effortreasoning.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 백엔드의 도구 호출 기능을 자동으로 감지합니다. 수동 설정 없이 자동으로 함수 호출 지원이 가능해집니다.

작동 방식:

  1. llama.cpp 백엔드가 검색되면 라우터가 /props 엔드포인트를 조회합니다
  2. chat_template 필드를 정밀한 Jinja2 패턴 매칭으로 분석하여 도구 관련 구문을 감지합니다
  3. 도구 호출 패턴이 감지되면 모델의 function_calling 기능이 자동으로 활성화됩니다
  4. 감지 결과가 참조용으로 저장됩니다 (채팅 템플릿의 해시 포함)

감지 패턴:

라우터는 오탐을 줄이기 위해 정밀한 패턴 매칭을 사용합니다:

  • 역할 기반 패턴: 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 백엔드는 다음으로 식별됩니다:

  1. 응답의 owned_by: "llamacpp"
  2. llama.cpp 전용 메타데이터 필드 존재 (n_ctx_train, n_params, vocab_type)
  3. 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 설정:

backends:
  - name: "mlxcel-local"
    type: mlxcel
    # 기본 http://localhost:8080 사용 시 URL 불필요

전체 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 형식:

unix:///path/to/socket.sock

플랫폼 지원:

플랫폼 지원
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 백엔드로 스트리밍 사용