로컬 GPU 모델

우리 GPU 에서 직접 돌아가는 모델과 콜드스타트

카탈로그의 일부 모델은 어디로도 중계하지 않습니다. 우리가 소유한 하드웨어에서 직접 돌아가고, 나머지와 똑같이 /api/v1 뒤에 있습니다. 이 문서는 그렇게 해서 무엇을 얻는지, 그리고 대신 무엇을 감수해야 하는지 — 잠들어 있던 모델은 먼저 깨어나야 한다는 점 — 를 설명합니다.

로컬 모델이란

슬롯은 GPU 노드 하나에 올라간 모델 하나이고, OpenAI 프로토콜을 말하는 추론 엔진이 그 앞에 있습니다.

모델엔진컨텍스트툴 콜링이미지
google/gemma-4-26b-a4bvLLM32,768지원지원
lgai/exaone-4.0-32bvLLM32,768미지원미지원

둘 다 입력 ₩30 / 1M 토큰, 출력 ₩150 / 1M 토큰입니다. 같은 노드에 실험용 슬롯이 더 있지만 공개하지 않습니다.

슬롯은 카탈로그에서 볼 수 있습니다. GET /api/v1/models/{author}/{slug}/endpoints 가 외부 엔드포인트와 함께 나열하고, tag 에 엔진 이름이 들어갑니다.

bash
curl https://openrouter.myip.co.kr/api/v1/models/google/gemma-4-26b-a4b/endpoints
json
{
  "data": {
    "id": "google/gemma-4-26b-a4b",
    "endpoints": [
      {
        "name": "Google: Gemma 4 26B A4B | MyIP Local GPU",
        "provider_name": "MyIP Local GPU",
        "tag": "vllm",
        "context_length": 32768,
        "max_completion_tokens": 32768,
        "status": 0,
        "pricing": { "prompt": "0.000030000000", "completion": "0.000150000000", "currency": "KRW" }
      }
    ]
  }
}

status: 0 은 슬롯이 지금 떠 있다는 뜻입니다. null 이면 정지·적재 중·오류 중 하나입니다.

왜 직접 돌리는가

가격. 로컬 단가는 provider 의 USD 요금을 환산한 값이 아니라 원화로 직접 정합니다. 그래서 환율을 따라 움직이지 않습니다.

국지성. 로컬 모델을 쓰면 프롬프트가 우리 네트워크 밖으로 나가지 않습니다. 그것을 기록할 업스트림 provider 자체가 없습니다. Provider 로깅 을 보세요.

예측 가능성. 엔진 플래그, 컨텍스트 창, 양자화를 우리가 정합니다. 벤더가 기본값을 바꿨다는 이유로 발밑이 흔들리는 일이 없습니다.

콜드스타트

여기가 설계에 반영해야 할 부분입니다.

요청이 로컬 후보를 고르면, 게이트웨이는 업스트림에 무엇을 보내기 전에 다음을 합니다.

  1. 슬롯을 찔러 봅니다. 응답하면 그대로 통과합니다 — 지연 없음.
  2. 응답이 없으면 노드 단위 락(한 번에 한 모델)을 잡고 유닛을 기동한 뒤, 슬롯이 응답하거나 대기 예산이 끝날 때까지 3초 간격으로 폴링합니다.
  3. 슬롯이 올라왔으면 요청은 정상적으로 진행됩니다.
  4. 예산을 넘겼으면 이 후보를 건너뛰고 체인의 다음 후보로 갑니다. 유닛은 백그라운드에서 계속 올라오므로, 조금 뒤 재시도하면 대개 따뜻한 슬롯을 만납니다.

대기 예산은 슬롯마다 다르고, 그 모델이 실제로 적재되는 데 걸리는 시간에 맞춰 잡혀 있습니다 — GPU 1장에서 큰 모델이면 수 분 단위입니다. 이 예산이 한 요청이 기다릴 수 있는 상한입니다.

클라이언트가 보는 것

상황결과
슬롯이 이미 떠 있음정상 응답, 추가 지연 없음
콜드였지만 예산 안에 기동정상 응답. 다만 적재 시간만큼 오래 걸림
콜드 + 예산 초과 + 다른 후보 있음다음 후보가 응답. X-MyIP-Provider 로 확인
콜드 + 예산 초과 + 다른 후보 없음error_type: model_loading503

503 본문과 헤더:

json
{
  "error": {
    "code": 503,
    "message": "로컬 모델을 기동하는 중입니다. 잠시 후 다시 시도하세요.",
    "metadata": { "error_type": "model_loading", "retry_after_sec": 300 }
  }
}

같은 값이 Retry-After 헤더로도 옵니다. 그 값을 지키세요 — 즉시 재시도하면 같은 적재 뒤에 다시 줄을 설 뿐입니다.

코드로 다루기

import time, requests

def chat(payload, tries=3):
    for attempt in range(tries):
        r = requests.post(
            "https://openrouter.myip.co.kr/api/v1/chat/completions",
            headers={"Authorization": f"Bearer {MYIP_API_KEY}"},
            json=payload,
            timeout=600,
        )
        if r.status_code != 503:
            return r
        wait = int(r.headers.get("Retry-After", "10"))
        time.sleep(wait)
    return r

실전에서 잘 통하는 세 가지 패턴입니다.

  • 필요해지기 전에 깨워 둡니다. 1 토큰짜리 요청을 보내고 결과는 버립니다. 비용은 1원의 몇 분의 1이고, 다음 요청은 따뜻한 요청이 됩니다.
  • 폴백을 줍니다. "models": ["lgai/exaone-4.0-32b", "google/gemma-4-26b-a4b"] 로 두면 503 대신 체인이 다음으로 넘어갑니다. 모델 폴백 을 보세요.
  • 요청마다 모델을 바꾸지 않습니다. 모델별로 작업을 묶어야 배타적 GPU 가 스래싱하지 않습니다.

로컬 슬롯이 건너뛰어지는 다른 이유

콜드스타트만이 아닙니다. 다음 경우에도 로컬 후보가 체인에서 빠집니다.

  • 프롬프트가 슬롯의 컨텍스트보다 깁니다. 추정 프롬프트 길이보다 컨텍스트 창이 작은 후보는 보내기 전에 제거됩니다. 어차피 실패할 요청에 콜드스타트를 낭비하지 않으려는 것입니다. 그 결과 아주 긴 프롬프트는 조용히 외부 provider 가 처리할 수 있습니다. 그게 중요하다면 X-MyIP-Provider 를 확인하세요.
  • 쿨다운 중입니다. 업스트림 실패가 3회 연속이면 그 후보는 60초 쿨다운에 들어가고, 그동안 체인은 그냥 지나칩니다.
  • 직접 제외했습니다. provider: { "ignore": ["local-gpu"] } 로 빼거나, provider.order · sort 로 순서를 바꾸면 1순위가 아니게 됩니다. Provider 라우팅 을 보세요.

슬롯을 관리하는 프로세스가 일시적으로 응답하지 않는 경우(예: 재시작 중)에는 후보를 버리지 않습니다. 이미 떠 있을 수도 있으니 그대로 시도하고, 아니라면 업스트림 호출이 빨리 실패해서 체인이 다음으로 넘어갑니다. 관리 프로세스의 가용성이 API 의 가용성을 결정하게 두지 않습니다.

로컬로 고정하기

데이터 국지성 같은 이유로 "로컬 아니면 안 된다"가 필요할 때:

json
{
  "model": "google/gemma-4-26b-a4b",
  "provider": { "only": ["local-gpu"] },
  "messages": [{ "role": "user", "content": "…" }]
}

only 를 쓰면 폴백이 없습니다. 슬롯이 제때 못 올라오면 503 model_loading, 매핑이 꺼져 있으면 404 no_endpoints_found 입니다. 국지성이 선호가 아니라 요구사항일 때는 보통 이쪽이 맞습니다. 반대 방향은 로컬 우선 라우팅 에서 다룹니다.

능력은 슬롯마다 다르다

툴 콜링과 이미지 입력은 모델 계열이 아니라 슬롯 단위로 켭니다. 현재는 google/gemma-4-26b-a4b 슬롯이 툴 콜링과 이미지 입력을 지원하고, lgai/exaone-4.0-32b 는 텍스트 전용이며 툴이 없습니다. 언제나 정답은 GET /api/v1/modelssupported_parametersarchitecture.input_modalities 입니다 — 짐작하지 말고 그걸 읽으세요.

과금

로컬이라고 과금이 다르지 않습니다. 산식은 같습니다 — 프롬프트 토큰 × 입력 단가, 완성 토큰 × 출력 단가, 둘 다 원화, 정산은 한 번만 하고 저장합니다. 실패한 요청은(슬롯을 끝내 못 받은 요청 포함) 비용이 0 입니다. 요금 계산 방식 을 보세요.

콜드스타트를 기다린 시간은 과금하지 않습니다. 우리가 세는 것은 토큰이지 초가 아닙니다.

마지막 수정 2026. 9. 5.