본문으로 건너뛰기

[vLLM] Plugin & Hardware: 플러그인 시스템과 하드웨어 플랫폼

들어가며

vLLM은 NVIDIA GPU뿐만 아니라 AMD GPU, Intel XPU, Google TPU, AWS Neuron 등 다양한 하드웨어를 지원한다. 이를 가능하게 하는 것이 vllm/plugins/의 플러그인 시스템과 vllm/platforms/의 하드웨어 추상화 레이어다.

공식 문서

vLLM 공식 문서: Plugin System

핵심 구조/코드 분석

플러그인 그룹

DEFAULT_PLUGINS_GROUP = "vllm.general_plugins"        # 모든 프로세스에서 로드
IO_PROCESSOR_PLUGINS_GROUP = "vllm.io_processor_plugins"  # process0에서만 로드
PLATFORM_PLUGINS_GROUP = "vllm.platform_plugins"       # 플랫폼 감지 시 로드
STAT_LOGGER_PLUGINS_GROUP = "vllm.stat_logger_plugins"    # async 서빙 시 로드

플러그인을 용도별로 네 그룹으로 분류한다. 각 그룹은 로드 시점과 프로세스 범위가 다르다. general_plugins는 API 서버, 엔진 코어, 워커 모든 프로세스에서 로드되고, io_processor_plugins는 API 서버(process0)에서만 로드된다.

entry_points 기반 플러그인 발견

def load_plugins_by_group(group: str) -> dict[str, Callable[[], Any]]:
    from importlib.metadata import entry_points
    allowed_plugins = envs.VLLM_PLUGINS
    discovered_plugins = entry_points(group=group)

    plugins = dict[str, Callable[[], Any]]()
    for plugin in discovered_plugins:
        if allowed_plugins is None or plugin.name in allowed_plugins:
            try:
                func = plugin.load()
                plugins[plugin.name] = func
            except Exception:
                logger.exception("Failed to load plugin %s", plugin.name)
    return plugins

Python의 entry_points 메커니즘을 사용하여 설치된 패키지에서 플러그인을 자동으로 발견한다. VLLM_PLUGINS 환경변수로 허용할 플러그인을 제어할 수 있다.

플랫폼 자동 감지

def cuda_platform_plugin() -> str | None:
    try:
        pynvml = import_pynvml()
        pynvml.nvmlInit()
        is_cuda = pynvml.nvmlDeviceGetCount() > 0 and not vllm_version_matches_substr("cpu")
        if is_cuda:
            return "vllm.platforms.cuda.CudaPlatform"
    except Exception:
        return None

def tpu_platform_plugin() -> str | None:
    if envs.VLLM_TPU_USING_PATHWAYS:
        return "tpu_inference.platforms.tpu_platform.TpuPlatform"
    try:
        import libtpu
        return "vllm.platforms.tpu.TpuPlatform"
    except Exception:
        return None

CUDA, TPU, ROCm, XPU 등을 순차적으로 감지한다. NVIDIA GPU는 pynvml로 감지하고, TPU는 libtpu 패키지 존재 여부로 판단한다. 엣지 케이스도 처리한다 - GPU 머신에서 CPU 빌드 vLLM을 사용하는 경우, vllm_version_matches_substr("cpu")로 CUDA를 비활성화한다.

IO Processor 플러그인

# vllm/plugins/io_processors/interface.py
class IOProcessorPlugin:
    """IO 프로세서 플러그인 인터페이스"""

IO 프로세서 플러그인은 요청/응답의 전처리/후처리를 커스터마이즈할 수 있다. 예를 들어 커스텀 토크나이저나 프롬프트 변환 로직을 플러그인으로 추가할 수 있다.

LoRA Resolver 플러그인

# vllm/plugins/lora_resolvers/
├── filesystem_resolver.py    # 파일시스템에서 LoRA 어댑터 로드
├── hf_hub_resolver.py        # HuggingFace Hub에서 LoRA 로드

LoRA 어댑터의 위치를 해석하는 resolver도 플러그인으로 구현되어 있다. 파일시스템과 HuggingFace Hub을 기본 제공하며, S3나 GCS 같은 커스텀 스토리지 지원도 플러그인으로 추가할 수 있다.

안전한 중복 로드 방지

plugins_loaded = False

def load_general_plugins():
    global plugins_loaded
    if plugins_loaded:
        return
    plugins_loaded = True
    plugins = load_plugins_by_group(group=DEFAULT_PLUGINS_GROUP)
    for func in plugins.values():
        func()

멀티프로세스 환경에서 각 프로세스가 독립적으로 load_general_plugins를 호출하므로, 전역 플래그로 중복 로드를 방지한다. 주석에 "플러그인은 여러 번 로드되어도 문제 없어야 한다"고 명시하고 있다.

왜 이 설계인가

  1. entry_points 선택: pip/setuptools의 entry_points는 Python 생태계의 표준 플러그인 메커니즘이다. 별도의 플러그인 레지스트리 서버 없이, 패키지 설치만으로 플러그인이 자동 등록된다. vLLM을 포크하지 않고도 기능을 확장할 수 있다.

  2. 그룹별 분리: 모든 플러그인을 한 번에 로드하면, 불필요한 의존성이 로드되어 시작 시간이 늘어나고 보안 위험이 생긴다. 그룹별로 분리하여 필요한 프로세스에서만 필요한 플러그인을 로드한다.

  3. VLLM_PLUGINS 화이트리스트: 기본적으로 모든 설치된 플러그인이 로드되지만, VLLM_PLUGINS 환경변수로 허용 목록을 지정할 수 있다. 프로덕션 환경에서 신뢰할 수 있는 플러그인만 로드하도록 제한할 수 있다.

참고 자료

댓글

관련 포스트

vLLM 의 다른글