렌더러 API
렌더러 API (Renderer APIs)
렌더러 API는 렌더(전처리) 단계를 분리해 token-in / token-out API 서버를 가능하게 하도록 설계되었습니다. 프론트엔드의 전처리·후처리를 GPU 없이 실행하고, 엔진을 순수 token-in / token-out 서비스로 만듭니다.
출처: 문서
본문
렌더러 API는 렌더 단계(전처리)를 분리하고 token-in / token-out API 서버를 가능하게 하도록 설계되었습니다.
- GPU 없는 프론트엔드 배포: 전처리(tokenization, MM 입력 처리)와 후처리(detokenization, tool call 파싱, reasoning 파싱)가 GPU 없이 실행되게 합니다.
- 분리된 토크나이제이션: llm-d, Dynamo, 커스텀 프론트엔드처럼 전체 추론 엔진을 실행하지 않고 vLLM의 전처리 로직을 활용해야 하는 사용 사례를 지원합니다.
- Tokens-in / tokens-out 엔진: 엔진을 요청 전처리에서 분리된 순수 token-in / token-out 서비스로 만듭니다.
전용 vllm launch render 서버는 항상 /render와 /derender 엔드포인트를 노출합니다.
/render, /derender, /inference/v1/generate를 포함한 스케일아웃 엔드포인트는 표준 추론 서버에서 기본적으로 비활성화됩니다. vllm serve로 노출하려면 명시적으로 옵트인하세요:
vllm serve <model> --enable-scale-out
API 레퍼런스
- Completions Render API (
/v1/completions/render) 완성 요청을 렌더링 - Chat Completions Render API (
/v1/chat/completions/render) 채팅 완성을 렌더링 - Responses Render API (
/v1/responses/render) 자급자족형 Responses 요청을 렌더링
Responses 프롬프트 토큰 ID 얻기 (Get Responses prompt token IDs)
모델 복제본을 선택하기 전에 /v1/responses/render로 프롬프트 토큰 ID를 얻을 수 있습니다. 렌더링은 추론을 실행하지 않고 프롬프트 구성과 전처리를 적용합니다.
Responses render 엔드포인트는 /v1/responses와 같은 프롬프트 구성을 사용하고 하나의 token-in GenerateRequest를 반환합니다. 무상태(stateless)입니다. 즉 인라인 히스토리는 지원하지만 previous_response_id는 지원하지 않습니다. 호출자는 저장된 응답 상태를 해석하고, 렌더링 전에 요청에 결과 히스토리를 포함해야 합니다.
렌더러와 생성 워커를 같은 모델·토크나이저·채팅 템플릿·전처리 옵션으로 구성하세요. 지침·히스토리·도구·템플릿·절단 옵션을 포함해 전체 요청을 렌더링하세요. 반환된 ID가 모델이 받을 프롬프트를 반영하게 하려면 그렇게 해야 합니다.
멀티모달 요청의 경우 GenerateRequest는 모델이 처리한 멀티모달 페이로드를 담는데, 이는 원본 이미지·비디오보다 훨씬 클 수 있습니다. 호출자는 해당 페이로드를 변경 없이 생성 서비스에 전달하고 전송 제한과 메모리를 그에 맞게 준비해야 합니다.
예를 들어 스케일아웃 엔드포인트를 활성화한 표준 추론 서버를 시작합니다:
VLLM_ENABLE_SCALE_OUT_ENDPOINTS=1 \
vllm serve meta-llama/Llama-3.1-8B-Instruct
Responses 요청을 보내고 jq로 token_ids 필드를 추출합니다:
curl --fail --silent --show-error http://localhost:8000/v1/responses/render \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Llama-3.1-8B-Instruct",
"input": "Explain prefix caching in one sentence.",
"max_output_tokens": 32
}' | jq '.token_ids'
이 텍스트 요청의 렌더된 프롬프트 토큰 수를 세려면 jq 필터를 '.token_ids | length'로 바꾸세요. 엔드포인트는 전체 GenerateRequest를 반환합니다. jq는 클라이언트에서 응답을 필터링합니다. 멀티모달 features를 포함해 /inference/v1/generate로 전달하려면 완전한 응답을 유지하세요.
서버에 --api-key 또는 VLLM_API_KEY가 구성되어 있으면 요청에 -H "Authorization: Bearer ***"를 추가하세요. 기존 인증 경계에 대해서는 API key authentication limitations를 참고하세요.
생성된 토큰 ID를 다시 OpenAI 호환 응답으로 바꾸는 후처리 대응편은 Derenderer APIs를 참고하세요.
멀티모달 렌더 기능 (Multimodal Render Features)
멀티모달 렌더 응답에는 modality별 해시·플레이스홀더 범위·직렬화된 프로세서 데이터가 있는 features 객체가 포함됩니다. 모델이 placeholder-metadata나 keep_on_cpu 필드(예: image_grid_thw)를 노출하면 응답에 mm_metadata도 포함됩니다. 각 mm_metadata 항목은 pixel_values 같은 인코더 입력이 아닌 그 필드들만 담는 base64 인코딩 MultiModalKwargsItem입니다.
mm_hashes, mm_placeholders, kwargs_data, mm_metadata의 배열은 같은 per-modality 항목 순서를 사용합니다. 다운스트림 워커는 이 필드들을 분할해야 합니다:
- 인코드 요청은
kwargs_data를 유지합니다. - 프리필 요청은
ec_transfer_params도 설정된 경우에만kwargs_data를 생략하고mm_metadata를 보냅니다. 그래야 임베딩을 EC 커넥터가 로드합니다.ec_transfer_params없이kwargs_data를 생략하면 거부됩니다. mm_metadata를 무시하고 계속kwargs_data를 보내는 레거시 클라이언트는 계속 동작합니다.
예시 (Example)
아래 예시는 분리된 encode/prefill 코디네이터가 멀티모달 렌더 응답을 어떻게 분할하는지 보여줍니다. 렌더 단계는 kwargs_data(인코더 텐서 + 메타데이터)와 mm_metadata(메타데이터만)를 모두 반환합니다. Encode는 전체 페이로드를 유지하고, prefill은 EC 커넥터가 임베딩을 게시한 뒤 kwargs_data를 버립니다.
import httpx
MODEL = "Qwen/Qwen3-VL-2B-Instruct"
RENDER = "http://localhost:8100" # vllm launch render ...
ENCODE = "http://localhost:8200" # encode worker
PREFILL = "http://localhost:8300" # prefill worker
chat_request = {
"model": MODEL,
"messages": [
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "<data-url>"}},
{"type": "text", "text": "Describe this image."},
],
}
],
}
with httpx.Client(timeout=120.0) as client:
# 1. Render: preprocess into token IDs and multimodal features.
render_response = client.post(
f"{RENDER}/v1/chat/completions/render", json=chat_request
).json()
features = render_response["features"]
# features["kwargs_data"]["image"][0] -> pixel_values + image_grid_thw
# features["mm_metadata"]["image"][0] -> image_grid_thw only
# 2. Encode: send full kwargs_data so the encoder can run vision towers.
encode_response = client.post(
f"{ENCODE}/inference/v1/generate",
json={
"token_ids": render_response["token_ids"],
"features": {
"mm_hashes": features["mm_hashes"],
"mm_placeholders": features["mm_placeholders"],
"kwargs_data": features["kwargs_data"],
},
"sampling_params": {"max_tokens": 1},
},
).json()
ec_transfer_params = encode_response["ec_transfer_params"]
# 3. Prefill: omit kwargs_data; load embeddings via EC connector.
prefill_response = client.post(
f"{PREFILL}/inference/v1/generate",
json={
"token_ids": render_response["token_ids"],
"features": {
"mm_hashes": features["mm_hashes"],
"mm_placeholders": features["mm_placeholders"],
"mm_metadata": features["mm_metadata"],
},
"ec_transfer_params": ec_transfer_params,
"sampling_params": {"max_tokens": 64},
},
).json()
print(prefill_response["choices"][0]["token_ids"])
단일 프로세스 클라이언트는 전체 렌더 응답을 /inference/v1/generate에 변경 없이 계속 전달할 수 있습니다. mm_metadata는 선택적이며 kwargs_data가 있으면 무시됩니다.
페이로드 형태
렌더 응답
/v1/chat/completions/render는 kwargs_data와 mm_metadata를 모두 반환합니다. 배열은 같은 per-modality 항목 순서를 공유합니다. 가독성을 위해 base64 blob은 아래에서 잘랐습니다.
{
"token_ids": [151644, 872],
"features": {
"mm_hashes": {"image": ["abc123..."]},
"mm_placeholders": {"image": [{"offset": 0, "length": 256}]},
"kwargs_data": {
"image": ["<base64 MultiModalKwargsItem: pixel_values + image_grid_thw>"]
},
"mm_metadata": {
"image": ["<base64 MultiModalKwargsItem: image_grid_thw only>"]
}
}
}
kwargs_data를 encode 워커로 전달하세요. mm_metadata는 prefill용으로 유지하세요.
프리필 요청
Prefill은 kwargs_data를 생략하고 encode 응답의 ec_transfer_params와 함께 mm_metadata를 보냅니다:
{
"token_ids": [151644, 872],
"features": {
"mm_hashes": {"image": ["abc123..."]},
"mm_placeholders": {"image": [{"offset": 0, "length": 256}]},
"mm_metadata": {
"image": ["<base64 MultiModalKwargsItem: image_grid_thw only>"]
}
},
"ec_transfer_params": {
"ec_items": [{"mm_hash": "abc123...", "peer_host": "10.0.0.1"}]
},
"sampling_params": {"max_tokens": 64}
}
더 알아보기 (Learn more)
- 디렌더러 API — 토큰 ID를 응답으로 후처리
- vllm launch render — GPU 없는 render 서버 시작
- 분리 서빙 — prefill/encode 분리 개요