플러그인 시스템
플러그인 시스템 (Plugin System)
커뮤니티에서 vLLM에 커스텀 기능을 추가하고 싶다는 요청이 자주 들어와요. 이를 돕기 위해 vLLM은 사용자가 vLLM 코드베이스를 수정하지 않고도 커스텀 기능을 추가할 수 있는 플러그인 시스템을 포함하고 있어요. 이 문서는 vLLM에서 플러그인이 어떻게 동작하는지, 그리고 vLLM용 플러그인을 어떻게 만드는지 설명할게요.
vLLM에서 플러그인이 동작하는 방식 (How Plugins Work in vLLM)
플러그인은 사용자가 등록한 코드로, vLLM이 실행해요. vLLM의 아키텍처(Arch Overview 참고)를 생각하면 다양한 병렬화 기법과 함께 분산 추론을 쓸 때 여러 프로세스가 관여할 수 있어요. 플러그인이 제대로 동작하려면 vLLM이 만드는 모든 프로세스가 플러그인을 로드해야 해요. 이 작업은 vllm.plugins 모듈의 [load_plugins_by_group][vllm.plugins.load_plugins_by_group] 함수가 담당해요.
vLLM이 플러그인을 발견하는 방식 (How vLLM Discovers Plugins)
vLLM의 플러그인 시스템은 표준 Python entry_points 메커니즘을 사용해요. 이 메커니즘은 개발자가 자신의 Python 패키지에 함수를 등록해 다른 패키지가 쓰게 해 줘요. 플러그인 예시를 볼게요.
??? code
```python
# inside `setup.py` file
from setuptools import setup
setup(name='vllm_add_dummy_model',
version='0.1',
packages=['vllm_add_dummy_model'],
entry_points={
'vllm.general_plugins':
["register_dummy_model = vllm_add_dummy_model:register"]
})
# inside `vllm_add_dummy_model/__init__.py` file
def register():
from vllm import ModelRegistry
if "MyLlava" not in ModelRegistry.get_supported_archs():
ModelRegistry.register_model(
"MyLlava",
"vllm_add_dummy_model.my_llava:MyLlava",
)
```
패키지에 엔트리 포인트를 추가하는 방법에 대한 자세한 내용은 공식 문서를 확인하세요.
모든 플러그인은 세 부분으로 구성돼요.
- 플러그인 그룹 (Plugin group): 엔트리 포인트 그룹의 이름이에요. vLLM은 일반 플러그인을 등록하기 위해 엔트리 포인트 그룹
vllm.general_plugins를 사용해요. 이것이setup.py파일에서entry_points의 키가 돼요. vLLM의 일반 플러그인에는 항상vllm.general_plugins를 사용하세요. - 플러그인 이름 (Plugin name): 플러그인의 이름이에요.
entry_points딕셔너리 안에서의 값이죠. 위 예시에서 플러그인 이름은register_dummy_model이에요.VLLM_PLUGINS환경변수로 플러그인을 이름별로 필터링할 수 있어요. 특정 플러그인만 로드하려면VLLM_PLUGINS를 그 플러그인 이름으로 설정하세요. - 플러그인 값 (Plugin value): 플러그인 시스템에 등록할 함수나 모듈의 정규화된 이름(full qualified name)이에요. 위 예시에서 플러그인 값은
vllm_add_dummy_model:register로,vllm_add_dummy_model모듈의register함수를 가리켜요.
지원되는 플러그인 유형 (Types of supported plugins)
-
일반 플러그인 (General plugins, 그룹 이름
vllm.general_plugins): 이 플러그인의 주 용도는 커스텀·외부(in-tree 밖) 모델을 vLLM에 등록하는 거예요. 플러그인 함수 안에서ModelRegistry.register_model을 호출해 모델을 등록해요. 공식 모델 플러그인 예시로는BartForConditionalGeneration지원을 추가하는 bart-plugin이 있어요. -
플랫폼 플러그인 (Platform plugins, 그룹 이름
vllm.platform_plugins): 주 용도는 커스텀·외부 플랫폼을 vLLM에 등록하는 거예요. 플러그인 함수는 현재 환경에서 플랫폼이 지원되지 않으면None을, 지원되면 플랫폼 클래스의 정규화된 이름을 반환해요. -
IO 프로세서 플러그인 (IO Processor plugins, 그룹 이름
vllm.io_processor_plugins): 주 용도는 pooling 모델의 모델 프롬프트·모델 출력에 커스텀 전·후처리를 등록하는 거예요. 플러그인 함수는 IOProcessor 클래스의 정규화된 이름을 반환해요. -
스탯 로거 플러그인 (Stat logger plugins, 그룹 이름
vllm.stat_logger_plugins): 주 용도는 커스텀·외부 로거를 vLLM에 등록하는 거예요. 엔트리 포인트는StatLoggerBase를 상속하는 클래스여야 해요. -
엔드포인트 플러그인 (Endpoint plugins, 그룹 이름
vllm.endpoint_plugins): 주 용도는 OpenAI 호환 API 서버에 커스텀·외부 HTTP 라우트를 등록하는 거예요. 위의 다른 플러그인 그룹과 달리, 엔드포인트 플러그인은 API 서버 프런트엔드 프로세스에서만 로드되며 기본적으로 로드되지 않아요. 인터페이스는 Endpoint Plugins, 옵트인과 신뢰 모델은 Security를 참고하세요.
플러그인 작성 가이드라인 (Guidelines for Writing Plugins)
- 재진입성(Re-entrant): 엔트리 포인트에 지정된 함수는 재진입이 가능해야 해요. 즉 여러 번 호출해도 문제가 없어야 하죠. 어떤 프로세스에서는 그 함수가 여러 번 호출될 수 있기 때문에 필요해요.
플랫폼 플러그인 가이드라인 (Platform plugins guidelines)
-
플랫폼 플러그인 프로젝트를 만들어요. 예:
vllm_add_dummy_platform. 프로젝트 구조는 이렇게 생겼어요.vllm_add_dummy_platform/ ├── vllm_add_dummy_platform/ │ ├── __init__.py │ ├── my_dummy_platform.py │ ├── my_dummy_worker.py │ ├── my_dummy_attention.py │ ├── my_dummy_device_communicator.py │ ├── my_dummy_custom_ops.py ├── setup.py -
setup.py파일에 다음 엔트리 포인트를 추가해요.setup( name="vllm_add_dummy_platform", ... entry_points={ "vllm.platform_plugins": [ "my_dummy_platform = vllm_add_dummy_platform:register" ] }, ... )vllm_add_dummy_platform:register가 호출 가능한 함수이고 플랫폼 클래스의 정규화된 이름을 반환하는지 확인하세요. 예:def register(): return "vllm_add_dummy_platform.my_dummy_platform.MyDummyPlatform" -
my_dummy_platform.py에 플랫폼 클래스MyDummyPlatform을 구현해요. 플랫폼 클래스는vllm.platforms.interface.Platform을 상속해야 해요. 인터페이스를 따라 함수를 하나씩 구현하세요. 최소한 구현해야 할 중요한 함수·프로퍼티가 있어요._enum: [PlatformEnum][vllm.platforms.interface.PlatformEnum]의 디바이스 열거값이에요. 보통PlatformEnum.OOT이어야 하며, 이는 플랫폼이 out-of-tree라는 뜻이에요.device_type: pytorch가 사용하는 디바이스 타입을 반환해야 해요. 예:"cpu","cuda".device_name: 보통device_type과 같은 값으로 설정해요. 주로 로깅 용도로 쓰여요.check_and_update_config: vLLM 초기화 과정에서 매우 일찍 호출돼요. 플러그인이 vllm 설정을 갱신할 때 써요. 예를 들어 블록 크기, 그래프 모드 설정 등을 이 함수에서 갱신할 수 있어요. 가장 중요한 건 이 함수에서 **worker_cls**를 설정해 vLLM이 워커 프로세스에 어떤 워커 클래스를 쓸지 알게 하는 거예요.get_attn_backend_cls: 어텐션 백엔드 클래스의 정규화된 이름을 반환해야 해요.get_device_communicator_cls: 디바이스 커뮤니케이터 클래스의 정규화된 이름을 반환해야 해요.
-
my_dummy_worker.py에 워커 클래스MyDummyWorker를 구현해요. 워커 클래스는 [WorkerBase][vllm.v1.worker.worker_base.WorkerBase]를 상속해야 해요. 인터페이스를 따라 함수를 하나씩 구현하세요. 기본적으로 기본 클래스의 모든 인터페이스를 구현해야 해요. vLLM 곳곳에서 호출되거든요. 모델이 실행되도록 하려면 최소한 다음 기본 함수를 구현해야 해요.init_device: 워커의 디바이스를 설정하기 위해 호출돼요.initialize_cache: 워커의 캐시 설정을 지정하기 위해 호출돼요.load_model: 모델 가중치를 디바이스에 로드하기 위해 호출돼요.get_kv_cache_spec: 모델의 kv cache 스펙을 생성하기 위해 호출돼요.determine_available_memory: OOM 없이 KV 캐시에 얼마나 많은 메모리를 쓸 수 있는지 결정하기 위해 모델의 최고 메모리 사용량을 프로파일링해요.initialize_from_config: 지정된 kv_cache_config로 디바이스 KV 캐시를 할당하기 위해 호출돼요.execute_model: 매 스텝마다 모델을 추론하기 위해 호출돼요.
추가로 구현할 수 있는 함수들이 있어요.
- sleep mode 기능을 지원하려면
sleep와wakeup함수를 구현해요. - graph mode 기능을 지원하려면
compile_or_warm_up_model함수를 구현해요. - 스펙큘레이티브 디코딩을 지원하려면
take_draft_token_ids함수를 구현해요. - lora 기능을 지원하려면
add_lora,remove_lora,list_loras,pin_lora함수를 구현해요. - 데이터 병렬 기능을 지원하려면
execute_dummy_batch함수를 구현해요.
구현할 수 있는 다른 함수들은 워커 기본 클래스 [WorkerBase][vllm.v1.worker.worker_base.WorkerBase]를 참고하세요.
-
my_dummy_attention.py에 어텐션 백엔드 클래스MyDummyAttention을 구현해요. 어텐션 백엔드 클래스는 [AttentionBackend][vllm.v1.attention.backend.AttentionBackend]를 상속해야 해요. 디바이스로 어텐션을 계산하는 데 쓰여요.vllm.v1.attention.backends를 예로 들면 어텐션 백엔드 구현이 많이 들어 있어요. -
고성능을 위한 커스텀 ops를 구현해요. 대부분의 ops는 pytorch 네이티브 구현으로 실행할 수 있지만, 성능이 좋지 않을 수 있어요. 그럴 때 플러그인용 특화 커스텀 ops를 구현할 수 있어요. 현재 vLLM이 지원하는 커스텀 ops 종류는 다음과 같아요.
-
pytorch ops pytorch ops는 3가지가 있어요.
communicator ops: 디바이스 커뮤니케이터 op예요. all-reduce, all-gather 등이 있어요.my_dummy_device_communicator.py에 디바이스 커뮤니케이터 클래스MyDummyDeviceCommunicator를 구현하세요. 이 클래스는 [DeviceCommunicatorBase][vllm.distributed.device_communicators.base_device_communicator.DeviceCommunicatorBase]를 상속해야 해요.common ops: 공통 op예요. matmul, softmax 등이 있어요. [CustomOp][vllm.model_executor.custom_op.CustomOp] 클래스에서 자세한 내용을 보듯이 oot 방식으로 등록해 구현하세요.csrc ops: C++ ops예요. C++로 구현되고 torch 커스텀 ops로 등록돼요. csrc 모듈과vllm._custom_ops를 따라 ops를 구현하세요.
-
triton ops triton ops에는 지금 커스텀 방식이 동작하지 않아요.
-
-
(선택) lora, graph backend, 양자화, mamba 어텐션 백엔드 등 다른 플러그 가능한 모듈을 구현해요.
호환성 보장 (Compatibility Guarantee)
vLLM은 ModelRegistry.register_model 같은 문서화된 플러그인 인터페이스가 플러그인이 모델을 등록할 때 항상 사용 가능하도록 보장해요. 다만 플러그인이 타깃으로 삼는 vLLM 버전과 호환되도록 하는 건 플러그인 개발자의 책임이에요. 예를 들어 "vllm_add_dummy_model.my_llava:MyLlava"는 타깃 vLLM 버전과 호환되어야 해요.
모델/모듈 인터페이스는 vLLM 개발 중 바뀔 수 있어요. deprecation 로그가 보이면 플러그인을 최신 버전으로 업그레이드하세요.
폐기 공지 (Deprecation announcement)
!!! warning "Deprecations"
- Platform.get_attn_backend_cls의 use_v1 파라미터는 deprecated예요. v0.13.0에서 제거됐어요.
- vllm.attention의 _Backend는 deprecated예요. v0.13.0에서 제거됐어요. 대신 vllm.v1.attention.backends.registry.register_backend를 사용해 AttentionBackendEnum에 새 어텐션 백엔드를 추가하세요.
- seed_everything 플랫폼 인터페이스는 deprecated예요. v0.16.0에서 제거됐어요. 대신 vllm.utils.torch_utils.set_random_seed를 사용하세요.
- Platform.validate_request의 prompt는 deprecated예요. v0.18.0에서 제거됐어요.
더 알아보기 (Learn more)
- Endpoint Plugins — 엔드포인트 플러그인 인터페이스
- IO Processor Plugins — IO 프로세서 플러그인
- LoRA Resolver Plugins — LoRA 리졸버 플러그인