LiteLLM 라우팅 가이드 - 로드밸런싱, 라우팅 그룹, Auto Router

LLM을 서비스에 연동하면 특정 제공자나 리전에 요청이 집중되어 속도 제한(Rate Limit)과 응답 지연이 발생할 수 있다. 또한 특정 제공자에 장애가 발생하면 서비스 전체가 중단될 위험이 있으며, 단순한 질문에도 고가 모델을 사용하면 불필요한 비용이 발생한다.

이를 해결하려면 요청 분산, 장애 시 자동 전환(fallback), 복잡도에 따른 모델 선택을 통합적으로 수행하는 LLM 로드밸런싱 및 라우팅 체계가 필요하다.

LiteLLM은 이를 같은 모델의 deployment 분산, 모델 간 fallback, 복잡도에 따른 모델 선택(Auto Router)으로 지원한다. 이 기능들은 router_settings, routing_groups, auto_router 모델 항목으로 나뉘어 설정하는데, 이 글은 사용 방법을 요청한 model_name이 후보 풀을 정하고, 전략이 그 풀에서 하나를 고른다는 하나의 규칙으로 정리한다.


목차


1. 개요

LiteLLM은 여러 LLM 서비스를 하나의 OpenAI 호환 API로 묶는 프록시이고, 라우팅은 요청을 어느 모델 또는 deployment로 보낼지 정하는 기능이다. 같은 모델을 여러 리전이나 제공자에 두고 부하를 나누거나 한쪽이 실패할 때 다른 모델로 넘기려면 이 설정이 필요하다.

이 글은 docker-compose 환경의 LiteLLM v1.104.0으로 주요 동작을 테스트하여 정리하였다. 버전에 따라 동작이 달라질 수 있다. 특히 Auto Router는 베타라서 설정 키와 기본값이 바뀔 수 있으니 버전을 고정해서 쓴다.

1-1. 용어

  • deployment: model_list의 항목 하나. 제공자, 리전, API 키가 정해진 실제 호출 대상(azure/gpt-4o-eastus 등)
  • 모델 그룹: 같은 model_name을 가진 deployment의 모음
  • 후보 풀: 한 요청에서 라우터가 고를 수 있는 deployment의 집합
  • 기본 전략: router_settings 바로 아래의 routing_strategy. 라우팅 그룹에 속하지 않은 모델에 적용됨
  • 라우팅 그룹: routing_groups로 여러 model_name을 묶고 전략을 따로 지정한 것(3절)

1-2. 라우팅의 두 층

LiteLLM의 라우팅은 무엇을 고르느냐에 따라 로드밸런싱과 Auto Router의 두 층으로 나뉜다.
로드밸런싱은 후보 풀 안에서 어느 deployment로 보낼지, Auto Router는 요청 내용에 따라 어떤 모델로 보낼지를 정한다.

층위고르는 대상설정 위치
로드밸런싱후보 풀의 deployment (기본은 같은 model_name의 리전, 제공자)router_settings
Auto Router요청 내용에 따라 서로 다른 모델auto_router 모델 항목

1-3. 선택 범위 규칙

  • routing_groups가 없으면 요청한 model_name이 같은 deployment들 중에서만 선택함. gpt-4o로 요청하면 claude-sonnet은 후보가 아님
  • 선택 방식은 기본 전략이 결정함. 없으면 simple-shuffle이며, router_settings 자체가 없어도 동일함
  • 클라이언트는 model_list의 model_name으로 요청함. litellm_params.model(azure/gpt-4o-eastus 등)로는 요청하지 않음

이 세 가지가 이후 모든 절의 전제다. 전략이 무엇이든 “누구 중에서 고르는가"는 요청한 이름이 정한다.1


2. 로드밸런싱

2-1. 모델 그룹

model_name이 같은 deployment는 한 모델 그룹이 된다.

model_list:
  - model_name: gpt-4o                       # 그룹 이름 = 클라이언트가 부르는 이름
    litellm_params:
      model: azure/gpt-4o-eastus
      api_base: https://eastus.openai.azure.com
      api_key: os.environ/AZURE_KEY_1
      weight: 9                              # 선택 비율 (또는 rpm/tpm, order)
  - model_name: gpt-4o                       # 같은 이름 → 같은 그룹
    litellm_params:
      model: azure/gpt-4o-koreacentral
      api_base: https://koreacentral.openai.azure.com
      api_key: os.environ/AZURE_KEY_2
      weight: 1
  - model_name: claude-sonnet                # 다른 이름 → 별개 그룹
    litellm_params:
      model: anthropic/claude-sonnet-5
      api_key: os.environ/ANTHROPIC_API_KEY

기본 전략 simple-shuffle에서는 아무 값도 주지 않으면 균등 랜덤이고, weight/rpm/tpm을 주면 그 비율로 선택한다.2 order는 낮은 숫자를 먼저 쓰고, 실패하면 다음 숫자로 넘어간다.

2-2. 라우팅 전략

전략비고
simple-shuffle기본값, 공식 권장
least-busy진행 중 요청이 가장 적은 곳
latency-based-routing최근 평균 지연이 가장 낮은 곳
cost-based-routing토큰당 가격이 가장 낮은 곳
usage-based-routing-v2TPM/RPM 기준, Redis 필요
usage-based-routingdeprecated. Redis 오버헤드로 성능이 나쁨

전략은 모두 후보 풀 안에서 고른다. 라우팅 그룹이 없으면 풀은 같은 model_name의 deployment들이다.

2-3. latency 전략의 선택 과정

기본 전략을 바꾸고 인자를 routing_strategy_args에 지정한다.

router_settings:
  routing_strategy: latency-based-routing
  routing_strategy_args:
    ttl: 60                                   # 지연 기록 보관 시간 (첫 기록 후 60초가 지나면 만료)
    lowest_latency_buffer: 0.5                # 가장 빠른 곳보다 50%까지 느린 곳도 후보에 포함

라우팅 그룹이 없는 경우는 model_name이 같은 deployment끼리 하나의 그룹이 되어, 그 그룹 안에서 아래 순서로 고른다. 요청이 들어올 때마다 적용된다.3

  1. deployment마다 최근 지연 기록(기본 최대 10개)의 평균을 계산
  2. 가장 낮은 평균 L을 기준으로 L × (1 + lowest_latency_buffer) 이하인 deployment를 후보로 선정
  3. 후보 중 무작위로 하나 선택

평균 지연이 A 1.0, B 1.4, C 2.0이고 버퍼가 0.5이면 상한은 1.0 × 1.5 = 1.5이므로 A와 B가 후보이고 C는 제외된다. 버퍼가 0이면 항상 A만 선택된다.

  • 지연 값은 응답 시간을 출력 토큰 수로 나눈 토큰당 시간
  • ttl은 지연 기록의 보관 시간이며 기본값은 1시간. 만료되면 그 시점부터 다시 최근 10개의 지연 기록으로 선정
  • lowest_latency_buffer 기본값은 0
  • max_latency_list_size는 deployment별 지연 기록 보관 개수이며 기본값은 10
  • 타임아웃으로 실패하면 지연 기록에 벌점 1000이 추가되어 평균이 크게 올라감

3. 라우팅 그룹

3-1. 구성

기본 전략은 모든 모델에 하나만 적용된다. 모델마다 다른 전략을 쓰거나 여러 모델을 한 풀로 묶으려면 routing_groups를 쓴다.

router_settings:
  routing_strategy: simple-shuffle            # 기본 전략: 그룹에 속하지 않은 모델에 적용 (이 예시는 두 모델이 모두 그룹에 속해 적용 대상 없음)
  routing_groups:                             # 선택 사항
    - group_name: hot-path
      models: [gpt-4o, claude-sonnet]         # model_name을 적음 (여러 개 가능)
      routing_strategy: latency-based-routing # 이 그룹에만 적용되는 전략
      routing_strategy_args:
        ttl: 60
        lowest_latency_buffer: 0.5

전략이 모델마다 같고 모델을 섞을 필요가 없다면 그룹 없이 2-3의 설정만으로 충분하다.

3-2. 요청한 이름에 따른 동작

그룹에 속한 모델은 요청한 이름이 model_name이든 그룹명이든 그룹의 전략을 따른다. 요청한 이름에 따라 달라지는 것은 후보 풀이다.4

요청한 이름전략후보 풀
gpt-4o그룹의 latencygpt-4o의 두 deployment
hot-path그룹의 latencygpt-4o + claude-sonnet 전체 (모델이 섞임)
그룹에 없는 모델기본 전략그 모델의 deployment
  • 그룹에 속한 모델은 그룹 전략으로 고르므로 2-1의 weight(9:1)는 무시됨
  • hot-path로 호출하려면 virtual key에 그룹명을 허용해야 하고, 그룹 전체가 실패했을 때 넘기려면 fallbacks에도 hot-path용 항목이 필요함
  • routing_groups가 없으면 hot-path라는 모델이 없으므로 요청이 400 Invalid model name passed in model=...으로 실패함
  • hot-path는 응답 형식, 도구 호출, 단가가 다른 모델이 섞이므로 서로 바꿔 써도 되는 모델끼리만 묶음

3-3. 규칙

  • 한 model_name은 한 그룹에만 소속 가능. 겹치면 시작 시 에러 발생
  • group_name이 기존 model_name과 같으면 경고(shadowed)만 나고 그 이름으로는 원래 모델이 응답하므로 그룹을 호출할 수 없음. default는 예약어이며 쓰면 시작 시 에러 발생
  • UI의 Routing Groups 메뉴나 /config/update로도 설정 가능

4. 장애 대응과 운영 설정

4-1. 요청 처리 흐름

  • 이미 나간 요청은 중간에 옮기지 않음. 응답이 오거나 timeout이 날 때까지 대기하며, timeout이면 num_retries만큼 재시도. 재시도가 실패한 deployment로 다시 갈 수도 있음
  • 429, 408, 500 같은 에러가 1분 안에 allowed_fails를 넘게 쌓이면 해당 deployment는 cooldown_time 동안 풀에서 제외. 실패 횟수는 1분이 지나면 초기화됨
  • fallbacks가 없으면 다른 model_name으로 넘어가지 않음. 모든 deployment가 막히면 No deployments available ... 에러가 클라이언트에 전달
  • 빠른 전환을 원하면 timeout을 낮추고, 더 집중시키려면 lowest_latency_buffer를 낮춤

4-2. 통합 예시

retry, cooldown, fallback, 세션 고정, Redis를 한 번에 설정한 예시다. Redis는 LiteLLM 인스턴스가 여러 개일 때 지연 기록을 공유하기 위한 설정이며, 하나면 생략한다.5

router_settings:
  routing_strategy: latency-based-routing
  routing_strategy_args:
    ttl: 300
    lowest_latency_buffer: 0.5
  enable_pre_call_checks: true               # 컨텍스트 창, 리전 부적합 deployment 제외
  num_retries: 2
  timeout: 30                                # 느린 요청을 포기하는 시간
  allowed_fails: 3                           # 1분 안의 실패 횟수가 이를 넘으면 cooldown
  cooldown_time: 30
  fallbacks: [{"gpt-4o": ["claude-sonnet"]}] # gpt-4o 모델 그룹 전체가 실패했을 때만 다른 모델로
  optional_pre_call_checks: ["session_affinity"]   # 세션을 첫 deployment에 고정 (프롬프트 캐시 보호)
  deployment_affinity_ttl_seconds: 3600
  redis_host: os.environ/REDIS_HOST          # replica가 여러 개면 지연 기록 공유용
  redis_port: os.environ/REDIS_PORT
  redis_password: os.environ/REDIS_PASSWORD

리전 필터는 요청에 allowed_model_region: eu를 보내고 deployment에 region_name: eu를 지정해야 동작하며, eu-west-1, europe-west1은 매칭되지 않았다.

4-3. 세션 고정

  • 클라이언트가 x-litellm-session-id 헤더나 metadata.session_id로 세션 ID를 보내야 동작함
  • 같은 세션의 요청을 한 deployment에 묶으므로, 그 세션 안에서는 지연 기반 선택이 일어나지 않음. 로드밸런싱은 세션 단위가 됨

5. Auto Router

5-1. 구조

auto_router/complexity_router는 실제 모델이 아니라 라우터 식별자다. LiteLLM에 내장된 complexity router를 쓰겠다는 선언이며, 판단 로직을 직접 쓰는 것이 아니다. 이 항목으로 들어온 요청은 티어로 분류된 뒤 티어별 실제 모델로 다시 보내진다. 문서에는 v1.94.x부터 제공되는 베타 기능으로 표시되어 있다.6

model_list:
  # ... gpt-4o-mini, gpt-4o, claude-sonnet, claude-opus 등 실제 모델 등록 ...
  - model_name: smart-router                   # 클라이언트가 부르는 이름
    litellm_params:
      model: auto_router/complexity_router
      complexity_router_config:
        tiers:
          SIMPLE:    ["gpt-4o-mini"]            # 리스트면 풀에서 랜덤
          MEDIUM:    gpt-4o
          COMPLEX:   claude-sonnet
          REASONING: claude-opus
        keyword_tier_rules:                     # 분류기보다 먼저 실행
          - keywords: ["안녕", "고마워", "hello", "thanks"]
            tier: SIMPLE
        custom_technical_keywords: [kafka, redis, kubernetes]
        classification_mode: user_turn          # 새 사용자 질문일 때만 분류
        session_affinity: true                  # 세션 중 모델 고정 (캐시 보호)
      complexity_router_default_model: gpt-4o

5-2. 판단 순서

  1. keyword_tier_rules에 걸리면 그 티어로 확정
  2. 걸리지 않으면 분류기가 티어를 결정. 기본 분류기(classifier_type: heuristic)는 5-3의 휴리스틱 점수 계산
  3. tiers에서 그 티어에 지정한 모델로 요청을 전달

5-3. 휴리스틱 점수 계산

API 호출이 없는 로컬 계산이다. 요청을 7개 항목으로 점수화하고, 항목별 가중치를 곱해 더한 합계를 경계값과 비교한다.

항목보는 것가중치
codePresencefunction, class, api, database 같은 단어0.30
reasoningMarkersstep by step, analyze this 같은 표현0.25
technicalTermsarchitecture, distributed, encryption 같은 단어0.25
tokenCount15 토큰 미만이면 짧음, 400 토큰 초과면 김0.10
simpleIndicatorswhat is, define, hello 같은 표현0.05
multiStepPatternsfirst…then, 번호 단계0.03
questionComplexity물음표가 여러 개0.02
합계티어
0.15 미만SIMPLE
0.15 ~ 0.35MEDIUM
0.35 ~ 0.60COMPLEX
0.60 이상REASONING
  • 가중치와 경계값은 기본값이며 dimension_weights, tier_boundaries로 조정 가능
  • reasoning marker가 2개 이상이면 REASONING으로 올리지만, 점수가 reasoning_override_min_score(기본값은 SIMPLE/MEDIUM 경계값 0.15) 이상일 때만 적용됨. 점수가 음수일 수 있어 하한을 0으로 두어도 음수 점수는 올라가지 않음
  • 점수는 사용자 발화만 대상으로 하며 system prompt는 반영되지 않음. 키워드 규칙도 사용자 발화에서만 찾음
  • custom_technical_keywords는 기본 기술 용어 목록(tcp, http 등)에 단어를 추가하는 설정이며, 기술 용어가 2개 이상 걸리면 technicalTerms 항목에 반영될 뿐 티어를 직접 정하지는 않음. 티어를 확정하려면 keyword_tier_rules를 사용

비용이 들지 않고 빠르지만 단어 신호에 의존한다.

5-4. 저비용 LLM 분류기

점수 계산 대신 작고 빠른 모델에게 “이 요청이 어느 티어인가"를 묻는 방식이다. classifier_type: llm으로 켜고 분류에 쓸 모델을 classifier_llm_config에 지정한다.

      complexity_router_config:
        classifier_type: llm
        classifier_llm_config:
          model: gpt-4o-mini                    # 저비용 모델, model_list에 등록된 이름
          timeout_ms: 2000                      # 이 시간 안에 못 받으면 fallback
        classifier_fallback: heuristic          # 기본값. default_model로 바꾸면 기본 모델로 보냄
        tiers:
          # ... 5-1과 동일 ...
  • 분류기가 돌려준 티어를 그대로 사용하며, 5-3의 reasoning marker 규칙은 적용되지 않음
  • 시간 초과, 빈 응답, 형식 불일치가 나면 휴리스틱 점수 계산으로 대체. classifier_fallback: default_model이면 기본 모델로 전달. Router의 fallbacks는 분류 호출에 적용되지 않음
  • 분류 모델에는 system 메시지, 직전 사용자 발화 최대 3개(classifier_context_window_size), 현재 질문이 전달되므로 다른 제공자라면 대화 일부가 그쪽으로 나감
  • 요청마다 분류 호출이 한 번 더 발생해 지연과 비용이 늘며, 분류 비용은 classifier_cost로 따로 기록됨

그 밖에 classifier_type으로 jev(외부 분류 서비스)와 custom(Python 플러그인)도 선택할 수 있다.

5-5. 한국어 프롬프트

기본 키워드가 영어라서 한국어 프롬프트에서는 휴리스틱 신호가 약하다. 테스트에서 복잡한 한국어 요청(분산 시스템 아키텍처를 단계별로 분석해서 설계해줘)이 SIMPLE로 분류됐다. 한국어 키워드 규칙을 넣거나, semantic_keyword_matching: true(임베딩 모델 지정 필요), 저비용 LLM 분류기로 보완할 수 있다.

5-6. 이미지가 포함된 요청

  • 티어 판단은 메시지 중 텍스트 블록(type == "text")만 읽음. 이미지 자체는 점수에 반영되지 않으므로 “이 사진 설명해줘"는 그 문장만으로 티어가 정해짐
  • 이미지만 있고 텍스트가 없으면 사용자 질문이 없는 것으로 보고 complexity_router_default_model로 전달
  • 기본 설정에서는 티어 모델이 비전을 지원하지 않아도 그대로 호출되어 provider 에러가 날 수 있음
  • modality_routing: true로 켜면 이미지 요청에서 supports_vision: false로 선언한 모델을 상위 티어의 모델로 바꾸고, 그래도 없으면 기본 모델로 보내며, 가능한 모델이 없으면 provider 호출 없이 400을 반환. /v1/chat/completions와 /v1/responses가 같음
  • supports_vision을 선언하지 않은 모델은 제외되지 않으므로 model_info에 명시해야 함

5-7. 비용과 세션 고정

턴마다 모델이 바뀌면 프롬프트 캐시가 날아가서 오히려 비쌀 수 있다. 5-1 예시의 session_affinity와 classification_mode: user_turn이 완화책이다.

complexity_router_config의 session_affinity는 세션의 모델과 그 모델의 deployment를 함께 고정하고, 4-2의 optional_pre_call_checks에 있는 session_affinity는 일반 요청의 deployment를 고정한다. 이름만 같은 별개의 설정이며, 둘을 함께 켜도 충돌 없이 세션이 고정된다.

POST /auto_router/test_routing으로 완성 요청 없이 분류만 미리 확인할 수 있다.


6. 라우팅 확인

curl -s -D - -o /dev/null http://localhost:4000/v1/chat/completions \
  -H "Authorization: Bearer $LITELLM_API_KEY" -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o","messages":[{"role":"user","content":"ping"}]}' | grep -i x-litellm-model-id
  • 처리한 deployment는 응답 헤더 x-litellm-model-id로 확인
  • 라우팅 그룹은 로그의 routing_group=... model=... strategy=... 줄(DEBUG 레벨이라 LITELLM_LOG=DEBUG 필요), Auto Router는 routing decision cause=... 줄을 grep하여 확인

7. 결론

LiteLLM의 라우팅은 두 층으로 정리된다. 로드밸런싱과 라우팅 그룹은 같은 model_name의 deployment 분산과 retry, cooldown, fallbacks로 요청 쏠림과 장애를 줄이고, Auto Router는 복잡도가 낮은 요청을 저렴한 모델에 보내 비용 낭비를 줄인다.

설정이 헷갈릴 때는 두 단계로 나누어 판단하면 된다. 먼저 요청한 모델 이름이 선택 범위(후보 풀)를 정하고, 그다음 라우팅 전략이 그 범위 안에서 deployment 하나를 고른다. 단, Auto Router는 요청 복잡도로 티어를 정한 뒤 그 티어의 모델로 보낸다.

라우팅 그룹과 Auto Router처럼 모델을 섞는 기능은 응답 형식, 도구 호출, 단가, 프롬프트 캐시에 영향을 주므로 서로 바꿔 써도 되는 모델끼리만 구성하고 세션 고정을 함께 고려한다. 특히 Auto Router는 문서상 베타라서 설정 키와 기본값이 릴리스마다 바뀔 수 있고, 판단이 텍스트 신호에 의존해 이미지 내용을 반영하지 못하고 한국어 프롬프트에서는 신호가 약하다. 저비용 LLM 분류기는 요청마다 호출이 하나 더 늘고 system 메시지와 최근 대화가 분류 모델로 전달되므로 이를 감안해 도입한다.


8. 참고문헌


  1. LiteLLM, Router - Load Balancing — 라우팅 전략, router_settings, retry, cooldown, fallback ↩︎

  2. BerriAI/litellm, simple_shuffle.py — weight, rpm, tpm 값을 읽어 비율로 선택하는 코드 ↩︎

  3. BerriAI/litellm, lowest_latency.py — deployment당 지연 기록을 최대 10개로 유지하고, 가장 낮은 값에 lowest_latency_buffer를 곱해 더한 값 이하인 deployment 중에서 무작위로 고른다. ↩︎

  4. BerriAI/litellm, router.py — 요청한 이름이 라우팅 그룹의 이름이거나 그룹의 models에 있으면 그 그룹의 전략을, 아니면 기본 전략을 고르는 코드(_get_routing_context) ↩︎

  5. LiteLLM, Proxy - Reliability — fallback, timeout, cooldown 설정 ↩︎

  6. LiteLLM, Auto Routing — complexity router의 분류기, 가중치와 경계값, 이미지 요청 처리 (베타) ↩︎