Disaggregated Encoder¶
Disaggregated Encoder 베타 상태
이 기능은 베타 버전입니다. 하위 호환성을 보장하지 않으며, 프로덕션 환경에서의 사용은 권장하지 않습니다.
Model implementation 지원
이 페이지에서 설명하는 설정은 transformers(optimum) model implementation에 적용됩니다.
개요¶
Disaggregated Encoder는 멀티모달 모델의 비전 인코더와 언어 모델을 별도의 vLLM 프로세스에서 실행합니다. 인코더는 이미지를 처리해 출력 텐서를 생성하고, 언어 모델은 이 텐서를 사용해 텍스트를 생성합니다.
비전 인코더와 언어 모델에 NPU를 독립적으로 할당할 수 있으며, 인코더 인스턴스를 추가해 이미지 인코딩 처리 용량을 늘릴 수 있습니다.
지원 모델¶
Disaggregated Encoder는 Qwen3-VL 모델군만 지원합니다.
아키텍처¶
배포 구성은 프록시, N개의 인코더 인스턴스, 하나의 prefill/decode(PD) 인스턴스로 이루어집니다. PD 인스턴스는 언어 모델의 prefill과 decode를 같은 프로세스에서 실행합니다.
각 인코더 인스턴스와 PD 인스턴스에 서로 겹치지 않는 NPU 집합을 할당해야 합니다.
| 구성 요소 | 역할 |
|---|---|
| Proxy | 클라이언트 요청을 받아 이미지를 인코더에 분배하고, 원본 요청을 PD에 전달 |
| Encoder | 비전 인코더로 이미지를 처리해 출력 텐서를 생성 |
| PD | 인코더 출력 텐서를 가져와 같은 인스턴스에서 언어 모델의 prefill과 decode를 실행 |
다음 다이어그램과 표는 이미지가 포함된 채팅 요청의 처리 과정을 보여줍니다.
---
config:
theme: base
themeVariables:
actorLineColor: "#0d9488"
---
sequenceDiagram
participant Client
participant Proxy
participant Encoder as Encoder × N
participant PD as PD (Prefill + Decode)
Client->>Proxy: 채팅 요청
Proxy->>Encoder: 1. 이미지 전용 요청
Note over Encoder: 2. 이미지 인코딩
Encoder->>PD: 3. 출력 텐서 메타데이터 (ZMQ)
Encoder-->>Proxy: 인코더 요청 성공
Proxy->>PD: 4. 원본 요청
Encoder->>PD: 5. 인코더 출력 텐서 (NIXL)
Note over PD: 6. Prefill 및 decode 실행
PD-->>Proxy: 응답
Proxy-->>Client: 응답 | 단계 | 동작 | 설명 |
|---|---|---|
| 1 | 이미지 분배 | 프록시는 라운드 로빈 방식으로 이미지를 인코더에 할당한 뒤, 이미지마다 텍스트를 제외한 요청을 하나씩 만들어 동시에 전송합니다. |
| 2 | 이미지 인코딩 | 각 인코더는 이미지를 처리하고, 출력 텐서를 NIXL에 등록합니다. |
| 3 | 출력 텐서 메타데이터 전송 | 각 인코더는 ZMQ를 통해 출력 텐서의 메타데이터(위치, 형태, 데이터 타입)를 PD에 전송한 뒤, 프록시에 성공 응답을 보냅니다. |
| 4 | 원본 요청 전달 | 모든 인코더 요청이 성공하면 프록시는 텍스트와 이미지를 포함한 원본 요청을 PD에 전달합니다. |
| 5 | 출력 텐서 가져오기 | PD는 메타데이터를 사용해 NIXL로 인코더 출력 텐서를 가져와 인코더 캐시에 저장합니다. |
| 6 | Prefill 및 decode 실행 | PD는 캐시된 인코더 출력 텐서를 사용해 prefill과 decode를 실행합니다. 프록시는 생성된 응답을 클라이언트에 반환합니다. |
텍스트만 포함된 요청은 프록시가 인코더를 거치지 않고 PD에 직접 전달합니다.
설정¶
nixl 설치
Disaggregated Encoder를 사용하려면 인코더와 PD 인스턴스를 실행하는 Python 환경에 nixl이 필요합니다. 설치 방법은 기능별 추가 패키지에서 확인할 수 있습니다.
인코더 및 PD¶
HTTP 서빙¶
각 인코더와 PD 인스턴스는 프록시의 요청을 받는 HTTP 서버를 실행합니다. 다음 vllm serve CLI 옵션으로 바인딩 주소와 포트를 설정합니다.
| CLI 옵션 | 설정 대상 | 설명 |
|---|---|---|
--host | Encoder, PD | 프록시의 HTTP 요청을 받을 바인딩 주소 |
--port | Encoder, PD | 프록시의 HTTP 요청을 받을 수신 포트 |
같은 호스트의 프록시에서만 요청을 받으려면 --host를 127.0.0.1로 설정합니다. 다른 호스트의 프록시에서 요청을 받으려면 로컬 인터페이스의 IP에 바인딩하거나, 모든 로컬 인터페이스에서 요청을 받도록 0.0.0.0을 사용합니다.
인코더 출력 텐서 전송¶
PD가 인코더 출력 텐서를 사용할 수 있도록 encoder-cache(EC) 커넥터를 설정해야 합니다.
각 인코더와 PD 인스턴스에서 vllm serve의 CLI 옵션인 --ec-transfer-config에 JSON 객체를 전달합니다. 객체의 구조는 다음과 같습니다.
ec_connector¶
인코더와 PD 인스턴스 모두 RblnECNixlConnector로 설정해 NIXL을 통해 인코더 출력 텐서를 전송합니다.
ec_role¶
각 인스턴스의 역할을 설정합니다.
| 설정 대상 | JSON 값 | 설명 |
|---|---|---|
| Encoder | ec_producer | 출력 텐서 제공 |
| PD | ec_consumer | 출력 텐서 가져오기 |
ec_connector_extra_config¶
인코더가 PD에 메타데이터를 전송할 때 사용할 연결 정보를 설정합니다.
| JSON 키 | 설정 대상 | 설명 |
|---|---|---|
pull_host | PD | 인코더가 보내는 메타데이터를 받을 바인딩 주소 |
pull_port | PD | 인코더가 보내는 메타데이터를 받을 수신 포트 |
llm_host | Encoder | 접속할 PD 메타데이터 소켓의 주소 |
llm_pull_port | Encoder | 접속할 포트. PD의 pull_port와 같아야 합니다. |
같은 호스트에서 실행할 때는 pull_host와 llm_host에 모두 127.0.0.1을 사용합니다.
서로 다른 호스트에서 실행할 때는 PD의 pull_host를 로컬 인터페이스의 IP 또는 0.0.0.0으로 설정하고, 각 인코더의 llm_host를 해당 인코더에서 접속할 수 있는 PD 주소로 설정합니다.
프록시¶
프록시는 자체 HTTP 포트로 클라이언트 요청을 받아 이미지 요청을 인코더에 보내고, 원본 요청을 PD에 전달합니다. 다음 CLI 옵션으로 프록시 스크립트를 설정합니다.
| CLI 옵션 | 설정 대상 | 설명 |
|---|---|---|
--host | Proxy | 클라이언트의 HTTP 요청을 받을 바인딩 주소 |
--port | Proxy | 클라이언트의 HTTP 요청을 받을 수신 포트 |
--encode-servers-urls | Proxy | 쉼표로 구분한 인코더 인스턴스의 HTTP URL 목록. 인코더를 추가할 때 이 목록을 갱신해야 합니다. |
--decode-servers-urls | Proxy | 단일 PD 인스턴스의 HTTP URL |
같은 호스트의 클라이언트에서만 요청을 받으려면 프록시의 --host를 127.0.0.1로 설정합니다. 다른 호스트의 클라이언트에서 요청을 받으려면 로컬 인터페이스의 IP에 바인딩하거나, 모든 로컬 인터페이스에서 요청을 받도록 0.0.0.0을 사용합니다.
예제¶
이 예제는 ATOM™ NPU를 사용하는 단일 호스트에 Qwen3-VL-8B-Instruct를 배포합니다.
인코더 인스턴스에는 컴파일된 모델이 필요하므로, 이 구성에서는 모델을 미리 컴파일하는 방식을 권장합니다.
시작하기 전에 RBLN vLLM과 nixl을 설치해야 합니다.
포트 및 디바이스¶
이 예제는 16개의 NPU에서 인코더 인스턴스 8개와 prefill/decode(PD) 인스턴스 1개를 실행합니다. 명령어에서 사용하는 포트와 디바이스는 다음과 같습니다.
| 구성 요소 | HTTP URL | PD 메타데이터 포트 | NPU 디바이스 |
|---|---|---|---|
| Proxy | http://127.0.0.1:19000 | — | — |
| PD | http://127.0.0.1:19100 | 19500 | 0–7 |
| Encoder 0–7 | http://127.0.0.1:19101 ~ http://127.0.0.1:19108 | 19500 | 8–15(인코더당 1개) |
사용 환경에서 이용 가능한 포트와 디바이스 ID를 선택합니다. 이 예제는 RBLN_VISIBLE_DEVICES로 각 인코더와 PD 프로세스에 NPU를 할당합니다. 커넥터와 프록시 설정은 설정에서 확인할 수 있습니다.
모델 컴파일¶
optimum-rbln Python API로 모델을 한 번 컴파일하고 Qwen3-VL-8B-Instruct에 저장해 인코더와 PD 인스턴스에서 함께 사용합니다.
Qwen3-VL-8B-Instruct 디렉터리가 있는 상위 디렉터리에서 서빙 명령어를 실행하거나, 각 명령어의 모델 경로를 변경해야 합니다.
PD 인스턴스 실행¶
PD를 EC consumer로 실행합니다.
필요하면 다른 터미널에서 다음 명령어를 실행해 PD가 요청을 받을 준비가 될 때까지 기다릴 수 있습니다. 서버 로그에서 PD가 준비된 것을 확인했다면 이 단계는 생략해도 됩니다.
인코더 인스턴스 실행¶
PD가 준비되면 인코더마다 별도의 터미널에서 다음 블록을 실행합니다. ENCODER_ID는 0부터 7까지 서로 다른 값으로 지정합니다.
필요하면 다른 터미널에서 다음 명령어로 모든 인코더 인스턴스가 요청을 받을 준비가 될 때까지 기다린 뒤 프록시를 실행할 수 있습니다. 각 인코더의 로그에서 모두 준비된 것을 확인했다면 이 단계는 생략해도 됩니다.
프록시 실행¶
별도 터미널에서 예제 프록시를 실행합니다. /path/to/vllm-rbln을 로컬에 내려받은 vllm-rbln 저장소 경로로 바꿉니다.
요청 전송¶
프록시가 준비되면 다른 터미널에서 /v1/chat/completions 엔드포인트로 이미지와 텍스트 프롬프트를 전송합니다.
응답의 choices[0].message.content에 모델이 생성한 이미지 설명이 포함됩니다.