From 49d76a10a6e78b1438836d70e6a8c61d4c320496 Mon Sep 17 00:00:00 2001 From: n00909098 Date: Mon, 8 Sep 2025 16:32:42 +0800 Subject: [PATCH 01/57] [Draft] EPD Signed-off-by: n00909098 --- .gitignore | 4 +- draft/launch.sh | 63 +++++ draft/pid.txt | 3 + draft/proxy.py | 257 ++++++++++++++++++ draft/send_request.py | 81 ++++++ draft/stop.sh | 36 +++ vllm/config/__init__.py | 104 +++++++ vllm/distributed/ec_transfer/__init__.py | 13 + .../ec_transfer/ec_connector/base.py | 233 ++++++++++++++++ .../ec_transfer/ec_connector/factory.py | 86 ++++++ .../ec_connector/shared_storage_connector.py | 225 +++++++++++++++ .../ec_transfer/ec_connector/utils.py | 0 .../ec_transfer/ec_transfer_state.py | 42 +++ vllm/engine/arg_utils.py | 11 +- vllm/entrypoints/openai/api_server.py | 1 + vllm/v1/core/sched/output.py | 7 + vllm/v1/core/sched/scheduler.py | 176 +++++++++++- vllm/v1/engine/core.py | 6 + vllm/v1/outputs.py | 8 + .../worker/ec_connector_model_runner_mixin.py | 109 ++++++++ vllm/v1/worker/gpu_model_runner.py | 41 ++- vllm/v1/worker/gpu_worker.py | 3 + 22 files changed, 1494 insertions(+), 15 deletions(-) create mode 100644 draft/launch.sh create mode 100644 draft/pid.txt create mode 100644 draft/proxy.py create mode 100644 draft/send_request.py create mode 100644 draft/stop.sh create mode 100644 vllm/distributed/ec_transfer/__init__.py create mode 100644 vllm/distributed/ec_transfer/ec_connector/base.py create mode 100644 vllm/distributed/ec_transfer/ec_connector/factory.py create mode 100644 vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py create mode 100644 vllm/distributed/ec_transfer/ec_connector/utils.py create mode 100644 vllm/distributed/ec_transfer/ec_transfer_state.py create mode 100644 vllm/v1/worker/ec_connector_model_runner_mixin.py diff --git a/.gitignore b/.gitignore index 465935d488f8..a6e7f7020095 100644 --- a/.gitignore +++ b/.gitignore @@ -209,4 +209,6 @@ shellcheck*/ csrc/moe/marlin_moe_wna16/kernel_* # Ignore ep_kernels_workspace folder -ep_kernels_workspace/ \ No newline at end of file +ep_kernels_workspace/ + +.safetensors \ No newline at end of file diff --git a/draft/launch.sh b/draft/launch.sh new file mode 100644 index 000000000000..eff75b1abc4f --- /dev/null +++ b/draft/launch.sh @@ -0,0 +1,63 @@ +#!/bin/bash + + +wait_for_server() { + local port=$1 + timeout 12000 bash -c " + until curl -s localhost:$port/v1/chat/completions > /dev/null; do + sleep 1 + done" && return 0 || return 1 +} + +MODEL="/home/n00909098/Qwen2.5-VL-3B-Instruct" +LOG_PATH=$LOG_PATH +ENCODE_PORT=19534 +ENCODE_RANK=0 +PREFILL_DECODE_PORT=19535 +PREFILL_DECODE_RANK=1 +PROXY_PORT=10001 +GPU_E="1" +GPU_PD="2" +START_TIME=$(date +"%Y%m%d_%H%M%S") +ENC_LOG=./logs/encoder.log +PD_LOG=./logs/pd.log +PROXY_LOG=./logs/proxy.log +PID_FILE="./pid.txt" + +CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ + --gpu-memory-utilization 0.7 \ + --port "$ENCODE_PORT" \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --enforce-eager \ + --ec-transfer-config \ + '{"ec_connector":"ECSharedStorageConnector","ec_role":"ec_producer"}' \ + >"${ENC_LOG}" 2>&1 & + +echo $! >> "$PID_FILE" + +CUDA_VISIBLE_DEVICES="$GPU_PD" vllm serve "$MODEL" \ + --gpu-memory-utilization 0.7 \ + --port "$PREFILL_DECODE_PORT" \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --enforce-eager \ + --ec-transfer-config \ + '{"ec_connector":"ECSharedStorageConnector","ec_role":"ec_consumer"}' \ + >"${PD_LOG}" 2>&1 & + +echo $! >> "$PID_FILE" + +wait_for_server $ENCODE_PORT +wait_for_server $PREFILL_DECODE_PORT + +python /home/n00909098/EPD/refactor/vllm/draft/proxy.py \ + --host "0.0.0.0" \ + --port "$PROXY_PORT" \ + --encode-servers-urls "http://localhost:$ENCODE_PORT" \ + --prefill-decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT" \ + >"${PROXY_LOG}" 2>&1 & + +echo $! >> "$PID_FILE" + +wait_for_server $PROXY_PORT \ No newline at end of file diff --git a/draft/pid.txt b/draft/pid.txt new file mode 100644 index 000000000000..fbd4acc39f24 --- /dev/null +++ b/draft/pid.txt @@ -0,0 +1,3 @@ +24618 +24619 +26250 diff --git a/draft/proxy.py b/draft/proxy.py new file mode 100644 index 000000000000..486ff895f4e6 --- /dev/null +++ b/draft/proxy.py @@ -0,0 +1,257 @@ +# api_proxy.py +import asyncio +import json +import time +import uuid +from typing import AsyncIterator, Optional, Dict, Any +from fastapi import FastAPI, Request, HTTPException +import aiohttp +from fastapi.responses import StreamingResponse, JSONResponse +import uvicorn +import argparse +import logging +import random + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +app = FastAPI() + +encode_session: Optional[aiohttp.ClientSession] = None +decode_session: Optional[aiohttp.ClientSession] = None + +@app.on_event("startup") +async def startup_event(): + global encode_session, decode_session + encode_session = aiohttp.ClientSession( + connector=aiohttp.TCPConnector(limit=0), + timeout=aiohttp.ClientTimeout(total=100000)) + decode_session = aiohttp.ClientSession( + connector=aiohttp.TCPConnector(limit=0), + timeout=aiohttp.ClientTimeout(total=100000)) + +@app.on_event("shutdown") +async def shutdown_event(): + global encode_session, decode_session + if encode_session: + await encode_session.close() + if decode_session: + await decode_session.close() + + +def has_mm_input(request_data: dict): + if "messages" not in request_data: + return False + for message in request_data["messages"]: + if not isinstance(message.get("content"), list): + continue + for content_item in message["content"]: + if content_item.get("type") in ["image_url", "audio_url", "input_audio"]: + return True + return False + +async def forward_streaming_request( + request_data: dict, + request_id: str, + e_server_url: str, + pd_server_url: str, +) -> AsyncIterator[str]: + + + headers = {"x-request-id": request_id} + # Skip request to encoder instance if we don't have mm input + # if has_mm_input(request_data): + # task1 = asyncio.create_task( + # encode_session.post( + # f"{e_server_url}/v1/chat/completions", + # json=request_data, + # headers=headers + # ) + # ) + # try: + # response = await task1 + # if response.status != 200: + # error_text = await response.text() + # raise HTTPException( + # status_code=response.status, + # detail={"error": "Request failed", "message": error_text} + # ) + # except Exception as e: + # raise HTTPException( + # status_code=500, + # detail={"error": "Internal server error", "message": str(e)} + # ) + + # import time + # time.sleep(10) + try: + async with decode_session.post( + f"{pd_server_url}/v1/chat/completions", + json=request_data, + headers=headers + ) as response: + response.raise_for_status() + async for chunk in response.content.iter_chunked(128): + if chunk: + yield chunk.decode('utf-8', errors='ignore') + except Exception as e: + logger.error(f"Error in streaming: {e}") + raise + +async def forward_non_streaming_request( + request_data: dict, + request_id: str, + e_server_url: str, + pd_server_url: str, +) -> dict: + headers = {"x-request-id": request_id} + # Skip request to encoder instance if we don't have mm input + if has_mm_input(request_data): + # Start request to encode server + task1 = asyncio.create_task( + encode_session.post( + f"{e_server_url}/v1/chat/completions", + json=request_data, + headers=headers + ) + ) + + try: + response = await task1 + if response.status != 200: + error_text = await response.text() + raise HTTPException( + status_code=response.status, + detail={"error": "Request failed", "message": error_text} + ) + except Exception as e: + raise HTTPException( + status_code=500, + detail={"error": "Internal server error", "message": str(e)} + ) + + try: + # Make request to decode server + async with decode_session.post( + f"{pd_server_url}/v1/chat/completions", + json=request_data, + headers=headers + ) as response2: + response2.raise_for_status() + result = await response2.json() + return result + except Exception as e: + logger.error(f"Error in non-streaming: {e}") + raise + +@app.post("/v1/chat/completions") +async def chat_completions(request: Request): + """Handle chat completion requests.""" + try: + e_instance = random.randint(0, len(app.state.e_urls) - 1) + pd_instance = random.randint(0, len(app.state.pd_urls) - 1) + e_server_url = app.state.e_urls[e_instance] + pd_server_url = app.state.pd_urls[pd_instance] + + + request_data = await request.json() + request_id = request.headers.get("x-request-id") + if not request_id: + request_id = str(uuid.uuid4()) + is_streaming = request_data.get("stream", False) + if is_streaming: + return StreamingResponse( + forward_streaming_request( + request_data, request_id, e_server_url, pd_server_url), + media_type="text/event-stream" + ) + else: + result = await forward_non_streaming_request( + request_data, request_id, e_server_url, pd_server_url) + return JSONResponse(content=result) + except Exception as e: + logger.error(f"Error processing request: {e}") + raise HTTPException(status_code=500, detail=str(e)) + +@app.get("/v1/models") +async def list_models(): + try: + async with decode_session.get(f"{app.state.pd_urls[0]}/v1/models") as response: + response.raise_for_status() + return await response.json() + except Exception as e: + logger.error(f"Error fetching models: {e}") + raise HTTPException(status_code=500, detail=str(e)) + +@app.get("/health") +async def health_check(): + """Health check endpoint.""" + try: + async def check_encode(): + try: + for e_url in app.state.e_urls: + async with encode_session.get(f"{e_url}/health") as response: + response.raise_for_status() + return True + except Exception: + return False + + async def check_decode(): + try: + for pd_url in app.state.pd_urls: + async with encode_session.get(f"{pd_url}/health") as response: + response.raise_for_status() + return True + except Exception: + return False + + encode_healthy, decode_healthy = await asyncio.gather( + check_encode(), check_decode(), return_exceptions=True + ) + + health_status = { + "proxy": "healthy", + "encode_servers": "healthy" if encode_healthy is True else "unhealthy", + "prefill_decode_servers": "healthy" if decode_healthy is True else "unhealthy" + } + + if not (encode_healthy is True and decode_healthy is True): + return JSONResponse(content=health_status, status_code=503) + + return health_status + + except Exception as e: + logger.error(f"Health check error: {e}") + return JSONResponse( + content={"proxy": "unhealthy", "error": str(e)}, + status_code=503 + ) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="API Proxy for distributed vLLM servers") + parser.add_argument("--host", type=str, default="0.0.0.0", help="Proxy host") + parser.add_argument("--port", type=int, default=8000, help="Proxy port") + + parser.add_argument("--encode-servers-urls", type=str, required=True, + help="URLs of the encode server in comma separated format" + "(e.g., \"http://localhost:8001,http://localhost:8002\")") + + parser.add_argument("--prefill-decode-servers-urls", type=str, required=True, + help="URLs of the prefill/decode servers in comma separated format" + "(e.g., \"http://localhost:8003,http://localhost:8004\")") + + + args = parser.parse_args() + app.state.e_urls = args.encode_servers_urls.split(",") + app.state.pd_urls = args.prefill_decode_servers_urls.split(",") + + logger.info(f"Starting API proxy on {args.host}:{args.port} with 1 worker") + + uvicorn.run( + app, + host=args.host, + port=args.port, + log_level="info", + access_log=False, + loop="uvloop" + ) \ No newline at end of file diff --git a/draft/send_request.py b/draft/send_request.py new file mode 100644 index 000000000000..8ceabcf52ac5 --- /dev/null +++ b/draft/send_request.py @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +import asyncio +import base64 +import time +import uuid +from openai import AsyncOpenAI + + +async def async_query_openai(query, model_path, port): + aclient = AsyncOpenAI( + base_url=f"http://localhost:{str(port)}/v1", + api_key="EMPTY", + timeout = 100000, + ) + completion = await aclient.chat.completions.create( + model=model_path, + messages=[ + {"role": "system", "content": "You are a helpful assistant."}, + { + "role": "user", + "content": query, + }, + ], + temperature=0.0, + top_p=0.1, + max_tokens=512, + ) + return completion.choices[0].message.content + + +async def async_process_queries(queries, model_path, port): + results = await asyncio.gather( + *(async_query_openai(query, model_path, port) for query in queries) + ) + return results + + +async def main(args): + # single query + image_path = args.image_path + with open(image_path, "rb") as f: + encoded_image = base64.b64encode(f.read()) + encoded_image_text = encoded_image.decode("utf-8") + image_base64 = f"data:image;base64,{encoded_image_text}" + query = [ + { + "type": "image_url", + "image_url": {"url": image_base64}, + }, + {"type": "text", "text": "What is shown in the image.?"}, + ] + bs = args.batch_size + queries = [query for i in range(bs)] + + start_time = time.time() + results = await async_process_queries( + queries, + args.model_path, + args.port + ) + end_time = time.time() + for result in results: + print(result) + print("-" * 50) + print(f"Total time: {end_time - start_time:.2f} seconds") + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="test") + parser.add_argument( + "--model_path", type=str, default=None + ) + parser.add_argument("--image_path", type=str, default="./demo.jpeg") + parser.add_argument("--batch_size", type=int, default=1) + parser.add_argument("--port", type=int, default=10001) + args, _ = parser.parse_known_args() + + asyncio.run(main(args)) \ No newline at end of file diff --git a/draft/stop.sh b/draft/stop.sh new file mode 100644 index 000000000000..839b21ab09ed --- /dev/null +++ b/draft/stop.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# +# Reads pid.txt created by run_servers.sh and kills every process. +# + +set -euo pipefail + +PID_FILE="./pid.txt" +[[ -f "$PID_FILE" ]] || { + echo "No $PID_FILE found – nothing to stop." + exit 0 +} + +echo "Stopping processes listed in $PID_FILE …" + +while read -r pid; do + [[ -z "$pid" ]] && continue # skip blank lines + if kill -0 "$pid" 2>/dev/null; then + echo " → SIGTERM $pid" + kill "$pid" + # wait up to 5 s, escalate to SIGKILL if still alive + for _ in {1..5}; do + kill -0 "$pid" 2>/dev/null || break + sleep 1 + done + if kill -0 "$pid" 2>/dev/null; then + echo " → SIGKILL $pid" + kill -9 "$pid" || true + fi + else + echo " → PID $pid is already gone" + fi +done < "$PID_FILE" + +rm -f "$PID_FILE" +echo "Done." \ No newline at end of file diff --git a/vllm/config/__init__.py b/vllm/config/__init__.py index cfc5e07d8329..21bfde0062a7 100644 --- a/vllm/config/__init__.py +++ b/vllm/config/__init__.py @@ -3196,6 +3196,103 @@ def _parse_collect_detailed_traces(self): list[DetailedTraceModules], self.collect_detailed_traces[0].split(",")) +ECProducer = Literal["ec_producer"] +ECConsumer = Literal["ec_consumer"] +ECRole = Literal[ECProducer, ECConsumer] +@config +@dataclass +class ECTransferConfig: + """Configuration for distributed EC cache transfer.""" + + ec_connector: Optional[str] = None + """The KV connector for vLLM to transmit KV caches between vLLM instances. + """ + + engine_id: Optional[str] = None + """The engine id for KV transfers.""" + + ec_buffer_device: Optional[str] = "cuda" + """The device used by ec connector to buffer the EC cache. + Currently only support 'cuda'.""" + + ec_buffer_size: float = 1e9 + """The buffer size for TorchDistributedConnector. Measured in number of + bytes. Recommended value: 1e9 (about 1GB).""" + + ec_role: Optional[ECRole] = None + """Whether this vLLM instance produces, consumes KV cache, or both. Choices + are 'ec_producer', 'ec_consumer'.""" + + ec_rank: Optional[int] = None + """The rank of this vLLM instance in the KV cache transfer. Typical value: + 0 for encoder, 1 for pd instance. + Currently only 1P1D is supported.""" + + ec_parallel_size: int = 1 + """The number of parallel instances for KV cache transfer. For + PyNcclConnector, this should be 2.""" + + ec_ip: str = "127.0.0.1" + """The KV connector ip, used to build distributed connection.""" + + ec_port: int = 14579 + """The KV connector port, used to build distributed connection.""" + + ec_connector_extra_config: dict[str, Any] = field(default_factory=dict) + """any extra config that the connector may need.""" + + ec_connector_module_path: Optional[str] = None + """The Python module path to dynamically load the KV connector from. + Only supported in V1.""" + + def compute_hash(self) -> str: + """ + WARNING: Whenever a new field is added to this config, + ensure that it is included in the factors list if + it affects the computation graph. + + Provide a hash that uniquely identifies all the configs + that affect the structure of the computation + graph from input ids/embeddings to the final hidden states, + excluding anything before input ids/embeddings and after + the final hidden states. + """ + # no factors to consider. + # this config will not affect the computation graph. + factors: list[Any] = [] + hash_str = hashlib.md5(str(factors).encode(), + usedforsecurity=False).hexdigest() + return hash_str + + def __post_init__(self) -> None: + if self.engine_id is None: + self.engine_id = str(uuid.uuid4()) + + if self.ec_role is not None and self.ec_role not in get_args(ECRole): + raise ValueError(f"Unsupported ec_role: {self.ec_role}. " + f"Supported roles are {get_args(ECRole)}") + + if self.ec_connector is not None and self.ec_role is None: + raise ValueError("Please specify ec_disagg_role when ec_connector " + f"is set, supported roles are {get_args(ECRole)}") + + @property + def is_ec_transfer_instance(self) -> bool: + return self.ec_connector is not None and \ + self.ec_role in get_args(ECRole) + + @property + def is_ec_producer(self) -> bool: + return self.ec_connector is not None and \ + self.ec_role in get_args(ECProducer) + + @property + def is_kv_consumer(self) -> bool: + return self.ec_connector is not None and \ + self.ec_role in get_args(ECConsumer) + + def get_from_extra_config(self, key, default) -> Any: + return self.ec_connector_extra_config.get(key, default) KVProducer = Literal["kv_producer", "kv_both"] KVConsumer = Literal["kv_consumer", "kv_both"] @@ -3391,6 +3488,9 @@ class VllmConfig: """The configurations for distributed KV cache transfer.""" kv_events_config: Optional[KVEventsConfig] = None """The configurations for event publishing.""" + + ec_transfer_config: Optional[ECTransferConfig] = None + # some opaque config, only used to provide additional information # for the hash computation, mainly used for testing, debugging or out of # tree config registration. @@ -3475,6 +3575,10 @@ def compute_hash(self) -> str: vllm_factors.append(self.kv_transfer_config.compute_hash()) else: vllm_factors.append("None") + if self.ec_transfer_config: + vllm_factors.append(self.ec_transfer_config.compute_hash()) + else: + vllm_factors.append("None") if self.additional_config: if isinstance(additional_config := self.additional_config, dict): additional_config_hash = hashlib.md5( diff --git a/vllm/distributed/ec_transfer/__init__.py b/vllm/distributed/ec_transfer/__init__.py new file mode 100644 index 000000000000..8320564818e3 --- /dev/null +++ b/vllm/distributed/ec_transfer/__init__.py @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project + +from vllm.distributed.ec_transfer.ec_transfer_state import ( + get_ec_transfer, + ensure_ec_transfer_initialized, + has_ec_transfer) + +__all__ = [ + "get_ec_transfer", + "ensure_ec_transfer_initialized", + "has_ec_transfer", +] diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py new file mode 100644 index 000000000000..a141253130f7 --- /dev/null +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -0,0 +1,233 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +""" +ECConnectorBase Class for Distributed Encoder Cache & P2P Encoder cache communication in V1 + +The class provides the following primitives: + Scheduler-side: runs in the scheduler, binds metadata, which + is used by the worker-side to load/save Encoder cache. + check_caches_exist() - Check whether Encoder cache of requests exist + update_state_after_alloc() - update ECConnector state after + allocate. This will decide to load the cache or not + request_finished() - called when a request is finished, free the cache with + the requests + + Worker-side: runs in each worker, loads/saves Encoder Cache to/from + the Connector based on the metadata. + start_load_ec() - starts loading all ECs (maybe async) + wait_for_save() - blocks until all saves are done + + get_finished() - called with ids of finished requests, returns + ids of requests that have completed async sending/recving. +""" + +import enum +from abc import ABC, abstractmethod +from collections.abc import Iterable +from typing import TYPE_CHECKING, Any, Callable, Literal, Optional + +import torch + +from vllm.logger import init_logger +from vllm.v1.core.sched.output import SchedulerOutput +from vllm.v1.outputs import KVConnectorOutput + +if TYPE_CHECKING: + from vllm.attention.backends.abstract import AttentionMetadata + from vllm.config import VllmConfig + from vllm.distributed.kv_events import KVCacheEvent + from vllm.forward_context import ForwardContext + from vllm.v1.core.kv_cache_manager import KVCacheBlocks + from vllm.v1.request import Request + +logger = init_logger(__name__) + + +class ECConnectorRole(enum.Enum): + # Connector running in the scheduler process + SCHEDULER = 0 + + # Connector running in the worker process + WORKER = 1 + + +class ECConnectorMetadata(ABC): # noqa: B024 + """ + Abstract Metadata used to communicate between the + Scheduler ECConnector and Worker ECConnector. + """ + pass + + +class ECConnectorBase(ABC): + + def __init__(self, vllm_config: "VllmConfig", role: ECConnectorRole): + self._connector_metadata: Optional[ECConnectorMetadata] = None + self._vllm_config = vllm_config + self._role = role + + @property + def role(self) -> ECConnectorRole: + return self._role + + # ============================== + # Worker-side methods + # ============================== + + def bind_connector_metadata( + self, connector_metadata: ECConnectorMetadata) -> None: + """Set the connector metadata from the scheduler. + + This function should be called by the model runner every time + before the model execution. The metadata will be used for runtime + KV cache loading and saving. + + Args: + connector_metadata (dict): the connector metadata. + """ + self._connector_metadata = connector_metadata + + def clear_connector_metadata(self) -> None: + """Clear the connector metadata. + + This function should be called by the model runner every time + after the model execution. + """ + self._connector_metadata = None + + def _get_connector_metadata(self) -> ECConnectorMetadata: + """Get the connector metadata. + + This function should only be called inside the connector. + + Returns: + ConnectorMetadata: the connector metadata. + """ + + # Should only be called while set to valid metadata. + assert self._connector_metadata is not None + return self._connector_metadata + + def register_caches(self, caches: dict[str, torch.Tensor],): + """ + Initialize with the EC caches. + Args: + ec_caches: dictionary of encoder cache + """ + return + + @abstractmethod + def start_load_caches(self, **kwargs) -> None: + """ + Start loading the cache from the connector to vLLM's encoder cache. + This is called before _gather_mm_embeddings for EC Connector + and before execute_model for KV Connector + forward_context does not need for EC Connector + + Args: + **kwargs: additional arguments for the load operation + + """ + pass + + @abstractmethod + def save_caches(self, **kwargs) -> None: + """ + Save caches into connector + """ + pass + + @abstractmethod + def wait_for_save(self): + """ + Block until all the save operations is done. + """ + pass + + def get_finished( + self, finished_req_ids: set[str] + ) -> tuple[Optional[set[str]], Optional[set[str]]]: + """ + Notifies worker-side connector ids of requests that have + finished generating tokens on the worker. + The scheduler process (via the Executors) will use this output + to track which workers are done. + + Returns: + ids of requests that have finished asynchronous transfer + (requests that previously returned True from request_finished()), + tuple of (sending/saving ids, recving/loading ids). + The finished saves/sends req ids must belong to a set provided in a + call to this method (this call or a prior one). + """ + return None, None + + # ============================== + # Scheduler-side methods + # ============================== + + @abstractmethod + def check_caches_exist( + self, + request: "Request", + ) -> list[bool]: + """ + Check if encoder cache exit for each mm data of requests + + Args: + request (Request): the request object. + + Returns: + A list bool where ith value is True if cache exist for + ith mm_data of requests + """ + pass + + @abstractmethod + def update_state_after_alloc(self, request: "Request"): + """ + Update ECConnector state to decide allocate cache for requests + + Args: + request (Request): the request object. + """ + pass + + @abstractmethod + def build_connector_meta( + self, scheduler_output: SchedulerOutput) -> ECConnectorMetadata: + """ + Build the connector metadata for this step. + + This function should NOT modify fields in the scheduler_output. + Also, calling this function will reset the state of the connector. + + Args: + scheduler_output (SchedulerOutput): the scheduler output object. + """ + pass + + def update_connector_output(self, connector_output: KVConnectorOutput): + """ + Update KVConnector state from worker-side connectors output. + + Args: + connector_output (KVConnectorOutput): the worker-side + connectors output. + """ + return + + def request_finished( + self, + request: "Request" + ) -> tuple[bool, Optional[dict[str, Any]]]: + """ + Called when a request has finished, before its freed the local encoder cached. + + Returns: + True if the request is being saved/sent asynchronously and cached + should not be freed until the request_id is returned from + get_finished(). + """ + return False, None + diff --git a/vllm/distributed/ec_transfer/ec_connector/factory.py b/vllm/distributed/ec_transfer/ec_connector/factory.py new file mode 100644 index 000000000000..22a83785fb86 --- /dev/null +++ b/vllm/distributed/ec_transfer/ec_connector/factory.py @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project + +import importlib +from typing import TYPE_CHECKING, Callable + +# yapf: disable +import vllm.envs as envs +from vllm.distributed.ec_transfer.ec_connector.base import (ECConnectorRole,ECConnectorBase) +from vllm.logger import init_logger + +# yapf: enable + +if TYPE_CHECKING: + from vllm.config import ECTransferConfig, VllmConfig + +logger = init_logger(__name__) + + +class ECConnectorFactory: + _registry: dict[str, Callable[[], type[ECConnectorBase]]] = {} + + @classmethod + def register_connector(cls, name: str, module_path: str, + class_name: str) -> None: + """Register a connector with a lazy-loading module and class name.""" + if name in cls._registry: + raise ValueError(f"Connector '{name}' is already registered.") + + def loader() -> type[ECConnectorBase]: + module = importlib.import_module(module_path) + return getattr(module, class_name) + + cls._registry[name] = loader + + @classmethod + def create_connector( + cls, + config: "VllmConfig", + role: ECConnectorRole, + ) -> ECConnectorBase: + if not envs.VLLM_USE_V1: + raise ValueError("Attempting to initialize a V1 Connector, " + f"but found {envs.VLLM_USE_V1=}") + + ec_transfer_config = config.ec_transfer_config + connector_cls = cls.get_connector_class(ec_transfer_config) + logger.info("Creating v1 connector with name: %s and engine_id: %s", + connector_cls.__name__, ec_transfer_config.engine_id) + # NOTE(Kuntai): v1 connector is explicitly separated into two roles. + # Scheduler connector: + # - Co-locate with scheduler process + # - Should only be used inside the Scheduler class + # Worker connector: + # - Co-locate with worker process + # - Should only be used inside the forward context & attention layer + # We build separately to enforce strict separation + return connector_cls(config, role) + + @classmethod + def get_connector_class( + cls, ec_transfer_config: "ECTransferConfig" + ) -> type[ECConnectorBase]: + """Get the connector class by name.""" + connector_name = ec_transfer_config.ec_connector + if connector_name in cls._registry: + connector_cls = cls._registry[connector_name]() + else: + connector_module_path = ec_transfer_config.ec_connector_module_path + if connector_module_path is None: + raise ValueError( + f"Unsupported connector type: {connector_name}") + connector_module = importlib.import_module(connector_module_path) + connector_cls = getattr(connector_module, connector_name) + return connector_cls + + +# Register various connectors here. +# The registration should not be done in each individual file, as we want to +# only load the files corresponding to the current connector. + +ECConnectorFactory.register_connector( + "ECSharedStorageConnector", + "vllm.distributed.ec_transfer.ec_connector.shared_storage_connector", + "ECSharedStorageConnector") + diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py new file mode 100644 index 000000000000..be259ffddfc2 --- /dev/null +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -0,0 +1,225 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +import hashlib +import os +from dataclasses import dataclass +from typing import TYPE_CHECKING + +import safetensors +import torch + +from vllm.config import VllmConfig +from vllm.distributed.ec_transfer.ec_connector.base import ( + ECConnectorBase, ECConnectorMetadata, ECConnectorRole) +from vllm.logger import init_logger +from vllm.v1.core.sched.output import SchedulerOutput + +if TYPE_CHECKING: + from vllm.forward_context import ForwardContext + from vllm.v1.request import Request + +logger = init_logger(__name__) + + +@dataclass +class MMMeta: + mm_hash: str + num_token: int + + @staticmethod + def make_meta(mm_hash, num_token) -> "MMMeta": + return MMMeta( + mm_hash=mm_hash, + num_token=num_token + ) + + + +@dataclass +class ECSharedStorageConnectorMetadata(ECConnectorMetadata): + mm_datas: list[MMMeta] + + def __init__(self): + self.mm_datas = [] + + def add_mm_data(self, mm_data:MMMeta): + self.mm_datas.append(mm_data) + + # def add_mm_data( + # self, + # mm_hash, + # num_token, + # ) -> None: + # self.mm_datas.append( + # MMMeta.make_meta(mm_hash, num_token)) + + +class ECSharedStorageConnector(ECConnectorBase): + # NOTE: This is Simple debug implementation of the KV connector. + # It save / load the KV cache to / from the disk. + # It does extra work which will overwrite the existing prefix-cache in GPU + # - to remove the overhead, need to add some "mask" in the ReqMeta class + + def __init__(self, vllm_config: "VllmConfig", role: ECConnectorBase): + super().__init__(vllm_config=vllm_config, role=role) + # req_id -> index -> mm_hash + self._mm_datas_need_loads: dict[str, dict[int, MMMeta]] = {} + # transfer_config = vllm_config.kv_transfer_config + # self._storage_path = transfer_config.get_from_extra_config( + # "shared_storage_path", "/tmp") + self.is_producer = (vllm_config.ec_transfer_config.ec_role == 'ec_producer') + logger.info(f"Init a ec share storage connector with role {role}") + self._storage_path = "/home/n00909098/EPD/refactor/vllm/draft/cache_save" + logger.info(vllm_config.ec_transfer_config) + logger.info("Shared storage path is %s", self._storage_path) + + def start_load_caches(self, **kwargs) -> None: + """Start loading the EC cache from the connector buffer to worker + encoder_cache + + Args: + **kwargs: additional arguments for the load operation + """ + + # Get the metadata + logger.info("Start load caches") + metadata: ECConnectorMetadata = self._get_connector_metadata() + assert isinstance(metadata, ECSharedStorageConnectorMetadata) + encoder_cache = kwargs.get("encoder_cache") # returns None if missing + assert encoder_cache is not None + if metadata is None: + logger.warning( + "In connector.start_load_kv, but the connector metadata is None" + ) + return + logger.info(f"At load cache meta data is {metadata}") + # Load the KV for each request each layer + for mm_data in metadata.mm_datas: + # TODO: Only load it once + # if mm_data in self._mm_datas_need_loads: + # continue + filename = self._generate_filename_debug(mm_data.mm_hash) + ec_cache = safetensors.torch.load_file(filename)["ec_cache"].cuda() + encoder_cache[mm_data.mm_hash] = ec_cache + logger.info(f"Success load hash for {mm_data.mm_hash}") + + def save_caches(self, **kwargs) -> None: + """Start saving the KV cache of the layer from encoder cache + + Args: + **kwargs: additional arguments for the save operation. + """ + if not self.is_producer: + return + encoder_cache = kwargs.get("encoder_cache") # returns None if missing + mm_hash = kwargs.get("mm_hash") + assert encoder_cache is not None + assert mm_hash is not None + logger.info(f"At save caches the mm hash is {mm_hash}") + filename = self._generate_filename_debug(mm_hash) + ec_cache = encoder_cache[mm_hash] + tensors = {"ec_cache": ec_cache.detach().cpu()} + safetensors.torch.save_file(tensors, filename) + + def wait_for_save(self): + return + + def check_caches_exist( + self, + request: "Request", + ) -> list[bool]: + """ + Check if cache exist externally for each mm_data of request + + Args: + request (Request): the request object. + + Returns: + List of bool indicate that ith mm_data exist in cache or not + """ + result = [] + for mm_hash in request.mm_hashes: + result.append(self._found_match_for_mm_data(mm_hash)) + return result + + def update_state_after_alloc(self, + request: "Request", + cache_exists: list[bool], + ) -> None: + """ + Update ECConnector state after block allocation. + + If cache exist for mm_data, need to load it + """ + # Create the per-request mapping only if it does not exist. + loads_for_request = self._mm_datas_need_loads.setdefault( + request.request_id, {} + ) + + for index, has_cache in enumerate(cache_exists): + if has_cache: + mm_hash = request.mm_hashes[index] + num_encoder_token = request.get_num_encoder_tokens(index) + # Insert mm_hash only if this block has not been recorded yet. + loads_for_request.setdefault(index, MMMeta.make_meta(mm_hash,num_encoder_token)) + logger.info(f"After update the _mm_datas_need_loads is {self._mm_datas_need_loads}") + def build_connector_meta( + self, + scheduler_output: SchedulerOutput, + ) -> ECConnectorMetadata: + """Build the connector metadata for this step. + + This function should NOT modify any fields in the scheduler_output. + Also, calling this function will reset the state of the connector. + + Args: + scheduler_output (SchedulerOutput): the scheduler output object. + """ + meta = ECSharedStorageConnectorMetadata() + scheduled_encoder_inputs = scheduler_output.scheduled_encoder_inputs + for req_id, encoder_input_ids in scheduled_encoder_inputs.items(): + for mm_input_id in encoder_input_ids: + if req_id in self._mm_datas_need_loads and mm_input_id in self._mm_datas_need_loads[req_id]: + mm_data = self._mm_datas_need_loads[req_id][mm_input_id] + meta.add_mm_data(mm_data) + self._mm_datas_need_loads.clear() + return meta + + # ============================== + # Helper functions + # ============================== + + def _found_match_for_mm_data( + self, + mm_hash + ) -> bool: + """Check if the cache is hit for the request. + """ + foldername = self._generate_foldername_debug(mm_hash,create_folder=False) + return os.path.exists(foldername) + + def _generate_foldername_debug( + self, + mm_hash: str, + create_folder: bool = True, # <- now defaults to True + ) -> str: + """ + Return the folder in which the cache for this mm_hash lives. + If `create_folder` is True (default) the directory is created + recursively the first time it is needed. + """ + foldername = os.path.join(self._storage_path, mm_hash) + if create_folder: + os.makedirs(foldername, exist_ok=True) + return foldername + + def _generate_filename_debug(self, mm_hash: str) -> str: + """ + Return the full path of the safetensors file for this mm_hash. + Ensures the parent directory exists because + `_generate_foldername_debug` is called with its default + (`create_folder=True`). + """ + foldername = self._generate_foldername_debug(mm_hash) # <- folder auto-created + return os.path.join(foldername, "encoder_cache.safetensors") + diff --git a/vllm/distributed/ec_transfer/ec_connector/utils.py b/vllm/distributed/ec_transfer/ec_connector/utils.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/vllm/distributed/ec_transfer/ec_transfer_state.py b/vllm/distributed/ec_transfer/ec_transfer_state.py new file mode 100644 index 000000000000..36e5f81f92e7 --- /dev/null +++ b/vllm/distributed/ec_transfer/ec_transfer_state.py @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +from typing import TYPE_CHECKING, Optional + +from vllm import envs +from vllm.distributed.ec_transfer.ec_connector.base import (ECConnectorBase, + ECConnectorRole) +from vllm.distributed.ec_transfer.ec_connector.factory import ( + ECConnectorFactory) + +if TYPE_CHECKING: + from vllm.config import VllmConfig + +_EC_CONNECTOR_AGENT: Optional[ECConnectorBase] = None + + +def get_ec_transfer() -> ECConnectorBase: + assert _EC_CONNECTOR_AGENT is not None, ( + "disaggregated EC cache is not initialized") + return _EC_CONNECTOR_AGENT + + +def has_ec_transfer() -> bool: + return _EC_CONNECTOR_AGENT is not None + +def ensure_ec_transfer_initialized(vllm_config: "VllmConfig") -> None: + """ + Initialize KV cache transfer parallel group. + """ + + global _EC_CONNECTOR_AGENT + + if vllm_config.ec_transfer_config is None: + return + + if (vllm_config.ec_transfer_config.is_ec_transfer_instance + and _EC_CONNECTOR_AGENT is None): + if envs.VLLM_USE_V1: + _EC_CONNECTOR_AGENT = ECConnectorFactory.create_connector( + config=vllm_config, role=ECConnectorRole.WORKER) + else: + raise ValueError("V0 is no longer supported") diff --git a/vllm/engine/arg_utils.py b/vllm/engine/arg_utils.py index 7802802f138b..aab1b65b2b7a 100644 --- a/vllm/engine/arg_utils.py +++ b/vllm/engine/arg_utils.py @@ -24,7 +24,7 @@ from vllm.config import (BlockSize, CacheConfig, CacheDType, CompilationConfig, ConfigFormat, ConfigType, ConvertOption, DecodingConfig, DetailedTraceModules, Device, - DeviceConfig, DistributedExecutorBackend, EPLBConfig, + DeviceConfig, DistributedExecutorBackend, ECTransferConfig, EPLBConfig, GuidedDecodingBackend, HfOverrides, KVEventsConfig, KVTransferConfig, LoadConfig, LogprobsMode, LoRAConfig, MambaDType, MMEncoderTPMode, ModelConfig, @@ -428,6 +428,8 @@ class EngineArgs: kv_transfer_config: Optional[KVTransferConfig] = None kv_events_config: Optional[KVEventsConfig] = None + ec_transfer_config: Optional[ECTransferConfig] = None + generation_config: str = ModelConfig.generation_config enable_sleep_mode: bool = ModelConfig.enable_sleep_mode override_generation_config: dict[str, Any] = \ @@ -886,9 +888,11 @@ def add_cli_args(parser: FlexibleArgumentParser) -> FlexibleArgumentParser: vllm_group.add_argument("--speculative-config", **vllm_kwargs["speculative_config"]) vllm_group.add_argument("--kv-transfer-config", - **vllm_kwargs["kv_transfer_config"]) + **vllm_kwargs["kv_transfer_config"]) vllm_group.add_argument('--kv-events-config', **vllm_kwargs["kv_events_config"]) + vllm_group.add_argument("--ec-transfer-config", + **vllm_kwargs["ec_transfer_config"]) vllm_group.add_argument("--compilation-config", "-O", **vllm_kwargs["compilation_config"]) vllm_group.add_argument("--additional-config", @@ -1378,7 +1382,7 @@ def create_engine_config( otlp_traces_endpoint=self.otlp_traces_endpoint, collect_detailed_traces=self.collect_detailed_traces, ) - + logger.info(f"At engine args the ec transfer config is {self.ec_transfer_config}") config = VllmConfig( model_config=model_config, cache_config=cache_config, @@ -1393,6 +1397,7 @@ def create_engine_config( compilation_config=self.compilation_config, kv_transfer_config=self.kv_transfer_config, kv_events_config=self.kv_events_config, + ec_transfer_config=self.ec_transfer_config, additional_config=self.additional_config, ) diff --git a/vllm/entrypoints/openai/api_server.py b/vllm/entrypoints/openai/api_server.py index a28d38729f9f..6f47819a3754 100644 --- a/vllm/entrypoints/openai/api_server.py +++ b/vllm/entrypoints/openai/api_server.py @@ -720,6 +720,7 @@ async def create_completion(request: CompletionRequest, raw_request: Request): message="The model does not support Completions API") try: + logger.info(f"Handler is {handler}") generator = await handler.create_completion(request, raw_request) except OverflowError as e: raise HTTPException(status_code=HTTPStatus.BAD_REQUEST.value, diff --git a/vllm/v1/core/sched/output.py b/vllm/v1/core/sched/output.py index b5cd6c5c8af5..5894dcd36f25 100644 --- a/vllm/v1/core/sched/output.py +++ b/vllm/v1/core/sched/output.py @@ -6,12 +6,16 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Optional + + if TYPE_CHECKING: import numpy as np import numpy.typing as npt from vllm.distributed.kv_transfer.kv_connector.v1.base import ( KVConnectorMetadata) + from vllm.distributed.ec_transfer.ec_connector.base import ( + ECConnectorMetadata) from vllm.lora.request import LoRARequest from vllm.multimodal.inputs import MultiModalKwargsItem, PlaceholderRange from vllm.pooling_params import PoolingParams @@ -155,3 +159,6 @@ class SchedulerOutput: # KV Cache Connector metadata. kv_connector_metadata: Optional[KVConnectorMetadata] = None + + # EC Cache Connector metadata + ec_connector_metadata: Optional[ECConnectorMetadata] = None diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index 3bd2fe2f0515..fb4c63302d01 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -10,6 +10,8 @@ from typing import Any, Optional, Union from vllm.config import VllmConfig +from vllm.distributed.ec_transfer.ec_connector.base import ECConnectorRole +from vllm.distributed.ec_transfer.ec_connector.factory import ECConnectorFactory from vllm.distributed.kv_events import EventPublisherFactory, KVEventBatch from vllm.distributed.kv_transfer.kv_connector.factory import ( KVConnectorFactory) @@ -94,6 +96,14 @@ def __init__( self.kv_events_config, self.parallel_config.data_parallel_rank, ) + self.is_encoder_instance = False + self.ec_connector = None + if self.vllm_config.ec_transfer_config is not None: + self.ec_connector = ECConnectorFactory.create_connector( + config=self.vllm_config, role=ECConnectorRole.SCHEDULER + ) + self.is_encoder_instance = (self.vllm_config.ec_transfer_config.ec_role=="ec_producer") + num_gpu_blocks = self.cache_config.num_gpu_blocks assert num_gpu_blocks is not None and num_gpu_blocks > 0 @@ -175,6 +185,8 @@ def schedule(self) -> SchedulerOutput: # num_tokens_with_spec. This is general enough to cover # chunked prefills, prefix caching, speculative decoding, # and the "jump decoding" optimization in the future. + if self.is_encoder_instance: + return self.scheduler_encoder_only() scheduled_new_reqs: list[Request] = [] scheduled_resumed_reqs: list[Request] = [] @@ -588,15 +600,123 @@ def schedule(self) -> SchedulerOutput: if self.connector is not None: meta = self.connector.build_connector_meta(scheduler_output) scheduler_output.kv_connector_metadata = meta - + events = self.kv_cache_manager.take_events() if events: batch = KVEventBatch(ts=time.time(), events=events) self.kv_event_publisher.publish(batch) + if self.ec_connector is not None: + meta = self.ec_connector.build_connector_meta(scheduler_output) + scheduler_output.ec_connector_metadata = meta + self._update_after_schedule(scheduler_output) return scheduler_output + def _try_schedule_encoder_inputs_only(self, request, encoder_compute_budget): + encoder_inputs_to_schedule: list[int] = [] + mm_positions = request.mm_positions + assert mm_positions is not None + assert len(mm_positions) > 0 + + # NOTE: since scheduler operates on the request level (possibly with + # multiple encoder inputs per request), we need to create temporary + # trackers for accounting at the encoder input level. + success = True + mm_hashes_to_schedule = set() + num_tokens_to_schedule = 0 + for i, pos_info in enumerate(mm_positions): + num_encoder_tokens = pos_info.length + if request.mm_hashes[i] in mm_hashes_to_schedule: + continue + + if self.encoder_cache_manager.check_and_update_cache(request, i): + # The encoder input is already computed and cached from a + # previous step. + continue + + if not self.encoder_cache_manager.can_allocate( + request, i, encoder_compute_budget, + num_tokens_to_schedule): + success = False + break + + num_tokens_to_schedule += num_encoder_tokens + encoder_compute_budget -= num_encoder_tokens + mm_hashes_to_schedule.add(request.mm_hashes[i]) + encoder_inputs_to_schedule.append(i) + + if not success: + encoder_compute_budget += num_tokens_to_schedule + return ( + encoder_inputs_to_schedule, + success, + encoder_compute_budget, + ) + def scheduler_encoder_only(self): + scheduled_encoder_inputs: dict[str, list[int]] = {} + scheduled_new_reqs: list[Request] = [] + encoder_compute_budget = self.max_num_encoder_input_tokens + + while self.waiting: + request = self.waiting.peek_request() + encoder_inputs_to_schedule = None + new_encoder_compute_budget = encoder_compute_budget + + if not request.has_encoder_inputs: + self.waiting.pop_request() + continue + (encoder_inputs_to_schedule, success, + new_encoder_compute_budget + ) = self._try_schedule_encoder_inputs_only( + request, encoder_compute_budget) + + if not success: + break + # Request was already popped from self.waiting + # unless it was re-added above due to new_blocks being None. + request = self.waiting.pop_request() + self.running.append(request) + if request.status == RequestStatus.WAITING: + scheduled_new_reqs.append(request) + + request.status = RequestStatus.RUNNING + scheduled_encoder_inputs[request.request_id] = ( + encoder_inputs_to_schedule) + # Allocate the encoder cache. + for i in encoder_inputs_to_schedule: + self.encoder_cache_manager.allocate(request, i) + encoder_compute_budget = new_encoder_compute_budget + + new_reqs_data = [ + NewRequestData.from_request(req, ([],)) + for req in scheduled_new_reqs + ] + + scheduler_output = SchedulerOutput( + scheduled_new_reqs=new_reqs_data, + scheduled_cached_reqs=CachedRequestData.make_empty(), + num_scheduled_tokens={}, + total_num_scheduled_tokens=0, + scheduled_spec_decode_tokens={}, + scheduled_encoder_inputs=scheduled_encoder_inputs, + num_common_prefix_blocks=[], + # finished_req_ids is an existing state in the scheduler, + # instead of being newly scheduled in this step. + # It contains the request IDs that are finished in between + # the previous and the current steps. + finished_req_ids=self.finished_req_ids, + free_encoder_mm_hashes=self.encoder_cache_manager. + get_freed_mm_hashes(), + structured_output_request_ids=None, + grammar_bitmask=None, + ) + if self.ec_connector is not None: + meta = self.ec_connector.build_connector_meta(scheduler_output) + scheduler_output.ec_connector_metadata = meta + self.finished_req_ids = set() + return scheduler_output + def _update_after_schedule( self, scheduler_output: SchedulerOutput, @@ -710,6 +830,10 @@ def _try_schedule_encoder_inputs( assert mm_positions is not None assert len(mm_positions) > 0 + # Check remote cache first + if self.ec_connector is not None: + remote_cache_bools = self.ec_connector.check_caches_exist(request) + load_cache_bools = [0] * len(remote_cache_bools) # NOTE: since scheduler operates on the request level (possibly with # multiple encoder inputs per request), we need to create temporary # trackers for accounting at the encoder input level. @@ -750,6 +874,13 @@ def _try_schedule_encoder_inputs( if request.mm_hashes[i] in mm_hashes_to_schedule: continue + if self.ec_connector is not None: + if remote_cache_bools[i]: + mm_hashes_to_schedule.add(request.mm_hashes[i]) + encoder_inputs_to_schedule.append(i) + num_tokens_to_schedule += num_encoder_tokens + continue + if self.encoder_cache_manager.check_and_update_cache(request, i): # The encoder input is already computed and cached from a # previous step. @@ -788,6 +919,8 @@ def _try_schedule_encoder_inputs( encoder_compute_budget -= num_encoder_tokens mm_hashes_to_schedule.add(request.mm_hashes[i]) encoder_inputs_to_schedule.append(i) + if self.ec_connector: + self.ec_connector.update_state_after_alloc(request, remote_cache_bools) return ( encoder_inputs_to_schedule, @@ -825,11 +958,52 @@ def get_grammar_bitmask( ) return structured_output_request_ids, bitmask + def update_from_output_encoder_only( + self, + scheduler_output: SchedulerOutput, + model_runner_output: ModelRunnerOutput, + ) -> dict[int, EngineCoreOutputs]: + + outputs: dict[int, list[EngineCoreOutput]] = defaultdict(list) + + # stop all requests from the current batch + model_finished = [] + for request in self.running: + req_id = request.request_id + model_finished.append(req_id) + outputs[request.client_index].append( + EngineCoreOutput(request_id=req_id, + new_token_ids=[], + finish_reason=RequestStatus.get_finished_reason( + RequestStatus.FINISHED_STOPPED + ), + stop_reason="stop", + kv_transfer_params={} + ) + ) + self.finish_requests(model_finished, RequestStatus.FINISHED_STOPPED) + # Create EngineCoreOutputs for all clients that have requests with + # outputs in this step. + engine_core_outputs = { + client_index: EngineCoreOutputs(outputs=outs) + for client_index, outs in outputs.items() + } + + if engine_core_outputs: + # Return stats to only one of the front-ends. + next(iter(engine_core_outputs.values())).scheduler_stats = ( + self.make_stats(None)) + + return engine_core_outputs + def update_from_output( self, scheduler_output: SchedulerOutput, model_runner_output: ModelRunnerOutput, ) -> dict[int, EngineCoreOutputs]: + + if self.is_encoder_instance: + return self.update_from_output_encoder_only(scheduler_output, model_runner_output) sampled_token_ids = model_runner_output.sampled_token_ids logprobs = model_runner_output.logprobs prompt_logprobs_dict = model_runner_output.prompt_logprobs_dict diff --git a/vllm/v1/engine/core.py b/vllm/v1/engine/core.py index a7038e2d2c26..000334e45dca 100644 --- a/vllm/v1/engine/core.py +++ b/vllm/v1/engine/core.py @@ -285,15 +285,19 @@ def step(self) -> tuple[dict[int, EngineCoreOutputs], bool]: # Check for any requests remaining in the scheduler - unfinished, # or finished and not yet removed from the batch. + logger.info("At beginning of step") if not self.scheduler.has_requests(): return {}, False scheduler_output = self.scheduler.schedule() + logger.info(f"At engine core scheduler output is {scheduler_output}") model_output = self.execute_model_with_error_logging( self.model_executor.execute_model, # type: ignore scheduler_output) + logger.info(f"Model output after execute is {model_output}") engine_core_outputs = self.scheduler.update_from_output( scheduler_output, model_output) # type: ignore + logger.info(f"Return result is {engine_core_outputs} and {(scheduler_output.total_num_scheduled_tokens > 0)}") return (engine_core_outputs, scheduler_output.total_num_scheduled_tokens > 0) @@ -755,9 +759,11 @@ def _process_engine_step(self) -> bool: # Step the engine core. outputs, model_executed = self.step_fn() + logger.info(f"At process engine the output is {outputs}") # Put EngineCoreOutputs into the output queue. for output in (outputs.items() if outputs else ()): self.output_queue.put_nowait(output) + logger.info("Put into output queue") # Post-step hook. self.post_step(model_executed) diff --git a/vllm/v1/outputs.py b/vllm/v1/outputs.py index f8d6b24702f3..33620764e50b 100644 --- a/vllm/v1/outputs.py +++ b/vllm/v1/outputs.py @@ -77,6 +77,12 @@ class KVConnectorOutput: finished_sending: Optional[set[str]] = None finished_recving: Optional[set[str]] = None +@dataclass +class ECConnectorOutput: + # [mm_hash] + finished_sending: Optional[set[str]] = None + finished_recving: Optional[set[str]] = None + # ModelRunnerOutput is serialized and sent to the scheduler process. # This is expensive for torch.Tensor so prefer to use list instead. @@ -110,6 +116,8 @@ class ModelRunnerOutput: kv_connector_output: Optional[KVConnectorOutput] = None + ec_connector_output: Optional[ECConnectorOutput] = None + # req_id -> num_nans_in_logits num_nans_in_logits: Optional[dict[str, int]] = None diff --git a/vllm/v1/worker/ec_connector_model_runner_mixin.py b/vllm/v1/worker/ec_connector_model_runner_mixin.py new file mode 100644 index 000000000000..f6d050732a1a --- /dev/null +++ b/vllm/v1/worker/ec_connector_model_runner_mixin.py @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +""" +Define KV connector functionality mixin for model runners. +""" +import copy +from contextlib import AbstractContextManager, contextmanager, nullcontext +from typing import Generator # noqa: UP035 +from typing import TYPE_CHECKING, Optional + +from vllm.config import VllmConfig +from vllm.distributed.ec_transfer import (get_ec_transfer, + has_ec_transfer) +from vllm.distributed.ec_transfer.ec_connector.base import ECConnectorBase +from vllm.logger import init_logger +from vllm.v1.outputs import ECConnectorOutput +import torch +if TYPE_CHECKING: + from vllm.v1.core.sched.output import SchedulerOutput + +logger = init_logger(__name__) + + +# Defined as a EC connector functionality mixin for ModelRunner (GPU, TPU) +class ECConnectorModelRunnerMixin: + + @staticmethod + def maybe_setup_ec_connector(scheduler_output: "SchedulerOutput"): + # Update KVConnector with the KVConnector metadata forward(). + if has_ec_transfer(): + ec_connector = get_ec_transfer() + assert isinstance(ec_connector, ECConnectorBase) + assert scheduler_output.kv_connector_metadata is not None + ec_connector.bind_connector_metadata( + scheduler_output.kv_connector_metadata) + + # Background KV cache transfers happen here. + # These transfers are designed to be async and the requests + # involved may be disjoint from the running requests. + # Do this here to save a collective_rpc. + ec_connector.start_load_caches() + + @staticmethod + def maybe_save_ec_to_connector( + encoder_cache: dict[str, torch.Tensor], + mm_hash: str, + ): + if not has_ec_transfer(): + logger.info("Not have ec transfer please check") + return + connector = get_ec_transfer() + logger.info("Start save caches") + connector.save_caches(encoder_cache=encoder_cache,mm_hash=mm_hash) + + @staticmethod + def maybe_wait_for_ec_save() -> None: + if has_ec_transfer(): + get_ec_transfer().wait_for_save() + + @staticmethod + def get_finished_kv_transfers( + scheduler_output: "SchedulerOutput", + ) -> tuple[Optional[set[str]], Optional[set[str]]]: + if has_ec_transfer(): + return get_ec_transfer().get_finished( + scheduler_output.finished_req_ids) + return None, None + + @staticmethod + def maybe_get_ec_connector_output( + scheduler_output: "SchedulerOutput", + **kwargs, + ) -> AbstractContextManager[Optional[ECConnectorOutput]]: + return ECConnectorModelRunnerMixin._get_ec_connector_output( + scheduler_output, **kwargs) if has_ec_transfer() else nullcontext() + + # This context manager must be used within an active forward context. + # It encapsulates the entire KV conector lifecycle within execute_model + @staticmethod + @contextmanager + def _get_ec_connector_output( + scheduler_output: "SchedulerOutput", + wait_for_save: bool = True, + **kwargs, + ) -> Generator[ECConnectorOutput, None, None]: + output = ECConnectorOutput() + + # Update KVConnector with the KVConnector metadata forward(). + ec_connector = get_ec_transfer() + assert isinstance(ec_connector, ECConnectorBase) + assert scheduler_output.ec_connector_metadata is not None + ec_connector.bind_connector_metadata( + scheduler_output.ec_connector_metadata) + + # Background KV cache transfers happen here. + # These transfers are designed to be async and the requests + # involved may be disjoint from the running requests. + # Do this here to save a collective_rpc. + ec_connector.start_load_caches(**kwargs) + try: + yield output + finally: + if wait_for_save: + ec_connector.wait_for_save() + + output.finished_sending, output.finished_recving = ( + ec_connector.get_finished(scheduler_output.finished_req_ids)) + + ec_connector.clear_connector_metadata() diff --git a/vllm/v1/worker/gpu_model_runner.py b/vllm/v1/worker/gpu_model_runner.py index 0250a4e19a02..27ef2670258f 100644 --- a/vllm/v1/worker/gpu_model_runner.py +++ b/vllm/v1/worker/gpu_model_runner.py @@ -23,7 +23,7 @@ from vllm.compilation.counter import compilation_counter from vllm.compilation.cuda_graph import CUDAGraphWrapper from vllm.compilation.monitor import set_cudagraph_capturing_enabled -from vllm.config import (CompilationLevel, CUDAGraphMode, VllmConfig, +from vllm.config import (CompilationLevel, CUDAGraphMode, ECProducer, VllmConfig, get_layers_from_vllm_config, update_config) from vllm.distributed.eplb.eplb_state import EplbState from vllm.distributed.kv_transfer import (get_kv_transfer_group, @@ -66,7 +66,7 @@ FullAttentionSpec, KVCacheConfig, KVCacheGroupSpec, KVCacheSpec, MambaSpec, SlidingWindowSpec) -from vllm.v1.outputs import (EMPTY_MODEL_RUNNER_OUTPUT, DraftTokenIds, +from vllm.v1.outputs import (EMPTY_MODEL_RUNNER_OUTPUT, DraftTokenIds, ECConnectorOutput, LogprobsTensors, ModelRunnerOutput) from vllm.v1.pool.metadata import PoolingMetadata from vllm.v1.sample.logits_processor import LogitsProcessors, build_logitsprocs @@ -78,6 +78,7 @@ from vllm.v1.spec_decode.metadata import SpecDecodeMetadata from vllm.v1.spec_decode.ngram_proposer import NgramProposer from vllm.v1.utils import CpuGpuBuffer +from vllm.v1.worker.ec_connector_model_runner_mixin import ECConnectorModelRunnerMixin from vllm.v1.worker.gpu_input_batch import CachedRequestState, InputBatch from vllm.v1.worker.kv_connector_model_runner_mixin import ( KVConnectorModelRunnerMixin, KVConnectorOutput) @@ -103,7 +104,8 @@ logger = init_logger(__name__) -class GPUModelRunner(LoRAModelRunnerMixin, KVConnectorModelRunnerMixin): +class GPUModelRunner(LoRAModelRunnerMixin, KVConnectorModelRunnerMixin, + ECConnectorModelRunnerMixin): def __init__( self, @@ -1163,6 +1165,7 @@ def _execute_mm_encoder(self, scheduler_output: "SchedulerOutput"): output, is_embed=pos_info.is_embed, ) + self.maybe_save_ec_to_connector(self.encoder_cache, mm_hash) def _gather_mm_embeddings( self, @@ -1417,6 +1420,7 @@ def _pool( num_scheduled_tokens: int, num_scheduled_tokens_np: np.ndarray, kv_connector_output: Optional[KVConnectorOutput], + ec_connector_output: Optional[ECConnectorOutput] ) -> ModelRunnerOutput: assert self.input_batch.num_reqs ==\ len(self.input_batch.pooling_params), \ @@ -1448,6 +1452,7 @@ def _pool( prompt_logprobs_dict={}, pooler_output=pooler_output, kv_connector_output=kv_connector_output, + ec_connector_output=ec_connector_output ) @torch.inference_mode() @@ -1456,26 +1461,34 @@ def execute_model( scheduler_output: "SchedulerOutput", intermediate_tensors: Optional[IntermediateTensors] = None, ) -> Union[ModelRunnerOutput, IntermediateTensors]: + self._update_states(scheduler_output) if not scheduler_output.total_num_scheduled_tokens: + if self.vllm_config.ec_transfer_config.ec_role == "ec_producer": + with self.maybe_get_ec_connector_output( + scheduler_output, + encoder_cache=self.encoder_cache, + ) as ec_connector_output: + self._execute_mm_encoder(scheduler_output) + return EMPTY_MODEL_RUNNER_OUTPUT + + if not has_kv_transfer_group(): # Return empty ModelRunnerOutput if there's no work to do. return EMPTY_MODEL_RUNNER_OUTPUT return self.kv_connector_no_forward(scheduler_output, self.vllm_config) - if self.cache_config.kv_sharing_fast_prefill: assert not self.input_batch.num_prompt_logprobs, ( "--kv-sharing-fast-prefill produces incorrect logprobs for " "prompt tokens, tokens, please disable it when the requests " "need prompt logprobs") - + # Prepare the decoder inputs. (attn_metadata, logits_indices, spec_decode_metadata, num_scheduled_tokens_np, spec_decode_common_attn_metadata, max_query_len) = self._prepare_inputs(scheduler_output) - num_scheduled_tokens = scheduler_output.total_num_scheduled_tokens if (self.compilation_config.cudagraph_mode != CUDAGraphMode.NONE and not envs.VLLM_DISABLE_PAD_FOR_CUDAGRAPH @@ -1494,7 +1507,6 @@ def execute_model( num_input_tokens = round_up(num_scheduled_tokens, tp_size) else: num_input_tokens = num_scheduled_tokens - # Padding for DP num_pad, num_tokens_across_dp = self.get_dp_padding(num_input_tokens) num_input_tokens += num_pad @@ -1502,9 +1514,15 @@ def execute_model( # _prepare_inputs may reorder the batch, so we must gather multi # modal outputs after that to ensure the correct order if self.supports_mm_inputs: - # Run the multimodal encoder if any. - self._execute_mm_encoder(scheduler_output) - mm_embeds = self._gather_mm_embeddings(scheduler_output) + with self.maybe_get_ec_connector_output( + scheduler_output, + encoder_cache=self.encoder_cache, + ) as ec_connector_output: + # Run the multimodal encoder if any. + self._execute_mm_encoder(scheduler_output) + if self.vllm_config.ec_transfer_config.ec_role == ECProducer: + return EMPTY_MODEL_RUNNER_OUTPUT + mm_embeds = self._gather_mm_embeddings(scheduler_output) else: mm_embeds = [] @@ -1746,6 +1764,8 @@ def execute_model( prompt_logprobs_dict=prompt_logprobs_dict, pooler_output=[], kv_connector_output=kv_connector_output, + ec_connector_output=ec_connector_output + if self.supports_mm_inputs else None, num_nans_in_logits=num_nans_in_logits, ) @@ -3116,6 +3136,7 @@ def initialize_kv_cache(self, kv_cache_config: KVCacheConfig) -> None: kv_cache_config: Configuration for the KV cache, including the KV cache size of each layer """ + #TODO skip this for encoder model runner kv_cache_config = deepcopy(kv_cache_config) self.kv_cache_config = kv_cache_config self.may_reinitialize_input_batch(kv_cache_config) diff --git a/vllm/v1/worker/gpu_worker.py b/vllm/v1/worker/gpu_worker.py index c25219331334..1f7a56ce77a5 100644 --- a/vllm/v1/worker/gpu_worker.py +++ b/vllm/v1/worker/gpu_worker.py @@ -17,6 +17,7 @@ init_distributed_environment, set_custom_all_reduce) from vllm.distributed.kv_transfer import ensure_kv_transfer_initialized +from vllm.distributed.ec_transfer import ensure_ec_transfer_initialized from vllm.distributed.parallel_state import get_pp_group, get_tp_group from vllm.logger import init_logger from vllm.lora.request import LoRARequest @@ -384,6 +385,7 @@ def execute_model( return output assert isinstance(output, ModelRunnerOutput) + logger.info(f"Output before return is {output}") return output def take_draft_token_ids(self) -> Optional[DraftTokenIds]: @@ -613,3 +615,4 @@ def init_worker_distributed_environment( parallel_config.pipeline_parallel_size) ensure_kv_transfer_initialized(vllm_config) + ensure_ec_transfer_initialized(vllm_config) From 00d11850e724b0dc5c397fd3b326d86a9053ba56 Mon Sep 17 00:00:00 2001 From: n00909098 Date: Tue, 9 Sep 2025 15:04:50 +0800 Subject: [PATCH 02/57] [Fix] Runable for non EPD mode Signed-off-by: n00909098 --- vllm/v1/worker/gpu_model_runner.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/vllm/v1/worker/gpu_model_runner.py b/vllm/v1/worker/gpu_model_runner.py index 27ef2670258f..6443eac8db18 100644 --- a/vllm/v1/worker/gpu_model_runner.py +++ b/vllm/v1/worker/gpu_model_runner.py @@ -28,6 +28,8 @@ from vllm.distributed.eplb.eplb_state import EplbState from vllm.distributed.kv_transfer import (get_kv_transfer_group, has_kv_transfer_group) +from vllm.distributed.ec_transfer import (get_ec_transfer, + has_ec_transfer) from vllm.distributed.parallel_state import ( get_pp_group, get_tp_group, graph_capture, is_global_first_rank, prepare_communication_buffer_for_model) @@ -1464,13 +1466,14 @@ def execute_model( self._update_states(scheduler_output) if not scheduler_output.total_num_scheduled_tokens: - if self.vllm_config.ec_transfer_config.ec_role == "ec_producer": - with self.maybe_get_ec_connector_output( - scheduler_output, - encoder_cache=self.encoder_cache, - ) as ec_connector_output: - self._execute_mm_encoder(scheduler_output) - return EMPTY_MODEL_RUNNER_OUTPUT + if has_ec_transfer(): + if self.vllm_config.ec_transfer_config.ec_role == "ec_producer": + with self.maybe_get_ec_connector_output( + scheduler_output, + encoder_cache=self.encoder_cache, + ) as ec_connector_output: + self._execute_mm_encoder(scheduler_output) + return EMPTY_MODEL_RUNNER_OUTPUT if not has_kv_transfer_group(): @@ -1520,8 +1523,9 @@ def execute_model( ) as ec_connector_output: # Run the multimodal encoder if any. self._execute_mm_encoder(scheduler_output) - if self.vllm_config.ec_transfer_config.ec_role == ECProducer: - return EMPTY_MODEL_RUNNER_OUTPUT + if has_ec_transfer(): + if self.vllm_config.ec_transfer_config.ec_role == ECProducer: + return EMPTY_MODEL_RUNNER_OUTPUT mm_embeds = self._gather_mm_embeddings(scheduler_output) else: mm_embeds = [] From 3031ea07a158a68bf5107c1ce8a5cda776761a6b Mon Sep 17 00:00:00 2001 From: n00909098 Date: Tue, 9 Sep 2025 15:55:59 +0800 Subject: [PATCH 03/57] [Fix] Remove hard code path in share storage connector Signed-off-by: n00909098 --- draft/launch.sh | 79 +++++++++++++------ .../ec_connector/shared_storage_connector.py | 11 +-- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/draft/launch.sh b/draft/launch.sh index eff75b1abc4f..1ce35926f096 100644 --- a/draft/launch.sh +++ b/draft/launch.sh @@ -1,63 +1,90 @@ -#!/bin/bash - +#!/usr/bin/env bash +set -euo pipefail wait_for_server() { local port=$1 - timeout 12000 bash -c " - until curl -s localhost:$port/v1/chat/completions > /dev/null; do + timeout 12000 bash -c ' + until curl -s "http://localhost:'"$port"'/v1/chat/completions" > /dev/null; do sleep 1 - done" && return 0 || return 1 + done + ' && return 0 || return 1 } -MODEL="/home/n00909098/Qwen2.5-VL-3B-Instruct" -LOG_PATH=$LOG_PATH +MODEL="/path/to/Qwen2.5-VL-3B-Instruct" + +LOG_PATH=${LOG_PATH:-./logs} +mkdir -p "$LOG_PATH" + ENCODE_PORT=19534 -ENCODE_RANK=0 PREFILL_DECODE_PORT=19535 -PREFILL_DECODE_RANK=1 PROXY_PORT=10001 -GPU_E="1" -GPU_PD="2" + +GPU_E=1 +GPU_PD=2 + START_TIME=$(date +"%Y%m%d_%H%M%S") -ENC_LOG=./logs/encoder.log -PD_LOG=./logs/pd.log -PROXY_LOG=./logs/proxy.log +ENC_LOG="$LOG_PATH/encoder_${START_TIME}.log" +PD_LOG="$LOG_PATH/pd_${START_TIME}.log" +PROXY_LOG="$LOG_PATH/proxy_${START_TIME}.log" PID_FILE="./pid.txt" +SHARED_STORAGE_PATH="/tmp/your/path" + +############################################################################### +# Encoder worker +############################################################################### CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ --gpu-memory-utilization 0.7 \ --port "$ENCODE_PORT" \ --enable-request-id-headers \ --max-num-seqs 128 \ --enforce-eager \ - --ec-transfer-config \ - '{"ec_connector":"ECSharedStorageConnector","ec_role":"ec_producer"}' \ - >"${ENC_LOG}" 2>&1 & + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_producer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$SHARED_STORAGE_PATH"'" + } + }' \ + >"$ENC_LOG" 2>&1 & echo $! >> "$PID_FILE" +############################################################################### +# Prefill / decode worker +############################################################################### CUDA_VISIBLE_DEVICES="$GPU_PD" vllm serve "$MODEL" \ --gpu-memory-utilization 0.7 \ --port "$PREFILL_DECODE_PORT" \ --enable-request-id-headers \ --max-num-seqs 128 \ --enforce-eager \ - --ec-transfer-config \ - '{"ec_connector":"ECSharedStorageConnector","ec_role":"ec_consumer"}' \ - >"${PD_LOG}" 2>&1 & - + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_consumer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$SHARED_STORAGE_PATH"'" + } + }' \ + >"$PD_LOG" 2>&1 & + echo $! >> "$PID_FILE" -wait_for_server $ENCODE_PORT -wait_for_server $PREFILL_DECODE_PORT +# Wait until both workers are ready +wait_for_server "$ENCODE_PORT" +wait_for_server "$PREFILL_DECODE_PORT" -python /home/n00909098/EPD/refactor/vllm/draft/proxy.py \ +############################################################################### +# Proxy +############################################################################### +python /path/to/your/vllm/draft/proxy.py \ --host "0.0.0.0" \ --port "$PROXY_PORT" \ --encode-servers-urls "http://localhost:$ENCODE_PORT" \ --prefill-decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT" \ - >"${PROXY_LOG}" 2>&1 & + >"$PROXY_LOG" 2>&1 & echo $! >> "$PID_FILE" -wait_for_server $PROXY_PORT \ No newline at end of file +wait_for_server "$PROXY_PORT" +echo "All services are up!" \ No newline at end of file diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index be259ffddfc2..dfe565250fba 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -64,13 +64,10 @@ def __init__(self, vllm_config: "VllmConfig", role: ECConnectorBase): super().__init__(vllm_config=vllm_config, role=role) # req_id -> index -> mm_hash self._mm_datas_need_loads: dict[str, dict[int, MMMeta]] = {} - # transfer_config = vllm_config.kv_transfer_config - # self._storage_path = transfer_config.get_from_extra_config( - # "shared_storage_path", "/tmp") - self.is_producer = (vllm_config.ec_transfer_config.ec_role == 'ec_producer') - logger.info(f"Init a ec share storage connector with role {role}") - self._storage_path = "/home/n00909098/EPD/refactor/vllm/draft/cache_save" - logger.info(vllm_config.ec_transfer_config) + transfer_config = vllm_config.ec_transfer_config + self.is_producer = (transfer_config.ec_role == 'ec_producer') + self._storage_path = transfer_config.get_from_extra_config("shared_storage_path", "/tmp") + logger.info(transfer_config) logger.info("Shared storage path is %s", self._storage_path) def start_load_caches(self, **kwargs) -> None: From c2ea7dbe456acdb38b3645414b07e5b9c86d32de Mon Sep 17 00:00:00 2001 From: n00909098 Date: Tue, 9 Sep 2025 16:28:58 +0800 Subject: [PATCH 04/57] [Misc] Clean code and docs Signed-off-by: n00909098 --- .../ec_transfer/ec_connector/base.py | 8 +++-- .../ec_connector/shared_storage_connector.py | 32 +++++++------------ .../worker/ec_connector_model_runner_mixin.py | 25 ++++----------- 3 files changed, 23 insertions(+), 42 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index a141253130f7..8fac1409afdd 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -80,7 +80,7 @@ def bind_connector_metadata( This function should be called by the model runner every time before the model execution. The metadata will be used for runtime - KV cache loading and saving. + EC cache loading. Args: connector_metadata (dict): the connector metadata. @@ -108,12 +108,13 @@ def _get_connector_metadata(self) -> ECConnectorMetadata: assert self._connector_metadata is not None return self._connector_metadata - def register_caches(self, caches: dict[str, torch.Tensor],): + def register_caches(self, ec_caches: dict[str, torch.Tensor],): """ Initialize with the EC caches. Args: ec_caches: dictionary of encoder cache """ + # TODO: Implement this later for P2P feature return @abstractmethod @@ -122,7 +123,7 @@ def start_load_caches(self, **kwargs) -> None: Start loading the cache from the connector to vLLM's encoder cache. This is called before _gather_mm_embeddings for EC Connector and before execute_model for KV Connector - forward_context does not need for EC Connector + For EC the encoder_cache and mm_hash is store in kwargs Args: **kwargs: additional arguments for the load operation @@ -134,6 +135,7 @@ def start_load_caches(self, **kwargs) -> None: def save_caches(self, **kwargs) -> None: """ Save caches into connector + For EC the encoder_cache and mm_hash is store in kwargs """ pass diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index dfe565250fba..a2d7006612b9 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -45,30 +45,20 @@ def __init__(self): def add_mm_data(self, mm_data:MMMeta): self.mm_datas.append(mm_data) - # def add_mm_data( - # self, - # mm_hash, - # num_token, - # ) -> None: - # self.mm_datas.append( - # MMMeta.make_meta(mm_hash, num_token)) - class ECSharedStorageConnector(ECConnectorBase): - # NOTE: This is Simple debug implementation of the KV connector. - # It save / load the KV cache to / from the disk. - # It does extra work which will overwrite the existing prefix-cache in GPU - # - to remove the overhead, need to add some "mask" in the ReqMeta class + # NOTE: This is Simple debug implementation of the EC connector. + # It save / load the EC cache to / from the disk. def __init__(self, vllm_config: "VllmConfig", role: ECConnectorBase): super().__init__(vllm_config=vllm_config, role=role) - # req_id -> index -> mm_hash + # req_id -> index -> MMMeta self._mm_datas_need_loads: dict[str, dict[int, MMMeta]] = {} transfer_config = vllm_config.ec_transfer_config self.is_producer = (transfer_config.ec_role == 'ec_producer') self._storage_path = transfer_config.get_from_extra_config("shared_storage_path", "/tmp") - logger.info(transfer_config) - logger.info("Shared storage path is %s", self._storage_path) + logger.debug(transfer_config) + logger.debug("Shared storage path is %s", self._storage_path) def start_load_caches(self, **kwargs) -> None: """Start loading the EC cache from the connector buffer to worker @@ -79,7 +69,6 @@ def start_load_caches(self, **kwargs) -> None: """ # Get the metadata - logger.info("Start load caches") metadata: ECConnectorMetadata = self._get_connector_metadata() assert isinstance(metadata, ECSharedStorageConnectorMetadata) encoder_cache = kwargs.get("encoder_cache") # returns None if missing @@ -89,7 +78,6 @@ def start_load_caches(self, **kwargs) -> None: "In connector.start_load_kv, but the connector metadata is None" ) return - logger.info(f"At load cache meta data is {metadata}") # Load the KV for each request each layer for mm_data in metadata.mm_datas: # TODO: Only load it once @@ -98,7 +86,7 @@ def start_load_caches(self, **kwargs) -> None: filename = self._generate_filename_debug(mm_data.mm_hash) ec_cache = safetensors.torch.load_file(filename)["ec_cache"].cuda() encoder_cache[mm_data.mm_hash] = ec_cache - logger.info(f"Success load hash for {mm_data.mm_hash}") + logger.debug(f"Success load encoder cache for hash {mm_data.mm_hash}") def save_caches(self, **kwargs) -> None: """Start saving the KV cache of the layer from encoder cache @@ -106,17 +94,18 @@ def save_caches(self, **kwargs) -> None: Args: **kwargs: additional arguments for the save operation. """ + # Return if it is PD Instance if not self.is_producer: return - encoder_cache = kwargs.get("encoder_cache") # returns None if missing + encoder_cache = kwargs.get("encoder_cache") mm_hash = kwargs.get("mm_hash") assert encoder_cache is not None assert mm_hash is not None - logger.info(f"At save caches the mm hash is {mm_hash}") filename = self._generate_filename_debug(mm_hash) ec_cache = encoder_cache[mm_hash] tensors = {"ec_cache": ec_cache.detach().cpu()} safetensors.torch.save_file(tensors, filename) + logger.debug(f"Save cache successful for mm_hash {mm_hash}") def wait_for_save(self): return @@ -160,6 +149,7 @@ def update_state_after_alloc(self, # Insert mm_hash only if this block has not been recorded yet. loads_for_request.setdefault(index, MMMeta.make_meta(mm_hash,num_encoder_token)) logger.info(f"After update the _mm_datas_need_loads is {self._mm_datas_need_loads}") + def build_connector_meta( self, scheduler_output: SchedulerOutput, @@ -168,7 +158,7 @@ def build_connector_meta( This function should NOT modify any fields in the scheduler_output. Also, calling this function will reset the state of the connector. - + This only build for load mm_data only Args: scheduler_output (SchedulerOutput): the scheduler output object. """ diff --git a/vllm/v1/worker/ec_connector_model_runner_mixin.py b/vllm/v1/worker/ec_connector_model_runner_mixin.py index f6d050732a1a..70658ed88906 100644 --- a/vllm/v1/worker/ec_connector_model_runner_mixin.py +++ b/vllm/v1/worker/ec_connector_model_runner_mixin.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project """ -Define KV connector functionality mixin for model runners. +Define EC connector functionality mixin for model runners. """ import copy from contextlib import AbstractContextManager, contextmanager, nullcontext @@ -26,18 +26,13 @@ class ECConnectorModelRunnerMixin: @staticmethod def maybe_setup_ec_connector(scheduler_output: "SchedulerOutput"): - # Update KVConnector with the KVConnector metadata forward(). + # Set up EC connector for load cache if has_ec_transfer(): ec_connector = get_ec_transfer() assert isinstance(ec_connector, ECConnectorBase) - assert scheduler_output.kv_connector_metadata is not None + assert scheduler_output.ec_connector_metadata is not None ec_connector.bind_connector_metadata( - scheduler_output.kv_connector_metadata) - - # Background KV cache transfers happen here. - # These transfers are designed to be async and the requests - # involved may be disjoint from the running requests. - # Do this here to save a collective_rpc. + scheduler_output.ec_connector_metadata) ec_connector.start_load_caches() @staticmethod @@ -46,10 +41,9 @@ def maybe_save_ec_to_connector( mm_hash: str, ): if not has_ec_transfer(): - logger.info("Not have ec transfer please check") + logger.debug("Not have ec transfer please check") return connector = get_ec_transfer() - logger.info("Start save caches") connector.save_caches(encoder_cache=encoder_cache,mm_hash=mm_hash) @staticmethod @@ -58,7 +52,7 @@ def maybe_wait_for_ec_save() -> None: get_ec_transfer().wait_for_save() @staticmethod - def get_finished_kv_transfers( + def get_finished_ec_transfers( scheduler_output: "SchedulerOutput", ) -> tuple[Optional[set[str]], Optional[set[str]]]: if has_ec_transfer(): @@ -75,7 +69,7 @@ def maybe_get_ec_connector_output( scheduler_output, **kwargs) if has_ec_transfer() else nullcontext() # This context manager must be used within an active forward context. - # It encapsulates the entire KV conector lifecycle within execute_model + # It encapsulates the entire EC conector lifecycle within execute_model @staticmethod @contextmanager def _get_ec_connector_output( @@ -85,17 +79,12 @@ def _get_ec_connector_output( ) -> Generator[ECConnectorOutput, None, None]: output = ECConnectorOutput() - # Update KVConnector with the KVConnector metadata forward(). ec_connector = get_ec_transfer() assert isinstance(ec_connector, ECConnectorBase) assert scheduler_output.ec_connector_metadata is not None ec_connector.bind_connector_metadata( scheduler_output.ec_connector_metadata) - # Background KV cache transfers happen here. - # These transfers are designed to be async and the requests - # involved may be disjoint from the running requests. - # Do this here to save a collective_rpc. ec_connector.start_load_caches(**kwargs) try: yield output From 7448888d44acb7354362429cb43e4c0e9a60bfda Mon Sep 17 00:00:00 2001 From: n00909098 Date: Tue, 9 Sep 2025 17:30:23 +0800 Subject: [PATCH 05/57] [Misc] Clean code Signed-off-by: n00909098 --- draft/launch.sh | 18 ++++---- draft/pid.txt | 3 -- draft/proxy.py | 42 +++++++++---------- .../ec_connector/shared_storage_connector.py | 1 - vllm/v1/engine/core.py | 6 --- vllm/v1/worker/gpu_worker.py | 1 - 6 files changed, 30 insertions(+), 41 deletions(-) delete mode 100644 draft/pid.txt diff --git a/draft/launch.sh b/draft/launch.sh index 1ce35926f096..f20b16f8df03 100644 --- a/draft/launch.sh +++ b/draft/launch.sh @@ -10,7 +10,7 @@ wait_for_server() { ' && return 0 || return 1 } -MODEL="/path/to/Qwen2.5-VL-3B-Instruct" +MODEL="/home/n00909098/Qwen2.5-VL-3B-Instruct" LOG_PATH=${LOG_PATH:-./logs} mkdir -p "$LOG_PATH" @@ -19,16 +19,16 @@ ENCODE_PORT=19534 PREFILL_DECODE_PORT=19535 PROXY_PORT=10001 -GPU_E=1 -GPU_PD=2 +GPU_E=0 +GPU_PD=1 START_TIME=$(date +"%Y%m%d_%H%M%S") -ENC_LOG="$LOG_PATH/encoder_${START_TIME}.log" -PD_LOG="$LOG_PATH/pd_${START_TIME}.log" -PROXY_LOG="$LOG_PATH/proxy_${START_TIME}.log" +ENC_LOG="$LOG_PATH/encoder.log" +PD_LOG="$LOG_PATH/pd.log" +PROXY_LOG="$LOG_PATH/proxy.log" PID_FILE="./pid.txt" -SHARED_STORAGE_PATH="/tmp/your/path" +SHARED_STORAGE_PATH="/home/n00909098/EPD/refactor/vllm/draft/test_save" ############################################################################### # Encoder worker @@ -77,8 +77,8 @@ wait_for_server "$PREFILL_DECODE_PORT" ############################################################################### # Proxy ############################################################################### -python /path/to/your/vllm/draft/proxy.py \ - --host "0.0.0.0" \ +python /home/n00909098/EPD/refactor/vllm/draft/proxy.py \ + --host "127.0.0.1" \ --port "$PROXY_PORT" \ --encode-servers-urls "http://localhost:$ENCODE_PORT" \ --prefill-decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT" \ diff --git a/draft/pid.txt b/draft/pid.txt deleted file mode 100644 index fbd4acc39f24..000000000000 --- a/draft/pid.txt +++ /dev/null @@ -1,3 +0,0 @@ -24618 -24619 -26250 diff --git a/draft/proxy.py b/draft/proxy.py index 486ff895f4e6..318e6295eb8a 100644 --- a/draft/proxy.py +++ b/draft/proxy.py @@ -60,27 +60,27 @@ async def forward_streaming_request( headers = {"x-request-id": request_id} # Skip request to encoder instance if we don't have mm input - # if has_mm_input(request_data): - # task1 = asyncio.create_task( - # encode_session.post( - # f"{e_server_url}/v1/chat/completions", - # json=request_data, - # headers=headers - # ) - # ) - # try: - # response = await task1 - # if response.status != 200: - # error_text = await response.text() - # raise HTTPException( - # status_code=response.status, - # detail={"error": "Request failed", "message": error_text} - # ) - # except Exception as e: - # raise HTTPException( - # status_code=500, - # detail={"error": "Internal server error", "message": str(e)} - # ) + if has_mm_input(request_data): + task1 = asyncio.create_task( + encode_session.post( + f"{e_server_url}/v1/chat/completions", + json=request_data, + headers=headers + ) + ) + try: + response = await task1 + if response.status != 200: + error_text = await response.text() + raise HTTPException( + status_code=response.status, + detail={"error": "Request failed", "message": error_text} + ) + except Exception as e: + raise HTTPException( + status_code=500, + detail={"error": "Internal server error", "message": str(e)} + ) # import time # time.sleep(10) diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index a2d7006612b9..60910a3c3e30 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -148,7 +148,6 @@ def update_state_after_alloc(self, num_encoder_token = request.get_num_encoder_tokens(index) # Insert mm_hash only if this block has not been recorded yet. loads_for_request.setdefault(index, MMMeta.make_meta(mm_hash,num_encoder_token)) - logger.info(f"After update the _mm_datas_need_loads is {self._mm_datas_need_loads}") def build_connector_meta( self, diff --git a/vllm/v1/engine/core.py b/vllm/v1/engine/core.py index 000334e45dca..a7038e2d2c26 100644 --- a/vllm/v1/engine/core.py +++ b/vllm/v1/engine/core.py @@ -285,19 +285,15 @@ def step(self) -> tuple[dict[int, EngineCoreOutputs], bool]: # Check for any requests remaining in the scheduler - unfinished, # or finished and not yet removed from the batch. - logger.info("At beginning of step") if not self.scheduler.has_requests(): return {}, False scheduler_output = self.scheduler.schedule() - logger.info(f"At engine core scheduler output is {scheduler_output}") model_output = self.execute_model_with_error_logging( self.model_executor.execute_model, # type: ignore scheduler_output) - logger.info(f"Model output after execute is {model_output}") engine_core_outputs = self.scheduler.update_from_output( scheduler_output, model_output) # type: ignore - logger.info(f"Return result is {engine_core_outputs} and {(scheduler_output.total_num_scheduled_tokens > 0)}") return (engine_core_outputs, scheduler_output.total_num_scheduled_tokens > 0) @@ -759,11 +755,9 @@ def _process_engine_step(self) -> bool: # Step the engine core. outputs, model_executed = self.step_fn() - logger.info(f"At process engine the output is {outputs}") # Put EngineCoreOutputs into the output queue. for output in (outputs.items() if outputs else ()): self.output_queue.put_nowait(output) - logger.info("Put into output queue") # Post-step hook. self.post_step(model_executed) diff --git a/vllm/v1/worker/gpu_worker.py b/vllm/v1/worker/gpu_worker.py index 1f7a56ce77a5..f282875e0244 100644 --- a/vllm/v1/worker/gpu_worker.py +++ b/vllm/v1/worker/gpu_worker.py @@ -385,7 +385,6 @@ def execute_model( return output assert isinstance(output, ModelRunnerOutput) - logger.info(f"Output before return is {output}") return output def take_draft_token_ids(self) -> Optional[DraftTokenIds]: From bc006584731e44f70e39c23cce0ae224a2ed5b9e Mon Sep 17 00:00:00 2001 From: n00909098 Date: Wed, 10 Sep 2025 12:15:33 +0800 Subject: [PATCH 06/57] [Fix] Enable start Encoder Instance without KVC and fix PD instance shceduler for remote load request Signed-off-by: n00909098 --- draft/launch.sh | 10 +- .../ec_transfer/ec_connector/base.py | 5 + .../ec_connector/shared_storage_connector.py | 22 +-- vllm/v1/core/sched/scheduler.py | 185 +++--------------- vllm/v1/outputs.py | 33 ++++ vllm/v1/worker/gpu_model_runner.py | 30 +-- 6 files changed, 90 insertions(+), 195 deletions(-) diff --git a/draft/launch.sh b/draft/launch.sh index f20b16f8df03..0bf6449c8612 100644 --- a/draft/launch.sh +++ b/draft/launch.sh @@ -10,7 +10,7 @@ wait_for_server() { ' && return 0 || return 1 } -MODEL="/home/n00909098/Qwen2.5-VL-3B-Instruct" +MODEL="/path/to/model/Qwen2.5-VL-3B-Instruct" LOG_PATH=${LOG_PATH:-./logs} mkdir -p "$LOG_PATH" @@ -19,8 +19,8 @@ ENCODE_PORT=19534 PREFILL_DECODE_PORT=19535 PROXY_PORT=10001 -GPU_E=0 -GPU_PD=1 +GPU_E=1 +GPU_PD=7 START_TIME=$(date +"%Y%m%d_%H%M%S") ENC_LOG="$LOG_PATH/encoder.log" @@ -28,7 +28,7 @@ PD_LOG="$LOG_PATH/pd.log" PROXY_LOG="$LOG_PATH/proxy.log" PID_FILE="./pid.txt" -SHARED_STORAGE_PATH="/home/n00909098/EPD/refactor/vllm/draft/test_save" +SHARED_STORAGE_PATH="/path/to/your/share/storage" ############################################################################### # Encoder worker @@ -77,7 +77,7 @@ wait_for_server "$PREFILL_DECODE_PORT" ############################################################################### # Proxy ############################################################################### -python /home/n00909098/EPD/refactor/vllm/draft/proxy.py \ +python /path/to/vllm/vllm/draft/proxy.py \ --host "127.0.0.1" \ --port "$PROXY_PORT" \ --encode-servers-urls "http://localhost:$ENCODE_PORT" \ diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 8fac1409afdd..219fffd93c11 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -65,11 +65,16 @@ def __init__(self, vllm_config: "VllmConfig", role: ECConnectorRole): self._connector_metadata: Optional[ECConnectorMetadata] = None self._vllm_config = vllm_config self._role = role + self._is_producer = (vllm_config.ec_transfer_config.ec_role == 'ec_producer') @property def role(self) -> ECConnectorRole: return self._role + @property + def is_producer(self) -> bool: + return self._is_producer + # ============================== # Worker-side methods # ============================== diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 60910a3c3e30..389f4605e3d6 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -53,9 +53,8 @@ class ECSharedStorageConnector(ECConnectorBase): def __init__(self, vllm_config: "VllmConfig", role: ECConnectorBase): super().__init__(vllm_config=vllm_config, role=role) # req_id -> index -> MMMeta - self._mm_datas_need_loads: dict[str, dict[int, MMMeta]] = {} + self._mm_datas_need_loads: dict[str, int] = {} transfer_config = vllm_config.ec_transfer_config - self.is_producer = (transfer_config.ec_role == 'ec_producer') self._storage_path = transfer_config.get_from_extra_config("shared_storage_path", "/tmp") logger.debug(transfer_config) logger.debug("Shared storage path is %s", self._storage_path) @@ -80,9 +79,8 @@ def start_load_caches(self, **kwargs) -> None: return # Load the KV for each request each layer for mm_data in metadata.mm_datas: - # TODO: Only load it once - # if mm_data in self._mm_datas_need_loads: - # continue + if mm_data.mm_hash in encoder_cache: + continue filename = self._generate_filename_debug(mm_data.mm_hash) ec_cache = safetensors.torch.load_file(filename)["ec_cache"].cuda() encoder_cache[mm_data.mm_hash] = ec_cache @@ -137,17 +135,13 @@ def update_state_after_alloc(self, If cache exist for mm_data, need to load it """ - # Create the per-request mapping only if it does not exist. - loads_for_request = self._mm_datas_need_loads.setdefault( - request.request_id, {} - ) for index, has_cache in enumerate(cache_exists): if has_cache: mm_hash = request.mm_hashes[index] num_encoder_token = request.get_num_encoder_tokens(index) # Insert mm_hash only if this block has not been recorded yet. - loads_for_request.setdefault(index, MMMeta.make_meta(mm_hash,num_encoder_token)) + self._mm_datas_need_loads[mm_hash] = num_encoder_token def build_connector_meta( self, @@ -162,12 +156,8 @@ def build_connector_meta( scheduler_output (SchedulerOutput): the scheduler output object. """ meta = ECSharedStorageConnectorMetadata() - scheduled_encoder_inputs = scheduler_output.scheduled_encoder_inputs - for req_id, encoder_input_ids in scheduled_encoder_inputs.items(): - for mm_input_id in encoder_input_ids: - if req_id in self._mm_datas_need_loads and mm_input_id in self._mm_datas_need_loads[req_id]: - mm_data = self._mm_datas_need_loads[req_id][mm_input_id] - meta.add_mm_data(mm_data) + for mm_hash, num_encoder_token in self._mm_datas_need_loads.items(): + meta.add_mm_data(MMMeta.make_meta(mm_hash, num_encoder_token)) self._mm_datas_need_loads.clear() return meta diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index fb4c63302d01..6792a38841d5 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -96,13 +96,15 @@ def __init__( self.kv_events_config, self.parallel_config.data_parallel_rank, ) - self.is_encoder_instance = False self.ec_connector = None if self.vllm_config.ec_transfer_config is not None: self.ec_connector = ECConnectorFactory.create_connector( config=self.vllm_config, role=ECConnectorRole.SCHEDULER ) - self.is_encoder_instance = (self.vllm_config.ec_transfer_config.ec_role=="ec_producer") + if self.ec_connector.is_producer: + # TODO(Long) Set this when set up + self.cache_config.enable_prefix_caching=False + self.max_model_len = 0 num_gpu_blocks = self.cache_config.num_gpu_blocks @@ -185,8 +187,6 @@ def schedule(self) -> SchedulerOutput: # num_tokens_with_spec. This is general enough to cover # chunked prefills, prefix caching, speculative decoding, # and the "jump decoding" optimization in the future. - if self.is_encoder_instance: - return self.scheduler_encoder_only() scheduled_new_reqs: list[Request] = [] scheduled_resumed_reqs: list[Request] = [] @@ -205,6 +205,9 @@ def schedule(self) -> SchedulerOutput: # For logging. scheduled_timestamp = time.monotonic() + # self.external_load_encoder_cache: dict[str, list[int]] = {} + # self.external_load_encoder_cache.clear() + # First, schedule the RUNNING requests. req_index = 0 while req_index < len(self.running) and token_budget > 0: @@ -230,7 +233,7 @@ def schedule(self) -> SchedulerOutput: new_encoder_compute_budget = encoder_compute_budget if request.has_encoder_inputs: (encoder_inputs_to_schedule, num_new_tokens, - new_encoder_compute_budget + new_encoder_compute_budget, external_load_encoder_input ) = self._try_schedule_encoder_inputs( request, request.num_computed_tokens, num_new_tokens, encoder_compute_budget) @@ -318,6 +321,9 @@ def schedule(self) -> SchedulerOutput: for i in encoder_inputs_to_schedule: self.encoder_cache_manager.allocate(request, i) encoder_compute_budget = new_encoder_compute_budget + if external_load_encoder_input: + for i in external_load_encoder_input: + self.encoder_cache_manager.allocate(request, i) # Record the LoRAs in scheduled_running_reqs scheduled_loras: set[int] = set() @@ -432,7 +438,7 @@ def schedule(self) -> SchedulerOutput: # Schedule encoder inputs. if request.has_encoder_inputs: (encoder_inputs_to_schedule, num_new_tokens, - new_encoder_compute_budget + new_encoder_compute_budget, external_load_encoder_input ) = self._try_schedule_encoder_inputs( request, num_computed_tokens, num_new_tokens, encoder_compute_budget) @@ -532,7 +538,10 @@ def schedule(self) -> SchedulerOutput: for i in encoder_inputs_to_schedule: self.encoder_cache_manager.allocate(request, i) encoder_compute_budget = new_encoder_compute_budget - + # Allocate for external load encoder cache + if external_load_encoder_input: + for i in external_load_encoder_input: + self.encoder_cache_manager.allocate(request, i) # Put back any skipped requests at the head of the waiting queue if skipped_waiting_requests: self.waiting.prepend_requests(skipped_waiting_requests) @@ -612,110 +621,6 @@ def schedule(self) -> SchedulerOutput: self._update_after_schedule(scheduler_output) return scheduler_output - - def _try_schedule_encoder_inputs_only(self, request, encoder_compute_budget): - encoder_inputs_to_schedule: list[int] = [] - mm_positions = request.mm_positions - assert mm_positions is not None - assert len(mm_positions) > 0 - - # NOTE: since scheduler operates on the request level (possibly with - # multiple encoder inputs per request), we need to create temporary - # trackers for accounting at the encoder input level. - success = True - mm_hashes_to_schedule = set() - num_tokens_to_schedule = 0 - for i, pos_info in enumerate(mm_positions): - num_encoder_tokens = pos_info.length - if request.mm_hashes[i] in mm_hashes_to_schedule: - continue - - if self.encoder_cache_manager.check_and_update_cache(request, i): - # The encoder input is already computed and cached from a - # previous step. - continue - - if not self.encoder_cache_manager.can_allocate( - request, i, encoder_compute_budget, - num_tokens_to_schedule): - success = False - break - - num_tokens_to_schedule += num_encoder_tokens - encoder_compute_budget -= num_encoder_tokens - mm_hashes_to_schedule.add(request.mm_hashes[i]) - encoder_inputs_to_schedule.append(i) - - if not success: - encoder_compute_budget += num_tokens_to_schedule - return ( - encoder_inputs_to_schedule, - success, - encoder_compute_budget, - ) - def scheduler_encoder_only(self): - scheduled_encoder_inputs: dict[str, list[int]] = {} - scheduled_new_reqs: list[Request] = [] - encoder_compute_budget = self.max_num_encoder_input_tokens - - while self.waiting: - request = self.waiting.peek_request() - encoder_inputs_to_schedule = None - new_encoder_compute_budget = encoder_compute_budget - - if not request.has_encoder_inputs: - self.waiting.pop_request() - continue - (encoder_inputs_to_schedule, success, - new_encoder_compute_budget - ) = self._try_schedule_encoder_inputs_only( - request, encoder_compute_budget) - - if not success: - break - # Request was already popped from self.waiting - # unless it was re-added above due to new_blocks being None. - request = self.waiting.pop_request() - self.running.append(request) - if request.status == RequestStatus.WAITING: - scheduled_new_reqs.append(request) - - request.status = RequestStatus.RUNNING - scheduled_encoder_inputs[request.request_id] = ( - encoder_inputs_to_schedule) - # Allocate the encoder cache. - for i in encoder_inputs_to_schedule: - self.encoder_cache_manager.allocate(request, i) - encoder_compute_budget = new_encoder_compute_budget - - new_reqs_data = [ - NewRequestData.from_request(req, ([],)) - for req in scheduled_new_reqs - ] - - scheduler_output = SchedulerOutput( - scheduled_new_reqs=new_reqs_data, - scheduled_cached_reqs=CachedRequestData.make_empty(), - num_scheduled_tokens={}, - total_num_scheduled_tokens=0, - scheduled_spec_decode_tokens={}, - scheduled_encoder_inputs=scheduled_encoder_inputs, - num_common_prefix_blocks=[], - # finished_req_ids is an existing state in the scheduler, - # instead of being newly scheduled in this step. - # It contains the request IDs that are finished in between - # the previous and the current steps. - finished_req_ids=self.finished_req_ids, - free_encoder_mm_hashes=self.encoder_cache_manager. - get_freed_mm_hashes(), - structured_output_request_ids=None, - grammar_bitmask=None, - ) - if self.ec_connector is not None: - meta = self.ec_connector.build_connector_meta(scheduler_output) - scheduler_output.ec_connector_metadata = meta - self.finished_req_ids = set() - return scheduler_output def _update_after_schedule( self, @@ -829,11 +734,11 @@ def _try_schedule_encoder_inputs( mm_positions = request.mm_positions assert mm_positions is not None assert len(mm_positions) > 0 + external_load_encoder_input = [] # Check remote cache first if self.ec_connector is not None: remote_cache_bools = self.ec_connector.check_caches_exist(request) - load_cache_bools = [0] * len(remote_cache_bools) # NOTE: since scheduler operates on the request level (possibly with # multiple encoder inputs per request), we need to create temporary # trackers for accounting at the encoder input level. @@ -874,13 +779,6 @@ def _try_schedule_encoder_inputs( if request.mm_hashes[i] in mm_hashes_to_schedule: continue - if self.ec_connector is not None: - if remote_cache_bools[i]: - mm_hashes_to_schedule.add(request.mm_hashes[i]) - encoder_inputs_to_schedule.append(i) - num_tokens_to_schedule += num_encoder_tokens - continue - if self.encoder_cache_manager.check_and_update_cache(request, i): # The encoder input is already computed and cached from a # previous step. @@ -915,6 +813,12 @@ def _try_schedule_encoder_inputs( num_new_tokens = 0 break + if self.ec_connector is not None: + if remote_cache_bools[i]: + mm_hashes_to_schedule.add(request.mm_hashes[i]) + external_load_encoder_input.append(i) + continue + num_tokens_to_schedule += num_encoder_tokens encoder_compute_budget -= num_encoder_tokens mm_hashes_to_schedule.add(request.mm_hashes[i]) @@ -926,6 +830,7 @@ def _try_schedule_encoder_inputs( encoder_inputs_to_schedule, num_new_tokens, encoder_compute_budget, + external_load_encoder_input ) def get_grammar_bitmask( @@ -958,52 +863,12 @@ def get_grammar_bitmask( ) return structured_output_request_ids, bitmask - def update_from_output_encoder_only( - self, - scheduler_output: SchedulerOutput, - model_runner_output: ModelRunnerOutput, - ) -> dict[int, EngineCoreOutputs]: - - outputs: dict[int, list[EngineCoreOutput]] = defaultdict(list) - - # stop all requests from the current batch - model_finished = [] - for request in self.running: - req_id = request.request_id - model_finished.append(req_id) - outputs[request.client_index].append( - EngineCoreOutput(request_id=req_id, - new_token_ids=[], - finish_reason=RequestStatus.get_finished_reason( - RequestStatus.FINISHED_STOPPED - ), - stop_reason="stop", - kv_transfer_params={} - ) - ) - self.finish_requests(model_finished, RequestStatus.FINISHED_STOPPED) - # Create EngineCoreOutputs for all clients that have requests with - # outputs in this step. - engine_core_outputs = { - client_index: EngineCoreOutputs(outputs=outs) - for client_index, outs in outputs.items() - } - - if engine_core_outputs: - # Return stats to only one of the front-ends. - next(iter(engine_core_outputs.values())).scheduler_stats = ( - self.make_stats(None)) - - return engine_core_outputs - def update_from_output( self, scheduler_output: SchedulerOutput, model_runner_output: ModelRunnerOutput, ) -> dict[int, EngineCoreOutputs]: - if self.is_encoder_instance: - return self.update_from_output_encoder_only(scheduler_output, model_runner_output) sampled_token_ids = model_runner_output.sampled_token_ids logprobs = model_runner_output.logprobs prompt_logprobs_dict = model_runner_output.prompt_logprobs_dict @@ -1020,7 +885,7 @@ def update_from_output( stopped_running_reqs: set[Request] = set() stopped_preempted_reqs: set[Request] = set() for req_id, num_tokens_scheduled in num_scheduled_tokens.items(): - assert num_tokens_scheduled > 0 + #assert num_tokens_scheduled > 0 request = self.requests.get(req_id) if request is None: # The request is already finished. This can happen if the diff --git a/vllm/v1/outputs.py b/vllm/v1/outputs.py index 33620764e50b..d24134533be5 100644 --- a/vllm/v1/outputs.py +++ b/vllm/v1/outputs.py @@ -130,6 +130,39 @@ class DraftTokenIds: # num_reqs x num_draft_tokens draft_token_ids: list[list[int]] +def make_empty_encoder_model_runner_output( + scheduler_output: "SchedulerOutput", +) -> ModelRunnerOutput: + """ + Create a ModelRunnerOutput stub that contains the correct + per-request bookkeeping but no generated data yet. + """ + if not scheduler_output.num_scheduled_tokens: + return EMPTY_MODEL_RUNNER_OUTPUT + + # Convert to list so we get a deterministic, indexable sequence + req_ids: list[str] = list(scheduler_output.num_scheduled_tokens.keys()) + + # Give every request its own contiguous index + req_id_to_index: dict[str, int] = {rid: idx for idx, rid in enumerate(req_ids)} + + # No tokens generated yet ⇒ one empty list per request + sampled_token_ids: list[list[int]] = [[] for _ in req_ids] + + # Pooler outputs are not available yet ⇒ use None placeholders + pooler_output: list[Optional[torch.Tensor]] = [None for _ in req_ids] + + return ModelRunnerOutput( + req_ids=req_ids, + req_id_to_index=req_id_to_index, + sampled_token_ids=sampled_token_ids, + logprobs=None, + prompt_logprobs_dict={}, + pooler_output=pooler_output, + kv_connector_output=None, + ec_connector_output=None, + num_nans_in_logits=None, + ) EMPTY_MODEL_RUNNER_OUTPUT = ModelRunnerOutput(req_ids=[], req_id_to_index={}, diff --git a/vllm/v1/worker/gpu_model_runner.py b/vllm/v1/worker/gpu_model_runner.py index 6443eac8db18..1ad01b41af9a 100644 --- a/vllm/v1/worker/gpu_model_runner.py +++ b/vllm/v1/worker/gpu_model_runner.py @@ -69,7 +69,7 @@ KVCacheGroupSpec, KVCacheSpec, MambaSpec, SlidingWindowSpec) from vllm.v1.outputs import (EMPTY_MODEL_RUNNER_OUTPUT, DraftTokenIds, ECConnectorOutput, - LogprobsTensors, ModelRunnerOutput) + LogprobsTensors, ModelRunnerOutput, make_empty_encoder_model_runner_output) from vllm.v1.pool.metadata import PoolingMetadata from vllm.v1.sample.logits_processor import LogitsProcessors, build_logitsprocs from vllm.v1.sample.metadata import SamplingMetadata @@ -1167,6 +1167,7 @@ def _execute_mm_encoder(self, scheduler_output: "SchedulerOutput"): output, is_embed=pos_info.is_embed, ) + logger.debug(f"Finish execute for mm hash {mm_hash}") self.maybe_save_ec_to_connector(self.encoder_cache, mm_hash) def _gather_mm_embeddings( @@ -1465,17 +1466,17 @@ def execute_model( ) -> Union[ModelRunnerOutput, IntermediateTensors]: self._update_states(scheduler_output) - if not scheduler_output.total_num_scheduled_tokens: - if has_ec_transfer(): - if self.vllm_config.ec_transfer_config.ec_role == "ec_producer": - with self.maybe_get_ec_connector_output( - scheduler_output, - encoder_cache=self.encoder_cache, - ) as ec_connector_output: - self._execute_mm_encoder(scheduler_output) - return EMPTY_MODEL_RUNNER_OUTPUT - + if has_ec_transfer(): + if get_ec_transfer().is_producer: + with self.maybe_get_ec_connector_output( + scheduler_output, + encoder_cache=self.encoder_cache, + ) as ec_connector_output: + self._execute_mm_encoder(scheduler_output) + return make_empty_encoder_model_runner_output(scheduler_output) + + if not scheduler_output.total_num_scheduled_tokens: if not has_kv_transfer_group(): # Return empty ModelRunnerOutput if there's no work to do. return EMPTY_MODEL_RUNNER_OUTPUT @@ -1523,9 +1524,6 @@ def execute_model( ) as ec_connector_output: # Run the multimodal encoder if any. self._execute_mm_encoder(scheduler_output) - if has_ec_transfer(): - if self.vllm_config.ec_transfer_config.ec_role == ECProducer: - return EMPTY_MODEL_RUNNER_OUTPUT mm_embeds = self._gather_mm_embeddings(scheduler_output) else: mm_embeds = [] @@ -3194,6 +3192,10 @@ def get_kv_cache_spec(self) -> dict[str, KVCacheSpec]: format. Layers that do not need KV cache are not included. """ + if has_ec_transfer(): + if get_ec_transfer().is_producer: + return {} + block_size = self.vllm_config.cache_config.block_size use_mla = self.vllm_config.model_config.use_mla kv_cache_spec: dict[str, KVCacheSpec] = {} From 946bfb4c41536876f6ee1961c54a1e0c1ad0cb0e Mon Sep 17 00:00:00 2001 From: n00909098 Date: Wed, 10 Sep 2025 14:34:18 +0800 Subject: [PATCH 07/57] [Minor] Fix EC update state after encoder cache allocation Signed-off-by: n00909098 --- .../ec_transfer/ec_connector/base.py | 2 +- .../ec_connector/shared_storage_connector.py | 17 ++++++----------- vllm/v1/core/sched/scheduler.py | 4 ++-- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 219fffd93c11..f6b5cce8ac9c 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -191,7 +191,7 @@ def check_caches_exist( pass @abstractmethod - def update_state_after_alloc(self, request: "Request"): + def update_state_after_alloc(self, request: "Request", index: int): """ Update ECConnector state to decide allocate cache for requests diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 389f4605e3d6..1351a59b4f9e 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -128,20 +128,15 @@ def check_caches_exist( def update_state_after_alloc(self, request: "Request", - cache_exists: list[bool], + index: int, ) -> None: """ - Update ECConnector state after block allocation. - - If cache exist for mm_data, need to load it + Update ECConnector state after encoder cache allocation. """ - - for index, has_cache in enumerate(cache_exists): - if has_cache: - mm_hash = request.mm_hashes[index] - num_encoder_token = request.get_num_encoder_tokens(index) - # Insert mm_hash only if this block has not been recorded yet. - self._mm_datas_need_loads[mm_hash] = num_encoder_token + mm_hash = request.mm_hashes[index] + num_encoder_token = request.get_num_encoder_tokens(index) + # Insert mm_hash only if this block has not been recorded yet. + self._mm_datas_need_loads[mm_hash] = num_encoder_token def build_connector_meta( self, diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index 6792a38841d5..b2c8ac881d32 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -324,6 +324,7 @@ def schedule(self) -> SchedulerOutput: if external_load_encoder_input: for i in external_load_encoder_input: self.encoder_cache_manager.allocate(request, i) + self.ec_connector.update_state_after_alloc(request, i) # Record the LoRAs in scheduled_running_reqs scheduled_loras: set[int] = set() @@ -542,6 +543,7 @@ def schedule(self) -> SchedulerOutput: if external_load_encoder_input: for i in external_load_encoder_input: self.encoder_cache_manager.allocate(request, i) + self.ec_connector.update_state_after_alloc(request, i) # Put back any skipped requests at the head of the waiting queue if skipped_waiting_requests: self.waiting.prepend_requests(skipped_waiting_requests) @@ -823,8 +825,6 @@ def _try_schedule_encoder_inputs( encoder_compute_budget -= num_encoder_tokens mm_hashes_to_schedule.add(request.mm_hashes[i]) encoder_inputs_to_schedule.append(i) - if self.ec_connector: - self.ec_connector.update_state_after_alloc(request, remote_cache_bools) return ( encoder_inputs_to_schedule, From e1ecb30e8d89c5c6d05ffb963ee672f1821f53ab Mon Sep 17 00:00:00 2001 From: n00909098 Date: Wed, 10 Sep 2025 15:46:45 +0800 Subject: [PATCH 08/57] [Bug] Check actualy tensor file for EC Cache exist in ECSharedStorageConnector Signed-off-by: n00909098 --- .../ec_transfer/ec_connector/shared_storage_connector.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 1351a59b4f9e..4d84590143cb 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -166,8 +166,8 @@ def _found_match_for_mm_data( ) -> bool: """Check if the cache is hit for the request. """ - foldername = self._generate_foldername_debug(mm_hash,create_folder=False) - return os.path.exists(foldername) + filename = self._generate_filename_debug(mm_hash) + return os.path.exists(filename) def _generate_foldername_debug( self, From d20c0f867bcf9519e4866f6855d9ef71ab13a2a4 Mon Sep 17 00:00:00 2001 From: n00909098 Date: Wed, 10 Sep 2025 16:41:37 +0800 Subject: [PATCH 09/57] [Bugfix] Encoder Instance does not return Output to client Signed-off-by: n00909098 --- vllm/v1/core/sched/scheduler.py | 2 +- vllm/v1/outputs.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index b2c8ac881d32..649b1862c5cd 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -104,7 +104,7 @@ def __init__( if self.ec_connector.is_producer: # TODO(Long) Set this when set up self.cache_config.enable_prefix_caching=False - self.max_model_len = 0 + self.max_model_len = 1 num_gpu_blocks = self.cache_config.num_gpu_blocks diff --git a/vllm/v1/outputs.py b/vllm/v1/outputs.py index d24134533be5..aab17993d70a 100644 --- a/vllm/v1/outputs.py +++ b/vllm/v1/outputs.py @@ -5,6 +5,7 @@ from typing import NamedTuple, Optional import torch +from vllm.v1.core.sched.output import SchedulerOutput class LogprobsLists(NamedTuple): @@ -147,7 +148,7 @@ def make_empty_encoder_model_runner_output( req_id_to_index: dict[str, int] = {rid: idx for idx, rid in enumerate(req_ids)} # No tokens generated yet ⇒ one empty list per request - sampled_token_ids: list[list[int]] = [[] for _ in req_ids] + sampled_token_ids: list[list[int]] = [[0] for _ in req_ids] # Pooler outputs are not available yet ⇒ use None placeholders pooler_output: list[Optional[torch.Tensor]] = [None for _ in req_ids] From a290dda8fdbf4ff0006374743f0bbae404cabc51 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Thu, 11 Sep 2025 09:29:59 +0800 Subject: [PATCH 10/57] [Bugfix] Fix try scheduler encoder inputs return when there is no encoder input Signed-off-by: knlnguyen1802 --- vllm/v1/core/sched/scheduler.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index 649b1862c5cd..2e8204dd9d8c 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -205,9 +205,6 @@ def schedule(self) -> SchedulerOutput: # For logging. scheduled_timestamp = time.monotonic() - # self.external_load_encoder_cache: dict[str, list[int]] = {} - # self.external_load_encoder_cache.clear() - # First, schedule the RUNNING requests. req_index = 0 while req_index < len(self.running) and token_budget > 0: @@ -710,7 +707,7 @@ def _try_schedule_encoder_inputs( num_computed_tokens: int, num_new_tokens: int, encoder_compute_budget: int, - ) -> tuple[list[int], int, int]: + ) -> tuple[list[int], int, int, list[int]]: """ Determine which encoder inputs need to be scheduled in the current step, and update `num_new_tokens` and encoder token budget accordingly. @@ -720,6 +717,7 @@ def _try_schedule_encoder_inputs( in this step, i.e., [num_computed_tokens, num_computed_tokens + num_new_tokens). - It is not already computed and stored in the encoder cache. + - It is not exist on remote encoder cache (via ECConnector) - There is sufficient encoder token budget to process it. - The encoder cache has space to store it. @@ -731,7 +729,7 @@ def _try_schedule_encoder_inputs( blocks and externally cached blocks (via KVConnector). """ if num_new_tokens == 0 or not request.has_encoder_inputs: - return [], num_new_tokens, encoder_compute_budget + return [], num_new_tokens, encoder_compute_budget, [] encoder_inputs_to_schedule: list[int] = [] mm_positions = request.mm_positions assert mm_positions is not None From 668125d4682d27f83bf8fd7f269446531c999967 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Fri, 12 Sep 2025 11:10:59 +0800 Subject: [PATCH 11/57] [Fix] Fix typo and move all hardcode to launch config Signed-off-by: knlnguyen1802 --- draft/launch.sh | 6 ++++-- draft/proxy.py | 13 ++++++++++-- vllm/config/__init__.py | 2 +- .../ec_transfer/ec_connector/base.py | 2 +- .../ec_connector/shared_storage_connector.py | 2 +- vllm/v1/core/sched/scheduler.py | 20 ++++++++++++------- 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/draft/launch.sh b/draft/launch.sh index 0bf6449c8612..44f2d351edfc 100644 --- a/draft/launch.sh +++ b/draft/launch.sh @@ -34,16 +34,18 @@ SHARED_STORAGE_PATH="/path/to/your/share/storage" # Encoder worker ############################################################################### CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ - --gpu-memory-utilization 0.7 \ + --gpu-memory-utilization 0.0 \ --port "$ENCODE_PORT" \ --enable-request-id-headers \ + --no-enable-prefix-caching \ --max-num-seqs 128 \ --enforce-eager \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_producer", "ec_connector_extra_config": { - "shared_storage_path": "'"$SHARED_STORAGE_PATH"'" + "shared_storage_path": "'"$SHARED_STORAGE_PATH"'", + "ec_max_num_scheduled_tokens": "4096" } }' \ >"$ENC_LOG" 2>&1 & diff --git a/draft/proxy.py b/draft/proxy.py index 318e6295eb8a..156f331f4d8b 100644 --- a/draft/proxy.py +++ b/draft/proxy.py @@ -1,5 +1,6 @@ # api_proxy.py import asyncio +import copy import json import time import uuid @@ -61,10 +62,14 @@ async def forward_streaming_request( headers = {"x-request-id": request_id} # Skip request to encoder instance if we don't have mm input if has_mm_input(request_data): + encoder_request_data = copy.deepcopy(request_data) + encoder_request_data["max_tokens"] = 1 + if "max_completion_tokens" in encoder_request_data: + encoder_request_data["max_completion_tokens"] = 1 task1 = asyncio.create_task( encode_session.post( f"{e_server_url}/v1/chat/completions", - json=request_data, + json=encoder_request_data, headers=headers ) ) @@ -107,11 +112,15 @@ async def forward_non_streaming_request( headers = {"x-request-id": request_id} # Skip request to encoder instance if we don't have mm input if has_mm_input(request_data): + encoder_request_data = copy.deepcopy(request_data) + encoder_request_data["max_tokens"] = 1 + if "max_completion_tokens" in encoder_request_data: + encoder_request_data["max_completion_tokens"] = 1 # Start request to encode server task1 = asyncio.create_task( encode_session.post( f"{e_server_url}/v1/chat/completions", - json=request_data, + json=encoder_request_data, headers=headers ) ) diff --git a/vllm/config/__init__.py b/vllm/config/__init__.py index 21bfde0062a7..008c0b8e0208 100644 --- a/vllm/config/__init__.py +++ b/vllm/config/__init__.py @@ -3287,7 +3287,7 @@ def is_ec_producer(self) -> bool: self.ec_role in get_args(ECProducer) @property - def is_kv_consumer(self) -> bool: + def is_ec_consumer(self) -> bool: return self.ec_connector is not None and \ self.ec_role in get_args(ECConsumer) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index f6b5cce8ac9c..2774c7b7dad0 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -65,7 +65,7 @@ def __init__(self, vllm_config: "VllmConfig", role: ECConnectorRole): self._connector_metadata: Optional[ECConnectorMetadata] = None self._vllm_config = vllm_config self._role = role - self._is_producer = (vllm_config.ec_transfer_config.ec_role == 'ec_producer') + self._is_producer = vllm_config.ec_transfer_config.is_ec_producer @property def role(self) -> ECConnectorRole: diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 4d84590143cb..f2ad5f39061c 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -50,7 +50,7 @@ class ECSharedStorageConnector(ECConnectorBase): # NOTE: This is Simple debug implementation of the EC connector. # It save / load the EC cache to / from the disk. - def __init__(self, vllm_config: "VllmConfig", role: ECConnectorBase): + def __init__(self, vllm_config: "VllmConfig", role: ECConnectorRole): super().__init__(vllm_config=vllm_config, role=role) # req_id -> index -> MMMeta self._mm_datas_need_loads: dict[str, int] = {} diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index 2e8204dd9d8c..f664cb76acfd 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -97,15 +97,17 @@ def __init__( self.parallel_config.data_parallel_rank, ) self.ec_connector = None + self.ec_max_num_scheduled_tokens = 0 if self.vllm_config.ec_transfer_config is not None: self.ec_connector = ECConnectorFactory.create_connector( config=self.vllm_config, role=ECConnectorRole.SCHEDULER ) - if self.ec_connector.is_producer: - # TODO(Long) Set this when set up - self.cache_config.enable_prefix_caching=False - self.max_model_len = 1 - + transfer_config = self.vllm_config.ec_transfer_config + self.ec_max_num_scheduled_tokens = int( + transfer_config.get_from_extra_config( + "ec_max_num_scheduled_tokens", 0 + ) + ) num_gpu_blocks = self.cache_config.num_gpu_blocks assert num_gpu_blocks is not None and num_gpu_blocks > 0 @@ -195,7 +197,8 @@ def schedule(self) -> SchedulerOutput: req_to_new_blocks: dict[str, KVCacheBlocks] = {} num_scheduled_tokens: dict[str, int] = {} - token_budget = self.max_num_scheduled_tokens + token_budget = max(self.max_num_scheduled_tokens, \ + self.ec_max_num_scheduled_tokens) # Encoder-related. scheduled_encoder_inputs: dict[str, list[int]] = {} encoder_compute_budget = self.max_num_encoder_input_tokens @@ -547,7 +550,10 @@ def schedule(self) -> SchedulerOutput: # Check if the scheduling constraints are satisfied. total_num_scheduled_tokens = sum(num_scheduled_tokens.values()) - assert total_num_scheduled_tokens <= self.max_num_scheduled_tokens + assert total_num_scheduled_tokens <= max( + self.max_num_scheduled_tokens, + self.ec_max_num_scheduled_tokens, + ) assert token_budget >= 0 assert len(self.running) <= self.max_num_running_reqs # Since some requests in the RUNNING queue may not be scheduled in From 62d4a2ab474a5bf2f0e136076d531a0df8a55a38 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Fri, 12 Sep 2025 11:54:49 +0800 Subject: [PATCH 12/57] [Fix] Fix typo in docs Signed-off-by: knlnguyen1802 --- vllm/distributed/ec_transfer/ec_connector/base.py | 9 ++++----- .../ec_transfer/ec_connector/shared_storage_connector.py | 6 +++--- vllm/distributed/ec_transfer/ec_transfer_state.py | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 2774c7b7dad0..b1dc978fd5f2 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -30,7 +30,7 @@ from vllm.logger import init_logger from vllm.v1.core.sched.output import SchedulerOutput -from vllm.v1.outputs import KVConnectorOutput +from vllm.v1.outputs import (KVConnectorOutput, ECConnectorOutput) if TYPE_CHECKING: from vllm.attention.backends.abstract import AttentionMetadata @@ -127,7 +127,6 @@ def start_load_caches(self, **kwargs) -> None: """ Start loading the cache from the connector to vLLM's encoder cache. This is called before _gather_mm_embeddings for EC Connector - and before execute_model for KV Connector For EC the encoder_cache and mm_hash is store in kwargs Args: @@ -214,12 +213,12 @@ def build_connector_meta( """ pass - def update_connector_output(self, connector_output: KVConnectorOutput): + def update_connector_output(self, connector_output: ECConnectorOutput): """ - Update KVConnector state from worker-side connectors output. + Update ECConnector state from worker-side connectors output. Args: - connector_output (KVConnectorOutput): the worker-side + connector_output (ECConnectorOutput): the worker-side connectors output. """ return diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index f2ad5f39061c..e0dfbbd07e4a 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -74,10 +74,10 @@ def start_load_caches(self, **kwargs) -> None: assert encoder_cache is not None if metadata is None: logger.warning( - "In connector.start_load_kv, but the connector metadata is None" + "In connector.start_load_caches, but the connector metadata is None" ) return - # Load the KV for each request each layer + # Load the EC for each mm datas for mm_data in metadata.mm_datas: if mm_data.mm_hash in encoder_cache: continue @@ -87,7 +87,7 @@ def start_load_caches(self, **kwargs) -> None: logger.debug(f"Success load encoder cache for hash {mm_data.mm_hash}") def save_caches(self, **kwargs) -> None: - """Start saving the KV cache of the layer from encoder cache + """Start saving the EC cache for each mm_datas from encoder cache Args: **kwargs: additional arguments for the save operation. diff --git a/vllm/distributed/ec_transfer/ec_transfer_state.py b/vllm/distributed/ec_transfer/ec_transfer_state.py index 36e5f81f92e7..8f35c25f1c3d 100644 --- a/vllm/distributed/ec_transfer/ec_transfer_state.py +++ b/vllm/distributed/ec_transfer/ec_transfer_state.py @@ -25,7 +25,7 @@ def has_ec_transfer() -> bool: def ensure_ec_transfer_initialized(vllm_config: "VllmConfig") -> None: """ - Initialize KV cache transfer parallel group. + Initialize EC cache connector. """ global _EC_CONNECTOR_AGENT From a0735ce011d945bd9ae039378983a7cb8431748e Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Mon, 15 Sep 2025 14:05:41 +0800 Subject: [PATCH 13/57] [Misc] Add example for disaggregate encoder Signed-off-by: knlnguyen1802 --- .../disagg_encoder_example.sh | 160 ++++++++ .../disagg_encoder_proxy.py | 346 ++++++++++++++++++ 2 files changed, 506 insertions(+) create mode 100644 examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh create mode 100644 examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh new file mode 100644 index 000000000000..46939e3f0d47 --- /dev/null +++ b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2086,SC2155 +set -euo pipefail + +############################################################################### +# Configuration -- override via env before running +############################################################################### +MODEL="${MODEL:-Qwen/Qwen2.5-VL-3B-Instruct}" + +LOG_PATH="${LOG_PATH:-./logs}" +ENCODE_PORT="${ENCODE_PORT:-19534}" +PREFILL_DECODE_PORT="${PREFILL_DECODE_PORT:-19535}" +PROXY_PORT="${PROXY_PORT:-10001}" + +GPU_E="${GPU_E:-0}" +GPU_PD="${GPU_PD:-1}" + +SHARED_STORAGE_PATH="${SHARED_STORAGE_PATH:-/tmp/}" +TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout + +############################################################################### +# Dependencies check ########################################################## +############################################################################### +ensure_python_library_installed() { + local lib=$1 + echo -n "[check] Python package '$lib' … " + if python3 - </dev/null 2>&1 +import importlib, sys +sys.exit(0) if importlib.util.find_spec("${lib}") else sys.exit(1) +EOF + then + echo "OK" + else + echo "NOT FOUND" + echo "Please install it, e.g.: pip install $lib" + exit 1 + fi +} + +ensure_python_library_installed vllm +ensure_python_library_installed pandas +ensure_python_library_installed datasets + +############################################################################### +# Helpers +############################################################################### +mkdir -p "$LOG_PATH" +START_TIME=$(date +"%Y%m%d_%H%M%S") +ENC_LOG="$LOG_PATH/encoder_$START_TIME.log" +PD_LOG="$LOG_PATH/pd_$START_TIME.log" +PROXY_LOG="$LOG_PATH/proxy_$START_TIME.log" + +wait_for_server() { + local port=$1 + timeout "$TIMEOUT_SECONDS" bash -c ' + until curl -s "http://localhost:'"$port"'/v1/chat/completions" > /dev/null; do + sleep 1 + done + ' +} + +# keep PIDs in memory +declare -a PIDS=() +CLEANED=0 +cleanup() { + (( CLEANED )) && return # run only once + CLEANED=1 + + echo "Cleaning up…" + # iterate backwards (proxy → PD → encoder) + for (( idx=${#PIDS[@]}-1 ; idx>=0 ; idx-- )); do + PID=${PIDS[idx]} + if kill -0 "$PID" 2>/dev/null; then + echo " • Killing $PID" + kill "$PID" + sleep 2 + kill -9 "$PID" 2>/dev/null || true + fi + done + echo "Done." +} + +trap cleanup EXIT INT TERM ERR + +############################################################################### +# Encoder worker +############################################################################### +CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ + --gpu-memory-utilization 0.0 \ + --port "$ENCODE_PORT" \ + --enable-request-id-headers \ + --no-enable-prefix-caching \ + --max-num-seqs 128 \ + --enforce-eager \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_producer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$SHARED_STORAGE_PATH"'", + "ec_max_num_scheduled_tokens": "4096" + } + }' \ + >"$ENC_LOG" 2>&1 & + +PIDS+=($!) + +############################################################################### +# Prefill / decode worker +############################################################################### +CUDA_VISIBLE_DEVICES="$GPU_PD" vllm serve "$MODEL" \ + --gpu-memory-utilization 0.7 \ + --port "$PREFILL_DECODE_PORT" \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --enforce-eager \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_consumer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$SHARED_STORAGE_PATH"'" + } + }' \ + >"$PD_LOG" 2>&1 & + +PIDS+=($!) + +# Wait for workers +wait_for_server "$ENCODE_PORT" +wait_for_server "$PREFILL_DECODE_PORT" + +############################################################################### +# Proxy +############################################################################### +python disagg_encoder_proxy.py \ + --host "127.0.0.1" \ + --port "$PROXY_PORT" \ + --encode-servers-urls "http://localhost:$ENCODE_PORT" \ + --prefill-decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT" \ + >"$PROXY_LOG" 2>&1 & + +PIDS+=($!) + +wait_for_server "$PROXY_PORT" +echo "All services are up!" + +############################################################################### +# Benchmark +cd ../../../../benchmarks +python benchmark_serving.py \ + --backend openai-chat \ + --model $MODEL \ + --dataset-name hf \ + --dataset-path lmarena-ai/VisionArena-Chat \ + --seed 0 \ + --endpoint /v1/chat/completions \ + --num-prompts 10 \ + --port $PROXY_PORT \ + --host 127.0.0.1 +############################################################################### +cleanup \ No newline at end of file diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py new file mode 100644 index 000000000000..b2389e0491e7 --- /dev/null +++ b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py @@ -0,0 +1,346 @@ +# disagg_encoder_proxy.py +""" +FastAPI-based proxy that routes “/v1/chat/completions” requests to a +pair of back-end clusters: + • encode (multimodal feature extraction) + • prefill/decode (language model inference) + +It supports both streaming and non-streaming Chat Completions, health +checks, and an ad-hoc profiling API that can be fanned out to all +back-ends. + +Run: + +$ python disagg_encoder_proxy.py \ + --encode-servers-urls "http://localhost:8001" \ + --prefill-decode-servers-urls "http://localhost:8003" +""" + +from __future__ import annotations + +import argparse +import asyncio +import copy +import json +import logging +import os +import random +import time +import uuid +from typing import Any, AsyncIterator, Dict, Optional + +import aiohttp +import uvicorn +from fastapi import FastAPI, HTTPException, Request +from fastapi.responses import JSONResponse, StreamingResponse + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +app = FastAPI() + +encode_session: Optional[aiohttp.ClientSession] = None +decode_session: Optional[aiohttp.ClientSession] = None + + +# --------------------------------------------------------------------------- +# FastAPI life-cycle hooks +# --------------------------------------------------------------------------- + + +@app.on_event("startup") +async def startup_event() -> None: + global encode_session, decode_session + + encode_session = aiohttp.ClientSession( + connector=aiohttp.TCPConnector(limit=0), + timeout=aiohttp.ClientTimeout(total=100_000), + ) + decode_session = aiohttp.ClientSession( + connector=aiohttp.TCPConnector(limit=0), + timeout=aiohttp.ClientTimeout(total=100_000), + ) + + +@app.on_event("shutdown") +async def shutdown_event() -> None: + global encode_session, decode_session + + if encode_session: + await encode_session.close() + if decode_session: + await decode_session.close() + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def has_mm_input(request_data: dict) -> bool: + """Return True if the chat request contains image or audio content.""" + if "messages" not in request_data: + return False + + for message in request_data["messages"]: + content = message.get("content") + if not isinstance(content, list): + continue + + for item in content: + if item.get("type") in {"image_url", "audio_url", "input_audio"}: + return True + return False + + +# --------------------------------------------------------------------------- +# Core forwarding logic +# --------------------------------------------------------------------------- + + +async def forward_streaming_request( + request_data: dict, + request_id: str, + e_server_url: str, + pd_server_url: str, +) -> AsyncIterator[str]: + """Yield SSE chunks from the decode server, optionally priming the encoder.""" + headers = {"x-request-id": request_id} + + # 1. Kick off a 1-token request to the encoder if MM input is present. + if has_mm_input(request_data): + encoder_req = copy.deepcopy(request_data) + encoder_req["max_tokens"] = 1 + if "max_completion_tokens" in encoder_req: + encoder_req["max_completion_tokens"] = 1 + + try: + resp = await encode_session.post( + f"{e_server_url}/v1/chat/completions", + json=encoder_req, + headers=headers, + ) + if resp.status != 200: + raise HTTPException( + status_code=resp.status, + detail={"error": "Encoder request failed", "message": await resp.text()}, + ) + except Exception as exc: + raise HTTPException(status_code=500, detail=str(exc)) from exc + + # 2. Stream from the decode server. + try: + async with decode_session.post( + f"{pd_server_url}/v1/chat/completions", + json=request_data, + headers=headers, + ) as resp: + resp.raise_for_status() + async for chunk in resp.content.iter_chunked(128): + if chunk: + yield chunk.decode("utf-8", errors="ignore") + except Exception as exc: + logger.error("Error in streaming: %s", exc) + raise + + +async def forward_non_streaming_request( + request_data: dict, + request_id: str, + e_server_url: str, + pd_server_url: str, +) -> dict: + """Return full JSON response from decode server, with optional encoder prime.""" + headers = {"x-request-id": request_id} + + # 1. Optional encoder prime. + if has_mm_input(request_data): + encoder_req = copy.deepcopy(request_data) + encoder_req["max_tokens"] = 1 + if "max_completion_tokens" in encoder_req: + encoder_req["max_completion_tokens"] = 1 + + try: + resp = await encode_session.post( + f"{e_server_url}/v1/chat/completions", + json=encoder_req, + headers=headers, + ) + if resp.status != 200: + raise HTTPException( + status_code=resp.status, + detail={"error": "Encoder request failed", "message": await resp.text()}, + ) + except Exception as exc: + raise HTTPException(status_code=500, detail=str(exc)) from exc + + # 2. Full decode request. + try: + async with decode_session.post( + f"{pd_server_url}/v1/chat/completions", + json=request_data, + headers=headers, + ) as resp: + resp.raise_for_status() + return await resp.json() + except Exception as exc: + logger.error("Error in non-streaming: %s", exc) + raise + + +# --------------------------------------------------------------------------- +# Public API routes +# --------------------------------------------------------------------------- + + +@app.post("/v1/chat/completions") +async def chat_completions(request: Request): + """Handle OpenAI-compatible Chat Completion requests.""" + try: + e_server_url = random.choice(app.state.e_urls) + pd_server_url = random.choice(app.state.pd_urls) + + req_data = await request.json() + req_id = request.headers.get("x-request-id", str(uuid.uuid4())) + is_stream = req_data.get("stream", False) + + if is_stream: + return StreamingResponse( + forward_streaming_request(req_data, req_id, e_server_url, pd_server_url), + media_type="text/event-stream", + ) + result = await forward_non_streaming_request( + req_data, req_id, e_server_url, pd_server_url + ) + return JSONResponse(content=result) + + except Exception as exc: + logger.error("Error processing request: %s", exc) + raise HTTPException(status_code=500, detail=str(exc)) from exc + + +@app.get("/v1/models") +async def list_models(): + """Proxy the model list from the first decode server.""" + try: + async with decode_session.get(f"{app.state.pd_urls[0]}/v1/models") as resp: + resp.raise_for_status() + return await resp.json() + except Exception as exc: + logger.error("Error fetching models: %s", exc) + raise HTTPException(status_code=500, detail=str(exc)) from exc + + +@app.get("/health") +async def health_check(): + """Aggregate health of proxy, encode, and decode servers.""" + async def check(urls, session): + try: + for u in urls: + async with session.get(f"{u}/health") as resp: + resp.raise_for_status() + return True + except Exception: + return False + + encode_ok, decode_ok = await asyncio.gather( + check(app.state.e_urls, encode_session), + check(app.state.pd_urls, encode_session), + ) + + status = { + "proxy": "healthy", + "encode_servers": "healthy" if encode_ok else "unhealthy", + "prefill_decode_servers": "healthy" if decode_ok else "unhealthy", + } + return JSONResponse(content=status, status_code=200 if encode_ok and decode_ok else 503) + + +# --------------------------------------------------------------------------- +# Profiling fan-out helpers +# --------------------------------------------------------------------------- + + +async def send_profile_cmd( + request: Request, + req_data: dict, + cmd: str, + e_server_url: str, + pd_server_url: str, +): + """Fan out a profiler start/stop command to all back-ends.""" + assert cmd in {"start", "stop"} + + headers = {"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}"} + + tasks = [ + encode_session.post(f"{e_server_url}/{cmd}_profile", json=req_data, headers=headers), + decode_session.post(f"{pd_server_url}/{cmd}_profile", json=req_data, headers=headers), + ] + + responses = await asyncio.gather(*tasks, return_exceptions=True) + for r in responses: + if isinstance(r, Exception): + raise r + r.raise_for_status() + + return await responses[0].json(content_type=None) + + +@app.post("/start_profile") +async def start_profile(request: Request): + """Start profiling on all back-ends.""" + e_server_url = random.choice(app.state.e_urls) + pd_server_url = random.choice(app.state.pd_urls) + data = await request.json() + return await send_profile_cmd(request, data, "start", e_server_url, pd_server_url) + + +@app.post("/stop_profile") +async def stop_profile(request: Request): + """Stop profiling on all back-ends.""" + e_server_url = random.choice(app.state.e_urls) + pd_server_url = random.choice(app.state.pd_urls) + data = await request.json() + return await send_profile_cmd(request, data, "stop", e_server_url, pd_server_url) + + +# --------------------------------------------------------------------------- +# Entrypoint +# --------------------------------------------------------------------------- + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="API Proxy for distributed vLLM servers") + parser.add_argument("--host", default="0.0.0.0", help="Proxy host") + parser.add_argument("--port", type=int, default=8000, help="Proxy port") + parser.add_argument( + "--encode-servers-urls", + required=True, + help='Comma-separated list of encode server URLs (e.g. "http://e1:8001,http://e2:8001")', + ) + parser.add_argument( + "--prefill-decode-servers-urls", + required=True, + help='Comma-separated list of prefill/decode server URLs (e.g. "http://d1:8003,http://d2:8003")', + ) + + args = parser.parse_args() + app.state.e_urls = args.encode_servers_urls.split(",") + app.state.pd_urls = args.prefill_decode_servers_urls.split(",") + + logger.info( + "Starting API proxy on %s:%s (encode=%s, decode=%s)", + args.host, + args.port, + app.state.e_urls, + app.state.pd_urls, + ) + + uvicorn.run( + app, + host=args.host, + port=args.port, + log_level="info", + access_log=False, + loop="uvloop", + ) \ No newline at end of file From bc1f9ba9825c8ddccc02423a83b58e9a54d22eaf Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Mon, 15 Sep 2025 14:31:47 +0800 Subject: [PATCH 14/57] [Fix] Clean code Signed-off-by: knlnguyen1802 --- .gitignore | 4 +- draft/launch.sh | 92 --------------- draft/proxy.py | 266 ------------------------------------------ draft/send_request.py | 81 ------------- draft/stop.sh | 36 ------ 5 files changed, 1 insertion(+), 478 deletions(-) delete mode 100644 draft/launch.sh delete mode 100644 draft/proxy.py delete mode 100644 draft/send_request.py delete mode 100644 draft/stop.sh diff --git a/.gitignore b/.gitignore index a6e7f7020095..465935d488f8 100644 --- a/.gitignore +++ b/.gitignore @@ -209,6 +209,4 @@ shellcheck*/ csrc/moe/marlin_moe_wna16/kernel_* # Ignore ep_kernels_workspace folder -ep_kernels_workspace/ - -.safetensors \ No newline at end of file +ep_kernels_workspace/ \ No newline at end of file diff --git a/draft/launch.sh b/draft/launch.sh deleted file mode 100644 index 44f2d351edfc..000000000000 --- a/draft/launch.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -wait_for_server() { - local port=$1 - timeout 12000 bash -c ' - until curl -s "http://localhost:'"$port"'/v1/chat/completions" > /dev/null; do - sleep 1 - done - ' && return 0 || return 1 -} - -MODEL="/path/to/model/Qwen2.5-VL-3B-Instruct" - -LOG_PATH=${LOG_PATH:-./logs} -mkdir -p "$LOG_PATH" - -ENCODE_PORT=19534 -PREFILL_DECODE_PORT=19535 -PROXY_PORT=10001 - -GPU_E=1 -GPU_PD=7 - -START_TIME=$(date +"%Y%m%d_%H%M%S") -ENC_LOG="$LOG_PATH/encoder.log" -PD_LOG="$LOG_PATH/pd.log" -PROXY_LOG="$LOG_PATH/proxy.log" -PID_FILE="./pid.txt" - -SHARED_STORAGE_PATH="/path/to/your/share/storage" - -############################################################################### -# Encoder worker -############################################################################### -CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ - --gpu-memory-utilization 0.0 \ - --port "$ENCODE_PORT" \ - --enable-request-id-headers \ - --no-enable-prefix-caching \ - --max-num-seqs 128 \ - --enforce-eager \ - --ec-transfer-config '{ - "ec_connector": "ECSharedStorageConnector", - "ec_role": "ec_producer", - "ec_connector_extra_config": { - "shared_storage_path": "'"$SHARED_STORAGE_PATH"'", - "ec_max_num_scheduled_tokens": "4096" - } - }' \ - >"$ENC_LOG" 2>&1 & - -echo $! >> "$PID_FILE" - -############################################################################### -# Prefill / decode worker -############################################################################### -CUDA_VISIBLE_DEVICES="$GPU_PD" vllm serve "$MODEL" \ - --gpu-memory-utilization 0.7 \ - --port "$PREFILL_DECODE_PORT" \ - --enable-request-id-headers \ - --max-num-seqs 128 \ - --enforce-eager \ - --ec-transfer-config '{ - "ec_connector": "ECSharedStorageConnector", - "ec_role": "ec_consumer", - "ec_connector_extra_config": { - "shared_storage_path": "'"$SHARED_STORAGE_PATH"'" - } - }' \ - >"$PD_LOG" 2>&1 & - -echo $! >> "$PID_FILE" - -# Wait until both workers are ready -wait_for_server "$ENCODE_PORT" -wait_for_server "$PREFILL_DECODE_PORT" - -############################################################################### -# Proxy -############################################################################### -python /path/to/vllm/vllm/draft/proxy.py \ - --host "127.0.0.1" \ - --port "$PROXY_PORT" \ - --encode-servers-urls "http://localhost:$ENCODE_PORT" \ - --prefill-decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT" \ - >"$PROXY_LOG" 2>&1 & - -echo $! >> "$PID_FILE" - -wait_for_server "$PROXY_PORT" -echo "All services are up!" \ No newline at end of file diff --git a/draft/proxy.py b/draft/proxy.py deleted file mode 100644 index 156f331f4d8b..000000000000 --- a/draft/proxy.py +++ /dev/null @@ -1,266 +0,0 @@ -# api_proxy.py -import asyncio -import copy -import json -import time -import uuid -from typing import AsyncIterator, Optional, Dict, Any -from fastapi import FastAPI, Request, HTTPException -import aiohttp -from fastapi.responses import StreamingResponse, JSONResponse -import uvicorn -import argparse -import logging -import random - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -app = FastAPI() - -encode_session: Optional[aiohttp.ClientSession] = None -decode_session: Optional[aiohttp.ClientSession] = None - -@app.on_event("startup") -async def startup_event(): - global encode_session, decode_session - encode_session = aiohttp.ClientSession( - connector=aiohttp.TCPConnector(limit=0), - timeout=aiohttp.ClientTimeout(total=100000)) - decode_session = aiohttp.ClientSession( - connector=aiohttp.TCPConnector(limit=0), - timeout=aiohttp.ClientTimeout(total=100000)) - -@app.on_event("shutdown") -async def shutdown_event(): - global encode_session, decode_session - if encode_session: - await encode_session.close() - if decode_session: - await decode_session.close() - - -def has_mm_input(request_data: dict): - if "messages" not in request_data: - return False - for message in request_data["messages"]: - if not isinstance(message.get("content"), list): - continue - for content_item in message["content"]: - if content_item.get("type") in ["image_url", "audio_url", "input_audio"]: - return True - return False - -async def forward_streaming_request( - request_data: dict, - request_id: str, - e_server_url: str, - pd_server_url: str, -) -> AsyncIterator[str]: - - - headers = {"x-request-id": request_id} - # Skip request to encoder instance if we don't have mm input - if has_mm_input(request_data): - encoder_request_data = copy.deepcopy(request_data) - encoder_request_data["max_tokens"] = 1 - if "max_completion_tokens" in encoder_request_data: - encoder_request_data["max_completion_tokens"] = 1 - task1 = asyncio.create_task( - encode_session.post( - f"{e_server_url}/v1/chat/completions", - json=encoder_request_data, - headers=headers - ) - ) - try: - response = await task1 - if response.status != 200: - error_text = await response.text() - raise HTTPException( - status_code=response.status, - detail={"error": "Request failed", "message": error_text} - ) - except Exception as e: - raise HTTPException( - status_code=500, - detail={"error": "Internal server error", "message": str(e)} - ) - - # import time - # time.sleep(10) - try: - async with decode_session.post( - f"{pd_server_url}/v1/chat/completions", - json=request_data, - headers=headers - ) as response: - response.raise_for_status() - async for chunk in response.content.iter_chunked(128): - if chunk: - yield chunk.decode('utf-8', errors='ignore') - except Exception as e: - logger.error(f"Error in streaming: {e}") - raise - -async def forward_non_streaming_request( - request_data: dict, - request_id: str, - e_server_url: str, - pd_server_url: str, -) -> dict: - headers = {"x-request-id": request_id} - # Skip request to encoder instance if we don't have mm input - if has_mm_input(request_data): - encoder_request_data = copy.deepcopy(request_data) - encoder_request_data["max_tokens"] = 1 - if "max_completion_tokens" in encoder_request_data: - encoder_request_data["max_completion_tokens"] = 1 - # Start request to encode server - task1 = asyncio.create_task( - encode_session.post( - f"{e_server_url}/v1/chat/completions", - json=encoder_request_data, - headers=headers - ) - ) - - try: - response = await task1 - if response.status != 200: - error_text = await response.text() - raise HTTPException( - status_code=response.status, - detail={"error": "Request failed", "message": error_text} - ) - except Exception as e: - raise HTTPException( - status_code=500, - detail={"error": "Internal server error", "message": str(e)} - ) - - try: - # Make request to decode server - async with decode_session.post( - f"{pd_server_url}/v1/chat/completions", - json=request_data, - headers=headers - ) as response2: - response2.raise_for_status() - result = await response2.json() - return result - except Exception as e: - logger.error(f"Error in non-streaming: {e}") - raise - -@app.post("/v1/chat/completions") -async def chat_completions(request: Request): - """Handle chat completion requests.""" - try: - e_instance = random.randint(0, len(app.state.e_urls) - 1) - pd_instance = random.randint(0, len(app.state.pd_urls) - 1) - e_server_url = app.state.e_urls[e_instance] - pd_server_url = app.state.pd_urls[pd_instance] - - - request_data = await request.json() - request_id = request.headers.get("x-request-id") - if not request_id: - request_id = str(uuid.uuid4()) - is_streaming = request_data.get("stream", False) - if is_streaming: - return StreamingResponse( - forward_streaming_request( - request_data, request_id, e_server_url, pd_server_url), - media_type="text/event-stream" - ) - else: - result = await forward_non_streaming_request( - request_data, request_id, e_server_url, pd_server_url) - return JSONResponse(content=result) - except Exception as e: - logger.error(f"Error processing request: {e}") - raise HTTPException(status_code=500, detail=str(e)) - -@app.get("/v1/models") -async def list_models(): - try: - async with decode_session.get(f"{app.state.pd_urls[0]}/v1/models") as response: - response.raise_for_status() - return await response.json() - except Exception as e: - logger.error(f"Error fetching models: {e}") - raise HTTPException(status_code=500, detail=str(e)) - -@app.get("/health") -async def health_check(): - """Health check endpoint.""" - try: - async def check_encode(): - try: - for e_url in app.state.e_urls: - async with encode_session.get(f"{e_url}/health") as response: - response.raise_for_status() - return True - except Exception: - return False - - async def check_decode(): - try: - for pd_url in app.state.pd_urls: - async with encode_session.get(f"{pd_url}/health") as response: - response.raise_for_status() - return True - except Exception: - return False - - encode_healthy, decode_healthy = await asyncio.gather( - check_encode(), check_decode(), return_exceptions=True - ) - - health_status = { - "proxy": "healthy", - "encode_servers": "healthy" if encode_healthy is True else "unhealthy", - "prefill_decode_servers": "healthy" if decode_healthy is True else "unhealthy" - } - - if not (encode_healthy is True and decode_healthy is True): - return JSONResponse(content=health_status, status_code=503) - - return health_status - - except Exception as e: - logger.error(f"Health check error: {e}") - return JSONResponse( - content={"proxy": "unhealthy", "error": str(e)}, - status_code=503 - ) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="API Proxy for distributed vLLM servers") - parser.add_argument("--host", type=str, default="0.0.0.0", help="Proxy host") - parser.add_argument("--port", type=int, default=8000, help="Proxy port") - - parser.add_argument("--encode-servers-urls", type=str, required=True, - help="URLs of the encode server in comma separated format" - "(e.g., \"http://localhost:8001,http://localhost:8002\")") - - parser.add_argument("--prefill-decode-servers-urls", type=str, required=True, - help="URLs of the prefill/decode servers in comma separated format" - "(e.g., \"http://localhost:8003,http://localhost:8004\")") - - - args = parser.parse_args() - app.state.e_urls = args.encode_servers_urls.split(",") - app.state.pd_urls = args.prefill_decode_servers_urls.split(",") - - logger.info(f"Starting API proxy on {args.host}:{args.port} with 1 worker") - - uvicorn.run( - app, - host=args.host, - port=args.port, - log_level="info", - access_log=False, - loop="uvloop" - ) \ No newline at end of file diff --git a/draft/send_request.py b/draft/send_request.py deleted file mode 100644 index 8ceabcf52ac5..000000000000 --- a/draft/send_request.py +++ /dev/null @@ -1,81 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project -import asyncio -import base64 -import time -import uuid -from openai import AsyncOpenAI - - -async def async_query_openai(query, model_path, port): - aclient = AsyncOpenAI( - base_url=f"http://localhost:{str(port)}/v1", - api_key="EMPTY", - timeout = 100000, - ) - completion = await aclient.chat.completions.create( - model=model_path, - messages=[ - {"role": "system", "content": "You are a helpful assistant."}, - { - "role": "user", - "content": query, - }, - ], - temperature=0.0, - top_p=0.1, - max_tokens=512, - ) - return completion.choices[0].message.content - - -async def async_process_queries(queries, model_path, port): - results = await asyncio.gather( - *(async_query_openai(query, model_path, port) for query in queries) - ) - return results - - -async def main(args): - # single query - image_path = args.image_path - with open(image_path, "rb") as f: - encoded_image = base64.b64encode(f.read()) - encoded_image_text = encoded_image.decode("utf-8") - image_base64 = f"data:image;base64,{encoded_image_text}" - query = [ - { - "type": "image_url", - "image_url": {"url": image_base64}, - }, - {"type": "text", "text": "What is shown in the image.?"}, - ] - bs = args.batch_size - queries = [query for i in range(bs)] - - start_time = time.time() - results = await async_process_queries( - queries, - args.model_path, - args.port - ) - end_time = time.time() - for result in results: - print(result) - print("-" * 50) - print(f"Total time: {end_time - start_time:.2f} seconds") - - -if __name__ == "__main__": - import argparse - - parser = argparse.ArgumentParser(description="test") - parser.add_argument( - "--model_path", type=str, default=None - ) - parser.add_argument("--image_path", type=str, default="./demo.jpeg") - parser.add_argument("--batch_size", type=int, default=1) - parser.add_argument("--port", type=int, default=10001) - args, _ = parser.parse_known_args() - - asyncio.run(main(args)) \ No newline at end of file diff --git a/draft/stop.sh b/draft/stop.sh deleted file mode 100644 index 839b21ab09ed..000000000000 --- a/draft/stop.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -# -# Reads pid.txt created by run_servers.sh and kills every process. -# - -set -euo pipefail - -PID_FILE="./pid.txt" -[[ -f "$PID_FILE" ]] || { - echo "No $PID_FILE found – nothing to stop." - exit 0 -} - -echo "Stopping processes listed in $PID_FILE …" - -while read -r pid; do - [[ -z "$pid" ]] && continue # skip blank lines - if kill -0 "$pid" 2>/dev/null; then - echo " → SIGTERM $pid" - kill "$pid" - # wait up to 5 s, escalate to SIGKILL if still alive - for _ in {1..5}; do - kill -0 "$pid" 2>/dev/null || break - sleep 1 - done - if kill -0 "$pid" 2>/dev/null; then - echo " → SIGKILL $pid" - kill -9 "$pid" || true - fi - else - echo " → PID $pid is already gone" - fi -done < "$PID_FILE" - -rm -f "$PID_FILE" -echo "Done." \ No newline at end of file From bcf5286b5b4e2869f19bfaed2ce6e4fa8b45a7ec Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Mon, 15 Sep 2025 15:33:17 +0800 Subject: [PATCH 15/57] [Bugfix] Fix bug when request there is no encoder input Signed-off-by: knlnguyen1802 --- vllm/v1/core/sched/scheduler.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index f664cb76acfd..00dab8744bb2 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -230,6 +230,7 @@ def schedule(self) -> SchedulerOutput: # Schedule encoder inputs. encoder_inputs_to_schedule = None + external_load_encoder_input = [] new_encoder_compute_budget = encoder_compute_budget if request.has_encoder_inputs: (encoder_inputs_to_schedule, num_new_tokens, @@ -408,6 +409,7 @@ def schedule(self) -> SchedulerOutput: num_computed_tokens = request.num_computed_tokens encoder_inputs_to_schedule = None + external_load_encoder_input = [] new_encoder_compute_budget = encoder_compute_budget # KVTransfer: loading remote KV, do not allocate for new work. From 250d9e31ff701c853792ee92aa187475d489818d Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Tue, 16 Sep 2025 11:17:04 +0800 Subject: [PATCH 16/57] [Misc] Optimize disaggregate encoder proxy Signed-off-by: knlnguyen1802 --- .../disagg_encoder_proxy.py | 501 +++++++++--------- 1 file changed, 260 insertions(+), 241 deletions(-) diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py index b2389e0491e7..90411843eed3 100644 --- a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py +++ b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py @@ -1,346 +1,365 @@ -# disagg_encoder_proxy.py +#!/usr/bin/env python3 """ -FastAPI-based proxy that routes “/v1/chat/completions” requests to a -pair of back-end clusters: - • encode (multimodal feature extraction) - • prefill/decode (language model inference) +disagg_encoder_proxy.py -It supports both streaming and non-streaming Chat Completions, health -checks, and an ad-hoc profiling API that can be fanned out to all -back-ends. +Proxy that routes OpenAI-compatible “/v1/chat/completions” requests to two +clusters: + • encode (multimodal feature extraction) + • decode (language-model inference) -Run: +For MM input we: + 1. Extract *every* image/audio item. + 2. Fire N concurrent requests to the encoder cluster + (one request per item, with **all text removed**). + 3. Wait for all of them to succeed. + 4. Forward the *original* request to a decode server. +Usage $ python disagg_encoder_proxy.py \ - --encode-servers-urls "http://localhost:8001" \ - --prefill-decode-servers-urls "http://localhost:8003" + --encode-servers-urls "http://e1:8001,http://e2:8001" \ + --prefill-decode-servers-urls "http://d1:8003,http://d2:8003" """ from __future__ import annotations import argparse import asyncio -import copy import json import logging import os import random -import time import uuid -from typing import Any, AsyncIterator, Dict, Optional +from copy import deepcopy +from typing import Any, AsyncIterator, List, Optional import aiohttp import uvicorn from fastapi import FastAPI, HTTPException, Request from fastapi.responses import JSONResponse, StreamingResponse -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) +############################################################################### +# FastAPI app & global state +############################################################################### -app = FastAPI() +logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s") +logger = logging.getLogger("proxy") +app = FastAPI() encode_session: Optional[aiohttp.ClientSession] = None decode_session: Optional[aiohttp.ClientSession] = None +############################################################################### +# Utils +############################################################################### -# --------------------------------------------------------------------------- -# FastAPI life-cycle hooks -# --------------------------------------------------------------------------- +MM_TYPES = {"image_url", "audio_url", "input_audio"} -@app.on_event("startup") -async def startup_event() -> None: - global encode_session, decode_session - encode_session = aiohttp.ClientSession( - connector=aiohttp.TCPConnector(limit=0), - timeout=aiohttp.ClientTimeout(total=100_000), - ) - decode_session = aiohttp.ClientSession( - connector=aiohttp.TCPConnector(limit=0), - timeout=aiohttp.ClientTimeout(total=100_000), - ) +def extract_mm_items(request_data: dict) -> List[dict]: + """ + Return *all* image/audio items that appear anywhere in `messages`. + Each returned dict looks like: + { "type": "image_url", "image_url": {...} } + """ + items: List[dict] = [] + for msg in request_data.get("messages", []): + content = msg.get("content") + if not isinstance(content, list): + continue -@app.on_event("shutdown") -async def shutdown_event() -> None: - global encode_session, decode_session + for item in content: + if item.get("type") in MM_TYPES: + items.append(item) + return items - if encode_session: - await encode_session.close() - if decode_session: - await decode_session.close() +async def fanout_encoder_primer( + orig_request: dict, + e_urls: List[str], + request_id: str, +) -> None: + """ + 1. Build one request *per MM item* with all text removed. + 2. Send them concurrently to the encode cluster. + 3. Raise if any of them fails. + """ + mm_items = extract_mm_items(orig_request) + if not mm_items: + return # nothing to do + + tasks = [] + + # Round-robin over encode servers to distribute load a bit + url_cycle = (e_urls[i % len(e_urls)] for i in range(len(mm_items))) + + for idx, (item, target_url) in enumerate(zip(mm_items, url_cycle)): + # Derive a *child* request id: :: + child_req_id = f"{request_id}:{idx}:{uuid.uuid4().hex[:6]}" + headers = {"x-request-id": child_req_id} + + encoder_req = { + # You *may* need to keep additional fields + "model": orig_request.get("model"), + "messages": [ + {"role": "user", "content": [item]}, + ], + # Only need 1 token so the server actually runs the encoder path + "max_tokens": 1, + "stream": False, + } + tasks.append( + encode_session.post( + f"{target_url}/v1/chat/completions", + json=encoder_req, + headers=headers, + ) + ) -# --------------------------------------------------------------------------- -# Helpers -# --------------------------------------------------------------------------- + results = await asyncio.gather(*tasks, return_exceptions=True) + # Fail fast if any sub-request failed + for r in results: + if isinstance(r, Exception): + logger.error("Encoder request raised: %s", r) + raise HTTPException(status_code=502, detail=str(r)) + if r.status != 200: + try: + detail = await r.text() + except Exception: + detail = "" + logger.error("Encoder request returned %s: %s", r.status, detail) + raise HTTPException( + status_code=r.status, + detail=f"Encoder request failed: {detail}", + ) -def has_mm_input(request_data: dict) -> bool: - """Return True if the chat request contains image or audio content.""" - if "messages" not in request_data: - return False - for message in request_data["messages"]: - content = message.get("content") - if not isinstance(content, list): - continue +############################################################################### +# FastAPI lifecycle +############################################################################### - for item in content: - if item.get("type") in {"image_url", "audio_url", "input_audio"}: - return True - return False +@app.on_event("startup") +async def on_startup() -> None: + global encode_session, decode_session + timeout = aiohttp.ClientTimeout(total=100_000) + connector = aiohttp.TCPConnector(limit=0, force_close=False) + encode_session = aiohttp.ClientSession(timeout=timeout, connector=connector) + decode_session = aiohttp.ClientSession(timeout=timeout, connector=connector) -# --------------------------------------------------------------------------- -# Core forwarding logic -# --------------------------------------------------------------------------- +@app.on_event("shutdown") +async def on_shutdown() -> None: + await encode_session.close() + await decode_session.close() -async def forward_streaming_request( - request_data: dict, - request_id: str, - e_server_url: str, - pd_server_url: str, -) -> AsyncIterator[str]: - """Yield SSE chunks from the decode server, optionally priming the encoder.""" - headers = {"x-request-id": request_id} - - # 1. Kick off a 1-token request to the encoder if MM input is present. - if has_mm_input(request_data): - encoder_req = copy.deepcopy(request_data) - encoder_req["max_tokens"] = 1 - if "max_completion_tokens" in encoder_req: - encoder_req["max_completion_tokens"] = 1 - - try: - resp = await encode_session.post( - f"{e_server_url}/v1/chat/completions", - json=encoder_req, - headers=headers, - ) - if resp.status != 200: - raise HTTPException( - status_code=resp.status, - detail={"error": "Encoder request failed", "message": await resp.text()}, - ) - except Exception as exc: - raise HTTPException(status_code=500, detail=str(exc)) from exc - - # 2. Stream from the decode server. - try: - async with decode_session.post( - f"{pd_server_url}/v1/chat/completions", - json=request_data, - headers=headers, - ) as resp: - resp.raise_for_status() - async for chunk in resp.content.iter_chunked(128): - if chunk: - yield chunk.decode("utf-8", errors="ignore") - except Exception as exc: - logger.error("Error in streaming: %s", exc) - raise +############################################################################### +# Core forwarding +############################################################################### -async def forward_non_streaming_request( - request_data: dict, - request_id: str, - e_server_url: str, - pd_server_url: str, + +async def forward_non_stream( + req_data: dict, req_id: str, e_urls: List[str], pd_url: str ) -> dict: - """Return full JSON response from decode server, with optional encoder prime.""" - headers = {"x-request-id": request_id} - - # 1. Optional encoder prime. - if has_mm_input(request_data): - encoder_req = copy.deepcopy(request_data) - encoder_req["max_tokens"] = 1 - if "max_completion_tokens" in encoder_req: - encoder_req["max_completion_tokens"] = 1 - - try: - resp = await encode_session.post( - f"{e_server_url}/v1/chat/completions", - json=encoder_req, - headers=headers, - ) - if resp.status != 200: - raise HTTPException( - status_code=resp.status, - detail={"error": "Encoder request failed", "message": await resp.text()}, - ) - except Exception as exc: - raise HTTPException(status_code=500, detail=str(exc)) from exc - - # 2. Full decode request. - try: - async with decode_session.post( - f"{pd_server_url}/v1/chat/completions", - json=request_data, - headers=headers, - ) as resp: - resp.raise_for_status() - return await resp.json() - except Exception as exc: - logger.error("Error in non-streaming: %s", exc) - raise + await fanout_encoder_primer(req_data, e_urls, req_id) + + headers = {"x-request-id": req_id} + async with decode_session.post( + f"{pd_url}/v1/chat/completions", json=req_data, headers=headers + ) as resp: + resp.raise_for_status() + return await resp.json() + + +async def forward_stream( + req_data: dict, req_id: str, e_urls: List[str], pd_url: str +) -> AsyncIterator[str]: + await fanout_encoder_primer(req_data, e_urls, req_id) + headers = {"x-request-id": req_id} + async with decode_session.post( + f"{pd_url}/v1/chat/completions", + json=req_data, + headers=headers, + ) as resp: + resp.raise_for_status() + async for chunk in resp.content.iter_chunked(1024): + if chunk: + yield chunk.decode("utf-8", errors="ignore") -# --------------------------------------------------------------------------- -# Public API routes -# --------------------------------------------------------------------------- + +############################################################################### +# Public routes +############################################################################### @app.post("/v1/chat/completions") async def chat_completions(request: Request): - """Handle OpenAI-compatible Chat Completion requests.""" - try: - e_server_url = random.choice(app.state.e_urls) - pd_server_url = random.choice(app.state.pd_urls) + req_data = await request.json() + req_id = request.headers.get("x-request-id", str(uuid.uuid4())) - req_data = await request.json() - req_id = request.headers.get("x-request-id", str(uuid.uuid4())) - is_stream = req_data.get("stream", False) + pd_url = random.choice(app.state.pd_urls) + e_urls = app.state.e_urls # we want the full list for fan-out - if is_stream: - return StreamingResponse( - forward_streaming_request(req_data, req_id, e_server_url, pd_server_url), - media_type="text/event-stream", - ) - result = await forward_non_streaming_request( - req_data, req_id, e_server_url, pd_server_url + if req_data.get("stream", False): + return StreamingResponse( + forward_stream(req_data, req_id, e_urls, pd_url), + media_type="text/event-stream", ) - return JSONResponse(content=result) - - except Exception as exc: - logger.error("Error processing request: %s", exc) - raise HTTPException(status_code=500, detail=str(exc)) from exc + result = await forward_non_stream(req_data, req_id, e_urls, pd_url) + return JSONResponse(content=result) @app.get("/v1/models") async def list_models(): - """Proxy the model list from the first decode server.""" - try: - async with decode_session.get(f"{app.state.pd_urls[0]}/v1/models") as resp: - resp.raise_for_status() - return await resp.json() - except Exception as exc: - logger.error("Error fetching models: %s", exc) - raise HTTPException(status_code=500, detail=str(exc)) from exc + async with decode_session.get(f"{app.state.pd_urls[0]}/v1/models") as resp: + resp.raise_for_status() + return await resp.json() @app.get("/health") -async def health_check(): - """Aggregate health of proxy, encode, and decode servers.""" - async def check(urls, session): - try: - for u in urls: - async with session.get(f"{u}/health") as resp: +async def health(): + async def healthy(urls): + for u in urls: + try: + async with encode_session.get(f"{u}/health") as resp: resp.raise_for_status() - return True - except Exception: - return False + except Exception: + return False + return True - encode_ok, decode_ok = await asyncio.gather( - check(app.state.e_urls, encode_session), - check(app.state.pd_urls, encode_session), + e_ok, pd_ok = await asyncio.gather( + healthy(app.state.e_urls), healthy(app.state.pd_urls) ) - status = { - "proxy": "healthy", - "encode_servers": "healthy" if encode_ok else "unhealthy", - "prefill_decode_servers": "healthy" if decode_ok else "unhealthy", - } - return JSONResponse(content=status, status_code=200 if encode_ok and decode_ok else 503) + status_code = 200 if e_ok and pd_ok else 503 + return JSONResponse( + { + "proxy": "healthy", + "encode_cluster": "healthy" if e_ok else "unhealthy", + "decode_cluster": "healthy" if pd_ok else "unhealthy", + }, + status_code=status_code, + ) -# --------------------------------------------------------------------------- -# Profiling fan-out helpers -# --------------------------------------------------------------------------- +############################################################################### +# Simple profiler fan-out (unchanged except for sessions) +############################################################################### -async def send_profile_cmd( - request: Request, - req_data: dict, - cmd: str, - e_server_url: str, - pd_server_url: str, -): - """Fan out a profiler start/stop command to all back-ends.""" - assert cmd in {"start", "stop"} +async def _post_if_available( + session: aiohttp.ClientSession, + url: str, + payload: dict, + headers: dict, +) -> Optional[dict]: + """ + POST `payload` to `url`. - headers = {"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}"} + Returns + ------- + • The decoded JSON body on success (2xx) + • None if the endpoint does not exist (404) + • Raises for anything else. + """ + try: + resp = await session.post(url, json=payload, headers=headers) + if resp.status == 404: # profiling disabled on that server + logger.warning("Profiling endpoint missing on %s", url) + return None + resp.raise_for_status() + return await resp.json(content_type=None) + except aiohttp.ClientResponseError as exc: + # Pass 404 through the branch above, re-raise everything else + if exc.status == 404: + logger.warning("Profiling endpoint missing on %s", url) + return None + raise + except Exception: + # Network errors etc.: propagate + raise - tasks = [ - encode_session.post(f"{e_server_url}/{cmd}_profile", json=req_data, headers=headers), - decode_session.post(f"{pd_server_url}/{cmd}_profile", json=req_data, headers=headers), - ] - responses = await asyncio.gather(*tasks, return_exceptions=True) - for r in responses: - if isinstance(r, Exception): - raise r - r.raise_for_status() +async def _profile_cmd(cmd: str, payload: dict, e_url: str, pd_url: str): + """ + Fire & forget to both clusters, tolerate 404. + """ + headers = {"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY', '')}"} + + encode_task = _post_if_available( + encode_session, f"{e_url}/{cmd}_profile", payload, headers + ) + decode_task = _post_if_available( + decode_session, f"{pd_url}/{cmd}_profile", payload, headers + ) + + encode_res, decode_res = await asyncio.gather(encode_task, decode_task) + + # If *both* clusters said “I don’t have that route”, surface an error + if encode_res is None and decode_res is None: + raise HTTPException( + status_code=503, + detail="Profiling endpoints are disabled on both clusters", + ) - return await responses[0].json(content_type=None) + return { + "encode": encode_res, # may be None + "decode": decode_res, # may be None + } @app.post("/start_profile") async def start_profile(request: Request): - """Start profiling on all back-ends.""" - e_server_url = random.choice(app.state.e_urls) - pd_server_url = random.choice(app.state.pd_urls) - data = await request.json() - return await send_profile_cmd(request, data, "start", e_server_url, pd_server_url) + body = await request.json() + e_url = random.choice(app.state.e_urls) + pd_url = random.choice(app.state.pd_urls) + return await _profile_cmd("start", body, e_url, pd_url) @app.post("/stop_profile") async def stop_profile(request: Request): - """Stop profiling on all back-ends.""" - e_server_url = random.choice(app.state.e_urls) - pd_server_url = random.choice(app.state.pd_urls) - data = await request.json() - return await send_profile_cmd(request, data, "stop", e_server_url, pd_server_url) + body = await request.json() + e_url = random.choice(app.state.e_urls) + pd_url = random.choice(app.state.pd_urls) + return await _profile_cmd("stop", body, e_url, pd_url) -# --------------------------------------------------------------------------- +############################################################################### # Entrypoint -# --------------------------------------------------------------------------- +############################################################################### if __name__ == "__main__": - parser = argparse.ArgumentParser(description="API Proxy for distributed vLLM servers") - parser.add_argument("--host", default="0.0.0.0", help="Proxy host") - parser.add_argument("--port", type=int, default=8000, help="Proxy port") + parser = argparse.ArgumentParser() + parser.add_argument("--host", default="0.0.0.0") + parser.add_argument("--port", type=int, default=8000) parser.add_argument( "--encode-servers-urls", required=True, - help='Comma-separated list of encode server URLs (e.g. "http://e1:8001,http://e2:8001")', + help='Comma-separated encode URLs ("http://e1:8001,http://e2:8001")', ) parser.add_argument( "--prefill-decode-servers-urls", required=True, - help='Comma-separated list of prefill/decode server URLs (e.g. "http://d1:8003,http://d2:8003")', + help='Comma-separated decode URLs ("http://d1:8003,http://d2:8003")', ) - args = parser.parse_args() - app.state.e_urls = args.encode_servers_urls.split(",") - app.state.pd_urls = args.prefill_decode_servers_urls.split(",") - - logger.info( - "Starting API proxy on %s:%s (encode=%s, decode=%s)", - args.host, - args.port, - app.state.e_urls, - app.state.pd_urls, - ) + + app.state.e_urls = [u.strip() for u in args.encode_servers_urls.split(",") if u.strip()] + app.state.pd_urls = [u.strip() for u in args.prefill_decode_servers_urls.split(",") if u.strip()] + + logger.info("Proxy listening on %s:%s", args.host, args.port) + logger.info("Encode servers: %s", app.state.e_urls) + logger.info("Decode servers: %s", app.state.pd_urls) uvicorn.run( app, host=args.host, port=args.port, log_level="info", - access_log=False, loop="uvloop", + access_log=False, ) \ No newline at end of file From f5ba236f910def76d83758622243b644714b6bc2 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Tue, 16 Sep 2025 14:02:53 +0800 Subject: [PATCH 17/57] [Minor] Remove some comments and update docs Signed-off-by: knlnguyen1802 --- vllm/config/__init__.py | 3 ++- vllm/distributed/ec_transfer/ec_connector/base.py | 2 +- .../ec_transfer/ec_connector/shared_storage_connector.py | 2 +- vllm/v1/core/sched/scheduler.py | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/vllm/config/__init__.py b/vllm/config/__init__.py index 008c0b8e0208..c983ab1b47f8 100644 --- a/vllm/config/__init__.py +++ b/vllm/config/__init__.py @@ -3490,7 +3490,8 @@ class VllmConfig: """The configurations for event publishing.""" ec_transfer_config: Optional[ECTransferConfig] = None - + """The configurations for distributed EC cache transfer.""" + # some opaque config, only used to provide additional information # for the hash computation, mainly used for testing, debugging or out of # tree config registration. diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index b1dc978fd5f2..1bb4636d59d9 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -178,7 +178,7 @@ def check_caches_exist( request: "Request", ) -> list[bool]: """ - Check if encoder cache exit for each mm data of requests + Check if encoder cache exists for each mm data of requests Args: request (Request): the request object. diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index e0dfbbd07e4a..35d5e2df2617 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -52,7 +52,7 @@ class ECSharedStorageConnector(ECConnectorBase): def __init__(self, vllm_config: "VllmConfig", role: ECConnectorRole): super().__init__(vllm_config=vllm_config, role=role) - # req_id -> index -> MMMeta + # req_id -> index self._mm_datas_need_loads: dict[str, int] = {} transfer_config = vllm_config.ec_transfer_config self._storage_path = transfer_config.get_from_extra_config("shared_storage_path", "/tmp") diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index 00dab8744bb2..e9a1c51a08eb 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -891,7 +891,7 @@ def update_from_output( stopped_running_reqs: set[Request] = set() stopped_preempted_reqs: set[Request] = set() for req_id, num_tokens_scheduled in num_scheduled_tokens.items(): - #assert num_tokens_scheduled > 0 + assert num_tokens_scheduled > 0 request = self.requests.get(req_id) if request is None: # The request is already finished. This can happen if the From c5514d6ee095970e012ae4e18060eea18c903994 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Tue, 16 Sep 2025 14:06:43 +0800 Subject: [PATCH 18/57] [Minor] Remove unused logging Signed-off-by: knlnguyen1802 --- vllm/engine/arg_utils.py | 1 - vllm/entrypoints/openai/api_server.py | 1 - 2 files changed, 2 deletions(-) diff --git a/vllm/engine/arg_utils.py b/vllm/engine/arg_utils.py index aab1b65b2b7a..53ff59c56542 100644 --- a/vllm/engine/arg_utils.py +++ b/vllm/engine/arg_utils.py @@ -1382,7 +1382,6 @@ def create_engine_config( otlp_traces_endpoint=self.otlp_traces_endpoint, collect_detailed_traces=self.collect_detailed_traces, ) - logger.info(f"At engine args the ec transfer config is {self.ec_transfer_config}") config = VllmConfig( model_config=model_config, cache_config=cache_config, diff --git a/vllm/entrypoints/openai/api_server.py b/vllm/entrypoints/openai/api_server.py index 6f47819a3754..a28d38729f9f 100644 --- a/vllm/entrypoints/openai/api_server.py +++ b/vllm/entrypoints/openai/api_server.py @@ -720,7 +720,6 @@ async def create_completion(request: CompletionRequest, raw_request: Request): message="The model does not support Completions API") try: - logger.info(f"Handler is {handler}") generator = await handler.create_completion(request, raw_request) except OverflowError as e: raise HTTPException(status_code=HTTPStatus.BAD_REQUEST.value, From f470d1726d25d1f08cade24ae89fff1446e4a1ab Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Tue, 16 Sep 2025 16:17:58 +0800 Subject: [PATCH 19/57] [Misc] Add docs for disaggregate encoder Signed-off-by: knlnguyen1802 --- .../disagg_encoder/disagg_encoder_flow.png | Bin 0 -> 85914 bytes docs/features/disagg_encoder.md | 58 ++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 docs/assets/features/disagg_encoder/disagg_encoder_flow.png create mode 100644 docs/features/disagg_encoder.md diff --git a/docs/assets/features/disagg_encoder/disagg_encoder_flow.png b/docs/assets/features/disagg_encoder/disagg_encoder_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..2951468c11d9a55f98af4c26eda60cebebb169f4 GIT binary patch literal 85914 zcmeEP2UwF?)((gYC;}>|h=d}dBGLsE2}PudpeRU}-U+=K2q;aEq9|Pu6+~$&B0V6z zHz^h%^eP=BwB)~$#9`Fknce+&cbuJh=9x)uzH+~F&VA20?>YD5rt*0iDoO@Q2n0eU zCwt~11hRz_0wHxF-vUNO z^YNI%?H$DkyEH#E~TvD34%KW=U00EWQtdL~BJgaZ`eZf2I2dhC2>1&{N9 zpAM^;SsTKg?ZL zo{gy@+|bApT-eZM{SthFLWEfwx~`9i@QSQY(!`E`nE6A+4YPWoV;T*5yc)rX3s( zuD3yH8-FGqWaT1dWQiB{H*y4a^N*kVRT_3*R{~+$|J3E|_=Wh)d5le^g!qJ|3``^( zl_mJO_}3M0@8C+bS0h6pYrac|2Ezda_B!l-V!9TVbLm|`FTQCUVdSM z3;p@?e%|kSo1a=0KQkT@n9~ib;-ZnQqYL1UdZK(g~S(=&Pi>3ykyo0Za zO5zIyW}v<&LHNPS%+L^DkCOaR#o^ak;ri`Y z|8O-2-tUv}@APG4Z76{+(&80lsb_C*X7Fq6{Z9G+>yBZAbcv@i?Nn{r79gcSe?1Sdpn{`bKNFAvcp5k1+r_xySB5RbVUpnIOU+^OTyA5&wdhq?9iK>OaaY_P2r26+6?r+}mr?p%D@A310B&z1+ z`Nj+K5y5Gr7bM!+AKMEO!?F!w_5V&Z!^TGQ{6!hynt?E}oqDHpu<|&(nFoyC)Iu zh{pd<8{+yi^GgAGR}b|1f8CE@gQq&}@iy`I>Al}4GeKeoN`UaMGW*8}QQ~C3V`6!~ zy8%%^|JV(_(3u3Lai=INn>hAFWjUP!|N7+kl)uxh{T=#(^K|;`_ZDe_k&pAV^372}_8d z7)@?iLd4awaRq&w?fmyw&|j(S_p$HyBR^o~1q6ScRSFO@TOvCC|0fV9cz@%T|8)NF z9}Izih#lWIuh;``3VbP#fgaeu_nlAu`QzXdM0g+|$X9-R1A=_*PWod*2=N^g|JgwJ zZ$?V%>+bIaszkQ2^74|>7n!db_V?&V={~ix@LM`%NesRZ-ZH~ZQ{`M*) zBwT;`#PSE5NPenSC`e@Me*V0YxC!rP1;lSv@e`+&#F%%3D!y|_e>Efio@PY8Z=K!0 zBSZPMAO7x^KW&D>`&Xj;eOmne$PW_bZ`)G^g#QCQvBJb)kCY z-$m;`v3DYx*eVggO-#vj=kUy(`!e_SlDuQc;}kNyKk{%xo&DD)qQ@4xfpKe+2p8{qT(m1}-)dEbxxz!twZ z3u1Q}k>LOT=RE#)M;q~;Kd&KvUzh!RplA)Z#=qLZP|qH`aupO0@LQZV^fvvvY_xu% zA9OnX>pcGk??a@dH^zR%vH#3QsBh^HLA)X3BXy#6{2MIt+cf99d;Yu@`ThF^4lCI> zfIroM|N9Qge9GXz_J9ul6DK{w#9kvJwMB%u4QBtf9=g%)|EoEVi^@f~`DJMZIWtEt z+Y=}F_0Q_55&s0nhKTv^!OQP{XUR7R!pHL+%KW~z@D1*&j`#J_g4{sZ9z{9g!K-+;nIm%c76 z8=yj)j|`kRo3%#sY-=Dr=hdT@+vaJuYRW%wdmflZ<`sAA%xxX>Q%{3Pxn6qIISm_6 zwu>xIW}1Aii_Q|;v%S6WnsNIwqGPe{y~+K;Ma72P@nC2hS-P%_ejBODxyhs$>l)$x zDsl&l$KSYIp00FpO1pLU6ZKfey`v1!Cj-m-j>FsD3*p@A;DNZm;K|6i--5#u8aqNfjQ!84NLrGht#Hd8n5Du=I?1 zOjGtPNt@%Px$Q?sG<`*5Yi-iAD3{w=<6j@o!yot|8r42~PY0RXzyBe3eL!ccPrcA% za&Mn=!gLhM+;qKrt}wX2WiI6oil1-B&oSP?J+aacWwiS`VS0Q6y;{EZX_uR_>6czP zHgn+*Y@g2x&zN7XJ%FZhH&Y!*I&O(#k!C(-Sn^cX)9opFQE|&i%$9u~W~+}w!trx_ zJkEJqY@X{84PkoWEY!n%u@-69QCU?_(gLmV2fj|q$U-D`=uTpMM-(zyg&g(fsE&~8 zvFti8P1>p;joBQ27A;UUtWwz~>P^lDkq&8JC=S!p|b zIZ)6&ZIH7NYgZ|BMmL%+_vyA6xGXLCwkVsUJ0IvAE#ZDHu$&~}tIGfzeUylwjH*g=w-0NiJb-h}nvFly#2=V8YQd#Dx)5;+#j@OzTBWG{4j~mFex=G= z-5^RRW)&L{QPUOLzLS(rhNC zxx~fg3o%JIaIQ;(5fP83bZ2OgVMnzbdn>z~K3YvKbm%%q9M`tXcb?LTW7DFtU7jDc zK94+?bF?o=sN3e0(dgOR-hW2iWjAU@Ht=j$- z&=q>?mP!QNz+*>$nr{fOcFRgsPtep1d{5^w5RxMcJH=K*V3?4% z(@0$njj?Fbc*N|@Ydv0DJDVTLblql?>HG*U>e9Y#yEJQ*?KrOLyo#AgKSCSdgqg{A zny@ozh#gI$s`NSJjq7SMEA3dZ*i}c-S$sBg4{w&(awj+@{&{&l`^WE7;LZEQjBw{Tj$blts8Z*&!#kv&eUbph)2lt_zYOeH$H8dpZ$%JeqX zA4)bkoIlraDnI4a>XZr;Q|O7XU^=Rf7QC^?2J-i{J5;wM=|&~nE_C`-A^(HFW2lma zm_w!6s0FUYPnnH**CumKM3!9@y@dd(4?mNhHdNYs>^cUF_1KEte3V$%=@P73E zzOH$5g-prp*YuhDXWiN?GfR-MBQb5z$H12~^_0b6mG>!CcI%8(f1Rz? zGn9z_6|3N#GgMETv0OsNg^QH+T{eOr3x=r`>n*!i#Ts1|hctNaHD#+>-)XO}c8$|r zT_MAv494Q6$8w-4MK1-k?&npBstn&fi9GMFV$dwALut~mC+R8Qk>&GY_q){U+&Q^vcjS{WU#vr8{!3Pm^W~#&pPWkQ+qE$5DTZ6Qv6VVc z7q{Fosf!)d&GU0!IqQ!rp5VszapO^Ce>M__rK_ieIg5&6d(MA2%O;1W@48b1w=8Ae zn)1TpNxRJ$hB24=KHFt1PlYZE{7npX_HckV>L6XPn1R;f!uKCBMstqXVd= z`aezt8HHNJmMsRd&)1h{47%Fc#SKQFph<>;uY%WXxeMo8v_f{=H>uIGtG};;*5Wmb zmDvg8GOHGO(0$J2iF3uyycw|iUihv2-G<5L_hpc#~~#cWwx9&t2s`ELYsK3d_?EPuYEF^ z9BWIlZqF7dq4VjD$zOx#R-#9!6a{crp>Rb1e(lVOf$Fg11ve?}eJZpgIlE8wr`%Hw zgsYY|G(zKs`#Pr87?y_Xz1@WehA+<)EvlXOiR>FP%-Q*@@t_WWrO=|vf?`T~mP~{{ zJdNT0qJ-sYl3P3D48Qj>Rri&ASHah+L8+?SX11!McC6WZuU@vpa|?H~mYL?A@qv@?GoM&o z#MrlaWU`{PU2-1DxL7~^JU4t~;j*KVG|o$-H=LL0YUji(e0r_gv*>Omx@7RS43lj} z!EDW}-$Crl5sc7g@10)AXJ}--+m>_w8AURc_I^v))ka+BL}%{X`@*&*R^0`z zx$k+$-}6dcR%&w|IcX5WNsA6;m_Ux~8{Q=rxe)E6SvNly1TWoV{dAAHb==nF?2$l= zvPM`2eIHzMiE~hrt8i&3rZ(G4gEOv&8%Of#E{uKtJ|9+fsG-`m>K@(9cw9#1G{b~$ z|4MfFYR?Voybhdmx2wsLd7=yV$Vy@nck0llqV|F$Yh)a@n|6i&b7?`xJT^^eZME_A zqLy=aRjHG3V-;l{u*hF~ZjWCF1KoXhBz?Hsjh@c9L$q_yfBIH#s~u!NklJ!Uu_ zV+R(daM-DQVi}P($Yac3yE%Xq+iR?4ga| znbkK+1@Q7l*_%^0P#?O7(9B%mA6>cTqFEj+k4Ql-CHl_&h3qDm>6zt19-Vx2s{fJ3 z{9BHy9(rAvm}=~eJmC-?XIzlsYQp?G>U+N|8rdLUA#^6|WXC|N!LmlVnuRx~?Xn=f zC{M~+L_Z7GS49+8FubK4+OQ+Y#LA~7_;3PT!~5jf;Q`TF?iu%>74)mXwO+G|Y^6Y5 z&VJulaIJaW+EQU8)9$#!m+cn%ILeS5+uNnoDH9Yk7R%-y2Ub2DP%}R7?s#ccK)u+N zA^oDUwC)l4WAri7*POcPrpeCd2wbg9@lyL^E(56gPX9}0}PF< z8bKnjy-@~zEhi3f40}wJQJFNR;T|j%^K}LvvzDy0P@RVhH5JiGbf!iQ-k3fXg$lM! zHCUr5nykzi#XeiGx#w3z*G^N^5NO}LT>EtDp@rs2riQ$>v*;5GTnYQ9cENBL?Q_^e z(avfsJCz#bk0!tyTvUdi-J8-76dRvf<1THq(3*zHbz0kNEYC1&5Y*tEqyJP~50J zyU!2xKA^e+im1;wH^}0Y@zqhM6??3pvat9_Wucy~vcOfoEL%0G;hM1zbQoD;C17&; z+{cdV$j=eDs71vY%wxD|P+7J^^n%x?)UYaPlw5<{Nb5aqCv2?P*h(VKW(hmT*>`S5 zZGIr|QFga|^Pull|g|=BM{7^$)Kp`?qyGZ@^O4g~NXchF!d+*!LZLAeC zq#sG6rEgXXqr9yPlnQ2QD7!h%tKjhHJ7Cd^dNftyDSZoSIwX5^#Gi72fSTIr`w9~R^+*`(T$_p&5q z4^m3V1`|`X6tmwWe%aFNlKb4{51*pGh|G73K}Mr^fLvo#^9#GZ4t03Q!fH5x>L zc}r)cMqXx1pf_&IL;AnKJr_V+&1>i96sEYJ_p-Jj{;f>rY72a1K{vm2jv3J|m7cnH zu8wl56jSg7i5x_Q^bd6@!|L)9tzEWMHkqi-_Ya&|vYv<04h9anug?P3);qbEK>& z!~Fe|e)L0)qmSCGH`6e1BGVamBXZaOEnJ-Jid<;=i)Bb0vNejYQWke@@4J)TpPN8f+W7ncv^5dC{X= z9bK_d6jH=Knm+^6RcvOTsciH^e;U?#!FFA*;eC93<@0)4MSle2&_2LXy z&+1g4reXL6v(=+%Bd5fq?z1&3K1mngbQm`m%xB3^!?PikL^eb@PiGn4xl$isgX_n- z*Z1G`72q7I-vyIxLFc1khg;A|#jxj&?Q3nN?vec_WZt>`VfX4|gz^DZl5ex$AM3td zDvaH_^%(Qp5h;c7Qzw-ZHuZ8`iae+HCH0FkWMTN?^rpKPulM|aW75?ng& z`Laj<<69T|Rn4T)w(my|_yF!qeeY<+ z(R@CTuN*^miEGW=t?5tCU3H_!ggDI$rl6WsK*%RxY5h%#DKF!PjqsfHSh`L$UHklj zyWEGM-ZyVxL&U4yMq%Rb{F>mZWz_Mpi=u%nYN~b790E+MZM$dEA|CbDv zwp2$=s1&KwGVw4{9u@6r!F9uAg>{}($SKIV3r16VFkD`9KmVmBF*z0~c5429+>7$C zHNH!Osnb)6uRqjURshluTtonGXu-TEcDbmD_vV>_1$)sipc|6nc z=nemKHcylhCCS%x9`0j*bMBVwmzeQyi==yhCcfB0Ie3}(G5K9K=EBY7che)XCfQFp zX0l@2!;r?(Ip!ro2ZliA&NSDq3C{(7CucbBTHY3Em)AZ;RF`ly0St@jTtA#s(}0{Q z*ZY|ZT(d^)(z?QxWb&~lb>^xVP4S5jS+(~?>?@Y+NpULu0F=y&Welp@4)|F+E-4k} z;d#PSj%%_pNIXyY_-VLE9E)_Qt6Y*rr1+@YXpt@S+WurPlPlTQ+Rk@u@T8W;+fpIA z-~*@HpANz2c3ZazOfB}loPGO5Dc|bj>)fFILV2gJeHO+|TOsZGV)kG;I!S9_aD(=H zbZfhkcN(c^pm&Pg)7s?0ZWf`dfG=5aW<;jbHD}+7BUUSX5uCC1_f6{DJe`;)I!5CC zyzN7qlBX-%UC^-C3>wYOmL3|F2{Echu*O<^C96%lP{{a8F{dU)UzYZ;jJVr2n&b=I zYYMOSkY~S_ve2f~kwP0wN7D+g3Op5=R8&zUZPis=ewz`5ddvUX<)yCgv)Iei7xr;! z^d0LJebl~!ebLr*2W4R2D!ijh;Mwv@Y%0FK)75rrvLMFTXZBg~K+WccSe+m@vk5B1 zj)AQ6vF0N&HzMwe^l(VuH0uk+18~xX@`hAU;<5Nz;z6-D>}=pSFT}4JuF+E`WP-q| zdGriGQ;N9|0h&6#LX&vmF-XcAsb(QXfxoJIe^vMX6xF?L$_azSUVy)f(fF$MU&Uxb zFA9-L<_Sv}%=mtMVIULH`P%AZc+B2-kL9NyQSSMt+?O2|SMUxw!($<3a;6eGcdul7l*g7v$C^rglg8HAw?JMIo z0o(Q*&$)lfId2!o`5X{9J1hFhQ^_Yo9HhFH7UXl~FgJzj`&`vHUhZ4_`;@ zqT97~2jj@gMf)!I#jcbSoZX1Idb;e$vBo{=75=t%`wy#^mnShRP(Qpa4es7jsv*!C zFIZmfObPBz`K-pQV%nptPHR2BTZkF)sAu#^yw2?? zxbf=hFw8jw@J6#~ar9;&{B0DHS#1pG((FuBh|nt1E4fE!7Z9i@5lnxEH3WhUeR4C= zKN+TA9yWf7Y`Xc9VN}OX5`>|gm7SFj1Z63Gq>oY3(=AC|B2(XAh2eA(a)0u4r+(Gzn0 zx%$`^(pIQ6iI)Q@=J0(MesKu&!X}zf8HjGpTW|l0U3l|rO5HmJonhPKYV3m)ehtI+ zl?Qf7y>{Q#n;4-pX1#9^>fHrm*j39w5VPV}Q&K-I!=4!go`d?tqwXDwqT{Re zQnWq@Zlsn- z&^(v${0VO?E<};B>xJ(caG!6M(QeP~c1y_zEg^Pq`(A&v9>>;GlQHx3QpCNv9jV!R+^mb5vb+>+19 zS<=Xr-Py-)J2_%hLDvrIfzitbWbs|*1_llC=_I+pJ61yy zYgteCU#JCkXgDe%U3L zp!gczFKYlPamnA2Q3O&t4IM|xMW%)>zz;YVcCi5GhBB`JRK zQVFe{k2ibqlD*qqp=@xAjucZG(84$O7;88tdC7_vh;CH+6(2QTdDgBonp_9(~^kyYyq(Ia2<9eG9|+vRc|J}35-sF??AtDnXTqf6X2S@;CPc9LMp(SOwva7&cqZ% z8_HI;cWxBxgKN?Emp8vA@1fRoQ>YDJ4of1Rc_j;hW+gN5b}-xEE8zG@Uh{*lneE#0 z!eCOlRd!eVS`3t2Tzm(~XCV;{8o84sV6{qjr1oqjrSXK2F+)hm#UWomx{wN?5%$hT z(wN-AaLrCB>eBpQ(Xc}NjCoabmt7MN4xSq!{6c z8r)RAWCKm9ku7?4R9+QeDguZ0_R_O^!UFn?Uoer3h1~HJKM7F0A#~sTuIa|)9H)us zQ#L)t0b4En>Sk_Z8JJ5ygJ}J;09)S@S+WTp3SE4FSi&iuA5q>;)1$ackU0#J(a7h> z@(jrR(d&8E4=2gO!^1m4MxdQ@=OJ{n*t195QY5be=W}QIA5i|88Q^4GZjv`KlOW8L z9m3Ay0DTpM5A7j8xD%i+S(Qy2IM3X*oI_^qW`sXvKQlmInwvD`0DXb^i39hRDA7#! z&*CD9KTLcJE zXVZYGotHQ(fcrC^+tm~S+=r_n>{{c27@w1X^GI%!Ul0Z7ff)$M0=VC;ZCkSr_W@Mr z&1tUOg~XIREEDeDNwTUZXXToE5edZj5E#HCU;z5AKp|iT$k?D+2EMNEH4BO`LKhA!KvmVU8h8+XoDD8gpC^Ue;&QsXfU zHB{_VLp*Fs$75;mX@t24mJw^pL`rdqO?>V0ui{X8guu}0Q^Wji@-4Pv{TQtbouwDE zWMs!a@dxVXk1hl9W6y!s*_quEwPUoW$Yys|&A9Ol)w{=*7t9E7&YB-E?yq07Nf%k= zMF<9a7t4c$l=wD@|6aD0^R@Kehq8=7H$0nVgk&Y@J9;u5jU!`jhwc-#PZPvylJ za~-+q+DEJG+zwr2mv){*^+b1J{z^L*v|^9FhNCAxPodG;`+8%jsYRzfPr1z}=OdP8 z>p+YgNvvQ{i(#%d-J`=&jlWfbb&cAMG$jnCh$1X2gAZuVtURyKcJ9hr&8Er3`L<>@ zihVqQ!>&x_JC3*K@|!f|fS%DOD_yBelDuWexnrws+twmg1Bd%VU{3fFr*K35or8!Q z7X1}LlUW@)_W0(eN|TOsZG49vr`=-ZBuHqtHD=DMy(m~{*Q_ntCQ|undFk1a`P(-K zrYoxw_iZ6T@ybw%GjAf%spJo|ivgG0Y6fLQ; zX-6xhAf)v>t6m(z2xVoUmdzIvu%PGo1!6o2-#guF>=Qo@5_wLsE4mY<*Qmu%WGf(z zQMdLl0GY!i$n5P*8sjFS*$9nf&Me1aClH=fuuqFKEB&imS3T-&V&UePp+KB6uJx%( zS0vzjjx`SN-!_wdt=oN3I~$xnc?AvnRI6qyQ|Xnim}KcwQuzyup_^tzP@tQ4@+L>z zl?G=ZoXN7AyR7Gi>hJHcW$Hbl?1ADjew(D&MG=7OrN0oL5?TtaM+wuoID*oRBL%rQ z2_WFa&sl(tgVuL2DRPnqMj+7OWH>2?b8SrRxifZe-X6o2Z4%YEgJi5RxZUvN0l?!O z&@_H6^<{GEu1pn6w-89p=|lvbKhK_Z=M|u3tx^HMe=M3x|b@riX(4Nwwrkc8N zEJ(dRfalP0@3!cpfm-Uk7Ly)t%CieJQq*||#%^NTRc%q7TgL2XMOG6grEho#&_2Kh zBp9=l17D+WE0?yHWSdwY!gw%qOMhPBB2jT~=?}S(53mE-OvA6D zJys?rHCM14T1GtMQPiN-uX8q&rG$%~^TSz(0 zrhgl>v_#SA-N&;<*>?hzZ2FSwK!5%gSSG7UW{J=ZNrNgFqo@bHECN(GKTYOOiN&eU zAWzixh7<%FolqeAmVCoc+IKFhUDWDLM4FjoK|g_yLSU z7j^R-p5}Ai!9mbC4E5yNjkFA%!Vjmbmi823d;sW}E;5e;5n^7S0oxYrL3`>aCe;b3 ze&L6ZkT>Y=DqPuk&wTVc{b5eckT#X58 zsu({bKR?@*r4p_Oedx;U=d*cB263)KQIjkKSe8Dl{I+qJ$g19bmZcC5@wFh6N?CF; zQjEU_K0?Gl(9mLbGgWrsAmUKhDV2t+Zz5D?4Xo7(!H%Kp9aCoIdw?suyn5_-ECfq) zJal$C88%27ri0Hk$&KkR0IuxFp2+!Vz?H?^4SFz4h;w@eNl0m~9BL{_qS0k(ia7tV z^nuCg>5~Hm)?Im%^cvXL=U4BtG+l?)gkHVJ0HSAxR&|yAU`Z=pn0+b%fhMX9BZlmK zV;diLT#O{q9Wtmsw?Ghg>mm!SxcGLG6PtN2()f#$Vx%4%_LY2y-F{Q?Sr`Zs!xD`2 zrGTZeypYSS2k2FG zce_SFAPursi_%m9`tuKa;{Ztw4Gp_%i<6G~Pgq7q(JefYwY>Ng)D1TJWPUQ2_;

Hj&>Dq-|{G5Yj=4PPg&2N#OAM-Su7PQ?C#&Nq4LA4o#>$xa2dwGIlS(r#`se zz4vR1CxPT!9tcxPH`P!^x@B=>+5sj^q&@X<1Yp8axT31ri&xI%exOnJApHcKx~b~G zA|1cv19d#LDlgNs8RSQ#p+VfX#4PVoPmzT4H(B0QQQ!+JGYt-sk&+-T`JcVXBz)7TDz57e>b9sb@VoIg_b53Hj~wKBrml zVhDKBP0Y6b>VN=BotNH8y~z5RnD;5J(cSivz6%nVn$3p_S%Kte>yD9n(E+W>N?c(r z7L&r~73`H^oMi3H#Yy5f#n;KNb8^MHa<&s61f6?|z38ahcUW9Rs8;BQ(60^b9tUc+EN2n99Tf_%w$fw2p z7(9yy$liqZ1vj238!-bcQVu zSaG6XmT5A~A|PyPHz>dCz7+MA0pNq8?W~m-D8ERs>odv|$}h>9!aGQ}fHZtBP1J4~ zkP-sH@oWNA@}@IMJRld0;wFI@f^3uzglpu6fIj5kWR&-e0I|=D^@-Xuq z2|nZrJNwAsDk$XWZt*{-7Y7mJ(0s8kunqp z3lVz(EGb{kGc%}z1pe6RRB5R-eDU)M5LwcLn%H&#KtK)fZJ?g9?I>-(GC^fhT_v_O zJmR39;aT-qI2sgEf`YyFfkFyUu#YPc8G-@=!eqoG3iUfkneDi$znXh^R zm66<*vlRd!%5Y#4Kg|OyUcqxfWJ^0C;(!)A4D|0QZcK{d<5x~fAy~`9XPea-NnZkM zscN}lY6ysjm-El*sTNFtW!=9H5sSWl)LsKn9(Xlyff5E+@|jyw1kbnKaa*NCF$Ab= z6KhzXDJjN4;N%u#X7M$=f`;+!8x^i>((NDdD}~2GDF&b zyzUGNe`EB)H#|uIRBbtPsJxkMy7I3@{nw)Y(W3rqA^)|I|3+8DU*7o-<()mZKnnpM zXx$ihdJ-@<)_`l_OfHzI*l!KWq4z~yTherkJZN}fLx7;M0W40T9!g>tx$sD{4Ac?q zGtLGD1y4^?G3wsw-qOj{rMbz$2wf(|w?vwa$)(5Zvb}oRmMz?eM#QO5yS>Adj}p5W zEG5JJJP!hQa;KG<-VAts0cp!}skQelF_uq2(KM;ICiOMB>GXw3>St!E=lV&a=}L3W zrw6AkMJ}FN4?!p=j&s1sj{)zmM{YB}{WJ7Yz>6ZstWSRK4LKx}Cs zY*JNPCWOfmj#^5(HkufbM_u3VI0-~E8GaVaQ8olP#2`9kEY1@xw7tX@^|ZNhxWs2$ zt?f#MBqB=^;d2wN>itoC$v`!bBQ-O6zvL#?;HewbVk35l;rq_v@R-55ce(aYPTBT( ze=KmdkATO@GJ zdr}kqV^a7C{>?o)qk@W~G^W=9&#{Y-)(|w3JOYg*6Cjk_O-j~6(euc`w+=!=B^CgC z^%;701&;Qs@WM@tTB~|fmz7@Lv9dVj?A&Qv8DOHby)dn{U|4b<2^I6lbB$^U|Lzce zkMn0uCFd(Kn9|kW(rfWjxB!0wsp#JyIDE@>2~diUs$gsftw%6g`2K(EJg}F)eNIT< z!#49FuJaB?IGV0tNaBGg3DwFuYjZ8|8mPl_5`fqRvA^lrqoir#5acD#hC8)@vkD*~ z9R>D(Qp(s9Eb)byZ7E<^nqRkVW{H}_s>Eujae2X37+{x*W@w_f&GpSgXBR7D#oXPb zUsPnnX0r{VJ5on z-FR51*fVr$q%&hZrOq6)a-65H`ynAg@M5K#d{8pxrtMy;LOyNhY5L&97@=7y4;R^P z8u>uz+hwU)jfKiSd0t8I9xJ7XN6T74e$^VSU&eVGKktlGe_U75OMTVMhx7O745I14 zOBVe1A3uWMH z-|QZki4S;f!Y~5{j?Vaue=SA8^euAac(QbyI&DUOJlGP+ya;X2_8tl;ry%Fc9B#n7#UZ#wJn0Wyr7N zHQ2#pFS^)i-^CAGRdO+w23ugDGMNwC)QTg+iZ*}0?- zxw_v9Ir8loe=TfeROxji5}x;EtxA1brBH$;we>9l-0aG= zAI{r4zffdE*G|qTWZgNUb8SL!n7i?F>Y5Z*G*fsH!#7s^4wl*kBWuEW#~L`jFt$bM zF4d^z@rH=b%2u``*=pk70rWC+JznI5(ay0HjdduibZs~SOIv1RH>s#$5nrorzApQL z9n^o@f~y8;ntC2#bERBxBk|fzFz3j&)aj{+e*3LBi6zk9%DGs>nURB?qh7A5cT+;O z=axPM8*&i6h1ocFoRfU-8q!6Vsrzk)(`0C-I&GxioHvRdyEwy@x_a#zvW~w|^zG?S z;6-UZE^Fx3NN(g(ZEaApjgG@~kHliFF1BR}Q!3SRdKaz^&kV{ zNYIg)RyKgKRdL4Bg>HsMueC71UvavH)9*d^c6p)!#n@PhF#s!n_WLo6pbX+Vo!knCED* zIMi9>8l0i(pTRQ&e_dLA4`!SNxA1XPor2 zC7>7sP$VXgHVaS#;O%#3HUTf(>UrV|O*c|(ZZEhb&g>+QJCkr`yFW+t8d)=hovGnTjl*ACcZG90@@&-U`^XpLxAM zx7qUo1ubbJ`K!Dm^YQ90G&1$u6FcMJorm|%Zof6X<+L>`#?^QYg?70zaB;FpS=fDf zK7h}k+iwSTP$2b)kU*dCaCxT2eXiNi0vig)NN%l$iT(R}YXa0cgvFkyQ{ByRZH7^7 z=aBM9vjH!9u(QKuGjb@VEk9}<-#UIy!E-q#oICR)pf)T=&V|1PkMMTZ$cg+Gizjy_ zXal=M;5IIH$!XCfi$7>nOh6h*ufma<4-*p;Cu6W!d2fJ0pa^pdbP(scv7$~sM#9>p z(^IQl(eHCunz?&1pa7$)jg4XfTZ2bn2jSiK=sdcnizORbxoHv~jew>0;B+d1_Z< z>4IR;_lxoD)II(D13xQhZ3c3sZNC|x(Yvh~x<|+?m{Eie6GbNyLpQ_ExyltGT8qcQ z`iGbk%9-y#C%bzs^?qu#Ja3ag7poQU4wg#Lh2L>{t`z6Z$+-+%kg)Zp#7U#tbCO`* zF|__?V!*VcLvJ$sfLNtuGplGA=gSFtlTT(okhaom*_OLAOpX`TYt`VxE3^3k`NQqCrTrM5@Jo2Q~q%6Q*9dkRh&K#-6rpaGOy? z^*C^c=_k&#?*Q&FSoO?Nz?9!fp}PH^-III5JcHMMz4Ilg;SdM;Ezq>Zvy-v(98EFw zkRg4{!37Rg22u-u(1#*>Op*??vEIDrTf7}`oxbI2ktf&tP$Uh)c9Ko_z8g?tAn?D%16a&R=8BR8>@AA(d0}9-VONbV8URX; z_l;aO=Z@l3S@PYECp^{(&T=C{m$NO<(TBp?v4-;)ah z1Y!jlhqf)TcdE;mYJa#vX+)nP>jN@^=qR@6A0~SRXt}1O!%G7PJz;h&hUuX19r>lD zp-#9tfAkQjcsMqJhBXR6xqn%(`^bsa7<;AD3zrt-;Tk=)+pk7RZvXOZ+~)e9WSMD_ zl{^&_P+QJ0M*u!MCCH~L8Mf_cSbr-}NUL`g8qmpx;K}cv``X7WIj)8r> zu#a0^Kws0JP&wMB?t6pfK@1>0t=+4S2SKp1{gopEfNN%eos}vE_R&i6HB|PxM4FBE z$X~&~?aplV9(~bD*HmYA(b~iyC)dSc6Hzkromb-%)ZfH>j^1HtMNZBJ_*PfdfanocOT7n=S+d~M$`%8L!aaE)YYyte>W_Qu1omxoDvqv${m zHWjDxhM)6HwG_|3|6}jH)+sFt8jeCFl)0gIi7dvR#U*98o9&7MR^kL zuF25Tx6DbnBNEZY3SpxCNtWX>s|7NSplm}be{xv&>4~bSoD<)~OumNhXBgevG_8c2 zQ(A9wSzhlhaq15K*+b~=apF!Xx9G*6s6}wbN_Rue?fQvfWRq<+S8siCGLaNiJo50(gT1JyR8x7|dk7OQrTP8$E1!{MoX?j@ zJGx&~^xh(+Kf_a3BX+19WK430cZsB!zO^D56*iMfamp#U{b4LIOWSc%+w1qJi7e0; z779eW?qjWR)7)~9D#aBdmof#kc?4Ox2v130bQVAz&l@KH8|Ytdlojc6aIbU~th~}5 z{m)8XZT22e{>oD0zhRJm; z11N6=n4e&>y}8hw(Gtj88pxEHrlz{I1%B`EmPdq-c3(m(Yd#MgHpO83GRVc>Mt00N zq!R}$dD0rj4;m@TMwF6BJh)xdF)mN7A5)_v8MWqs} z)D*mS!Ar0!NFk^XP9u!q(MiD5Kl&M>o3W0k*Sc<}<6Dse(?!o&GaUn0xte8t{k@f_ z#}rhB5E&Id-b+;vEg574(2;5N`fmWIL!j}9i~#NdHQy9Ijo9@!Pwv?pm0hUY$QvBZ zSbGjQfc#kkf(9d+FpaH%0c}k*Rp18{Y9x%{B=8EiAiTog#0S>9P^dU48;}hhzcclG z(h{(c3jg;mFUOE` zF2eVsIL@6l0xE=Tn5qq2xo>OqiJIjQ>tB=1IO0KyDx+)gTLR(2h@tJKApSJsD!zq&g@oIO|x=#Q@0 zqh?)*9x0S=$zA4tYP$f?>P9V6sOZMcGO^gxREZt`C#_Ni&?-G_L&e!nmNm~UE-L3M zD+I%3w4~PoZYVGP{nj`bZv4Hl3Nru&nTgn$>wl-i$W|PJXbm`ji&zvd5o4gdw9OYE zS4r~Q=1VFft*(o2A~e2L5g>UC~<~ zN3o-~!RcefguFdXtvszna@HWf^okQ`g!s$YI6BayHG0$8BmJJ_mo3tFPE6oqjw_UZ z4H|Ai>9M51tjXEn#uR(FEFjeD1Ar;*ZN)%8K?axDDJ^q0&?yLS0=)R}o4Vynj+85(qJHy?m zgK($beU3c?QMR^;4^=Ki*&qEHOe53Q@75zGF4X=N9dNgPF|DFbL7it zLry0~wKnOYd!;Fn{O$KXweBihakUuEAY# z4epBZk|b$Vfljw_4AY)O{@jYtyad{t+=!Ao_%Igir2r#ZleNE1czu)x*j|cdOw2B z0X`_p@WQQP?e#dTefGp&c`wtgqGaAwX#O&b=MnvwVa1&%_fZLB75d?(>qk+S17}9r zZzq}@0C`iKTa*7L4y9ka%vP&^o7Nf`ASb*K(DRJZhdUe@MI*cvrcUEOPOX!YE;lV+ z-RWHnmnF|`Oau3&H!SoH*9&V}GLQlO?nyv#2fq3jfOA>uw_UW^n56}G%^K_@!;`yY zFQLhI*v9b>h|Aril5ai*18fn834Z0}CkXH&YPKyWWiNrugv!ak3Dq~J>7e3&I!%`j z!+RdG1vUF?ZS4Q!wb{TLo~)>h=h`6=7ICo(`+^DvC<4i|=wa60+fe9Jcqfa+o<)LS z?B4{zo71HHA5YT*H7|AVJ|sxmSQ{(m|8#9Op4C&>{HcsOxiI!L1|hUHGQdzcFQGe> zmw=qc4m$*m)`vWS*6(lfgpDmM@MjDE*}|K7+@CG{=NA6wf=PuDaS34aU7DUVG)VE! zR3hh|NkK3#hS{1nNSX38ydNXfSTCrNDtiZ|JqjZ$Kf|3h?6>jSp2njiq|o}v!*>uK zz6vSa5?A#e+>*S@($wWee?j**P-(+k(X;1~JEY6+L*Vz4@TN%`QDuRMgfcWAOz%S~ zo&CC|VI!3mIUb+DdL$Bvq{?)DrI5I-X9%UP&2Jo&IC+T!iad9}Gn)FyPATD4sB+U@ z5f(Z@mZJ?P+UV0pRy>m&`j;&34EzZWgM9}JpaszJ`J&0-#>>a_P+bGdr~(x#4)K6k zR_xmJJNEEb$aow{vofTDgvCa&o-qWNGbnMr^JU{}_>9J(WFhj4Nup0wHNaIP^<$Nx zCOdFXwDlY;A3}HH!pXky&Hlnv9MA>$X<#N9k(o3y&|kxo7D-)@x?|)pr{%obhJe4F z1$png2j9~qDS-Dyq0i-yAP8dp!rxSG)@?9HIeTRval!XRw4;uDLl><#FK0^TsZ4=f z$+npO{`s%ZR|XPq17un;(v2UUlbFxkE?E#AoVgZcwNcb>3=#Tpc_%s=mR0Kzzr{7S zBTX#5d+BA?diQiQluvDi>cVIKQ6UQS6;zqD?jEc%l%78B6^3dXl_(iG@O;yO=W8yt z+5DI$UgkizLfb)$o0sAmM}CZq`=>r`ndRV4JPuc*7fXpsqB)yQ{EjBa49lLug5;<_ACGM_>=$r zq1FHYPOI0h6WHjElt9ylzgCeD92sOmiiXvh}Mh*#1Br!6?r_Y$jYfe(|Gl9xw-=~iz1 z$aQr&EF&}tFH1?D8sYYmnX}^Oe2cUR_Di|u??6C6j+)ZTX{&Gccz(|X{2-@7pOSi;|Y!N<>s|1EB$g@_wL z4(d5nP8hcpG`3*lGfMH6-G}^5dG3^GxN7RY1pd4Z{pDj$ZE>O-iJZPm6a)GcfZZ6$ zL)lC*Rm7!li{(S*B*J8T-9v>@?0=CtLcl<+6hV4y%|PB768VpFiS>f|;o{$1uD-ta zl=d@NtyE-uf1Sr>P*9=u*$D72w*EU&h-s|XN~KVD_ZXj4=D1thzq3{CqDc+c_8Rm?091tldZ zc(10%7_*Ydh|PJ=26kr2)Qw=z0gFtVPnGKNRrnsyk5`%AgHYi~*@v=?P~pbS_#DxP9kGB}358r^}3}dA*=$XXD7+;v#c*y_VZj_K8 z(S*G8K18fU z!Dkdg6Tc8t1y#Ac!a1_#uS3eNmi>OTA%3HS^SG#v5|s+5g*%lstn2_`rb_nDP$3|n z5eEWTagnz#`2)H~&Yz9{6Fj{Z%bz(lHx%#$s2aPS#9Ao`Y? zF>vr~GL$u7s_Q}j$->Cfscs|O`X8{Im+Dvo_pmq*H6^(S;@6&=UzXWymOym7E=U;? zCMqhfHh=$p$Tao=f=Al-j|j#ARt?~!#vt3gE@daW|6KGcyU0%0Z1pso^is%0J*SrwtZFlK_SMP%Iy~ z8_^-Vfd@s=vtrU~Hu{&B0^Wgu#OuCScIj2%MOE5UYqgB4b;J`_MkhcrVlp>psiUoY z&~vSy#l@}4>cj2QYPrv6aRMW<4b~8~SdS{r2}40)?{Vx_i0PIhZ~om~VNLwmBUgvZ zCyiw1IX4C`y$@+_7WZ6Ra&Y{fTRJfkHrwb6h^xb5f@`mkju5Hbu2-%NGu^*ZWIkgB z?~hZh2dFSjcyB*ohXA(0dS%%1U6aRO6hUtEuL_NWrP1xhXSD}LYnFz z5=1%IG5Mmb&?bA)cPL=Vl7hsB$A7Fe{`@`f(NvK=Wn&OgAVE&Z@0^N1uF2BU4_{rB zPKlo_x>W+(!r=V1mLxtAAwaO%#b?>MCzx1OKY2zp`sC%>36Xh6Tg1*0Smk+9RupCq z?iNeAzY#ThvC3ZV(+AzK8*q4xJufP{E6RZsyk|iQZvJgf$^-C|!UsPC_oUf4I=1b* z{IgyYMa&g;&%hnB%tV#!4%c+~DFyRzxTYT$58m0#=p+-mSo2xog5TvSzp+ zRRCg6BY*e3MON5F&}DYh0+E%IZv_(i`r+)oT$3F)gqC3s(u&RYCxYeyDmYvcz|3vU zL2c6}gr>62)5~0^NQU$UOh@1-{v5Pe1{WdE(D}zJTYU!<;6^xjjV-eVu1gTBJx>Ey zGevA8hYDQH-v`?6bgR&U_7=3|b}jd%OS?H;Xm1AV7ty4R&Ze{t7c#HF>`zE?FE6o6dt;cYXdupv*vd|NkR5wwB~ zrwj8u8VO6aG7~dFZ3zrTABB^o1l&a=uFxL=a`j#yeaFLhh>yDCWw5D0{6-CpX3akh zW#%hLnR&@~BvZv}rSz^RiC&fHOE56@D74b30{MY}n(6-9`|(>`x}6MM5^N8gFLSjo zcI&Nuc--m9>LPUROHKu`wBZ$_jIAszvLq*Q9aN%#WEbOlJ<-?5qmiiWBuGEz)R8^@5jdsrxlQ+rxf?fwodh zeEe(Swx(UMV)dlmRt>8j%<^5QDGapclGIy_KZ%LU_4h+n=DbaU-z$0FDpGt>HCzeR zu|g=62Z)ozd3gb*NC&_$BLAXElh2zO740VsAW_g|{aguH&9Cn&Kkq>NV-YE(Hm~*< z7N0`08T+z1*8#ZAqEsJ}=DSc7!H zDBncSN&CJk3P&Jm{TR|)a^aYp1pOku6&IPEPo-{{!FwSz_#s5Gk@EiAm9LHp7;<-7 zxnL94{9~Y>;V&x-2qa!mp^MYlMCg{_7%995F?KrU8amXf%49eWzq&K2&@RuuyX?XS zNWj9*Zx-(X+ijh=R(fQtfM@I|H^^+^E%#+6_ru{dy&hF%&Hm#+nDt~%ep62VuHCE8 z&uM&>JTf-RbJ2ZT(GeguM_Y69YfH@Z+t=b&P5gdg0alvY7%wR7{O-61I&o;UI148t zWuOd=11^v<*ieUlWiGg>D3I_MGQT;H`SQAr0~B|3nyz1gf``HWY3W6hJuxcwJIx!wZntM-QTojV}&Q~g`EWg3z-WaP2{ zh!Ymo9^_NmSksiWEr$D0m9VB*E=+F_AkY-*k`FVEXg(a^kOI*Jku7I3&Oj8N6_wz} z2LgzEprq)#SrbKf`fp)tmL}Jr9Je|h@CmSw!()tlHN94Do4wl!84Ms#0BD!$3Zyx2 zz#3n(OldHP+!P^D+5Y?(+K=jc+CKol@)rQ`dmI42AemskE%S6%7@4#Vw*-X&2&?OZ z_UN`v)+pxXj_q=fJWvU=9c>SGJ_c0dr>{c7a6vFMMeN-uE>=N6HI1+rv*4(-D#Ye- zY*srXH*v-)8wms8(>Vi6E@jF%MMh15U_#4Itymq<>`H@4&-EfJ&jA(3om?9WM0K5E zx1a1PEYOQQp}iVV(a0z;xe8@eL1a1Cb<%?%p6f#@tvZlrWI>*yviX*AZssXbK1WVs zlxRWRLv^>)8!g-j2X`-`fwK3JaQbnG&tTHegPxh8x3VAO>5TohtyYVL8o{DhjRI8Zy-5>A6C}JMzed6Cl)%OA_Lfy~I!ME)m06tF}3O zwy()m+dvCKocHRs4-R^;zx3)ppU-bKc8rYFx`INSxV{37(hUr(8{l=3Xn#?m6r6nY zA!x)Xr;l+6B#@QU9>(^DZsIzH-U~DD^nQs9>zwiP+hB>%wi8>(6UyjB$M5U z$q67MW}bS&wI!Vx7kw{{nr7*POZlhn3-|+%#PoK zhfDRViV<|UdC#*}?o-^nv7)buGoq|%zNa<6EWgSCI^k8*CO4SL&*3y>2sgSo?gT*R zq)CQU=0+kcmY(wW=ys?V=q3@z%w(*}iSv2!P%qg^t4xKOrTTu;T>53hPH(8i|2X4t zCu)WtDi(44Az{)ZVOOYhCe)KQ@w!Ct0{ z7|t;7iW{iWW!II4JAP#73@C8v)(L3<_iZd(>u*d71DWqojt^t#h~qHAi~Q`;hvVq^-lZ*xqEaX?@>9{ z7_#y^obOy!Hm?^BiO938S`XlQsr((uHEvfThzbf(oT3K)@}34@?^q+0-XGg77avzC z-Hq70n|uPqvsqaq$%e!L7S^h;c@$_G-yXrdQ1*(FyZt0m_Yi7{ola#iRu1@3a-l*U znDZdYe!b&`#pRAA<#UP=lgw}^na{-1pzPrSVU{^nzq$X|>Z264c&EU2rmb%3tAvV8 zFG}>lf%&#q6>0YY)A`;fR*?ygBNIrHJ%MgPHb{~&{E{RaUza4SP(h+HNT_{Bcpxg{ z1B}->z`Ynj!9W#)Qck2`5C93;p;XSzu?rvt1FQ;+okKQ24CHP^{sCs*3K#6we_+is z0c(DS=jPi@VOx=PXz^KCkQxxEREIJV*Kc9l5xCVy{zcgK(Vvg}g%bZiY+{?AhfA+b z$#SW{yScpsn z!*7A}dn33fT3s&(ROC@0;(rT~SRC(ctA04@1eBoytG2_yrCWRew6hP-ujg#b^0oY` zlw~Nyf_8xVb+K}R#%@&WtmS(#C;|!m@DjYXD?~Pgx{4h7d#*A(dE`{@AO{|>Ol1=u z(e!;kATH(|<8c)~ho3B8EfJjQX84KF-e(vV7j{g7A!0n}pWdj=nV*TL;}v-}`?an4 z{_-)K)tP-eZ3w`H&M~iOuc?MkrGM_-%f>Gar@=GfFlZJ?gEDoAM8>=N4<`!_!leMl z1y?XH+&ypiR<<99i!IwJ)ll0^fJPLJ#KPSE5DTY(T3V{1MYi&tm29Ar(P})>W0{}4 zm~TA7BIDVWAn9UL-My381Gww%iLhYf<$K1%9nk|?biKD&|$2mbJ1UN zk!v^gv6fwGq;la7#09=>zQB@uCIIwg`&?Xf+g&G1MsxKVDJ362octg;dHyrwbpL{h zqj~}?%LC&6{eippk5sNfFQRDV1Fcw(AmO8+Q*C>xQ9zu~%jp@U6H`0qcHxy>^6Dyt z!7+t1lZ^J$XVn8ImOhObs}GaG5zD?p-W+26cui8qoi`8| z^|%6)wI$oq@t5$m@v*%#-#R~n2UH88boAv?grl={-H}nNzXeqir2ax9*WUR zdTUTVa}RzV*9{dxr*n#kdWh6)!_oby`tI0sKc<-Jzba)|vosvlpecG9?I9gNx*jy?xma2csR?ejsAgpL z!l+GHa;el>``Xj&>$6vXF0*<@)y&MzJ{!9bRVPhzRXcZjVtIJy(-j_0_CX(68(2Xx z`!DfP8?kP6!fq2A%$Za0Y+Uo9veAbpkI#mF6xho=6qqU+^A;ufCJT(U{*v*XytW+I zANLFzQp2T7`c8hF*x}xmW9NdtW37MoTH8&Yh32E;^xcZjGF1a!nvBSlb%xCsy`3rg zI5IQ>da*%^MorJBiV_{BJ0!)&>TMHW;YMXHfql4L=jme53eD-eaCFMQPF-y8weaPH zE$ohRti0azO|~lJLWX*qPyLhU{BPtgU4(aP5HQnD5L-Kq8r+&|H6Ev=#-ov`#+fPp zgbYuTZ_Rj8^L4?MFw^Q3K|<{@zVn3T#{H{B$!53O@r!#iN(xevG=Dy%^EAoo$$16R z%5jZ}t>3IZD`iO_*A9d|5*7ttx;8&|(0T8y{G)^LxreB4YZbufe!W}pNXcs@m6;W* ziJa=9vrHv4ZwPUuhS;Mu(oJs&MYnd#g_!AsA}<&phj^O2!QXyE=zL)6-(#MCo&H2Y zC63;|dzw8??w`XC;IFyw3k#<;;+^{yc*cW$F6csiD z%0k7lw{mO0?f!vs*`6ZXq-T3v7I2>@n}!qjwDg2L!S9MDOo9e?bJ^TSweI`lM5~s! zFUE!BJ2}7N_jo+R>pQ(#x}Lc3L#D0L_^sKCFAwRQch|mgDA?0SY<(@RXj)mJY!MUfu>)q+Wvc&&+zBfgz&z<3)`OnGW$J5)Ucucmi^rJ#qso4E_wyI+-VPnt=UQ^x z?ChM~xJ294iDk@-vDD>Ep`++Q=+F(pR&ra9OqZ@HTx@#AgjRrvoE2gaw*mqeU<+}KvWAnFJcLMPGj zz-97V_tTanHEV6L2v_U!>tqtV4Zj3lPWcLnqAl5>wt1{NNQ@gGzEQ`lK+PZ5ivCBV zpu_ztz5(y>;lXk~Wd=J1S<^ zE`lmtb})*$^Kmnfkh|SkM}s1V2nH?Nhb@GPqtUP;hXx@y!khIFY`8-V5mSoT%tj?o znn(Eb$Soy63bx7SAmwgdw9Pe~hTZ)1yKQ)p`tG)ze3v8bBtoOD=O_2Uqe;UPA$Bf; zuf|i?=GRL12E_49oV^to_=r_pGHRgNKI= zI(sB#yY8y-Lg$d?QeN`YcxlpdQ@pLm=($0JA)M@-ot`|ua!=$}XOptX6mQu3vN$EO z^PpC|U}uWvv8?qx#9TkknQr#vqbo?lNgv*92HhM}kg&G`@k^dPkl1Xtj|!JFd(cx! zhL@9eU7pNn2hZdg-=e3L6R~s?%e#q=>|GCcFGw&f{Fune?>tl-cwu$V_(iJ|c<`tN z$jO6eO=WhS%Ef^urQ6+C&z&z0yoq1xyFJ*PEMLEi8gF>HZB%Bd6PLLC^M(KYX_2Hq zulweSMUj`oIpO)DUA1;*Q7Mh&8H3HTbs@K)YBXW<%DY?@v& zh7^(bZxbJ~<@R14y1XOPdF?#R51S^J<7SQg!COP9#Hd1lCllbV9{|63^-aUU9Uz4n zz3um5g)Z@~|3;TM^{x;ZDjSe&At=z!qn4y?5u_ zJonKzSgqt`8KGxgiDqNghHH^WqIIi00qJj>L9xIT=p`etMWG>V2c3s&(9*ebWV6z9 zsnm`Y-N6m-mq%!w-Eq+Sf4H9=_$#>eR`a@K6nGxcB3k6u>Y^g7@fmi-a{ z9+C;PeiU-zDIhJQ?U1=6U_}@D+fC3sZX~#b&l)bkruaEad=DzCBX@y7(10|aZSf4J6dPCbWYbUWg} z!0q2qVVDbTx70($aXVsGtN_Vz2nIk0sY!4cC2D#vEWY`VmIG>gvRNr(%s?hur3LCJwF?w=%B*@E6_cmDUVnj}PE&A4=IUlA$L0Bi@^f7=Ih*2{J z%7Y_=bPE4JUXMGRQx7NIYu8)SGQ@tF2BZZ8GA>sWUHgK6WcWK9L&N6nAoNv^!BZS2 z;V=*+;X3u`8BWq^1*m*tGpq$K@mRHGY75Y$WR9ndjYx$<^w8L7%sHE3;v$G! z8_v$>;ktQNyXPrG$L=qKrivlar{@^@y6zjB?m2M2iu={RQKwk7y)S5d43S%DvqO|( zN=z{E7z`7{}>8MMvP7+3d>%h+uJNNWJyz0oy%JeO1B!qs!haCS#7uh`P2T z_zFS;py@{7*FqU+ixmJMZx-qI+*!P5a8U@%2+hT623?73%RgMld(P8b0|46v-TpAi ziJybHKdOfkKdZLnWTxK?ra@tqHDDt-q@8ZZlCQNyJfO>vBk1ukvE62uEs#s#K%Zgr zo`=505Fg1lnKThrK#e8u6x zuC5V)b;p)+0zG{zdQ9uWTma3~-+i1Q5%|S%v^1g{3D~073cL5y63lex9A8YA*3|B^ zEqm4_{;a7zVyPi?Uc17%!;!p;xVm-Fv`xKm-b~Q>CDBG5d`jaX#+TS^rh;|q>&wjs&q&TkkVpo`ej{j z9Noh1ZL4_va-(fr69jPG7pNvCwibCr;}daWZ?$Nu_ghU)<-6e8#}m5hZRDLm#(Y;z zCn$MB=rloX@7N8dYlEO?*}b4AS|;9tdx=m=#hgOxaW#7Bnu%jq6`j+_1TNOq4>U*~`7jFxeo9_l`_%7Dzcsl3TL|;5%$gTC# z?s1@*TzOL-BuXnN1m}4e;wt5)=)IjVaUCtsYfgjjnI5~T1x%cXV$kDLFy>RAgNmI| z3p*B*x%}(ZVA3Ye+Np1?e`iDfZEpw83YcUX*ghm*zOY$-bvW09LRN%z|H}nR*m!;pYFLey8mL&=Ze1D*IK4S5}#d zqI(63x~@pC{A8a6=D0Jd&DLl`H0}i$a(T;gKHBJ_X@MhhCZLCg3@Mm4webnpb;jSyX-uJ%4?D&y2L z+=n0zxxE#IriWJG8Q4p$#wsg0-Rtx(kYtJkPVc%T)9H$pNCv1WtlPM`=)Y>Kl_A>C z#^aac2cb_W!guq^$DGWkCBY2ve4O&y!&0XutnCZ&f^Uj`H1)i}-Lrm&Vt_u!x64}( zBxLkB=#!s-0`q6(?$aqTASmi({-6Lr*?NElDuUEy8~V5u-?nJK+t zHL247E3C6or2<-zHrEG0`|-dF^%Hp+ngv%rgj}`3$jXYq3Z(pCdsPVoxlA4{s7c@z zB>SidWF^iw?>OGWeg9*t>bybqLBM&_3TwQc0foEneu+rjr=Tfj33SS6y5|nr3^rwrklOLvjQ=+ z2e1Qf0^Ick!VUm9;$F3XWd|IAneg9w$*l$AaC5h~Jz*iAwz7xM3w9kNp_95EWz3W<`B798i#^n4k zToVwZgx-yO)Ne7$dAKA0avZ4;G0NuuFCS@@HI%9p9#?-~FrML}>t$!r_1HJggYM*x zRvolY1QjJZ4(t+77JQ663&Un7SIBq(MEUqTVcyWw^a|(M_Kyn2Zvd>f5$u}kJ9;{5 zR1HC1S!`t9N!afMFP;As0cSF@{0qeNQD!qlb_2hX1|Tjp0`si_RCGgo&b->p20*J` zPHYgOW>H89Y!~r8z!NI~NkpgmR)9kWdDS+X!)+iU$K^%V*`u=st1Rm^tBpd8&Z^-4 zy8=dM(X!?zI=QM4yA@G7Fdy#DZLx#vAb0r^sZo>~q!>@mepC~Tg^+z;XIH*p+xhlV zm%L)v>6BvdY;6EjSrcIPS-iCA?%3}FI)BcjqRi=Dv6I(RO~4~(5F&h2BubSZfGAb@ zr6O%(ND60NAJ$7&1(nS0A1MUDW>shyroSu5<&-68Z^s6~>G_?j{T5(2?j3Q{*+sd1 zoA2xR%JTERZ-_;NMMT1Qt-FWtP{O`Xp{-&GoC6wx?$m(TFc6C3`=QX>?TY8^O)(xl zybA&}F^#cqT7vy2i#1n{#*niAkkyA{mC$NGbTi;;*XS#Lpm)mYg7fi-O^S5sHo5-!h8b4x<3=cz9(FC;}S1 zvi1_fT&ME?N22-<^gC9ki3kyCERAQwOQFj}xRq+-HO1L1O^+v~tChsYo{>5k&z6T+ z0)Dkqd43W>k~loKPFh*B(2veh{t`fj4xz?K@Y3!A_e8A-C?8^y(w8IefqF9vRTj<- zEP)ZYPv<$wfHp9dE~|~P5cY1qxlnYm#ChDPsQMEkBU$5TeW*R~(qvb0LFeufq&(M@ zlJET$a6#KGJBQA)UI8Vce~g*vC@{u^U&+RIgc{E^P>K)`D*{`B7&2y>$mdW8QG=Dvw8bJv5Ih~VT zR!6V8bVjddU7&$z-O&mfh~SCS%~-lM`qrTT>)TflE^3bp&=|VR?X23ZACBQkKb2&R zJY|arwne!z(mx>3I}k^ws1{ibM?DfjD(48@NS<5^#t<|GIW(wIPe4=fiI#|*O(Mwp zT)d)3VVOM?;clUy`JAi{wz#x+gqTXuNmv?A6_Xq0}(Qq~u(Q@B7lDCsTg&0Wx$F%`bcW< zji`p8q>qE`5hZ*FN=5d8K_J2ma_ZlE^z!EJy8EX7hjv8pqgg8ig+YqPj|x*9gozJM zMO548#S-_jBLwa6Oaz_yUwAZ|pC3sFmx-6GHj2$QQgI8I_0j_0iL%nnLY|;uRkPoJsX=(ds(dH zAHhqj9Vu<4i~9@d>0jC-vgb|&4yYAexp@Lq@v)f+vhU)r{@|sSMsq<<5d~JkR-WFZdi@JY?a|Xj`I&S>q1TCw6y%sQ8gOEs&(Kn^prU}dRR7c~*u%OP%L;oL&}_ITF;UG3_Pou|PXS`F5^6}H?6SVL1lUHD(vj+^|59-@_r-iC=-p;&CiZ-B*-*V&E!hISIz6*!;2XblfY2KY; zI}!`M6G$5;9Hm-0so}s`6C865N4DS}@yD*mp|sU4)HA za?oG{jrdN#P?RTFfbaAWoWDWvo$i2C)*5`LcR_lw>kyR*k9YFTm+B!%E8!T(WQek? zw%0b`h(ovl4Q}EqEa_toR*;<>UKK|w*kuV;)`R|D(6x~-k+ZH2 zdoST~emT!sdK@n2<4)`&mrl=$O2Er3`N|x@&r0Gy?JP(BtobP$Y9K|_ zAh!;)BzLX+BRaVB=r~6kd{?q{#ZqEG+^G)Cq(`85H_{rK*$MYX=NE%>&My;jbE)9g zsq>1jRpH+2;ME)!m`Ljn^YUKb1`oFH_oYf6@nFvv+6|ql{ zSh)uEiA9GIDDoC81J6EA9=^lw*}-_*+*k&9>8^6KVPsjO$rvP()5JAE+$~w#NkT#w z=kS6x@+M5e%|dnu3E27omqbJ5r#y|`=wLp;nL*c^AT#UBvi2zbhOa}iA(daSFT8s6 z6n1w%r92sk4uM)Z=;UR<>B-PC*$GmI6-sCR0w(#*I;{Yde>)U$vkSqRFF(VO3ZXfZ zd2=CuC@qKM9z34P=tv7L05)@7Ho+pgtxB~2_77>DDBW(|Ids;2%!K7A_}%gBy|Pef zp?_8BgAdlrixzc$Kv~;IoCEFzYP}X3n)$~{R>BX#!XYkP;OHo<`<%IY#yoHz=gk$< zMnPFG(fU*0zMiE3XrEQA(1_kZH--dMaezGjC1xl&)lB!9Uw~bC_;vaJP`vwRT8kL=HBhAle&V19wxWyjAGJd>e1!%+L=Rl8^w?-l zQbN>)%r>l(+P&vu@gf_;Em+_Z!rXzr^JS@{r+z}qV9s1XNO#>U^UOXNZam_Z32G!T z+ZIq~Ei{llx4bb&FaB>_(mPZ;p8diC{8`>VC-%>YJ;8TfpBd>M{opeeLS%T&Jwf*N zR?MsICRP|ci@`N098;H|SQb8Rd4{|3P;7wa9 zs?0z*&w^Cbv5bfp&K=}!8O?V4^b!881b)6%g-8y7AGIYQK+L6y)8X;(Avj_D)DHY5 zh=Pc<=kcE1Yv3Gr1R7aS#7-WBOvwirL|8E2gi<~Wr6NPL@I1HjPPr`Ty*$xBj$(k` z3k9{W7V8uZ$eZbygMxlpd0e9yA3y5Wb|f5XK#a(oLn+QN%FG^>F#+HP#Vle$Hmci) zfmnPms*FX1oii932e<}6(ttn(?oB3Ogm%FF4~q1^GNQkVUtEkY4>9$()>vC>B9$#8 z9jR+fGK-EfW<;Qb#FidXEs27>$_r`|TOSo%6@~j+R7Z3#&wLvaE`a>t`<)3t;^0j~ z^a%h@DaZ$SN`rOq+zs^gw)Yb|Ore(fHHq*QxK>?yZ%VhKZ%}_H$UdI9y8jdz&d<3oU07J%EVl&v0y4LU5KXRCc#~ zrgJF2F@qz_w>^*{^Fzj)83wp4Jfse#5JqOwan`{;a6bb{to$WNx6_1;fNH-dJ8Ka6 z{Ba|~7h6J%8=y+u^cB@6xEL^}Su0lGpv`w`%ah?U?;2fAX-!f##5@s(za{(zV*r1P zLx9x!)-%}+ra}#J-8k=6tQ7&b^K=rrP-tUk7d`vD% zFl(seiKBbj=;s20se{F9-x|Ss3@U4S5pVm7+g5ojwQKqx5?Nm#( zWxl#pJsl-&R8s!2KMEOavsk#C-G{fut%rWb2TE;@IOZTr(czNyAB->Wn7MZmm({ct*!oz3_9paIj#gBbmo1ZsiXX%<@OQ1 z47Hjo=EEzh;hM-`<$I(k-$?8k(#d{gdthdB#OFfXyGnl2BR^=pVp(r+laL-Jr~rk8 ztgIdJf@v5(|I^}IDYOK)_L`k#^5|!MD;SnE*Ya`x-hm`!uz}@nv_6gpKBViP?2#Ji z-57BZ?eZ(976If3JLW#e7@%EugK^$YFpY>KS>S1Wk|AkT}DdHeC_zU_PeY|uX&^v?$U-@ZXr<{dWa zDgvLxH`>(S<8C1A7)NO3=HBWuifVT<#u1zxC%PmGKu_q6e4a7h#(BKs8i*@jngHCK zPe|xFqsa39gZJ%UaCk1Ud#Edabm5U4o=!JVXuAWqyY27W{UWtlZs13&!zw*`iuzau&ntoBraV#G^om5Ju=WES^irUxAAL z6_^Eap_n*2tJ?yKJye{$BU-#`Q?*jp*c5vdzp8}W9?+X>2q|}a5%BvSOt%}nX@1~! z`cFws=kX6AHsh9R1u53nqNWTpo{9x2)9*37J~dPk-!Lehk?Ldn$3{V77JD#;rT0e0_y&7mtD{#4)gjKY}NY z;%z*a-m*Bm=u0iMo7B5lE&*N+m{8S#%qx57QX96v-sM`m>o?C;Yk)^iK8TQ%Kcy@> zti`*cL3y!)b^Ys9vns-^Kl_u}T%Zyuc%*%x3LLS+p)5LtdqHo$86IYGbRxR3bGM;O$ZM3hP$KzmH zZ#C3KaW@`qk}^RWOcP;ufCuy!Kr3lW=>ARYYPF4#OM;bLJKp~opH1obF>vxb;J7em zSOECb++h3K{Vq4usY?g%@fm#S(y{cDY6(IM(ryuDj!NjHzO0hh@Xz0YZqWV*foV9dsx= z>uV}B$7eN?Mi6oT4*8~xseRPMhgd}Xu_&|^>Gg{qUc(i*p6`Dvomy$@=htOu4-$TK zO|O227tOA^1l@^XUrvskQ%^h}K*2fvmSuSB{j^Cf=a2nrc|o~*Tg1Y@{SFq&I6j=; zliqedvV6F}%H`AzD}!@!bkC!~+s2&Q?66YelBd1xel=x}fLkTQTkqw$8TzWk|R+wgs>Bu4p1Ta{hvtEBSWi z!9bb59SYCOnPk$c_>9_iejLp^9Ctg_-;qys_mFqF+uXf|*wN%AridI{ci6XHuy3=c z9RcGH!mH+`+jerqHEvMHBdLpRA<4%_Txf5*-a9F=&E?)Y;rbxz* z5r-p{PC8=ka^LS3y&q|EA(qbO_G5#KZr7%~+X-g+Wgxa$-;^~~6vT8BfTV*}0Cg!1 zwCmjN2(I>|Sh|-~eKL#W)YE*cja)1h?4uumn$wIUtK|P zwWup%+_qTg#`ur8(g~ZFicKs=#`oO9^4$(w3O5z>trQG4yAXIfWDar;DSAF@qgW_0 znP_`(e4^HJlHbYYaagR`M8cIJ%`DsN`~u4o}3OTpS{{Pkt1=V|M;`>gn{Ow z^Um1@hwn{lh1#~~C*S&#MaVV#*|VDDcm|<3IQ@d3XN99*_L3M0Xr( z^}?Y&ageuDt>d97+`h75z0Xzp$?NgyDCeqacTd8i&-}}kuvEFy%pNd6K);Q&t2H)| z(BdnR=KZkVu)XH9^@fwu>z%(`ZYrw5hC6AIk3owK&XK35js((*%n>z1j7R zuu2B2n~Ft8t{Ml_xbPNOSdrkVBw!?xL92ZyW6OFQce}KflnIi~aC*9xlm0*kq+2Q^Mnf_UGt~72$MkE$k%3<9nn&aPK@&cE4o(GW&nFs4PP0| zN~mRQ=dCIUBj8eM>s8&akShlLbSd|5Lg588-xezlf{!i$^eqpQSwA#Wn{7nz{=j5&Vi@TBv0~=b5{A0yD_S=TZWtpBlgW9+ zpv9NZ&wLyH=zH!{oqxfbpMB)wOcIu16d`9Lrd)G1)}p99tbdt3{{X?U7%uVQC1oIZ zMYA^ElO1?jsesLK{UYH>HR41bWJh^Oi5yXnMIU`um;etKgIz z*hKMuuQ5oqxf$Aa4a)>0hF#Iu= zifx96@y;wNcUM7_94o^CQ5)e#1H?gOqo+#?y;AgvZKnhus(gDaG2{pcu&Yrh&mT#B=wA2fp*iRAw25B6G zhJVkhpH;(~C#az4bHM0h;`bhEAk8(ZZ$3z(dfy^jYyFY%VB!~4r|qW*O4LDgi*%B# z(}Kk zs#l=?4=|K4%7y|y(44>Y?G)Fki2L5k+M8%$SFj~GviZU6UT*}ST;uZTz|4&a;yE7i zTT?Jtq#JKm_fB21MH%z9wGLXRPeL)+? z;=+5$rFKg-`t&lB2WL2C{{EI)baY`HHFP2!VOG3}xb)bUqL)Ynax>jr`9jU_kp>(A zDvCTE$o7l3k0Z%MU8G9X1aea#hg#3t)mt4MWrA&P*}dcKX7OA9fLk~kb7b5# z>iF*}GIFcGbm*tY*OUlb(nj_*UyEFvWbINK=oRqxPMB?q<#{1z068-7tfT+kv)u81 z3d~#c3wnoaVD?ncIG9ut0cgdYQwHzJCQvy@w2c;U$vy!=2? zsFBRYLdSk0Y7<0;6Y^PgDY#oX9p}gJVA4v}mefG>Z2~pU0Q4elNLV6T!uw3`F${1Q z>NE@O*qlj@%(jVhuV6%O;q{H;_!gr>Q6%9u zp@=erJc*WvI6=iw;j~O>CKY+(%Fy$oG0!VXl|2g89?a|#T5{$Go8k9?G;hjpA#Y|_ zloH9$Cfl=iyB@bNjiovcq0q-1=>BMhk6VK9v;~tNI*UrR&#QHhxrPpi_H$UpLNe7+ z`tgm=Sh=z2X&j_=KD%wsj5u#L%5AyNmb`W)#E~gU;^yYgFAHhrj8M&yI%~eg6QbwN zP&T|m(Z3Uiir*FAnxoFVMJjO{E6xWyH?uKy@#sjcCnE6eN}1p0bnnCE4FnjM(M?QF zt!E9O)oXxoymBUyJi@E_pTP%l+bwV+FpyhASd*A)%S0X0~$K*j1Vd%sohM$@1NMDkFju5zx%Y`sNVPP zYjIND&BIKV^V=L%Kz`AO^yv@=V-H-XVo#AJQdIn;K9OX0^ciGvaXh{e(3S-?g?$K5 zN~>IJo7PO`>t8V>zpR`5ih|8MC)D*J0Hj*Bk0P6X|AnhW(tonL!FNbs>AMgn3B9)p z-8)70lj2`bujEZnMsg%so5g}+DFsaU^|bo84dY(0OP);C0m+;SqKK$>xweY~$waki z`v6=N83{C{gsjm_+~8+Rt}vxuMkZ9F3@Oy=FYhW&$g|j@h@ZY>xQ_MU0*pF`)ze{b zO1596h8wJ)&tsLVC8%QkcAU}kP%5$wd>lBe9NHIt=pAPTT}FN#3U#4?UO~$P&DcPn zMMiy%93-{ENe`#P<$z}AFGn>_9^SCs^WJBJ9f`G`Vl|%BH@beLEwHbLb7mbh1Y$tP_G2v?=B zQx@-bP^cCm@2U@iR~Rm}z>E3M{YHB%DOB(IyIP#yD03>^7(y|Xw7ZKx_RoP-2k-yM zni-k|^)+tPu4$}=O2r$QQpds^Rs6G2=7jkbf2Tg}v8Qr4y3(V*u>31@JnZymf*Qg+ zN`x`N{l>#aeeTp7*0SVk-R#FW_r^XRtP1wF&y{&{NuzV3P5f0Nh)2-$(e6Q|uMfoR zgHoJKE15_lzFOxK@o-t>+Wr)_I=kK>K;eNKXT#I8O*z$zpAzcac5uNL=s22y39!{T zS^nsN(#OXeyXMKasNv_B4dL`jebG;g_VBa`GeZY=(MfWQD?c+0SvcHIcJjIG{DNFW zpRyY)x#YapQ(ect-F!u-`u?qc^$SRT?W*IVbQM|Sk7_oIZCv{8oN)KySA)kdP<%p+ z)lwiFrIOun84#tmvTOzED#HDTWvwmzx+?ohpI@gw)NX7*61W2Hf+0XU6CLDU<(k9&h8zM!^WImaUMEK4n?CJLoe2W zpeMvZ8I!t?7vVCab`lH5Nj;SFX8`-;d}DHJyQQA(3vLg^q>u|T=c@7s(J7wTzm3*8 z53ugPAn6rB^kB`3JP_vk+TWU#<#(SVQ61;~Lp5qD3Z@d~JLPo>R`FnWpS-5(RvbAWLm)-(v{o z9%_dARKwKsWSJ^@!s0ga%+1ciq4t5L*;S09hc2g^+z|J+VrjJPYib&fe00ybq-%GO zv!QgGGC3L>Kbe=~8_iyUni;Gg9cm&q6LyrA$akGyu{|e$vBFZB?dl{)MBYt&Lqsb6 zy5XP({Di5ToU^y|0z#zo%2d4v714{dmGjsu{S#sH|CBLdi5g$tAOFJRF=X)?uNWM+HZtJ< zn}289?aBw;zk9rusI=W~_6JeiztO&=ycF54e%%JLu>B0>dP+OR^{(OyV{j)0(4Fn{ z_?q`Kz_Q$ivO@W?1%Fv~Xy+%(f-d<p{`og~Q2O*aJ5}cW_O}iKxBs;Z8#!9=-MsQX3iX=geAtocbiozmPsRSA3RX zwu_8=y + +--- + +## 1 Motivation + +### 1. Independent, fine-grained scaling +* Vision encoders are lightweight, while language models are orders of magnitude larger. +* The language model can be parallelised without affecting the encoder fleet. +* Encoder nodes can be added or removed independently. + +### 2. Lower time-to-first-token (TTFT) +* Language-only requests bypass the vision encoder entirely. +* Encoder output is injected only at required attention layers, shortening the pre-fill critical path. + +### 3. Cross-process reuse and caching +* In-process encoders confine reuse to a single worker. +* A remote, shared cache lets any worker retrieve existing embeddings, eliminating redundant computation. + +--- + +## 2 Usage Example + +The current reference pathway is **SharedStorageConnector**. +A ready-to-run script shows the workflow: + +`examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh` + +--- + +## 3 Development + +Disaggregated prefilling is implemented by running two vLLM instances: + +* **Encoder instance** – performs vision encoding. +* **Prefill/Decode (PD) instance** – runs language pre-fill and decode. + +A connector transfers encoder-cache (EC) embeddings from the encoder instance to the PD instance. +All related code is under `vllm/distributed/ec_transfer`. + +### Key abstractions + +* **ECConnector** – interface for retrieving EC caches produced by the encoder. + * *Scheduler role* – checks cache existence and schedules loads. + * *Worker role* – loads the embeddings into memory. + +Here is a figure illustrating disaggregate encoder flow: + +![Disaggregated Encoder Flow](../assets/features/disagg_encoder/disagg_encoder_flow.png) + From 756663cbb284becf8c3885f141717a2e4a6034d2 Mon Sep 17 00:00:00 2001 From: herotai214 Date: Tue, 16 Sep 2025 10:13:46 +0000 Subject: [PATCH 20/57] [Feature] E+P+D disagg with proxy & example Signed-off-by: herotai214 --- .../disagg_epd_example.sh | 174 +++++++ .../disagg_epd_proxy.py | 461 ++++++++++++++++++ 2 files changed, 635 insertions(+) create mode 100644 examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_example.sh create mode 100644 examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_example.sh b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_example.sh new file mode 100644 index 000000000000..c06260587a82 --- /dev/null +++ b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_example.sh @@ -0,0 +1,174 @@ +#!/bin/bash +set -euo pipefail + +############################################################################### +# Configuration -- override via env before running +############################################################################### +MODEL="${MODEL:-Qwen/Qwen2.5-VL-3B-Instruct}" +LOG_PATH="${LOG_PATH:-./logs}" +mkdir -p $LOG_PATH + +ENCODE_PORT="${ENCODE_PORT:-19534}" +PREFILL_PORT="${PREFILL_PORT:-19535}" +DECODE_PORT="${DECODE_PORT:-19536}" +PROXY_PORT="${PROXY_PORT:-10001}" + +GPU_E="${GPU_E:-2}" +GPU_P="${GPU_P:-2}" +GPU_D="${GPU_D:-3}" + +EC_SHARED_STORAGE_PATH=/workspace/hero/hero_EPD/test/epd_long/ec_cache_save +TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout + +NUM_PROMPTS="${NUM_PROMPTS:100}" # number of prompts to send in benchmark + +############################################################################### +# Helpers +############################################################################### +START_TIME=$(date +"%Y%m%d_%H%M%S") +ENC_LOG=$LOG_PATH/encoder_${START_TIME}.log +P_LOG=$LOG_PATH/p_${START_TIME}.log +D_LOG=$LOG_PATH/d_${START_TIME}.log +PROXY_LOG=$LOG_PATH/proxy_${START_TIME}.log + +wait_for_server() { + local port=$1 + timeout "$TIMEOUT_SECONDS" bash -c " + until curl -s localhost:$port/v1/chat/completions > /dev/null; do + sleep 1 + done" && return 0 || return 1 +} + +# Cleanup function +cleanup() { + echo "Stopping everything…" + trap - INT TERM USR1 # prevent re-entrancy + + # Kill all tracked PIDs + for pid in "${PIDS[@]}"; do + if kill -0 "$pid" 2>/dev/null; then + echo "Killing process $pid" + kill "$pid" 2>/dev/null + fi + done + + # Wait a moment for graceful shutdown + sleep 2 + + # Force kill any remaining processes + for pid in "${PIDS[@]}"; do + if kill -0 "$pid" 2>/dev/null; then + echo "Force killing process $pid" + kill -9 "$pid" 2>/dev/null + fi + done + + # Kill the entire process group as backup + kill -- -$$ 2>/dev/null + + echo "All processes stopped." + exit 0 +} + +trap cleanup INT +trap cleanup USR1 +trap cleanup TERM + +# clear previous cache +echo "remove previous ec cache folder" +rm -rf $EC_SHARED_STORAGE_PATH + +echo "make ec cache folder" +mkdir -p $EC_SHARED_STORAGE_PATH + +############################################################################### +# Encoder worker +############################################################################### +CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ + --gpu-memory-utilization 0.0 \ + --port "$ENCODE_PORT" \ + --enable-request-id-headers \ + --no-enable-prefix-caching \ + --max-num-seqs 128 \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_producer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'", + "ec_max_num_scheduled_tokens": "4096" + } + }' \ + >"${ENC_LOG}" 2>&1 & + +############################################################################### +# Prefill worker +############################################################################### +CUDA_VISIBLE_DEVICES="$GPU_P" VLLM_NIXL_SIDE_CHANNEL_PORT=5559 vllm serve "$MODEL" \ + --gpu-memory-utilization 0.7 \ + --port "$PREFILL_PORT" \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_consumer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'" + } + }' \ + --kv-transfer-config '{ + "kv_connector": "NixlConnector", + "kv_role": "kv_producer" + }' \ + >"${P_LOG}" 2>&1 & + +############################################################################### +# Decode worker +############################################################################### +CUDA_VISIBLE_DEVICES="$GPU_D" VLLM_NIXL_SIDE_CHANNEL_PORT=6000 vllm serve "$MODEL" \ + --gpu-memory-utilization 0.7 \ + --port "$DECODE_PORT" \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --kv-transfer-config '{ + "kv_connector": "NixlConnector", + "kv_role": "kv_consumer" + }' \ + >"${D_LOG}" 2>&1 & + +# Wait for workers +wait_for_server $ENCODE_PORT +wait_for_server $PREFILL_PORT +wait_for_server $DECODE_PORT + +############################################################################### +# Proxy +############################################################################### +python disagg_epd_proxy.py \ + --host "0.0.0.0" \ + --port "$PROXY_PORT" \ + --encode-servers-urls "http://localhost:$ENCODE_PORT" \ + --prefill-servers-urls "http://localhost:$PREFILL_PORT" \ + --decode-servers-urls "http://localhost:$DECODE_PORT" \ + >"${PROXY_LOG}" 2>&1 & + +wait_for_server $PROXY_PORT +echo "All services are up!" + +############################################################################### +# Benchmark +cd ../../../../benchmarks/ +python benchmark_serving.py \ + --backend openai-chat \ + --model $MODEL \ + --dataset-name hf \ + --dataset-path lmarena-ai/VisionArena-Chat \ + --seed 0 \ + --endpoint /v1/chat/completions \ + --num-prompts $NUM_PROMPTS \ + --port $PROXY_PORT \ + --port $PROXY_PORT +############################################################################### + +# cleanup +echo "cleanup..." +cleanup \ No newline at end of file diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py new file mode 100644 index 000000000000..ecff98a3cacb --- /dev/null +++ b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py @@ -0,0 +1,461 @@ +# epd_proxy.py - E+P+D Separation Proxy +import asyncio +import copy +import json +import logging +import os +import time +import uuid +import random +from typing import AsyncIterator, Optional, Dict, Any, Union +from fastapi import FastAPI, Request, HTTPException +import aiohttp +from fastapi.responses import StreamingResponse, JSONResponse +import uvicorn +import argparse + + +logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s") +logger = logging.getLogger("proxy") + +app = FastAPI() + +encode_session: Optional[aiohttp.ClientSession] = None +prefill_session: Optional[aiohttp.ClientSession] = None +decode_session: Optional[aiohttp.ClientSession] = None + + +@app.on_event("startup") +async def startup_event(): + global encode_session, prefill_session, decode_session + encode_session = aiohttp.ClientSession( + connector=aiohttp.TCPConnector(limit=0), + timeout=aiohttp.ClientTimeout(total=100000)) + prefill_session = aiohttp.ClientSession( + connector=aiohttp.TCPConnector(limit=0), + timeout=aiohttp.ClientTimeout(total=100000)) + decode_session = aiohttp.ClientSession( + connector=aiohttp.TCPConnector(limit=0), + timeout=aiohttp.ClientTimeout(total=100000)) + + +@app.on_event("shutdown") +async def shutdown_event(): + global encode_session, prefill_session, decode_session + if encode_session: + await encode_session.close() + if prefill_session: + await prefill_session.close() + if decode_session: + await decode_session.close() + + +def has_mm_input(request_data: dict): + """Check if request has multimodal input (images, audio, etc.)""" + if "messages" not in request_data: + return False + for message in request_data["messages"]: + if not isinstance(message.get("content"), list): + continue + for content_item in message["content"]: + if content_item.get("type") in ["image_url", "audio_url", "input_audio"]: + return True + return False + + +async def process_encoder_stage( + request_data: dict, + request_id: str, + e_server_url: str +): + """Process request through Encoder stage (if has MM input)""" + if not has_mm_input(request_data): + return + + logger.debug(f"Processing MM input through encoder for request_id: {request_id}/ url: {e_server_url}") + encoder_request_data = request_data.copy() + encoder_request_data["max_tokens"] = 1 + if "max_completion_tokens" in encoder_request_data: + encoder_request_data["max_completion_tokens"] = 1 + + headers = {"x-request-id": request_id} + task1 = asyncio.create_task( + encode_session.post( + f"{e_server_url}/v1/chat/completions", + json=encoder_request_data, + headers=headers + ) + ) + try: + response = await task1 # seems fire-and-forget didnt gain any benefit + if response.status != 200: + error_text = await response.text() + raise HTTPException( + status_code=response.status, + detail={"error": "Encoder request failed", "message": error_text} + ) + logger.debug(f"Encoder processing completed successfully for request_id: {request_id}") + return + except Exception as e: + logger.error(f"Encoder processing failed: {e}") + raise HTTPException( + status_code=500, + detail={"error": "Encoder processing error", "message": str(e)} + ) + + +async def process_prefill_stage( + request_data: dict, + request_id: str, + p_server_url: str +) -> dict: + """Process request through Prefill stage and return kv_transfer_params""" + logger.debug(f"Processing through prefill for request_id: {request_id}/ url: {p_server_url}") + + prefill_request = request_data.copy() + prefill_request['kv_transfer_params'] = { + "do_remote_decode": True, + "do_remote_prefill": False, + "remote_engine_id": None, + "remote_block_ids": None, + "remote_host": None, + "remote_port": None + } + prefill_request["stream"] = False + prefill_request["max_tokens"] = 1 + if "max_completion_tokens" in prefill_request: + prefill_request["max_completion_tokens"] = 1 + if "stream_options" in prefill_request: + del prefill_request["stream_options"] + + headers = {"x-request-id": request_id} + try: + prefill_response = await prefill_session.post( + f"{p_server_url}/v1/chat/completions", + json=prefill_request, + headers=headers + ) + prefill_response.raise_for_status() + + if prefill_response.status != 200: + error_text = await prefill_response.text() + raise HTTPException( + status_code=prefill_response.status, + detail={"error": "Prefill request failed", "message": error_text} + ) + logger.debug(f"Prefill processing completed successfully for request_id: {request_id}") + + return prefill_response + + except Exception as e: + logger.error(f"Prefill processing failed: {e}") + raise HTTPException( + status_code=500, + detail={"error": "Prefill processing error", "message": str(e)} + ) + + +async def forward_request( + request_data: dict, + request_id: str, + e_server_url: str, + p_server_url: str, + d_server_url: str, + is_streaming: bool = False +) -> Union[AsyncIterator[str], dict]: + """Forward request through E->P->D pipeline""" + + # Step 1: Process through Encoder instance (if has MM input) + await process_encoder_stage( + request_data, request_id, e_server_url + ) + + # Step 2: Process through Prefill instance + prefill_response = await process_prefill_stage( + request_data, request_id, p_server_url + ) + # for nixl connector to facilitate kv transfer... + prefill_response_json = await prefill_response.json() + kv_transfer_params = prefill_response_json.get('kv_transfer_params', {}) + if kv_transfer_params: + request_data["kv_transfer_params"] = kv_transfer_params + logger.debug(f"kv_transfer_params: {kv_transfer_params}") + + # Step 3: Process through Decode instance + logger.debug(f"{'Streaming' if is_streaming else 'Getting'} response from decode for request_id: {request_id}/ url: {d_server_url}") + + headers = {"x-request-id": request_id} + + if is_streaming: + # Streaming response + async def generate_stream(): + try: + async with decode_session.post( + f"{d_server_url}/v1/chat/completions", + json=request_data, + headers=headers + ) as response: + response.raise_for_status() + async for chunk in response.content.iter_chunked(128): + if chunk: + yield chunk.decode('utf-8', errors='ignore') + except Exception as e: + logger.error(f"Error in decode streaming: {e}") + raise + + return generate_stream() + else: + # Non-streaming response + try: + async with decode_session.post( + f"{d_server_url}/v1/chat/completions", + json=request_data, + headers=headers + ) as response: + response.raise_for_status() + result = await response.json() + return result + except Exception as e: + logger.error(f"Error in decode response: {e}") + raise + + +@app.post("/v1/chat/completions") +async def chat_completions(request: Request): + """Handle chat completion requests through E->P->D pipeline.""" + try: + # Load balance across instances + e_instance = random.randint(0, len(app.state.e_urls) - 1) + p_instance = random.randint(0, len(app.state.p_urls) - 1) + d_instance = random.randint(0, len(app.state.d_urls) - 1) + + e_server_url = app.state.e_urls[e_instance] + p_server_url = app.state.p_urls[p_instance] + d_server_url = app.state.d_urls[d_instance] + + request_data = await request.json() + request_id = request.headers.get("x-request-id") + if not request_id: + request_id = str(uuid.uuid4()) + + is_streaming = request_data.get("stream", False) + + logger.debug(f"Processing request {request_id} through E->P->D: {e_server_url} -> {p_server_url} -> {d_server_url}") + + if is_streaming: + stream_generator = await forward_request( + request_data, request_id, e_server_url, p_server_url, d_server_url, is_streaming=True + ) + return StreamingResponse(stream_generator, media_type="text/event-stream") + else: + result = await forward_request( + request_data, request_id, e_server_url, p_server_url, d_server_url, is_streaming=False + ) + return JSONResponse(content=result) + except Exception as e: + logger.error(f"Error processing request: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + +@app.get("/v1/models") +async def list_models(): + """List available models from decode instances.""" + try: + async with decode_session.get(f"{app.state.d_urls[0]}/v1/models") as response: + response.raise_for_status() + return await response.json() + except Exception as e: + logger.error(f"Error fetching models: {e}") + raise HTTPException(status_code=500, detail=str(e)) + + +@app.get("/health") +async def health_check(): + """Health check endpoint for all instances.""" + try: + async def check_encode(): + try: + for e_url in app.state.e_urls: + async with encode_session.get(f"{e_url}/health") as response: + response.raise_for_status() + return True + except Exception: + return False + + async def check_prefill(): + try: + for p_url in app.state.p_urls: + async with prefill_session.get(f"{p_url}/health") as response: + response.raise_for_status() + return True + except Exception: + return False + + async def check_decode(): + try: + for d_url in app.state.d_urls: + async with decode_session.get(f"{d_url}/health") as response: + response.raise_for_status() + return True + except Exception: + return False + + encode_healthy, prefill_healthy, decode_healthy = await asyncio.gather( + check_encode(), check_prefill(), check_decode(), return_exceptions=True + ) + + if not (encode_healthy is True and prefill_healthy is True and decode_healthy is True): + status_code = 503 + else: + status_code = 200 + + return JSONResponse( + { + "proxy": "healthy", + "encode_servers": "healthy" if encode_healthy is True else "unhealthy", + "prefill_servers": "healthy" if prefill_healthy is True else "unhealthy", + "decode_servers": "healthy" if decode_healthy is True else "unhealthy" + }, + status_code=status_code, + ) + + return health_status + + except Exception as e: + logger.error(f"Health check error: {e}") + return JSONResponse( + content={"proxy": "unhealthy", "error": str(e)}, + status_code=503 + ) + + +@app.get("/status") +async def get_status(): + """Get status of all instances.""" + return { + "encode_instance_count": len(app.state.e_urls), + "prefill_instance_count": len(app.state.p_urls), + "decode_instance_count": len(app.state.d_urls), + "encode_instances": app.state.e_urls, + "prefill_instances": app.state.p_urls, + "decode_instances": app.state.d_urls + } + +## profiler methods ## + +async def _post_if_available( + session: aiohttp.ClientSession, + url: str, + payload: dict, + headers: dict, +) -> Optional[dict]: + """ + POST `payload` to `url`. + Returns + ------- + • The decoded JSON body on success (2xx) + • None if the endpoint does not exist (404) + • Raises for anything else. + """ + try: + resp = await session.post(url, json=payload, headers=headers) + if resp.status == 404: # profiling disabled on that server + logger.warning("Profiling endpoint missing on %s", url) + return None + resp.raise_for_status() + return await resp.json(content_type=None) + except aiohttp.ClientResponseError as exc: + # Pass 404 through the branch above, re-raise everything else + if exc.status == 404: + logger.warning("Profiling endpoint missing on %s", url) + return None + raise + except Exception: + # Network errors etc.: propagate + raise + +async def _profile_cmd(cmd: str, payload: dict, e_url: str, p_url: str, d_url: str): + """ + Fire & forget to both clusters, tolerate 404. + """ + headers = {"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY', '')}"} + + encode_task = _post_if_available( + encode_session, f"{e_url}/{cmd}_profile", payload, headers + ) + prefill_task = _post_if_available( + prefill_session, f"{p_url}/{cmd}_profile", payload, headers + ) + decode_task = _post_if_available( + decode_session, f"{d_url}/{cmd}_profile", payload, headers + ) + + encode_res, prefill_res, decode_res = await asyncio.gather(encode_task, prefill_task, decode_task) + + # If *all* clusters said “I don’t have that route”, surface an error + if encode_res is prefill_res is decode_res is None: + raise HTTPException( + status_code=503, + detail="Profiling endpoints are disabled on all clusters", + ) + + return { + "encode": encode_res, # may be None + "prefill": decode_res, # may be None + "decode": decode_res, # may be None + } + +@app.post("/start_profile") +async def start_profile(request: Request): + body = await request.json() + # TODO: handle multi urls properly + e_url = random.choice(app.state.e_urls) + p_url = random.choice(app.state.p_urls) + d_url = random.choice(app.state.d_urls) + return await _profile_cmd("start", body, e_url, p_url, d_url) + + +@app.post("/stop_profile") +async def stop_profile(request: Request): + body = await request.json() + # TODO: handle multi urls properly + e_url = random.choice(app.state.e_urls) + p_url = random.choice(app.state.p_urls) + d_url = random.choice(app.state.d_urls) + return await _profile_cmd("stop", body, e_url, p_url, d_url) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="E+PD Separation Proxy for distributed vLLM servers") + parser.add_argument("--host", type=str, default="0.0.0.0", help="Proxy host") + parser.add_argument("--port", type=int, default=8000, help="Proxy port") + + parser.add_argument("--encode-servers-urls", type=str, required=True, + help="URLs of the encode servers in comma separated format" + "(e.g., \"http://localhost:8001,http://localhost:8002\")") + + parser.add_argument("--prefill-servers-urls", type=str, required=True, + help="URLs of the prefill servers in comma separated format" + "(e.g., \"http://localhost:8003,http://localhost:8004\")") + + parser.add_argument("--decode-servers-urls", type=str, required=True, + help="URLs of the decode servers in comma separated format" + "(e.g., \"http://localhost:8005,http://localhost:8006\")") + + args = parser.parse_args() + app.state.e_urls = args.encode_servers_urls.split(",") + app.state.p_urls = args.prefill_servers_urls.split(",") + app.state.d_urls = args.decode_servers_urls.split(",") + + logger.info(f"Starting E+PD separation proxy on {args.host}:{args.port}") + logger.info(f"Encode instances: {app.state.e_urls}") + logger.info(f"Prefill instances: {app.state.p_urls}") + logger.info(f"Decode instances: {app.state.d_urls}") + + uvicorn.run( + app, + host=args.host, + port=args.port, + log_level="info", + access_log=False, + loop="uvloop" + ) \ No newline at end of file From 3613eccdb7ffa8523091474ad5ebfa5023848a3e Mon Sep 17 00:00:00 2001 From: herotai214 Date: Wed, 17 Sep 2025 09:25:48 +0000 Subject: [PATCH 21/57] [Misc] Proxy support E+P+D & E+PD / Update docs & examples Signed-off-by: herotai214 --- docs/features/disagg_encoder.md | 19 +- ...pd_example.sh => disagg_1e1p1d_example.sh} | 2 +- .../disagg_1e1pd_example.sh | 149 +++++ .../disagg_epd_proxy.py | 582 ++++++++++-------- 4 files changed, 475 insertions(+), 277 deletions(-) rename examples/online_serving/disaggregated_encoder/shared_storage_connector/{disagg_epd_example.sh => disagg_1e1p1d_example.sh} (98%) create mode 100644 examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1pd_example.sh diff --git a/docs/features/disagg_encoder.md b/docs/features/disagg_encoder.md index 68aca1f8be7c..42f1164f56eb 100644 --- a/docs/features/disagg_encoder.md +++ b/docs/features/disagg_encoder.md @@ -30,18 +30,23 @@ Design doc: PD) or in disaggregated instances with `disagg_epd_example.sh` (E->P->D) A connector transfers encoder-cache (EC) embeddings from the encoder instance to the PD instance. All related code is under `vllm/distributed/ec_transfer`. @@ -56,3 +61,9 @@ Here is a figure illustrating disaggregate encoder flow: ![Disaggregated Encoder Flow](../assets/features/disagg_encoder/disagg_encoder_flow.png) +For the PD disaggregation part, the Prefill instance receive cache exactly the same as the disaggregate encoder flow above. Prefill instance executes 1 step (prefill -> 1 token output) and then transfer KV cache to the Decode instance for the remaining execution. The KV transfer part purely happens after the execute of the PDinstance. + +`docs/features/disagg_prefill.md` shows the brief idea about the disaggregated prefill (v0) + + +We create the example setup with the **NixlConnector** from `vllm/distributed/kv_transfer/kv_connector/v1/nixl_connector.py` and referred to the `tests/v1/kv_connector/nixl_integration/toy_proxy_server.py` to facilitate the kv transfer between P and D; \ No newline at end of file diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_example.sh b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1p1d_example.sh similarity index 98% rename from examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_example.sh rename to examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1p1d_example.sh index c06260587a82..c1864e7a0f99 100644 --- a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_example.sh +++ b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1p1d_example.sh @@ -17,7 +17,7 @@ GPU_E="${GPU_E:-2}" GPU_P="${GPU_P:-2}" GPU_D="${GPU_D:-3}" -EC_SHARED_STORAGE_PATH=/workspace/hero/hero_EPD/test/epd_long/ec_cache_save +EC_SHARED_STORAGE_PATH="${SHARED_STORAGE_PATH:-/tmp/}" TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout NUM_PROMPTS="${NUM_PROMPTS:100}" # number of prompts to send in benchmark diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1pd_example.sh b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1pd_example.sh new file mode 100644 index 000000000000..a3e42e6a8079 --- /dev/null +++ b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1pd_example.sh @@ -0,0 +1,149 @@ +#!/bin/bash +set -euo pipefail + +############################################################################### +# Configuration -- override via env before running +############################################################################### +MODEL="${MODEL:-Qwen/Qwen2.5-VL-3B-Instruct}" +LOG_PATH="${LOG_PATH:-./logs}" +mkdir -p $LOG_PATH + +ENCODE_PORT="${ENCODE_PORT:-19534}" +PREFILL_DECODE_PORT="${PREFILL_DECODE_PORT:-19535}" +PROXY_PORT="${PROXY_PORT:-10001}" + +GPU_E="${GPU_E:-2}" +GPU_PD="${GPU_PD:-3}" + +EC_SHARED_STORAGE_PATH="${SHARED_STORAGE_PATH:-/tmp/}" +TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout + +NUM_PROMPTS="${NUM_PROMPTS:100}" # number of prompts to send in benchmark + +############################################################################### +# Helpers +############################################################################### +START_TIME=$(date +"%Y%m%d_%H%M%S") +ENC_LOG=$LOG_PATH/encoder_${START_TIME}.log +PD_LOG=$LOG_PATH/pd_${START_TIME}.log +PROXY_LOG=$LOG_PATH/proxy_${START_TIME}.log + +wait_for_server() { + local port=$1 + timeout "$TIMEOUT_SECONDS" bash -c " + until curl -s localhost:$port/v1/chat/completions > /dev/null; do + sleep 1 + done" && return 0 || return 1 +} + +# Cleanup function +cleanup() { + echo "Stopping everything…" + trap - INT TERM USR1 # prevent re-entrancy + + # Kill all tracked PIDs + for pid in "${PIDS[@]}"; do + if kill -0 "$pid" 2>/dev/null; then + echo "Killing process $pid" + kill "$pid" 2>/dev/null + fi + done + + # Wait a moment for graceful shutdown + sleep 2 + + # Force kill any remaining processes + for pid in "${PIDS[@]}"; do + if kill -0 "$pid" 2>/dev/null; then + echo "Force killing process $pid" + kill -9 "$pid" 2>/dev/null + fi + done + + # Kill the entire process group as backup + kill -- -$$ 2>/dev/null + + echo "All processes stopped." + exit 0 +} + +trap cleanup INT +trap cleanup USR1 +trap cleanup TERM + +# clear previous cache +echo "remove previous ec cache folder" +rm -rf $EC_SHARED_STORAGE_PATH + +echo "make ec cache folder" +mkdir -p $EC_SHARED_STORAGE_PATH + +############################################################################### +# Encoder worker +############################################################################### +CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ + --gpu-memory-utilization 0.0 \ + --port "$ENCODE_PORT" \ + --enable-request-id-headers \ + --no-enable-prefix-caching \ + --max-num-seqs 128 \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_producer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'", + "ec_max_num_scheduled_tokens": "4096" + } + }' \ + >"${ENC_LOG}" 2>&1 & + +############################################################################### +# Prefill+Decode worker +############################################################################### +CUDA_VISIBLE_DEVICES="$GPU_PD" VLLM_NIXL_SIDE_CHANNEL_PORT=6000 vllm serve "$MODEL" \ + --gpu-memory-utilization 0.7 \ + --port "$PREFILL_DECODE_PORT" \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --kv-transfer-config '{ + "kv_connector": "NixlConnector", + "kv_role": "kv_consumer" + }' \ + >"${PD_LOG}" 2>&1 & + +# Wait for workers +wait_for_server $ENCODE_PORT +wait_for_server $PREFILL_DECODE_PORT + +############################################################################### +# Proxy +############################################################################### +python disagg_epd_proxy.py \ + --host "0.0.0.0" \ + --port "$PROXY_PORT" \ + --encode-servers-urls "http://localhost:$ENCODE_PORT" \ + --prefill-servers-urls "disable" \ + --decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT" \ + >"${PROXY_LOG}" 2>&1 & + +wait_for_server $PROXY_PORT +echo "All services are up!" + +############################################################################### +# Benchmark +cd ../../../../benchmarks/ +python benchmark_serving.py \ + --backend openai-chat \ + --model $MODEL \ + --dataset-name hf \ + --dataset-path lmarena-ai/VisionArena-Chat \ + --seed 0 \ + --endpoint /v1/chat/completions \ + --num-prompts $NUM_PROMPTS \ + --port $PROXY_PORT \ + --port $PROXY_PORT +############################################################################### + +# cleanup +echo "cleanup..." +cleanup \ No newline at end of file diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py index ecff98a3cacb..dd4a50dba319 100644 --- a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py +++ b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py @@ -1,118 +1,184 @@ -# epd_proxy.py - E+P+D Separation Proxy +#!/usr/bin/env python3 +""" +disagg_encoder_proxy.py + +Proxy that routes OpenAI-compatible “/v1/chat/completions” requests to two +clusters: + • encode (multimodal feature extraction) + • decode (language-model inference) + +For MM input we: + 1. Extract *every* image/audio item. + 2. Fire N concurrent requests to the encoder cluster + (one request per item, with **all text removed**). + 3. Wait for all of them to succeed. + 4. Forward the *original* request to a decode server. + +Usage +For E + PD setup: +$ python disagg_encoder_proxy.py \ + --encode-servers-urls "http://e1:8001,http://e2:8002" \ + --prefill-servers-urls "disable" \ + --decode-servers-urls "http://pd1:8003,http://pd2:8004" + +For E + P + D setup: +$ python disagg_encoder_proxy.py \ + --encode-servers-urls "http://e1:8001,http://e2:8001" \ + --prefill-servers-urls "http://p1:8003,http://p2:8004" \ + --decode-servers-urls "http://d1:8005,http://d2:8006" +""" + +from __future__ import annotations + +import argparse import asyncio -import copy import json import logging import os -import time -import uuid import random -from typing import AsyncIterator, Optional, Dict, Any, Union -from fastapi import FastAPI, Request, HTTPException +import uuid +import copy +from typing import Any, AsyncIterator, List, Optional import aiohttp -from fastapi.responses import StreamingResponse, JSONResponse import uvicorn -import argparse +from fastapi import FastAPI, HTTPException, Request +from fastapi.responses import JSONResponse, StreamingResponse +############################################################################### +# FastAPI app & global state +############################################################################### logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s") logger = logging.getLogger("proxy") app = FastAPI() - encode_session: Optional[aiohttp.ClientSession] = None prefill_session: Optional[aiohttp.ClientSession] = None decode_session: Optional[aiohttp.ClientSession] = None +############################################################################### +# Utils +############################################################################### -@app.on_event("startup") -async def startup_event(): - global encode_session, prefill_session, decode_session - encode_session = aiohttp.ClientSession( - connector=aiohttp.TCPConnector(limit=0), - timeout=aiohttp.ClientTimeout(total=100000)) - prefill_session = aiohttp.ClientSession( - connector=aiohttp.TCPConnector(limit=0), - timeout=aiohttp.ClientTimeout(total=100000)) - decode_session = aiohttp.ClientSession( - connector=aiohttp.TCPConnector(limit=0), - timeout=aiohttp.ClientTimeout(total=100000)) +MM_TYPES = {"image_url", "audio_url", "input_audio"} -@app.on_event("shutdown") -async def shutdown_event(): - global encode_session, prefill_session, decode_session - if encode_session: - await encode_session.close() - if prefill_session: - await prefill_session.close() - if decode_session: - await decode_session.close() +def extract_mm_items(request_data: dict) -> List[dict]: + """ + Return *all* image/audio items that appear anywhere in `messages`. -def has_mm_input(request_data: dict): - """Check if request has multimodal input (images, audio, etc.)""" - if "messages" not in request_data: - return False - for message in request_data["messages"]: - if not isinstance(message.get("content"), list): + Each returned dict looks like: + { "type": "image_url", "image_url": {...} } + """ + items: List[dict] = [] + for msg in request_data.get("messages", []): + content = msg.get("content") + if not isinstance(content, list): continue - for content_item in message["content"]: - if content_item.get("type") in ["image_url", "audio_url", "input_audio"]: - return True - return False + for item in content: + if item.get("type") in MM_TYPES: + items.append(item) + return items -async def process_encoder_stage( - request_data: dict, + +async def fanout_encoder_primer( + orig_request: dict, + e_urls: List[str], request_id: str, - e_server_url: str -): - """Process request through Encoder stage (if has MM input)""" - if not has_mm_input(request_data): - return - - logger.debug(f"Processing MM input through encoder for request_id: {request_id}/ url: {e_server_url}") - encoder_request_data = request_data.copy() - encoder_request_data["max_tokens"] = 1 - if "max_completion_tokens" in encoder_request_data: - encoder_request_data["max_completion_tokens"] = 1 - - headers = {"x-request-id": request_id} - task1 = asyncio.create_task( - encode_session.post( - f"{e_server_url}/v1/chat/completions", - json=encoder_request_data, - headers=headers +) -> None: + """ + 1. Build one request *per MM item* with all text removed. + 2. Send them concurrently to the encode cluster. + 3. Raise if any of them fails. + """ + mm_items = extract_mm_items(orig_request) + if not mm_items: + return # nothing to do + + tasks = [] + + # Round-robin over encode servers to distribute load a bit + url_cycle = (e_urls[i % len(e_urls)] for i in range(len(mm_items))) + + for idx, (item, target_url) in enumerate(zip(mm_items, url_cycle)): + # Derive a *child* request id: :: + child_req_id = f"{request_id}:{idx}:{uuid.uuid4().hex[:6]}" + headers = {"x-request-id": child_req_id} + + encoder_req = { + # You *may* need to keep additional fields + "model": orig_request.get("model"), + "messages": [ + {"role": "user", "content": [item]}, + ], + # Only need 1 token so the server actually runs the encoder path + "max_tokens": 1, + "stream": False, + } + tasks.append( + encode_session.post( + f"{target_url}/v1/chat/completions", + json=encoder_req, + headers=headers, + ) ) - ) - try: - response = await task1 # seems fire-and-forget didnt gain any benefit - if response.status != 200: - error_text = await response.text() + + results = await asyncio.gather(*tasks, return_exceptions=True) + + # Fail fast if any sub-request failed + for r in results: + if isinstance(r, Exception): + logger.error("Encoder request raised: %s", r) + raise HTTPException(status_code=502, detail=str(r)) + if r.status != 200: + try: + detail = await r.text() + except Exception: + detail = "" + logger.error("Encoder request returned %s: %s", r.status, detail) raise HTTPException( - status_code=response.status, - detail={"error": "Encoder request failed", "message": error_text} + status_code=r.status, + detail=f"Encoder request failed: {detail}", ) - logger.debug(f"Encoder processing completed successfully for request_id: {request_id}") - return - except Exception as e: - logger.error(f"Encoder processing failed: {e}") - raise HTTPException( - status_code=500, - detail={"error": "Encoder processing error", "message": str(e)} + + +async def maybe_prefill( + req_data: dict, + p_url: str, + req_id: str, +) -> dict: + """ + - Do prefill-only task if p_url exist; + - Return modified request data with kv transfer params (for nixl connector) + - Else, skip and return the original request data for decode + """ + if p_url: + prefill_response = await process_prefill_stage( + req_data, p_url, req_id ) + # for nixl connector to facilitate kv transfer... + prefill_response_json = await prefill_response.json() + kv_transfer_params = prefill_response_json.get('kv_transfer_params', {}) + if kv_transfer_params: + req_data["kv_transfer_params"] = kv_transfer_params + logger.debug(f"kv_transfer_params: {kv_transfer_params}") + + return req_data + else: + return req_data async def process_prefill_stage( - request_data: dict, - request_id: str, - p_server_url: str + req_data: dict, + p_url: str, + req_id: str, ) -> dict: """Process request through Prefill stage and return kv_transfer_params""" - logger.debug(f"Processing through prefill for request_id: {request_id}/ url: {p_server_url}") + logger.debug(f"Processing through prefill for req_id: {req_id}/ url: {p_url}") - prefill_request = request_data.copy() + prefill_request = req_data.copy() prefill_request['kv_transfer_params'] = { "do_remote_decode": True, "do_remote_prefill": False, @@ -128,10 +194,10 @@ async def process_prefill_stage( if "stream_options" in prefill_request: del prefill_request["stream_options"] - headers = {"x-request-id": request_id} + headers = {"x-request-id": req_id} try: prefill_response = await prefill_session.post( - f"{p_server_url}/v1/chat/completions", + f"{p_url}/v1/chat/completions", json=prefill_request, headers=headers ) @@ -143,7 +209,7 @@ async def process_prefill_stage( status_code=prefill_response.status, detail={"error": "Prefill request failed", "message": error_text} ) - logger.debug(f"Prefill processing completed successfully for request_id: {request_id}") + logger.debug(f"Prefill processing completed successfully for req_id: {req_id}") return prefill_response @@ -155,193 +221,152 @@ async def process_prefill_stage( ) -async def forward_request( - request_data: dict, - request_id: str, - e_server_url: str, - p_server_url: str, - d_server_url: str, - is_streaming: bool = False -) -> Union[AsyncIterator[str], dict]: - """Forward request through E->P->D pipeline""" - +############################################################################### +# FastAPI lifecycle +############################################################################### + + +@app.on_event("startup") +async def on_startup() -> None: + global encode_session, prefill_session, decode_session + timeout = aiohttp.ClientTimeout(total=100_000) + connector = aiohttp.TCPConnector(limit=0, force_close=False) + encode_session = aiohttp.ClientSession(timeout=timeout, connector=connector) + if app.state.p_urls: + # only setup if prefill instance(s) exist + prefill_session = aiohttp.ClientSession(timeout=timeout, connector=connector) + decode_session = aiohttp.ClientSession(timeout=timeout, connector=connector) + + +@app.on_event("shutdown") +async def on_shutdown() -> None: + global encode_session, prefill_session, decode_session + if encode_session: + await encode_session.close() + if prefill_session: + await prefill_session.close() + if decode_session: + await decode_session.close() + + +############################################################################### +# Core forwarding +############################################################################### + + +async def forward_non_stream( + req_data: dict, req_id: str, e_urls: List[str], p_url: str, d_url: str +) -> dict: # Step 1: Process through Encoder instance (if has MM input) - await process_encoder_stage( - request_data, request_id, e_server_url - ) - + await fanout_encoder_primer(req_data, e_urls, req_id) + # Step 2: Process through Prefill instance - prefill_response = await process_prefill_stage( - request_data, request_id, p_server_url - ) - # for nixl connector to facilitate kv transfer... - prefill_response_json = await prefill_response.json() - kv_transfer_params = prefill_response_json.get('kv_transfer_params', {}) - if kv_transfer_params: - request_data["kv_transfer_params"] = kv_transfer_params - logger.debug(f"kv_transfer_params: {kv_transfer_params}") + req_data = await maybe_prefill(req_data, p_url, req_id) # Step 3: Process through Decode instance - logger.debug(f"{'Streaming' if is_streaming else 'Getting'} response from decode for request_id: {request_id}/ url: {d_server_url}") + logger.debug(f"Getting response from decode for req_id: {req_id}/ url: {d_url}") + headers = {"x-request-id": req_id} - headers = {"x-request-id": request_id} - - if is_streaming: - # Streaming response - async def generate_stream(): - try: - async with decode_session.post( - f"{d_server_url}/v1/chat/completions", - json=request_data, - headers=headers - ) as response: - response.raise_for_status() - async for chunk in response.content.iter_chunked(128): - if chunk: - yield chunk.decode('utf-8', errors='ignore') - except Exception as e: - logger.error(f"Error in decode streaming: {e}") - raise + # Non-streaming response + async with decode_session.post( + f"{d_url}/v1/chat/completions", json=req_data, headers=headers + ) as resp: + resp.raise_for_status() + return await resp.json() + + +async def forward_stream( + req_data: dict, req_id: str, e_urls: List[str], p_url: str, d_url: str +) -> AsyncIterator[str]: + # Step 1: Process through Encoder instance (if has MM input) + await fanout_encoder_primer(req_data, e_urls, req_id) - return generate_stream() - else: - # Non-streaming response - try: - async with decode_session.post( - f"{d_server_url}/v1/chat/completions", - json=request_data, - headers=headers - ) as response: - response.raise_for_status() - result = await response.json() - return result - except Exception as e: - logger.error(f"Error in decode response: {e}") - raise + # Step 2: Process through Prefill instance + req_data = await maybe_prefill(req_data, p_url, req_id) + + # Step 3: Process through Decode instance + logger.debug(f"Streaming response from decode for req_id: {req_id}/ url: {d_url}") + headers = {"x-request-id": req_id} + + # Streaming response + async with decode_session.post( + f"{d_url}/v1/chat/completions", + json=req_data, + headers=headers, + ) as resp: + resp.raise_for_status() + async for chunk in resp.content.iter_chunked(1024): + if chunk: + yield chunk.decode("utf-8", errors="ignore") + +############################################################################### +# Public routes +############################################################################### @app.post("/v1/chat/completions") async def chat_completions(request: Request): - """Handle chat completion requests through E->P->D pipeline.""" - try: - # Load balance across instances - e_instance = random.randint(0, len(app.state.e_urls) - 1) - p_instance = random.randint(0, len(app.state.p_urls) - 1) - d_instance = random.randint(0, len(app.state.d_urls) - 1) - - e_server_url = app.state.e_urls[e_instance] - p_server_url = app.state.p_urls[p_instance] - d_server_url = app.state.d_urls[d_instance] - - request_data = await request.json() - request_id = request.headers.get("x-request-id") - if not request_id: - request_id = str(uuid.uuid4()) - - is_streaming = request_data.get("stream", False) - - logger.debug(f"Processing request {request_id} through E->P->D: {e_server_url} -> {p_server_url} -> {d_server_url}") - - if is_streaming: - stream_generator = await forward_request( - request_data, request_id, e_server_url, p_server_url, d_server_url, is_streaming=True - ) - return StreamingResponse(stream_generator, media_type="text/event-stream") - else: - result = await forward_request( - request_data, request_id, e_server_url, p_server_url, d_server_url, is_streaming=False - ) - return JSONResponse(content=result) - except Exception as e: - logger.error(f"Error processing request: {e}") - raise HTTPException(status_code=500, detail=str(e)) + req_data = await request.json() + req_id = request.headers.get("x-request-id", str(uuid.uuid4())) + + e_urls = app.state.e_urls # we want the full list for fan-out + p_url = random.choice(app.state.p_urls) if app.state.p_urls else None + d_url = random.choice(app.state.d_urls) + + is_streaming = req_data.get("stream", False) + + if is_streaming: + return StreamingResponse( + forward_stream(req_data, req_id, e_urls, p_url, d_url), + media_type="text/event-stream", + ) + result = await forward_non_stream(req_data, req_id, e_urls, p_url, d_url) + return JSONResponse(content=result) @app.get("/v1/models") async def list_models(): - """List available models from decode instances.""" - try: - async with decode_session.get(f"{app.state.d_urls[0]}/v1/models") as response: - response.raise_for_status() - return await response.json() - except Exception as e: - logger.error(f"Error fetching models: {e}") - raise HTTPException(status_code=500, detail=str(e)) + async with decode_session.get(f"{app.state.d_urls[0]}/v1/models") as resp: + resp.raise_for_status() + return await resp.json() @app.get("/health") async def health_check(): - """Health check endpoint for all instances.""" - try: - async def check_encode(): - try: - for e_url in app.state.e_urls: - async with encode_session.get(f"{e_url}/health") as response: - response.raise_for_status() - return True - except Exception: - return False - - async def check_prefill(): + async def healthy(urls): + if not urls: + return "empty" + for u in urls: try: - for p_url in app.state.p_urls: - async with prefill_session.get(f"{p_url}/health") as response: - response.raise_for_status() - return True + async with encode_session.get(f"{u}/health") as resp: + resp.raise_for_status() except Exception: - return False - - async def check_decode(): - try: - for d_url in app.state.d_urls: - async with decode_session.get(f"{d_url}/health") as response: - response.raise_for_status() - return True - except Exception: - return False - - encode_healthy, prefill_healthy, decode_healthy = await asyncio.gather( - check_encode(), check_prefill(), check_decode(), return_exceptions=True - ) + return "unhealthy" + return "healthy" - if not (encode_healthy is True and prefill_healthy is True and decode_healthy is True): - status_code = 503 - else: - status_code = 200 - - return JSONResponse( - { - "proxy": "healthy", - "encode_servers": "healthy" if encode_healthy is True else "unhealthy", - "prefill_servers": "healthy" if prefill_healthy is True else "unhealthy", - "decode_servers": "healthy" if decode_healthy is True else "unhealthy" - }, - status_code=status_code, - ) - - return health_status - - except Exception as e: - logger.error(f"Health check error: {e}") - return JSONResponse( - content={"proxy": "unhealthy", "error": str(e)}, - status_code=503 - ) + e_status, p_status, d_status = await asyncio.gather( + healthy(app.state.e_urls), healthy(app.state.p_urls), healthy(app.state.d_urls) + ) + overall_healthy = all(status != "unhealthy" for status in (e_status, p_status, d_status)) -@app.get("/status") -async def get_status(): - """Get status of all instances.""" - return { - "encode_instance_count": len(app.state.e_urls), - "prefill_instance_count": len(app.state.p_urls), - "decode_instance_count": len(app.state.d_urls), - "encode_instances": app.state.e_urls, - "prefill_instances": app.state.p_urls, - "decode_instances": app.state.d_urls - } + status_code = 200 if overall_healthy else 503 + + return JSONResponse( + { + "proxy": "healthy", + "encode_cluster": e_status, + "prefill_cluster": p_status, + "decode_cluster": d_status, + }, + status_code=status_code, + ) + + +############################################################################### +# Simple profiler fan-out (unchanged except for sessions) +############################################################################### -## profiler methods ## async def _post_if_available( session: aiohttp.ClientSession, @@ -351,6 +376,7 @@ async def _post_if_available( ) -> Optional[dict]: """ POST `payload` to `url`. + Returns ------- • The decoded JSON body on success (2xx) @@ -374,6 +400,7 @@ async def _post_if_available( # Network errors etc.: propagate raise + async def _profile_cmd(cmd: str, payload: dict, e_url: str, p_url: str, d_url: str): """ Fire & forget to both clusters, tolerate 404. @@ -385,7 +412,7 @@ async def _profile_cmd(cmd: str, payload: dict, e_url: str, p_url: str, d_url: s ) prefill_task = _post_if_available( prefill_session, f"{p_url}/{cmd}_profile", payload, headers - ) + ) if p_url is not None else asyncio.sleep(0) decode_task = _post_if_available( decode_session, f"{d_url}/{cmd}_profile", payload, headers ) @@ -401,16 +428,17 @@ async def _profile_cmd(cmd: str, payload: dict, e_url: str, p_url: str, d_url: s return { "encode": encode_res, # may be None - "prefill": decode_res, # may be None + "prefill": prefill_res, # may be None "decode": decode_res, # may be None } + @app.post("/start_profile") async def start_profile(request: Request): body = await request.json() # TODO: handle multi urls properly e_url = random.choice(app.state.e_urls) - p_url = random.choice(app.state.p_urls) + p_url = random.choice(app.state.p_urls) if app.state.p_urls else None d_url = random.choice(app.state.d_urls) return await _profile_cmd("start", body, e_url, p_url, d_url) @@ -420,42 +448,52 @@ async def stop_profile(request: Request): body = await request.json() # TODO: handle multi urls properly e_url = random.choice(app.state.e_urls) - p_url = random.choice(app.state.p_urls) + p_url = random.choice(app.state.p_urls) if app.state.p_urls else None d_url = random.choice(app.state.d_urls) return await _profile_cmd("stop", body, e_url, p_url, d_url) if __name__ == "__main__": - parser = argparse.ArgumentParser(description="E+PD Separation Proxy for distributed vLLM servers") - parser.add_argument("--host", type=str, default="0.0.0.0", help="Proxy host") - parser.add_argument("--port", type=int, default=8000, help="Proxy port") - - parser.add_argument("--encode-servers-urls", type=str, required=True, - help="URLs of the encode servers in comma separated format" - "(e.g., \"http://localhost:8001,http://localhost:8002\")") - - parser.add_argument("--prefill-servers-urls", type=str, required=True, - help="URLs of the prefill servers in comma separated format" - "(e.g., \"http://localhost:8003,http://localhost:8004\")") - - parser.add_argument("--decode-servers-urls", type=str, required=True, - help="URLs of the decode servers in comma separated format" - "(e.g., \"http://localhost:8005,http://localhost:8006\")") + parser = argparse.ArgumentParser() + parser.add_argument("--host", default="0.0.0.0") + parser.add_argument("--port", type=int, default=8000) + parser.add_argument( + "--encode-servers-urls", + required=True, + help='Comma-separated encode URLs ("http://e1:8001,http://e2:8001")', + ) + parser.add_argument( + "--prefill-servers-urls", + required=True, + help='Comma-separated prefill URLs ("http://p1:8003,http://p2:8004") to enable E->P->D, set "disable" or "none" to enable E->PD', + ) + parser.add_argument( + "--decode-servers-urls", + required=True, + help='Comma-separated decode URLs ("http://d1:8005,http://d2:8006")', + ) args = parser.parse_args() - app.state.e_urls = args.encode_servers_urls.split(",") - app.state.p_urls = args.prefill_servers_urls.split(",") + app.state.e_urls = [u.strip() for u in args.encode_servers_urls.split(",") if u.strip()] app.state.d_urls = args.decode_servers_urls.split(",") - - logger.info(f"Starting E+PD separation proxy on {args.host}:{args.port}") - logger.info(f"Encode instances: {app.state.e_urls}") - logger.info(f"Prefill instances: {app.state.p_urls}") - logger.info(f"Decode instances: {app.state.d_urls}") + app.state.d_urls = [u.strip() for u in args.decode_servers_urls.split(",") if u.strip()] + # handle prefill instances + if args.prefill_servers_urls.lower() in ("disable", "none", ""): + app.state.p_urls = [] + logger.info("Disaggregated prefill phase explicitly disabled by user. Running E + PD...") + else: + app.state.p_urls = [u.strip() for u in args.prefill_servers_urls.split(",") if u.strip()] + logger.info("Disaggregated prefill phase is enabled. Running E + P + D...") + + logger.info("Proxy listening on %s:%s", args.host, args.port) + logger.info("Encode servers: %s", app.state.e_urls) + logger.info("Prefill instances %s", app.state.p_urls) + logger.info("Decode servers: %s", app.state.d_urls) uvicorn.run( app, host=args.host, port=args.port, log_level="info", + loop="uvloop", access_log=False, - loop="uvloop" ) \ No newline at end of file From 23c490254efe9e54d4977bd656877a67d2de5f23 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Mon, 22 Sep 2025 17:00:16 +0800 Subject: [PATCH 22/57] Update vllm/config/__init__.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: knlnguyen1802 --- vllm/config/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vllm/config/__init__.py b/vllm/config/__init__.py index c983ab1b47f8..bf15a92d4dc5 100644 --- a/vllm/config/__init__.py +++ b/vllm/config/__init__.py @@ -3273,7 +3273,7 @@ def __post_init__(self) -> None: f"Supported roles are {get_args(ECRole)}") if self.ec_connector is not None and self.ec_role is None: - raise ValueError("Please specify ec_disagg_role when ec_connector " + raise ValueError("Please specify ec_role when ec_connector " f"is set, supported roles are {get_args(ECRole)}") @property From 7ef47ad9fb2c1a64fd998b02b2c52b15db21b019 Mon Sep 17 00:00:00 2001 From: herotai214 Date: Wed, 8 Oct 2025 06:19:21 +0000 Subject: [PATCH 23/57] [Misc] Resolve comments Signed-off-by: herotai214 --- .../disaggregated_encoder/README.md | 13 + .../disagg_1e1p1d_example.sh | 7 +- .../disagg_1e1pd_example.sh | 7 +- .../disagg_epd_proxy.py | 1 - .../disagg_encoder_example.sh | 160 -------- .../disagg_encoder_proxy.py | 365 ------------------ 6 files changed, 21 insertions(+), 532 deletions(-) create mode 100644 examples/online_serving/disaggregated_encoder/README.md rename examples/online_serving/disaggregated_encoder/{shared_storage_connector => }/disagg_1e1p1d_example.sh (97%) rename examples/online_serving/disaggregated_encoder/{shared_storage_connector => }/disagg_1e1pd_example.sh (97%) rename examples/online_serving/disaggregated_encoder/{shared_storage_connector => }/disagg_epd_proxy.py (99%) delete mode 100644 examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh delete mode 100644 examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py diff --git a/examples/online_serving/disaggregated_encoder/README.md b/examples/online_serving/disaggregated_encoder/README.md new file mode 100644 index 000000000000..d4ba603d0fac --- /dev/null +++ b/examples/online_serving/disaggregated_encoder/README.md @@ -0,0 +1,13 @@ +# Disaggregated Encoder + +This example contains scripts that demonstrate the disaggregated encoder (EPD) features of vLLM. + +Please refer to [Disaggregated Encoder Feature](../../../docs/features/disagg_encoder.md) for the detailed explanation for the EPD features. + +## Files + +- `disagg_epd_proxy.py` - Proxy to demonstrates XeYpZd (X encode instances, Y prefill instances, Z decode instances); Currently stable for 1e1p1d. +- `disagg_1e1p1d_example.sh` - Setup 1e1p1d and run VisionArena benchmark. +- `disagg_1e1pd_example.sh` - Setup 1e1pd and run VisionArena benchmark. + +Detailed explanations are commnented in the scripts. diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1p1d_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh similarity index 97% rename from examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1p1d_example.sh rename to examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh index c1864e7a0f99..fab314304100 100644 --- a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1p1d_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh @@ -1,6 +1,8 @@ #!/bin/bash set -euo pipefail +PIDS=() + ############################################################################### # Configuration -- override via env before running ############################################################################### @@ -17,7 +19,7 @@ GPU_E="${GPU_E:-2}" GPU_P="${GPU_P:-2}" GPU_D="${GPU_D:-3}" -EC_SHARED_STORAGE_PATH="${SHARED_STORAGE_PATH:-/tmp/}" +EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/}" TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout NUM_PROMPTS="${NUM_PROMPTS:100}" # number of prompts to send in benchmark @@ -165,8 +167,7 @@ python benchmark_serving.py \ --seed 0 \ --endpoint /v1/chat/completions \ --num-prompts $NUM_PROMPTS \ - --port $PROXY_PORT \ - --port $PROXY_PORT + --port $PROXY_PORT ############################################################################### # cleanup diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1pd_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh similarity index 97% rename from examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1pd_example.sh rename to examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh index a3e42e6a8079..e62e66b4b69b 100644 --- a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_1e1pd_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh @@ -1,6 +1,8 @@ #!/bin/bash set -euo pipefail +PIDS=() + ############################################################################### # Configuration -- override via env before running ############################################################################### @@ -15,7 +17,7 @@ PROXY_PORT="${PROXY_PORT:-10001}" GPU_E="${GPU_E:-2}" GPU_PD="${GPU_PD:-3}" -EC_SHARED_STORAGE_PATH="${SHARED_STORAGE_PATH:-/tmp/}" +EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/}" TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout NUM_PROMPTS="${NUM_PROMPTS:100}" # number of prompts to send in benchmark @@ -140,8 +142,7 @@ python benchmark_serving.py \ --seed 0 \ --endpoint /v1/chat/completions \ --num-prompts $NUM_PROMPTS \ - --port $PROXY_PORT \ - --port $PROXY_PORT + --port $PROXY_PORT ############################################################################### # cleanup diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py similarity index 99% rename from examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py rename to examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py index dd4a50dba319..f84b1912ac51 100644 --- a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_epd_proxy.py +++ b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py @@ -474,7 +474,6 @@ async def stop_profile(request: Request): args = parser.parse_args() app.state.e_urls = [u.strip() for u in args.encode_servers_urls.split(",") if u.strip()] - app.state.d_urls = args.decode_servers_urls.split(",") app.state.d_urls = [u.strip() for u in args.decode_servers_urls.split(",") if u.strip()] # handle prefill instances if args.prefill_servers_urls.lower() in ("disable", "none", ""): diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh deleted file mode 100644 index 46939e3f0d47..000000000000 --- a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_example.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env bash -# shellcheck disable=SC2086,SC2155 -set -euo pipefail - -############################################################################### -# Configuration -- override via env before running -############################################################################### -MODEL="${MODEL:-Qwen/Qwen2.5-VL-3B-Instruct}" - -LOG_PATH="${LOG_PATH:-./logs}" -ENCODE_PORT="${ENCODE_PORT:-19534}" -PREFILL_DECODE_PORT="${PREFILL_DECODE_PORT:-19535}" -PROXY_PORT="${PROXY_PORT:-10001}" - -GPU_E="${GPU_E:-0}" -GPU_PD="${GPU_PD:-1}" - -SHARED_STORAGE_PATH="${SHARED_STORAGE_PATH:-/tmp/}" -TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout - -############################################################################### -# Dependencies check ########################################################## -############################################################################### -ensure_python_library_installed() { - local lib=$1 - echo -n "[check] Python package '$lib' … " - if python3 - </dev/null 2>&1 -import importlib, sys -sys.exit(0) if importlib.util.find_spec("${lib}") else sys.exit(1) -EOF - then - echo "OK" - else - echo "NOT FOUND" - echo "Please install it, e.g.: pip install $lib" - exit 1 - fi -} - -ensure_python_library_installed vllm -ensure_python_library_installed pandas -ensure_python_library_installed datasets - -############################################################################### -# Helpers -############################################################################### -mkdir -p "$LOG_PATH" -START_TIME=$(date +"%Y%m%d_%H%M%S") -ENC_LOG="$LOG_PATH/encoder_$START_TIME.log" -PD_LOG="$LOG_PATH/pd_$START_TIME.log" -PROXY_LOG="$LOG_PATH/proxy_$START_TIME.log" - -wait_for_server() { - local port=$1 - timeout "$TIMEOUT_SECONDS" bash -c ' - until curl -s "http://localhost:'"$port"'/v1/chat/completions" > /dev/null; do - sleep 1 - done - ' -} - -# keep PIDs in memory -declare -a PIDS=() -CLEANED=0 -cleanup() { - (( CLEANED )) && return # run only once - CLEANED=1 - - echo "Cleaning up…" - # iterate backwards (proxy → PD → encoder) - for (( idx=${#PIDS[@]}-1 ; idx>=0 ; idx-- )); do - PID=${PIDS[idx]} - if kill -0 "$PID" 2>/dev/null; then - echo " • Killing $PID" - kill "$PID" - sleep 2 - kill -9 "$PID" 2>/dev/null || true - fi - done - echo "Done." -} - -trap cleanup EXIT INT TERM ERR - -############################################################################### -# Encoder worker -############################################################################### -CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ - --gpu-memory-utilization 0.0 \ - --port "$ENCODE_PORT" \ - --enable-request-id-headers \ - --no-enable-prefix-caching \ - --max-num-seqs 128 \ - --enforce-eager \ - --ec-transfer-config '{ - "ec_connector": "ECSharedStorageConnector", - "ec_role": "ec_producer", - "ec_connector_extra_config": { - "shared_storage_path": "'"$SHARED_STORAGE_PATH"'", - "ec_max_num_scheduled_tokens": "4096" - } - }' \ - >"$ENC_LOG" 2>&1 & - -PIDS+=($!) - -############################################################################### -# Prefill / decode worker -############################################################################### -CUDA_VISIBLE_DEVICES="$GPU_PD" vllm serve "$MODEL" \ - --gpu-memory-utilization 0.7 \ - --port "$PREFILL_DECODE_PORT" \ - --enable-request-id-headers \ - --max-num-seqs 128 \ - --enforce-eager \ - --ec-transfer-config '{ - "ec_connector": "ECSharedStorageConnector", - "ec_role": "ec_consumer", - "ec_connector_extra_config": { - "shared_storage_path": "'"$SHARED_STORAGE_PATH"'" - } - }' \ - >"$PD_LOG" 2>&1 & - -PIDS+=($!) - -# Wait for workers -wait_for_server "$ENCODE_PORT" -wait_for_server "$PREFILL_DECODE_PORT" - -############################################################################### -# Proxy -############################################################################### -python disagg_encoder_proxy.py \ - --host "127.0.0.1" \ - --port "$PROXY_PORT" \ - --encode-servers-urls "http://localhost:$ENCODE_PORT" \ - --prefill-decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT" \ - >"$PROXY_LOG" 2>&1 & - -PIDS+=($!) - -wait_for_server "$PROXY_PORT" -echo "All services are up!" - -############################################################################### -# Benchmark -cd ../../../../benchmarks -python benchmark_serving.py \ - --backend openai-chat \ - --model $MODEL \ - --dataset-name hf \ - --dataset-path lmarena-ai/VisionArena-Chat \ - --seed 0 \ - --endpoint /v1/chat/completions \ - --num-prompts 10 \ - --port $PROXY_PORT \ - --host 127.0.0.1 -############################################################################### -cleanup \ No newline at end of file diff --git a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py b/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py deleted file mode 100644 index 90411843eed3..000000000000 --- a/examples/online_serving/disaggregated_encoder/shared_storage_connector/disagg_encoder_proxy.py +++ /dev/null @@ -1,365 +0,0 @@ -#!/usr/bin/env python3 -""" -disagg_encoder_proxy.py - -Proxy that routes OpenAI-compatible “/v1/chat/completions” requests to two -clusters: - • encode (multimodal feature extraction) - • decode (language-model inference) - -For MM input we: - 1. Extract *every* image/audio item. - 2. Fire N concurrent requests to the encoder cluster - (one request per item, with **all text removed**). - 3. Wait for all of them to succeed. - 4. Forward the *original* request to a decode server. - -Usage -$ python disagg_encoder_proxy.py \ - --encode-servers-urls "http://e1:8001,http://e2:8001" \ - --prefill-decode-servers-urls "http://d1:8003,http://d2:8003" -""" - -from __future__ import annotations - -import argparse -import asyncio -import json -import logging -import os -import random -import uuid -from copy import deepcopy -from typing import Any, AsyncIterator, List, Optional - -import aiohttp -import uvicorn -from fastapi import FastAPI, HTTPException, Request -from fastapi.responses import JSONResponse, StreamingResponse - -############################################################################### -# FastAPI app & global state -############################################################################### - -logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s") -logger = logging.getLogger("proxy") - -app = FastAPI() -encode_session: Optional[aiohttp.ClientSession] = None -decode_session: Optional[aiohttp.ClientSession] = None - -############################################################################### -# Utils -############################################################################### - - -MM_TYPES = {"image_url", "audio_url", "input_audio"} - - -def extract_mm_items(request_data: dict) -> List[dict]: - """ - Return *all* image/audio items that appear anywhere in `messages`. - - Each returned dict looks like: - { "type": "image_url", "image_url": {...} } - """ - items: List[dict] = [] - for msg in request_data.get("messages", []): - content = msg.get("content") - if not isinstance(content, list): - continue - - for item in content: - if item.get("type") in MM_TYPES: - items.append(item) - return items - - -async def fanout_encoder_primer( - orig_request: dict, - e_urls: List[str], - request_id: str, -) -> None: - """ - 1. Build one request *per MM item* with all text removed. - 2. Send them concurrently to the encode cluster. - 3. Raise if any of them fails. - """ - mm_items = extract_mm_items(orig_request) - if not mm_items: - return # nothing to do - - tasks = [] - - # Round-robin over encode servers to distribute load a bit - url_cycle = (e_urls[i % len(e_urls)] for i in range(len(mm_items))) - - for idx, (item, target_url) in enumerate(zip(mm_items, url_cycle)): - # Derive a *child* request id: :: - child_req_id = f"{request_id}:{idx}:{uuid.uuid4().hex[:6]}" - headers = {"x-request-id": child_req_id} - - encoder_req = { - # You *may* need to keep additional fields - "model": orig_request.get("model"), - "messages": [ - {"role": "user", "content": [item]}, - ], - # Only need 1 token so the server actually runs the encoder path - "max_tokens": 1, - "stream": False, - } - tasks.append( - encode_session.post( - f"{target_url}/v1/chat/completions", - json=encoder_req, - headers=headers, - ) - ) - - results = await asyncio.gather(*tasks, return_exceptions=True) - - # Fail fast if any sub-request failed - for r in results: - if isinstance(r, Exception): - logger.error("Encoder request raised: %s", r) - raise HTTPException(status_code=502, detail=str(r)) - if r.status != 200: - try: - detail = await r.text() - except Exception: - detail = "" - logger.error("Encoder request returned %s: %s", r.status, detail) - raise HTTPException( - status_code=r.status, - detail=f"Encoder request failed: {detail}", - ) - - -############################################################################### -# FastAPI lifecycle -############################################################################### - - -@app.on_event("startup") -async def on_startup() -> None: - global encode_session, decode_session - timeout = aiohttp.ClientTimeout(total=100_000) - connector = aiohttp.TCPConnector(limit=0, force_close=False) - encode_session = aiohttp.ClientSession(timeout=timeout, connector=connector) - decode_session = aiohttp.ClientSession(timeout=timeout, connector=connector) - - -@app.on_event("shutdown") -async def on_shutdown() -> None: - await encode_session.close() - await decode_session.close() - - -############################################################################### -# Core forwarding -############################################################################### - - -async def forward_non_stream( - req_data: dict, req_id: str, e_urls: List[str], pd_url: str -) -> dict: - await fanout_encoder_primer(req_data, e_urls, req_id) - - headers = {"x-request-id": req_id} - async with decode_session.post( - f"{pd_url}/v1/chat/completions", json=req_data, headers=headers - ) as resp: - resp.raise_for_status() - return await resp.json() - - -async def forward_stream( - req_data: dict, req_id: str, e_urls: List[str], pd_url: str -) -> AsyncIterator[str]: - await fanout_encoder_primer(req_data, e_urls, req_id) - - headers = {"x-request-id": req_id} - async with decode_session.post( - f"{pd_url}/v1/chat/completions", - json=req_data, - headers=headers, - ) as resp: - resp.raise_for_status() - async for chunk in resp.content.iter_chunked(1024): - if chunk: - yield chunk.decode("utf-8", errors="ignore") - - -############################################################################### -# Public routes -############################################################################### - - -@app.post("/v1/chat/completions") -async def chat_completions(request: Request): - req_data = await request.json() - req_id = request.headers.get("x-request-id", str(uuid.uuid4())) - - pd_url = random.choice(app.state.pd_urls) - e_urls = app.state.e_urls # we want the full list for fan-out - - if req_data.get("stream", False): - return StreamingResponse( - forward_stream(req_data, req_id, e_urls, pd_url), - media_type="text/event-stream", - ) - result = await forward_non_stream(req_data, req_id, e_urls, pd_url) - return JSONResponse(content=result) - - -@app.get("/v1/models") -async def list_models(): - async with decode_session.get(f"{app.state.pd_urls[0]}/v1/models") as resp: - resp.raise_for_status() - return await resp.json() - - -@app.get("/health") -async def health(): - async def healthy(urls): - for u in urls: - try: - async with encode_session.get(f"{u}/health") as resp: - resp.raise_for_status() - except Exception: - return False - return True - - e_ok, pd_ok = await asyncio.gather( - healthy(app.state.e_urls), healthy(app.state.pd_urls) - ) - - status_code = 200 if e_ok and pd_ok else 503 - return JSONResponse( - { - "proxy": "healthy", - "encode_cluster": "healthy" if e_ok else "unhealthy", - "decode_cluster": "healthy" if pd_ok else "unhealthy", - }, - status_code=status_code, - ) - - -############################################################################### -# Simple profiler fan-out (unchanged except for sessions) -############################################################################### - - -async def _post_if_available( - session: aiohttp.ClientSession, - url: str, - payload: dict, - headers: dict, -) -> Optional[dict]: - """ - POST `payload` to `url`. - - Returns - ------- - • The decoded JSON body on success (2xx) - • None if the endpoint does not exist (404) - • Raises for anything else. - """ - try: - resp = await session.post(url, json=payload, headers=headers) - if resp.status == 404: # profiling disabled on that server - logger.warning("Profiling endpoint missing on %s", url) - return None - resp.raise_for_status() - return await resp.json(content_type=None) - except aiohttp.ClientResponseError as exc: - # Pass 404 through the branch above, re-raise everything else - if exc.status == 404: - logger.warning("Profiling endpoint missing on %s", url) - return None - raise - except Exception: - # Network errors etc.: propagate - raise - - -async def _profile_cmd(cmd: str, payload: dict, e_url: str, pd_url: str): - """ - Fire & forget to both clusters, tolerate 404. - """ - headers = {"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY', '')}"} - - encode_task = _post_if_available( - encode_session, f"{e_url}/{cmd}_profile", payload, headers - ) - decode_task = _post_if_available( - decode_session, f"{pd_url}/{cmd}_profile", payload, headers - ) - - encode_res, decode_res = await asyncio.gather(encode_task, decode_task) - - # If *both* clusters said “I don’t have that route”, surface an error - if encode_res is None and decode_res is None: - raise HTTPException( - status_code=503, - detail="Profiling endpoints are disabled on both clusters", - ) - - return { - "encode": encode_res, # may be None - "decode": decode_res, # may be None - } - - -@app.post("/start_profile") -async def start_profile(request: Request): - body = await request.json() - e_url = random.choice(app.state.e_urls) - pd_url = random.choice(app.state.pd_urls) - return await _profile_cmd("start", body, e_url, pd_url) - - -@app.post("/stop_profile") -async def stop_profile(request: Request): - body = await request.json() - e_url = random.choice(app.state.e_urls) - pd_url = random.choice(app.state.pd_urls) - return await _profile_cmd("stop", body, e_url, pd_url) - - -############################################################################### -# Entrypoint -############################################################################### - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--host", default="0.0.0.0") - parser.add_argument("--port", type=int, default=8000) - parser.add_argument( - "--encode-servers-urls", - required=True, - help='Comma-separated encode URLs ("http://e1:8001,http://e2:8001")', - ) - parser.add_argument( - "--prefill-decode-servers-urls", - required=True, - help='Comma-separated decode URLs ("http://d1:8003,http://d2:8003")', - ) - args = parser.parse_args() - - app.state.e_urls = [u.strip() for u in args.encode_servers_urls.split(",") if u.strip()] - app.state.pd_urls = [u.strip() for u in args.prefill_decode_servers_urls.split(",") if u.strip()] - - logger.info("Proxy listening on %s:%s", args.host, args.port) - logger.info("Encode servers: %s", app.state.e_urls) - logger.info("Decode servers: %s", app.state.pd_urls) - - uvicorn.run( - app, - host=args.host, - port=args.port, - log_level="info", - loop="uvloop", - access_log=False, - ) \ No newline at end of file From 1b79908d221149a4b7218945b931b742fb3d4447 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Wed, 8 Oct 2025 15:58:12 +0800 Subject: [PATCH 24/57] Update examples/online_serving/disaggregated_encoder/README.md Co-authored-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Signed-off-by: knlnguyen1802 --- examples/online_serving/disaggregated_encoder/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/online_serving/disaggregated_encoder/README.md b/examples/online_serving/disaggregated_encoder/README.md index d4ba603d0fac..fa6d357300e6 100644 --- a/examples/online_serving/disaggregated_encoder/README.md +++ b/examples/online_serving/disaggregated_encoder/README.md @@ -2,7 +2,7 @@ This example contains scripts that demonstrate the disaggregated encoder (EPD) features of vLLM. -Please refer to [Disaggregated Encoder Feature](../../../docs/features/disagg_encoder.md) for the detailed explanation for the EPD features. +Please refer to [Disaggregated Encoder Feature](../../features/disagg_encoder.md) for the detailed explanation for the EPD features. ## Files From e4c917474431c3fa4e4c6dc1184d062022b64c28 Mon Sep 17 00:00:00 2001 From: Khuong Le Date: Wed, 8 Oct 2025 03:45:45 -0700 Subject: [PATCH 25/57] [Misc] resolve comment and fix example script Signed-off-by: knlnguyen1802 --- .../disagg_1e1p1d_example.sh | 23 +++++++++++++++---- .../disagg_1e1pd_example.sh | 17 ++++++++++---- .../worker/ec_connector_model_runner_mixin.py | 4 +++- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh index fab314304100..57c815d0a569 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh @@ -22,7 +22,10 @@ GPU_D="${GPU_D:-3}" EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/}" TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout -NUM_PROMPTS="${NUM_PROMPTS:100}" # number of prompts to send in benchmark +NUM_PROMPTS="${NUM_PROMPTS:-100}" # number of prompts to send in benchmark + +export UCX_TLS=all +export UCX_NET_DEVICES=all ############################################################################### # Helpers @@ -102,10 +105,15 @@ CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ }' \ >"${ENC_LOG}" 2>&1 & +PIDS+=($!) + ############################################################################### # Prefill worker ############################################################################### -CUDA_VISIBLE_DEVICES="$GPU_P" VLLM_NIXL_SIDE_CHANNEL_PORT=5559 vllm serve "$MODEL" \ +CUDA_VISIBLE_DEVICES="$GPU_P" \ +UCX_NET_DEVICES=all \ +VLLM_NIXL_SIDE_CHANNEL_PORT=5559 \ +vllm serve "$MODEL" \ --gpu-memory-utilization 0.7 \ --port "$PREFILL_PORT" \ --enable-request-id-headers \ @@ -123,10 +131,15 @@ CUDA_VISIBLE_DEVICES="$GPU_P" VLLM_NIXL_SIDE_CHANNEL_PORT=5559 vllm serve "$MODE }' \ >"${P_LOG}" 2>&1 & +PIDS+=($!) + ############################################################################### # Decode worker ############################################################################### -CUDA_VISIBLE_DEVICES="$GPU_D" VLLM_NIXL_SIDE_CHANNEL_PORT=6000 vllm serve "$MODEL" \ +CUDA_VISIBLE_DEVICES="$GPU_D" \ +UCX_NET_DEVICES=all \ +VLLM_NIXL_SIDE_CHANNEL_PORT=6000 \ +vllm serve "$MODEL" \ --gpu-memory-utilization 0.7 \ --port "$DECODE_PORT" \ --enable-request-id-headers \ @@ -137,6 +150,8 @@ CUDA_VISIBLE_DEVICES="$GPU_D" VLLM_NIXL_SIDE_CHANNEL_PORT=6000 vllm serve "$MODE }' \ >"${D_LOG}" 2>&1 & +PIDS+=($!) + # Wait for workers wait_for_server $ENCODE_PORT wait_for_server $PREFILL_PORT @@ -158,7 +173,7 @@ echo "All services are up!" ############################################################################### # Benchmark -cd ../../../../benchmarks/ +cd ../../../benchmarks/ python benchmark_serving.py \ --backend openai-chat \ --model $MODEL \ diff --git a/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh index e62e66b4b69b..bdef689cdd83 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh @@ -20,7 +20,7 @@ GPU_PD="${GPU_PD:-3}" EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/}" TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout -NUM_PROMPTS="${NUM_PROMPTS:100}" # number of prompts to send in benchmark +NUM_PROMPTS="${NUM_PROMPTS:-100}" # number of prompts to send in benchmark ############################################################################### # Helpers @@ -99,6 +99,8 @@ CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ }' \ >"${ENC_LOG}" 2>&1 & +PIDS+=($!) + ############################################################################### # Prefill+Decode worker ############################################################################### @@ -107,12 +109,17 @@ CUDA_VISIBLE_DEVICES="$GPU_PD" VLLM_NIXL_SIDE_CHANNEL_PORT=6000 vllm serve "$MOD --port "$PREFILL_DECODE_PORT" \ --enable-request-id-headers \ --max-num-seqs 128 \ - --kv-transfer-config '{ - "kv_connector": "NixlConnector", - "kv_role": "kv_consumer" + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_consumer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'" + } }' \ >"${PD_LOG}" 2>&1 & +PIDS+=($!) + # Wait for workers wait_for_server $ENCODE_PORT wait_for_server $PREFILL_DECODE_PORT @@ -133,7 +140,7 @@ echo "All services are up!" ############################################################################### # Benchmark -cd ../../../../benchmarks/ +cd ../../../benchmarks/ python benchmark_serving.py \ --backend openai-chat \ --model $MODEL \ diff --git a/vllm/v1/worker/ec_connector_model_runner_mixin.py b/vllm/v1/worker/ec_connector_model_runner_mixin.py index 70658ed88906..7d285a07800b 100644 --- a/vllm/v1/worker/ec_connector_model_runner_mixin.py +++ b/vllm/v1/worker/ec_connector_model_runner_mixin.py @@ -85,7 +85,9 @@ def _get_ec_connector_output( ec_connector.bind_connector_metadata( scheduler_output.ec_connector_metadata) - ec_connector.start_load_caches(**kwargs) + if not ec_connector.is_producer: + ec_connector.start_load_caches(**kwargs) + try: yield output finally: From 7ba00e3fbd73aa8f786767cfe68bbca5e0586296 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Thu, 9 Oct 2025 10:26:40 +0800 Subject: [PATCH 26/57] [Misc] Resolve comment Signed-off-by: knlnguyen1802 --- .../disaggregated_encoder/disagg_1e1pd_example.sh | 6 +++--- vllm/distributed/ec_transfer/ec_connector/base.py | 15 +++++---------- .../ec_connector/shared_storage_connector.py | 11 ++--------- .../distributed/ec_transfer/ec_connector/utils.py | 0 vllm/v1/core/sched/scheduler.py | 4 ++-- vllm/v1/worker/ec_connector_model_runner_mixin.py | 9 --------- 6 files changed, 12 insertions(+), 33 deletions(-) delete mode 100644 vllm/distributed/ec_transfer/ec_connector/utils.py diff --git a/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh index bdef689cdd83..95d7220a3523 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh @@ -14,10 +14,10 @@ ENCODE_PORT="${ENCODE_PORT:-19534}" PREFILL_DECODE_PORT="${PREFILL_DECODE_PORT:-19535}" PROXY_PORT="${PROXY_PORT:-10001}" -GPU_E="${GPU_E:-2}" -GPU_PD="${GPU_PD:-3}" +GPU_E="${GPU_E:-0}" +GPU_PD="${GPU_PD:-1}" -EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/}" +EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/ec_cache}" TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout NUM_PROMPTS="${NUM_PROMPTS:-100}" # number of prompts to send in benchmark diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 1bb4636d59d9..54b5cda2afd1 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -136,17 +136,12 @@ def start_load_caches(self, **kwargs) -> None: pass @abstractmethod - def save_caches(self, **kwargs) -> None: + def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: """ Save caches into connector - For EC the encoder_cache and mm_hash is store in kwargs - """ - pass - - @abstractmethod - def wait_for_save(self): - """ - Block until all the save operations is done. + Args: + encoder_cache: Reference to encoder cache storage inside worker + mm_hash: Hash of the multimodal data """ pass @@ -173,7 +168,7 @@ def get_finished( # ============================== @abstractmethod - def check_caches_exist( + def has_caches( self, request: "Request", ) -> list[bool]: diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 35d5e2df2617..512953b3eed0 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -86,7 +86,7 @@ def start_load_caches(self, **kwargs) -> None: encoder_cache[mm_data.mm_hash] = ec_cache logger.debug(f"Success load encoder cache for hash {mm_data.mm_hash}") - def save_caches(self, **kwargs) -> None: + def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: """Start saving the EC cache for each mm_datas from encoder cache Args: @@ -95,20 +95,13 @@ def save_caches(self, **kwargs) -> None: # Return if it is PD Instance if not self.is_producer: return - encoder_cache = kwargs.get("encoder_cache") - mm_hash = kwargs.get("mm_hash") - assert encoder_cache is not None - assert mm_hash is not None filename = self._generate_filename_debug(mm_hash) ec_cache = encoder_cache[mm_hash] tensors = {"ec_cache": ec_cache.detach().cpu()} safetensors.torch.save_file(tensors, filename) logger.debug(f"Save cache successful for mm_hash {mm_hash}") - - def wait_for_save(self): - return - def check_caches_exist( + def has_caches( self, request: "Request", ) -> list[bool]: diff --git a/vllm/distributed/ec_transfer/ec_connector/utils.py b/vllm/distributed/ec_transfer/ec_connector/utils.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index e9a1c51a08eb..fef10e03928f 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -746,7 +746,7 @@ def _try_schedule_encoder_inputs( # Check remote cache first if self.ec_connector is not None: - remote_cache_bools = self.ec_connector.check_caches_exist(request) + remote_cache_has_item = self.ec_connector.has_caches(request) # NOTE: since scheduler operates on the request level (possibly with # multiple encoder inputs per request), we need to create temporary # trackers for accounting at the encoder input level. @@ -822,7 +822,7 @@ def _try_schedule_encoder_inputs( break if self.ec_connector is not None: - if remote_cache_bools[i]: + if remote_cache_has_item[i]: mm_hashes_to_schedule.add(request.mm_hashes[i]) external_load_encoder_input.append(i) continue diff --git a/vllm/v1/worker/ec_connector_model_runner_mixin.py b/vllm/v1/worker/ec_connector_model_runner_mixin.py index 7d285a07800b..55d997030514 100644 --- a/vllm/v1/worker/ec_connector_model_runner_mixin.py +++ b/vllm/v1/worker/ec_connector_model_runner_mixin.py @@ -46,11 +46,6 @@ def maybe_save_ec_to_connector( connector = get_ec_transfer() connector.save_caches(encoder_cache=encoder_cache,mm_hash=mm_hash) - @staticmethod - def maybe_wait_for_ec_save() -> None: - if has_ec_transfer(): - get_ec_transfer().wait_for_save() - @staticmethod def get_finished_ec_transfers( scheduler_output: "SchedulerOutput", @@ -74,7 +69,6 @@ def maybe_get_ec_connector_output( @contextmanager def _get_ec_connector_output( scheduler_output: "SchedulerOutput", - wait_for_save: bool = True, **kwargs, ) -> Generator[ECConnectorOutput, None, None]: output = ECConnectorOutput() @@ -91,9 +85,6 @@ def _get_ec_connector_output( try: yield output finally: - if wait_for_save: - ec_connector.wait_for_save() - output.finished_sending, output.finished_recving = ( ec_connector.get_finished(scheduler_output.finished_req_ids)) From 99b34e3e5eaf21fc848d481c1e221df6d212ffc2 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Thu, 9 Oct 2025 16:06:51 +0800 Subject: [PATCH 27/57] [Misc] Resolve comment Signed-off-by: knlnguyen1802 --- .../disagg_1e1p1d_example.sh | 6 +++--- .../disagg_1e1pd_example.sh | 4 ++-- vllm/v1/core/sched/scheduler.py | 16 +++------------- .../v1/worker/ec_connector_model_runner_mixin.py | 11 ----------- 4 files changed, 8 insertions(+), 29 deletions(-) diff --git a/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh index 57c815d0a569..d23d4606680a 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh @@ -19,7 +19,7 @@ GPU_E="${GPU_E:-2}" GPU_P="${GPU_P:-2}" GPU_D="${GPU_D:-3}" -EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/}" +EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/ec_cache}" TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-12000}" # wait_for_server timeout NUM_PROMPTS="${NUM_PROMPTS:-100}" # number of prompts to send in benchmark @@ -95,12 +95,12 @@ CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ --enable-request-id-headers \ --no-enable-prefix-caching \ --max-num-seqs 128 \ + --max-num-batched-tokens 4096 \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_producer", "ec_connector_extra_config": { - "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'", - "ec_max_num_scheduled_tokens": "4096" + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'" } }' \ >"${ENC_LOG}" 2>&1 & diff --git a/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh index 95d7220a3523..3304155b537d 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh @@ -88,13 +88,13 @@ CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ --port "$ENCODE_PORT" \ --enable-request-id-headers \ --no-enable-prefix-caching \ + --max-num-batched-tokens 4096 \ --max-num-seqs 128 \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_producer", "ec_connector_extra_config": { - "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'", - "ec_max_num_scheduled_tokens": "4096" + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'" } }' \ >"${ENC_LOG}" 2>&1 & diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index fef10e03928f..fa1f90f5e687 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -97,17 +97,10 @@ def __init__( self.parallel_config.data_parallel_rank, ) self.ec_connector = None - self.ec_max_num_scheduled_tokens = 0 if self.vllm_config.ec_transfer_config is not None: self.ec_connector = ECConnectorFactory.create_connector( config=self.vllm_config, role=ECConnectorRole.SCHEDULER ) - transfer_config = self.vllm_config.ec_transfer_config - self.ec_max_num_scheduled_tokens = int( - transfer_config.get_from_extra_config( - "ec_max_num_scheduled_tokens", 0 - ) - ) num_gpu_blocks = self.cache_config.num_gpu_blocks assert num_gpu_blocks is not None and num_gpu_blocks > 0 @@ -197,8 +190,7 @@ def schedule(self) -> SchedulerOutput: req_to_new_blocks: dict[str, KVCacheBlocks] = {} num_scheduled_tokens: dict[str, int] = {} - token_budget = max(self.max_num_scheduled_tokens, \ - self.ec_max_num_scheduled_tokens) + token_budget = self.max_num_scheduled_tokens # Encoder-related. scheduled_encoder_inputs: dict[str, list[int]] = {} encoder_compute_budget = self.max_num_encoder_input_tokens @@ -552,10 +544,8 @@ def schedule(self) -> SchedulerOutput: # Check if the scheduling constraints are satisfied. total_num_scheduled_tokens = sum(num_scheduled_tokens.values()) - assert total_num_scheduled_tokens <= max( - self.max_num_scheduled_tokens, - self.ec_max_num_scheduled_tokens, - ) + assert total_num_scheduled_tokens <= self.max_num_scheduled_tokens + assert token_budget >= 0 assert len(self.running) <= self.max_num_running_reqs # Since some requests in the RUNNING queue may not be scheduled in diff --git a/vllm/v1/worker/ec_connector_model_runner_mixin.py b/vllm/v1/worker/ec_connector_model_runner_mixin.py index 55d997030514..8827bcfc8a98 100644 --- a/vllm/v1/worker/ec_connector_model_runner_mixin.py +++ b/vllm/v1/worker/ec_connector_model_runner_mixin.py @@ -23,17 +23,6 @@ # Defined as a EC connector functionality mixin for ModelRunner (GPU, TPU) class ECConnectorModelRunnerMixin: - - @staticmethod - def maybe_setup_ec_connector(scheduler_output: "SchedulerOutput"): - # Set up EC connector for load cache - if has_ec_transfer(): - ec_connector = get_ec_transfer() - assert isinstance(ec_connector, ECConnectorBase) - assert scheduler_output.ec_connector_metadata is not None - ec_connector.bind_connector_metadata( - scheduler_output.ec_connector_metadata) - ec_connector.start_load_caches() @staticmethod def maybe_save_ec_to_connector( From dc9e2a9be5978434af3effc329ccb9ec1848f7bb Mon Sep 17 00:00:00 2001 From: herotai214 Date: Fri, 10 Oct 2025 03:46:54 +0000 Subject: [PATCH 28/57] [CI/Build] Unit test for ECSharedStorageConnector Signed-off-by: herotai214 --- .../unit/test_ec_shared_storage_connector.py | 564 ++++++++++++++++++ 1 file changed, 564 insertions(+) create mode 100644 tests/v1/ec_connector/unit/test_ec_shared_storage_connector.py diff --git a/tests/v1/ec_connector/unit/test_ec_shared_storage_connector.py b/tests/v1/ec_connector/unit/test_ec_shared_storage_connector.py new file mode 100644 index 000000000000..371b9587173c --- /dev/null +++ b/tests/v1/ec_connector/unit/test_ec_shared_storage_connector.py @@ -0,0 +1,564 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +""" +Unit tests for ECSharedStorageConnector. +""" + +import os +from unittest.mock import Mock, patch + +import pytest +import safetensors +import torch + +from vllm.config import VllmConfig +from vllm.distributed.ec_transfer.ec_connector.base import ECConnectorRole +from vllm.distributed.ec_transfer.ec_connector.shared_storage_connector import ( + ECSharedStorageConnector, ECSharedStorageConnectorMetadata, MMMeta) +from vllm.v1.core.sched.output import SchedulerOutput + +@pytest.fixture +def temp_storage(tmp_path): + """Fixture providing temporary storage path.""" + return str(tmp_path) + +@pytest.fixture +def mock_vllm_config_producer(temp_storage): + """Fixture providing mock VllmConfig for producer role.""" + config = Mock(spec=VllmConfig) + config.ec_transfer_config = Mock() + config.ec_transfer_config.get_from_extra_config = Mock( + return_value=temp_storage) + config.ec_transfer_config.is_ec_producer = True + return config + +@pytest.fixture +def mock_vllm_config_consumer(temp_storage): + """Fixture providing mock VllmConfig for consumer role.""" + config = Mock(spec=VllmConfig) + config.ec_transfer_config = Mock() + config.ec_transfer_config.get_from_extra_config = Mock( + return_value=temp_storage) + config.ec_transfer_config.is_ec_producer = False + return config + +@pytest.fixture +def mock_request_with_3_mm(): + """Fixture providing mock Request with 3 multimodal items.""" + request = Mock() + request.request_id = "test_req_123" + request.mm_hashes = ["img_hash_1", "img_hash_2", "audio_hash_1"] + request.get_num_encoder_tokens = Mock(side_effect=lambda idx: [100, 150, 200][idx]) + return request + +class TestECSharedStorageConnectorBasics: + """Test basic EC connector functionality.""" + + def test_initialization_producer(self, mock_vllm_config_producer, temp_storage): + """Test connector initializes correctly as producer.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + assert connector.role == ECConnectorRole.SCHEDULER + assert connector.is_producer == True + assert connector._storage_path == temp_storage + assert connector._mm_datas_need_loads == {} + + def test_initialization_consumer(self, mock_vllm_config_consumer, temp_storage): + """Test connector initializes correctly as consumer.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + assert connector.role == ECConnectorRole.WORKER + assert connector.is_producer == False + assert connector._storage_path == temp_storage + + def test_role_assignment(self, mock_vllm_config_producer): + """Test role is correctly assigned.""" + scheduler_connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + worker_connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.WORKER, + ) + + assert scheduler_connector.role == ECConnectorRole.SCHEDULER + assert worker_connector.role == ECConnectorRole.WORKER + +class TestCacheExistence: + """Test cache existence checking using has_caches() API.""" + + def test_has_caches_all_exist_3_items(self, mock_vllm_config_producer, + mock_vllm_config_consumer, mock_request_with_3_mm): + """Test has_caches returns True when all 3 caches exist.""" + # Test for producer first + producer = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + # Create cache files using save_caches (proper way) + encoder_cache = {} + for mm_hash in mock_request_with_3_mm.mm_hashes: + encoder_cache[mm_hash] = torch.randn(10, 768) + producer.save_caches(encoder_cache, mm_hash) + + # Test using has_caches API + producer_result = producer.has_caches(mock_request_with_3_mm) + + # Assert + assert len(producer_result) == 3 + assert all(producer_result), f"Expected all True, got {producer_result}" + + # Also test consumer can check if cache exists + consumer = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.SCHEDULER, + ) + + # Test using has_caches API + consumer_result = consumer.has_caches(mock_request_with_3_mm) + + # Assert + assert len(consumer_result) == 3 + assert all(consumer_result), f"Expected all True, got {consumer_result}" + + def test_has_caches_none_exist(self, mock_vllm_config_producer, + mock_request_with_3_mm): + """Test has_caches returns False when no caches exist.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + # Test without creating any files + result = connector.has_caches(mock_request_with_3_mm) + + # Assert + assert len(result) == 3 + assert not any(result), f"Expected all False, got {result}" + + def test_has_caches_partial_exist(self, mock_vllm_config_producer, + mock_request_with_3_mm): + """Test has_caches with some caches existing (1 of 3).""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + # Create only the second cache file + encoder_cache = { + mock_request_with_3_mm.mm_hashes[1]: torch.randn(10, 768) + } + connector.save_caches( + encoder_cache, + mock_request_with_3_mm.mm_hashes[1] + ) + + # Test + result = connector.has_caches(mock_request_with_3_mm) + + # Assert + assert len(result) == 3 + assert result[0] == False # First doesn't exist + assert result[1] == True # Second exists + assert result[2] == False # Third doesn't exist + +class TestStateManagement: + """Test connector state management.""" + + def test_update_state_after_alloc_3_items(self, mock_vllm_config_producer, + mock_request_with_3_mm): + """Test state update after allocation for 3 MM items.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + # Initial state should be empty + assert len(connector._mm_datas_need_loads) == 0 + + # Update state for all 3 items + for i in range(3): + connector.update_state_after_alloc(mock_request_with_3_mm, index=i) + + # Check state updated for all 3 + assert len(connector._mm_datas_need_loads) == 3 + assert "img_hash_1" in connector._mm_datas_need_loads + assert "img_hash_2" in connector._mm_datas_need_loads + assert "audio_hash_1" in connector._mm_datas_need_loads + assert connector._mm_datas_need_loads["img_hash_1"] == 100 + assert connector._mm_datas_need_loads["img_hash_2"] == 150 + assert connector._mm_datas_need_loads["audio_hash_1"] == 200 + + def test_build_connector_meta_3_items(self, mock_vllm_config_producer, + mock_request_with_3_mm): + """Test metadata building for 3 MM items.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + # Setup state for all 3 items + for i in range(3): + connector.update_state_after_alloc(mock_request_with_3_mm, index=i) + + # Build metadata + scheduler_output = Mock(spec=SchedulerOutput) + metadata = connector.build_connector_meta(scheduler_output) + + # Assert + assert isinstance(metadata, ECSharedStorageConnectorMetadata) + assert len(metadata.mm_datas) == 3 + assert metadata.mm_datas[0].mm_hash == "img_hash_1" + assert metadata.mm_datas[0].num_token == 100 + assert metadata.mm_datas[1].mm_hash == "img_hash_2" + assert metadata.mm_datas[1].num_token == 150 + assert metadata.mm_datas[2].mm_hash == "audio_hash_1" + assert metadata.mm_datas[2].num_token == 200 + + # State should be cleared after building + assert len(connector._mm_datas_need_loads) == 0 + + def test_build_connector_meta_empty(self, mock_vllm_config_producer): + """Test metadata building with empty state.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + scheduler_output = Mock(spec=SchedulerOutput) + metadata = connector.build_connector_meta(scheduler_output) + + assert isinstance(metadata, ECSharedStorageConnectorMetadata) + assert len(metadata.mm_datas) == 0 + + def test_state_cleared_after_metadata_build(self, mock_vllm_config_producer, + mock_request_with_3_mm): + """Test that state is properly cleared after building metadata.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + # Add state + for i in range(3): + connector.update_state_after_alloc(mock_request_with_3_mm, index=i) + assert len(connector._mm_datas_need_loads) == 3 + + # Build metadata (should clear state) + scheduler_output = Mock(spec=SchedulerOutput) + connector.build_connector_meta(scheduler_output) + + # State should be empty + assert len(connector._mm_datas_need_loads) == 0 + + # Build again should return empty metadata + metadata2 = connector.build_connector_meta(scheduler_output) + assert len(metadata2.mm_datas) == 0 + +class TestCacheSaving: + """Test encoder cache saving (producer only).""" + + def test_save_caches_producer_3_items(self, mock_vllm_config_producer, + mock_request_with_3_mm, temp_storage): + """Test cache saving as producer for 3 different MM items.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.WORKER, + ) + + # Create and save 3 different caches + mm_hashes = mock_request_with_3_mm.mm_hashes + encoder_cache = {} + + for mm_hash in mm_hashes: + encoder_cache[mm_hash] = torch.randn(10, 768) + connector.save_caches(encoder_cache, mm_hash) + + # Verify all files exist using has_caches + result = connector.has_caches(mock_request_with_3_mm) + assert all(result), f"Not all caches were saved: {result}" + + # Verify each file's content + for mm_hash in mm_hashes: + filename = connector._generate_filename_debug(mm_hash) + loaded = safetensors.torch.load_file(filename) + assert "ec_cache" in loaded + assert torch.allclose(loaded["ec_cache"], + encoder_cache[mm_hash].cpu()) + + def test_save_caches_consumer_skips(self, mock_vllm_config_consumer): + """Test cache saving is skipped for consumer.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + mm_hash = "test_hash_consumer" + encoder_cache = {mm_hash: torch.randn(10, 768)} + + # Save should not raise but also not create file + connector.save_caches(encoder_cache, mm_hash) + + # Verify file doesn't exist using has_caches + mock_request = Mock() + mock_request.mm_hashes = [mm_hash] + result = connector.has_caches(mock_request) + assert result[0] == False, "Consumer should not save caches" + +class TestCacheLoading: + """Test encoder cache loading (consumer).""" + + @pytest.mark.skipif(not torch.cuda.is_available(), + reason="CUDA not available") + def test_start_load_caches_consumer_3_items(self, mock_vllm_config_producer, + mock_vllm_config_consumer, mock_request_with_3_mm, + temp_storage): + """Test consumer loads 3 caches from storage.""" + # First, create producer to save caches + producer = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.WORKER, + ) + + # Producer saves 3 caches + mm_hashes = mock_request_with_3_mm.mm_hashes + saved_caches = {} + for mm_hash in mm_hashes: + saved_caches[mm_hash] = torch.randn(10, 768) + producer.save_caches(saved_caches, mm_hash) + + # Now consumer loads + consumer = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + # Setup metadata for all 3 + metadata = ECSharedStorageConnectorMetadata() + for mm_hash in mm_hashes: + metadata.add_mm_data(MMMeta.make_meta(mm_hash, 100)) + consumer.bind_connector_metadata(metadata) + + # Load + encoder_cache = {} + consumer.start_load_caches(encoder_cache=encoder_cache) + + # Verify all 3 loaded + assert len(encoder_cache) == 3 + for mm_hash in mm_hashes: + assert mm_hash in encoder_cache, f"{mm_hash} missing in encoder_cache" + assert encoder_cache[mm_hash].is_cuda, f"{mm_hash} cache is in {encoder_cache[mm_hash].device}" + assert torch.allclose( + encoder_cache[mm_hash].cpu(), + saved_caches[mm_hash] + ), f"{mm_hash} cache saved and loaded tesnor are not the same" + + def test_start_load_caches_skip_existing(self, mock_vllm_config_producer, + mock_vllm_config_consumer, temp_storage): + """Test cache loading skips already cached items.""" + # Setup: producer saves cache + producer = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.WORKER, + ) + + mm_hash = "existing_hash" + saved_cache = torch.randn(10, 768) + producer.save_caches({mm_hash: saved_cache}, mm_hash) + + # Consumer setup + consumer = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + metadata = ECSharedStorageConnectorMetadata() + metadata.add_mm_data(MMMeta.make_meta(mm_hash, 100)) + consumer.bind_connector_metadata(metadata) + + # Pre-populate encoder_cache with different value + existing_cache = torch.randn(5, 512) + encoder_cache = {mm_hash: existing_cache} + + # Load (should skip since already exists) + with patch('safetensors.torch.load_file') as mock_load: + consumer.start_load_caches(encoder_cache=encoder_cache) + # Should not call load_file since cache exists + mock_load.assert_not_called() + + # Verify original cache unchanged + assert torch.equal(encoder_cache[mm_hash], existing_cache) + + def test_start_load_caches_empty_metadata(self, mock_vllm_config_consumer): + """Test loading with empty metadata does nothing.""" + consumer = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + # Setup empty metadata + metadata = ECSharedStorageConnectorMetadata() + consumer.bind_connector_metadata(metadata) + + # Load (should not raise) + encoder_cache = {} + consumer.start_load_caches(encoder_cache=encoder_cache) + + # Cache should remain empty + assert len(encoder_cache) == 0 + +class TestFilenameGeneration: + """Test filename and path generation.""" + + def test_generate_foldername(self, mock_vllm_config_producer, + temp_storage): + """Test folder name generation.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.WORKER, + ) + + mm_hash = "test_folder_hash" + folder = connector._generate_foldername_debug(mm_hash) + + assert folder == os.path.join(temp_storage, mm_hash) + assert os.path.isdir(folder) # Should be created + + def test_generate_filename(self, mock_vllm_config_producer, temp_storage): + """Test filename generation.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.WORKER, + ) + + mm_hash = "test_file_hash" + filename = connector._generate_filename_debug(mm_hash) + + expected = os.path.join(temp_storage, mm_hash, + "encoder_cache.safetensors") + assert filename == expected + assert os.path.isdir(os.path.dirname(filename)) # Folder created + + def test_generate_filename_consistency(self, mock_vllm_config_producer): + """Test filename generation is consistent.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.WORKER, + ) + + mm_hash = "consistency_hash" + filename1 = connector._generate_filename_debug(mm_hash) + filename2 = connector._generate_filename_debug(mm_hash) + + assert filename1 == filename2 + +class TestMetadataBindingLifecycle: + """Test metadata binding and clearing lifecycle.""" + + def test_bind_connector_metadata(self, mock_vllm_config_consumer): + """Test binding connector metadata.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + metadata = ECSharedStorageConnectorMetadata() + metadata.add_mm_data(MMMeta.make_meta("hash_1", 100)) + + connector.bind_connector_metadata(metadata) + + assert connector._connector_metadata is metadata + + def test_clear_connector_metadata(self, mock_vllm_config_consumer): + """Test clearing connector metadata.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + metadata = ECSharedStorageConnectorMetadata() + connector.bind_connector_metadata(metadata) + + connector.clear_connector_metadata() + + assert connector._connector_metadata is None + + def test_get_connector_metadata(self, mock_vllm_config_consumer): + """Test getting connector metadata.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + metadata = ECSharedStorageConnectorMetadata() + connector.bind_connector_metadata(metadata) + + retrieved = connector._get_connector_metadata() + + assert retrieved is metadata + + def test_get_connector_metadata_not_set(self, mock_vllm_config_consumer): + """Test getting metadata when not set raises.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + with pytest.raises(AssertionError): + connector._get_connector_metadata() + +class TestEdgeCases: + """Test edge cases and error handling.""" + + def test_save_empty_cache(self, mock_vllm_config_producer): + """Test saving empty tensor.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.WORKER, + ) + + mm_hash = "empty_hash" + encoder_cache = {mm_hash: torch.empty(0)} + + # Should not raise + connector.save_caches(encoder_cache, mm_hash) + + def test_load_nonexistent_cache(self, mock_vllm_config_consumer): + """Test loading cache that doesn't exist raises error.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_consumer, + role=ECConnectorRole.WORKER, + ) + + metadata = ECSharedStorageConnectorMetadata() + metadata.add_mm_data(MMMeta.make_meta("nonexistent_hash", 100)) + connector.bind_connector_metadata(metadata) + + encoder_cache = {} + + # Should raise FileNotFoundError + with pytest.raises(FileNotFoundError): + connector.start_load_caches(encoder_cache=encoder_cache) + + def test_has_caches_empty_request(self, mock_vllm_config_producer): + """Test has_caches with request that has no MM data.""" + connector = ECSharedStorageConnector( + vllm_config=mock_vllm_config_producer, + role=ECConnectorRole.SCHEDULER, + ) + + mock_request = Mock() + mock_request.mm_hashes = [] + + result = connector.has_caches(mock_request) + + assert len(result) == 0 + assert result == [] From 2169531195b2771a6428d62b440051d9f6bd4656 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Fri, 10 Oct 2025 16:18:03 +0800 Subject: [PATCH 29/57] [Fix] remove v1 check for create_connector and update docs Signed-off-by: knlnguyen1802 --- vllm/distributed/ec_transfer/ec_connector/factory.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/factory.py b/vllm/distributed/ec_transfer/ec_connector/factory.py index 22a83785fb86..0bca7e2a30d5 100644 --- a/vllm/distributed/ec_transfer/ec_connector/factory.py +++ b/vllm/distributed/ec_transfer/ec_connector/factory.py @@ -39,22 +39,16 @@ def create_connector( config: "VllmConfig", role: ECConnectorRole, ) -> ECConnectorBase: - if not envs.VLLM_USE_V1: - raise ValueError("Attempting to initialize a V1 Connector, " - f"but found {envs.VLLM_USE_V1=}") - ec_transfer_config = config.ec_transfer_config connector_cls = cls.get_connector_class(ec_transfer_config) - logger.info("Creating v1 connector with name: %s and engine_id: %s", + logger.info("Creating connector with name: %s and engine_id: %s", connector_cls.__name__, ec_transfer_config.engine_id) - # NOTE(Kuntai): v1 connector is explicitly separated into two roles. + # Connector is explicitly separated into two roles. # Scheduler connector: # - Co-locate with scheduler process # - Should only be used inside the Scheduler class # Worker connector: # - Co-locate with worker process - # - Should only be used inside the forward context & attention layer - # We build separately to enforce strict separation return connector_cls(config, role) @classmethod From a2221ea9656c524c46b793297ad290a3ded67ed6 Mon Sep 17 00:00:00 2001 From: Khuong Le Date: Tue, 14 Oct 2025 00:29:09 -0700 Subject: [PATCH 30/57] [Misc] Clean code to pass pre-commit rules Signed-off-by: Khuong Le --- docs/features/disagg_encoder.md | 14 +- .../disaggregated_encoder/README.md | 2 +- .../disaggregated_encoder/disagg_epd_proxy.py | 125 +++++---- .../unit/test_ec_shared_storage_connector.py | 240 ++++++++++-------- vllm/config/__init__.py | 6 +- vllm/distributed/ec_transfer/__init__.py | 8 +- .../ec_transfer/ec_connector/base.py | 28 +- .../ec_transfer/ec_connector/factory.py | 9 +- .../ec_connector/shared_storage_connector.py | 54 ++-- .../ec_transfer/ec_transfer_state.py | 3 +- vllm/engine/arg_utils.py | 23 +- vllm/v1/core/sched/output.py | 8 +- vllm/v1/core/sched/scheduler.py | 39 ++- vllm/v1/outputs.py | 12 +- .../worker/ec_connector_model_runner_mixin.py | 16 +- vllm/v1/worker/gpu_model_runner.py | 62 +++-- vllm/v1/worker/gpu_worker.py | 2 +- 17 files changed, 343 insertions(+), 308 deletions(-) diff --git a/docs/features/disagg_encoder.md b/docs/features/disagg_encoder.md index 42f1164f56eb..46a5848b2e1c 100644 --- a/docs/features/disagg_encoder.md +++ b/docs/features/disagg_encoder.md @@ -13,15 +13,18 @@ Design doc: PD) or in disaggregated instances with `disagg_epd_example.sh` (E->P->D) + * PD can be in either a single normal instance with `disagg_encoder_example.sh` (E->PD) or in disaggregated instances with `disagg_epd_example.sh` (E->P->D) A connector transfers encoder-cache (EC) embeddings from the encoder instance to the PD instance. All related code is under `vllm/distributed/ec_transfer`. @@ -54,8 +57,8 @@ All related code is under `vllm/distributed/ec_transfer`. ### Key abstractions * **ECConnector** – interface for retrieving EC caches produced by the encoder. - * *Scheduler role* – checks cache existence and schedules loads. - * *Worker role* – loads the embeddings into memory. + * *Scheduler role* – checks cache existence and schedules loads. + * *Worker role* – loads the embeddings into memory. Here is a figure illustrating disaggregate encoder flow: @@ -63,7 +66,6 @@ Here is a figure illustrating disaggregate encoder flow: For the PD disaggregation part, the Prefill instance receive cache exactly the same as the disaggregate encoder flow above. Prefill instance executes 1 step (prefill -> 1 token output) and then transfer KV cache to the Decode instance for the remaining execution. The KV transfer part purely happens after the execute of the PDinstance. -`docs/features/disagg_prefill.md` shows the brief idea about the disaggregated prefill (v0) - +`docs/features/disagg_prefill.md` shows the brief idea about the disaggregated prefill (v0) -We create the example setup with the **NixlConnector** from `vllm/distributed/kv_transfer/kv_connector/v1/nixl_connector.py` and referred to the `tests/v1/kv_connector/nixl_integration/toy_proxy_server.py` to facilitate the kv transfer between P and D; \ No newline at end of file +We create the example setup with the **NixlConnector** from `vllm/distributed/kv_transfer/kv_connector/v1/nixl_connector.py` and referred to the `tests/v1/kv_connector/nixl_integration/toy_proxy_server.py` to facilitate the kv transfer between P and D; diff --git a/examples/online_serving/disaggregated_encoder/README.md b/examples/online_serving/disaggregated_encoder/README.md index fa6d357300e6..fd11ff88ace6 100644 --- a/examples/online_serving/disaggregated_encoder/README.md +++ b/examples/online_serving/disaggregated_encoder/README.md @@ -10,4 +10,4 @@ Please refer to [Disaggregated Encoder Feature](../../features/disagg_encoder.md - `disagg_1e1p1d_example.sh` - Setup 1e1p1d and run VisionArena benchmark. - `disagg_1e1pd_example.sh` - Setup 1e1pd and run VisionArena benchmark. -Detailed explanations are commnented in the scripts. +Detailed explanations are commnented in the scripts. diff --git a/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py index f84b1912ac51..0a51d16e4617 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py +++ b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project """ disagg_encoder_proxy.py @@ -32,13 +34,13 @@ import argparse import asyncio -import json import logging import os import random import uuid -import copy -from typing import Any, AsyncIterator, List, Optional +from collections.abc import AsyncIterator +from typing import Optional + import aiohttp import uvicorn from fastapi import FastAPI, HTTPException, Request @@ -64,14 +66,14 @@ MM_TYPES = {"image_url", "audio_url", "input_audio"} -def extract_mm_items(request_data: dict) -> List[dict]: +def extract_mm_items(request_data: dict) -> list[dict]: """ Return *all* image/audio items that appear anywhere in `messages`. Each returned dict looks like: { "type": "image_url", "image_url": {...} } """ - items: List[dict] = [] + items: list[dict] = [] for msg in request_data.get("messages", []): content = msg.get("content") if not isinstance(content, list): @@ -85,7 +87,7 @@ def extract_mm_items(request_data: dict) -> List[dict]: async def fanout_encoder_primer( orig_request: dict, - e_urls: List[str], + e_urls: list[str], request_id: str, ) -> None: """ @@ -150,20 +152,18 @@ async def maybe_prefill( req_id: str, ) -> dict: """ - - Do prefill-only task if p_url exist; + - Do prefill-only task if p_url exist; - Return modified request data with kv transfer params (for nixl connector) - Else, skip and return the original request data for decode """ if p_url: - prefill_response = await process_prefill_stage( - req_data, p_url, req_id - ) + prefill_response = await process_prefill_stage(req_data, p_url, req_id) # for nixl connector to facilitate kv transfer... prefill_response_json = await prefill_response.json() - kv_transfer_params = prefill_response_json.get('kv_transfer_params', {}) + kv_transfer_params = prefill_response_json.get("kv_transfer_params", {}) if kv_transfer_params: req_data["kv_transfer_params"] = kv_transfer_params - logger.debug(f"kv_transfer_params: {kv_transfer_params}") + logger.debug("kv_transfer_params: %s", kv_transfer_params) return req_data else: @@ -176,16 +176,16 @@ async def process_prefill_stage( req_id: str, ) -> dict: """Process request through Prefill stage and return kv_transfer_params""" - logger.debug(f"Processing through prefill for req_id: {req_id}/ url: {p_url}") - + logger.debug("Processing through prefill for req_id: %s/ url: %s", req_id, p_url) + prefill_request = req_data.copy() - prefill_request['kv_transfer_params'] = { + prefill_request["kv_transfer_params"] = { "do_remote_decode": True, "do_remote_prefill": False, "remote_engine_id": None, "remote_block_ids": None, "remote_host": None, - "remote_port": None + "remote_port": None, } prefill_request["stream"] = False prefill_request["max_tokens"] = 1 @@ -193,13 +193,11 @@ async def process_prefill_stage( prefill_request["max_completion_tokens"] = 1 if "stream_options" in prefill_request: del prefill_request["stream_options"] - + headers = {"x-request-id": req_id} try: prefill_response = await prefill_session.post( - f"{p_url}/v1/chat/completions", - json=prefill_request, - headers=headers + f"{p_url}/v1/chat/completions", json=prefill_request, headers=headers ) prefill_response.raise_for_status() @@ -207,18 +205,18 @@ async def process_prefill_stage( error_text = await prefill_response.text() raise HTTPException( status_code=prefill_response.status, - detail={"error": "Prefill request failed", "message": error_text} + detail={"error": "Prefill request failed", "message": error_text}, ) - logger.debug(f"Prefill processing completed successfully for req_id: {req_id}") - + logger.debug("Prefill processing completed successfully for req_id: %s", req_id) + return prefill_response except Exception as e: - logger.error(f"Prefill processing failed: {e}") + logger.error("Prefill processing failed: %s", str(e)) raise HTTPException( status_code=500, - detail={"error": "Prefill processing error", "message": str(e)} - ) + detail={"error": "Prefill processing error", "message": str(e)}, + ) from e ############################################################################### @@ -255,18 +253,18 @@ async def on_shutdown() -> None: async def forward_non_stream( - req_data: dict, req_id: str, e_urls: List[str], p_url: str, d_url: str + req_data: dict, req_id: str, e_urls: list[str], p_url: str, d_url: str ) -> dict: # Step 1: Process through Encoder instance (if has MM input) await fanout_encoder_primer(req_data, e_urls, req_id) - + # Step 2: Process through Prefill instance req_data = await maybe_prefill(req_data, p_url, req_id) # Step 3: Process through Decode instance - logger.debug(f"Getting response from decode for req_id: {req_id}/ url: {d_url}") + logger.debug("Getting response from decode for req_id: %s/ url: %s", req_id, d_url) headers = {"x-request-id": req_id} - + # Non-streaming response async with decode_session.post( f"{d_url}/v1/chat/completions", json=req_data, headers=headers @@ -276,16 +274,18 @@ async def forward_non_stream( async def forward_stream( - req_data: dict, req_id: str, e_urls: List[str], p_url: str, d_url: str + req_data: dict, req_id: str, e_urls: list[str], p_url: str, d_url: str ) -> AsyncIterator[str]: # Step 1: Process through Encoder instance (if has MM input) await fanout_encoder_primer(req_data, e_urls, req_id) - + # Step 2: Process through Prefill instance req_data = await maybe_prefill(req_data, p_url, req_id) # Step 3: Process through Decode instance - logger.debug(f"Streaming response from decode for req_id: {req_id}/ url: {d_url}") + logger.debug( + "Streaming response from decode for req_id: %s/ url: %s", req_id, d_url + ) headers = {"x-request-id": req_id} # Streaming response @@ -299,6 +299,7 @@ async def forward_stream( if chunk: yield chunk.decode("utf-8", errors="ignore") + ############################################################################### # Public routes ############################################################################### @@ -312,9 +313,9 @@ async def chat_completions(request: Request): e_urls = app.state.e_urls # we want the full list for fan-out p_url = random.choice(app.state.p_urls) if app.state.p_urls else None d_url = random.choice(app.state.d_urls) - + is_streaming = req_data.get("stream", False) - + if is_streaming: return StreamingResponse( forward_stream(req_data, req_id, e_urls, p_url, d_url), @@ -348,7 +349,9 @@ async def healthy(urls): healthy(app.state.e_urls), healthy(app.state.p_urls), healthy(app.state.d_urls) ) - overall_healthy = all(status != "unhealthy" for status in (e_status, p_status, d_status)) + overall_healthy = all( + status != "unhealthy" for status in (e_status, p_status, d_status) + ) status_code = 200 if overall_healthy else 503 @@ -379,13 +382,13 @@ async def _post_if_available( Returns ------- - • The decoded JSON body on success (2xx) - • None if the endpoint does not exist (404) + • The decoded JSON body on success (2xx) + • None if the endpoint does not exist (404) • Raises for anything else. """ try: resp = await session.post(url, json=payload, headers=headers) - if resp.status == 404: # profiling disabled on that server + if resp.status == 404: # profiling disabled on that server logger.warning("Profiling endpoint missing on %s", url) return None resp.raise_for_status() @@ -410,14 +413,18 @@ async def _profile_cmd(cmd: str, payload: dict, e_url: str, p_url: str, d_url: s encode_task = _post_if_available( encode_session, f"{e_url}/{cmd}_profile", payload, headers ) - prefill_task = _post_if_available( - prefill_session, f"{p_url}/{cmd}_profile", payload, headers - ) if p_url is not None else asyncio.sleep(0) + prefill_task = ( + _post_if_available(prefill_session, f"{p_url}/{cmd}_profile", payload, headers) + if p_url is not None + else asyncio.sleep(0) + ) decode_task = _post_if_available( decode_session, f"{d_url}/{cmd}_profile", payload, headers ) - encode_res, prefill_res, decode_res = await asyncio.gather(encode_task, prefill_task, decode_task) + encode_res, prefill_res, decode_res = await asyncio.gather( + encode_task, prefill_task, decode_task + ) # If *all* clusters said “I don’t have that route”, surface an error if encode_res is prefill_res is decode_res is None: @@ -427,9 +434,9 @@ async def _profile_cmd(cmd: str, payload: dict, e_url: str, p_url: str, d_url: s ) return { - "encode": encode_res, # may be None - "prefill": prefill_res, # may be None - "decode": decode_res, # may be None + "encode": encode_res, # may be None + "prefill": prefill_res, # may be None + "decode": decode_res, # may be None } @@ -452,6 +459,7 @@ async def stop_profile(request: Request): d_url = random.choice(app.state.d_urls) return await _profile_cmd("stop", body, e_url, p_url, d_url) + if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--host", default="0.0.0.0") @@ -464,23 +472,34 @@ async def stop_profile(request: Request): parser.add_argument( "--prefill-servers-urls", required=True, - help='Comma-separated prefill URLs ("http://p1:8003,http://p2:8004") to enable E->P->D, set "disable" or "none" to enable E->PD', + help=( + 'Comma-separated prefill URLs ("http://p1:8003,http://p2:8004") ', + 'to enable E->P->D, set "disable" or "none" to enable E->PD', + ), ) parser.add_argument( "--decode-servers-urls", required=True, help='Comma-separated decode URLs ("http://d1:8005,http://d2:8006")', ) - + args = parser.parse_args() - app.state.e_urls = [u.strip() for u in args.encode_servers_urls.split(",") if u.strip()] - app.state.d_urls = [u.strip() for u in args.decode_servers_urls.split(",") if u.strip()] + app.state.e_urls = [ + u.strip() for u in args.encode_servers_urls.split(",") if u.strip() + ] + app.state.d_urls = [ + u.strip() for u in args.decode_servers_urls.split(",") if u.strip() + ] # handle prefill instances if args.prefill_servers_urls.lower() in ("disable", "none", ""): app.state.p_urls = [] - logger.info("Disaggregated prefill phase explicitly disabled by user. Running E + PD...") + logger.info( + "Disaggregated prefill phase explicitly disabled by user. Running E + PD..." + ) else: - app.state.p_urls = [u.strip() for u in args.prefill_servers_urls.split(",") if u.strip()] + app.state.p_urls = [ + u.strip() for u in args.prefill_servers_urls.split(",") if u.strip() + ] logger.info("Disaggregated prefill phase is enabled. Running E + P + D...") logger.info("Proxy listening on %s:%s", args.host, args.port) @@ -495,4 +514,4 @@ async def stop_profile(request: Request): log_level="info", loop="uvloop", access_log=False, - ) \ No newline at end of file + ) diff --git a/tests/v1/ec_connector/unit/test_ec_shared_storage_connector.py b/tests/v1/ec_connector/unit/test_ec_shared_storage_connector.py index 371b9587173c..ce7844589c1b 100644 --- a/tests/v1/ec_connector/unit/test_ec_shared_storage_connector.py +++ b/tests/v1/ec_connector/unit/test_ec_shared_storage_connector.py @@ -17,11 +17,13 @@ ECSharedStorageConnector, ECSharedStorageConnectorMetadata, MMMeta) from vllm.v1.core.sched.output import SchedulerOutput + @pytest.fixture def temp_storage(tmp_path): """Fixture providing temporary storage path.""" return str(tmp_path) + @pytest.fixture def mock_vllm_config_producer(temp_storage): """Fixture providing mock VllmConfig for producer role.""" @@ -32,6 +34,7 @@ def mock_vllm_config_producer(temp_storage): config.ec_transfer_config.is_ec_producer = True return config + @pytest.fixture def mock_vllm_config_consumer(temp_storage): """Fixture providing mock VllmConfig for consumer role.""" @@ -42,39 +45,44 @@ def mock_vllm_config_consumer(temp_storage): config.ec_transfer_config.is_ec_producer = False return config + @pytest.fixture def mock_request_with_3_mm(): """Fixture providing mock Request with 3 multimodal items.""" request = Mock() request.request_id = "test_req_123" request.mm_hashes = ["img_hash_1", "img_hash_2", "audio_hash_1"] - request.get_num_encoder_tokens = Mock(side_effect=lambda idx: [100, 150, 200][idx]) + request.get_num_encoder_tokens = Mock( + side_effect=lambda idx: [100, 150, 200][idx]) return request + class TestECSharedStorageConnectorBasics: """Test basic EC connector functionality.""" - def test_initialization_producer(self, mock_vllm_config_producer, temp_storage): + def test_initialization_producer(self, mock_vllm_config_producer, + temp_storage): """Test connector initializes correctly as producer.""" connector = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + assert connector.role == ECConnectorRole.SCHEDULER - assert connector.is_producer == True + assert connector.is_producer assert connector._storage_path == temp_storage assert connector._mm_datas_need_loads == {} - def test_initialization_consumer(self, mock_vllm_config_consumer, temp_storage): + def test_initialization_consumer(self, mock_vllm_config_consumer, + temp_storage): """Test connector initializes correctly as consumer.""" connector = ECSharedStorageConnector( vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + assert connector.role == ECConnectorRole.WORKER - assert connector.is_producer == False + assert not connector.is_producer assert connector._storage_path == temp_storage def test_role_assignment(self, mock_vllm_config_producer): @@ -87,34 +95,37 @@ def test_role_assignment(self, mock_vllm_config_producer): vllm_config=mock_vllm_config_producer, role=ECConnectorRole.WORKER, ) - + assert scheduler_connector.role == ECConnectorRole.SCHEDULER assert worker_connector.role == ECConnectorRole.WORKER + class TestCacheExistence: """Test cache existence checking using has_caches() API.""" def test_has_caches_all_exist_3_items(self, mock_vllm_config_producer, - mock_vllm_config_consumer, mock_request_with_3_mm): + mock_vllm_config_consumer, + mock_request_with_3_mm): """Test has_caches returns True when all 3 caches exist.""" # Test for producer first producer = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + # Create cache files using save_caches (proper way) - encoder_cache = {} + encoder_cache: dict[str, torch.Tensor] = {} for mm_hash in mock_request_with_3_mm.mm_hashes: encoder_cache[mm_hash] = torch.randn(10, 768) producer.save_caches(encoder_cache, mm_hash) - + # Test using has_caches API producer_result = producer.has_caches(mock_request_with_3_mm) - + # Assert assert len(producer_result) == 3 - assert all(producer_result), f"Expected all True, got {producer_result}" + assert all( + producer_result), f"Expected all True, got {producer_result}" # Also test consumer can check if cache exists consumer = ECSharedStorageConnector( @@ -124,70 +135,70 @@ def test_has_caches_all_exist_3_items(self, mock_vllm_config_producer, # Test using has_caches API consumer_result = consumer.has_caches(mock_request_with_3_mm) - + # Assert assert len(consumer_result) == 3 - assert all(consumer_result), f"Expected all True, got {consumer_result}" + assert all( + consumer_result), f"Expected all True, got {consumer_result}" def test_has_caches_none_exist(self, mock_vllm_config_producer, - mock_request_with_3_mm): + mock_request_with_3_mm): """Test has_caches returns False when no caches exist.""" connector = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + # Test without creating any files result = connector.has_caches(mock_request_with_3_mm) - + # Assert assert len(result) == 3 assert not any(result), f"Expected all False, got {result}" def test_has_caches_partial_exist(self, mock_vllm_config_producer, - mock_request_with_3_mm): + mock_request_with_3_mm): """Test has_caches with some caches existing (1 of 3).""" connector = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + # Create only the second cache file encoder_cache = { mock_request_with_3_mm.mm_hashes[1]: torch.randn(10, 768) } - connector.save_caches( - encoder_cache, - mock_request_with_3_mm.mm_hashes[1] - ) - + connector.save_caches(encoder_cache, + mock_request_with_3_mm.mm_hashes[1]) + # Test result = connector.has_caches(mock_request_with_3_mm) - + # Assert assert len(result) == 3 - assert result[0] == False # First doesn't exist - assert result[1] == True # Second exists - assert result[2] == False # Third doesn't exist + assert not result[0] # First doesn't exist + assert result[1] # Second exists + assert not result[2] # Third doesn't exist + class TestStateManagement: """Test connector state management.""" def test_update_state_after_alloc_3_items(self, mock_vllm_config_producer, - mock_request_with_3_mm): + mock_request_with_3_mm): """Test state update after allocation for 3 MM items.""" connector = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + # Initial state should be empty assert len(connector._mm_datas_need_loads) == 0 - + # Update state for all 3 items for i in range(3): connector.update_state_after_alloc(mock_request_with_3_mm, index=i) - + # Check state updated for all 3 assert len(connector._mm_datas_need_loads) == 3 assert "img_hash_1" in connector._mm_datas_need_loads @@ -204,15 +215,15 @@ def test_build_connector_meta_3_items(self, mock_vllm_config_producer, vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + # Setup state for all 3 items for i in range(3): connector.update_state_after_alloc(mock_request_with_3_mm, index=i) - + # Build metadata scheduler_output = Mock(spec=SchedulerOutput) metadata = connector.build_connector_meta(scheduler_output) - + # Assert assert isinstance(metadata, ECSharedStorageConnectorMetadata) assert len(metadata.mm_datas) == 3 @@ -222,7 +233,7 @@ def test_build_connector_meta_3_items(self, mock_vllm_config_producer, assert metadata.mm_datas[1].num_token == 150 assert metadata.mm_datas[2].mm_hash == "audio_hash_1" assert metadata.mm_datas[2].num_token == 200 - + # State should be cleared after building assert len(connector._mm_datas_need_loads) == 0 @@ -232,67 +243,70 @@ def test_build_connector_meta_empty(self, mock_vllm_config_producer): vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + scheduler_output = Mock(spec=SchedulerOutput) metadata = connector.build_connector_meta(scheduler_output) - + assert isinstance(metadata, ECSharedStorageConnectorMetadata) assert len(metadata.mm_datas) == 0 - def test_state_cleared_after_metadata_build(self, mock_vllm_config_producer, - mock_request_with_3_mm): + def test_state_cleared_after_metadata_build(self, + mock_vllm_config_producer, + mock_request_with_3_mm): """Test that state is properly cleared after building metadata.""" connector = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + # Add state for i in range(3): connector.update_state_after_alloc(mock_request_with_3_mm, index=i) assert len(connector._mm_datas_need_loads) == 3 - + # Build metadata (should clear state) scheduler_output = Mock(spec=SchedulerOutput) connector.build_connector_meta(scheduler_output) - + # State should be empty assert len(connector._mm_datas_need_loads) == 0 - + # Build again should return empty metadata metadata2 = connector.build_connector_meta(scheduler_output) assert len(metadata2.mm_datas) == 0 + class TestCacheSaving: """Test encoder cache saving (producer only).""" def test_save_caches_producer_3_items(self, mock_vllm_config_producer, - mock_request_with_3_mm, temp_storage): + mock_request_with_3_mm, + temp_storage): """Test cache saving as producer for 3 different MM items.""" connector = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.WORKER, ) - + # Create and save 3 different caches mm_hashes = mock_request_with_3_mm.mm_hashes - encoder_cache = {} - + encoder_cache: dict[str, torch.Tensor] = {} + for mm_hash in mm_hashes: encoder_cache[mm_hash] = torch.randn(10, 768) connector.save_caches(encoder_cache, mm_hash) - + # Verify all files exist using has_caches result = connector.has_caches(mock_request_with_3_mm) assert all(result), f"Not all caches were saved: {result}" - + # Verify each file's content for mm_hash in mm_hashes: filename = connector._generate_filename_debug(mm_hash) loaded = safetensors.torch.load_file(filename) assert "ec_cache" in loaded - assert torch.allclose(loaded["ec_cache"], - encoder_cache[mm_hash].cpu()) + assert torch.allclose(loaded["ec_cache"], + encoder_cache[mm_hash].cpu()) def test_save_caches_consumer_skips(self, mock_vllm_config_consumer): """Test cache saving is skipped for consumer.""" @@ -300,100 +314,105 @@ def test_save_caches_consumer_skips(self, mock_vllm_config_consumer): vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + mm_hash = "test_hash_consumer" encoder_cache = {mm_hash: torch.randn(10, 768)} - + # Save should not raise but also not create file connector.save_caches(encoder_cache, mm_hash) - + # Verify file doesn't exist using has_caches mock_request = Mock() mock_request.mm_hashes = [mm_hash] result = connector.has_caches(mock_request) - assert result[0] == False, "Consumer should not save caches" + assert not result[0], "Consumer should not save caches" + class TestCacheLoading: """Test encoder cache loading (consumer).""" @pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA not available") - def test_start_load_caches_consumer_3_items(self, mock_vllm_config_producer, - mock_vllm_config_consumer, mock_request_with_3_mm, - temp_storage): + def test_start_load_caches_consumer_3_items(self, + mock_vllm_config_producer, + mock_vllm_config_consumer, + mock_request_with_3_mm, + temp_storage): """Test consumer loads 3 caches from storage.""" - # First, create producer to save caches + # First, create producer to save caches producer = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.WORKER, ) - + # Producer saves 3 caches mm_hashes = mock_request_with_3_mm.mm_hashes saved_caches = {} for mm_hash in mm_hashes: saved_caches[mm_hash] = torch.randn(10, 768) producer.save_caches(saved_caches, mm_hash) - + # Now consumer loads consumer = ECSharedStorageConnector( vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + # Setup metadata for all 3 metadata = ECSharedStorageConnectorMetadata() for mm_hash in mm_hashes: metadata.add_mm_data(MMMeta.make_meta(mm_hash, 100)) consumer.bind_connector_metadata(metadata) - + # Load - encoder_cache = {} + encoder_cache: dict[str, torch.Tensor] = {} consumer.start_load_caches(encoder_cache=encoder_cache) - + # Verify all 3 loaded assert len(encoder_cache) == 3 for mm_hash in mm_hashes: - assert mm_hash in encoder_cache, f"{mm_hash} missing in encoder_cache" - assert encoder_cache[mm_hash].is_cuda, f"{mm_hash} cache is in {encoder_cache[mm_hash].device}" + assert mm_hash in encoder_cache,\ + f"{mm_hash} missing in encoder_cache" + assert encoder_cache[mm_hash].is_cuda,\ + f"{mm_hash} cache is in {encoder_cache[mm_hash].device}" assert torch.allclose( - encoder_cache[mm_hash].cpu(), - saved_caches[mm_hash] + encoder_cache[mm_hash].cpu(), saved_caches[mm_hash] ), f"{mm_hash} cache saved and loaded tesnor are not the same" def test_start_load_caches_skip_existing(self, mock_vllm_config_producer, - mock_vllm_config_consumer, temp_storage): + mock_vllm_config_consumer, + temp_storage): """Test cache loading skips already cached items.""" # Setup: producer saves cache producer = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.WORKER, ) - + mm_hash = "existing_hash" saved_cache = torch.randn(10, 768) producer.save_caches({mm_hash: saved_cache}, mm_hash) - + # Consumer setup consumer = ECSharedStorageConnector( vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + metadata = ECSharedStorageConnectorMetadata() metadata.add_mm_data(MMMeta.make_meta(mm_hash, 100)) consumer.bind_connector_metadata(metadata) - + # Pre-populate encoder_cache with different value existing_cache = torch.randn(5, 512) encoder_cache = {mm_hash: existing_cache} - + # Load (should skip since already exists) with patch('safetensors.torch.load_file') as mock_load: consumer.start_load_caches(encoder_cache=encoder_cache) # Should not call load_file since cache exists mock_load.assert_not_called() - + # Verify original cache unchanged assert torch.equal(encoder_cache[mm_hash], existing_cache) @@ -403,32 +422,33 @@ def test_start_load_caches_empty_metadata(self, mock_vllm_config_consumer): vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + # Setup empty metadata metadata = ECSharedStorageConnectorMetadata() consumer.bind_connector_metadata(metadata) - + # Load (should not raise) - encoder_cache = {} + encoder_cache: dict[str, torch.Tensor] = {} consumer.start_load_caches(encoder_cache=encoder_cache) - + # Cache should remain empty assert len(encoder_cache) == 0 + class TestFilenameGeneration: """Test filename and path generation.""" def test_generate_foldername(self, mock_vllm_config_producer, - temp_storage): + temp_storage): """Test folder name generation.""" connector = ECSharedStorageConnector( vllm_config=mock_vllm_config_producer, role=ECConnectorRole.WORKER, ) - + mm_hash = "test_folder_hash" folder = connector._generate_foldername_debug(mm_hash) - + assert folder == os.path.join(temp_storage, mm_hash) assert os.path.isdir(folder) # Should be created @@ -438,10 +458,10 @@ def test_generate_filename(self, mock_vllm_config_producer, temp_storage): vllm_config=mock_vllm_config_producer, role=ECConnectorRole.WORKER, ) - + mm_hash = "test_file_hash" filename = connector._generate_filename_debug(mm_hash) - + expected = os.path.join(temp_storage, mm_hash, "encoder_cache.safetensors") assert filename == expected @@ -453,13 +473,14 @@ def test_generate_filename_consistency(self, mock_vllm_config_producer): vllm_config=mock_vllm_config_producer, role=ECConnectorRole.WORKER, ) - + mm_hash = "consistency_hash" filename1 = connector._generate_filename_debug(mm_hash) filename2 = connector._generate_filename_debug(mm_hash) - + assert filename1 == filename2 + class TestMetadataBindingLifecycle: """Test metadata binding and clearing lifecycle.""" @@ -469,12 +490,12 @@ def test_bind_connector_metadata(self, mock_vllm_config_consumer): vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + metadata = ECSharedStorageConnectorMetadata() metadata.add_mm_data(MMMeta.make_meta("hash_1", 100)) - + connector.bind_connector_metadata(metadata) - + assert connector._connector_metadata is metadata def test_clear_connector_metadata(self, mock_vllm_config_consumer): @@ -483,12 +504,12 @@ def test_clear_connector_metadata(self, mock_vllm_config_consumer): vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + metadata = ECSharedStorageConnectorMetadata() connector.bind_connector_metadata(metadata) - + connector.clear_connector_metadata() - + assert connector._connector_metadata is None def test_get_connector_metadata(self, mock_vllm_config_consumer): @@ -497,12 +518,12 @@ def test_get_connector_metadata(self, mock_vllm_config_consumer): vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + metadata = ECSharedStorageConnectorMetadata() connector.bind_connector_metadata(metadata) - + retrieved = connector._get_connector_metadata() - + assert retrieved is metadata def test_get_connector_metadata_not_set(self, mock_vllm_config_consumer): @@ -511,10 +532,11 @@ def test_get_connector_metadata_not_set(self, mock_vllm_config_consumer): vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + with pytest.raises(AssertionError): connector._get_connector_metadata() + class TestEdgeCases: """Test edge cases and error handling.""" @@ -524,10 +546,10 @@ def test_save_empty_cache(self, mock_vllm_config_producer): vllm_config=mock_vllm_config_producer, role=ECConnectorRole.WORKER, ) - + mm_hash = "empty_hash" encoder_cache = {mm_hash: torch.empty(0)} - + # Should not raise connector.save_caches(encoder_cache, mm_hash) @@ -537,13 +559,13 @@ def test_load_nonexistent_cache(self, mock_vllm_config_consumer): vllm_config=mock_vllm_config_consumer, role=ECConnectorRole.WORKER, ) - + metadata = ECSharedStorageConnectorMetadata() metadata.add_mm_data(MMMeta.make_meta("nonexistent_hash", 100)) connector.bind_connector_metadata(metadata) - - encoder_cache = {} - + + encoder_cache: dict[str, torch.Tensor] = {} + # Should raise FileNotFoundError with pytest.raises(FileNotFoundError): connector.start_load_caches(encoder_cache=encoder_cache) @@ -554,11 +576,11 @@ def test_has_caches_empty_request(self, mock_vllm_config_producer): vllm_config=mock_vllm_config_producer, role=ECConnectorRole.SCHEDULER, ) - + mock_request = Mock() mock_request.mm_hashes = [] - + result = connector.has_caches(mock_request) - + assert len(result) == 0 assert result == [] diff --git a/vllm/config/__init__.py b/vllm/config/__init__.py index bf15a92d4dc5..fd9ab2a626bd 100644 --- a/vllm/config/__init__.py +++ b/vllm/config/__init__.py @@ -3196,9 +3196,12 @@ def _parse_collect_detailed_traces(self): list[DetailedTraceModules], self.collect_detailed_traces[0].split(",")) + ECProducer = Literal["ec_producer"] ECConsumer = Literal["ec_consumer"] ECRole = Literal[ECProducer, ECConsumer] + + @config @dataclass class ECTransferConfig: @@ -3294,6 +3297,7 @@ def is_ec_consumer(self) -> bool: def get_from_extra_config(self, key, default) -> Any: return self.ec_connector_extra_config.get(key, default) + KVProducer = Literal["kv_producer", "kv_both"] KVConsumer = Literal["kv_consumer", "kv_both"] KVRole = Literal[KVProducer, KVConsumer] @@ -3491,7 +3495,7 @@ class VllmConfig: ec_transfer_config: Optional[ECTransferConfig] = None """The configurations for distributed EC cache transfer.""" - + # some opaque config, only used to provide additional information # for the hash computation, mainly used for testing, debugging or out of # tree config registration. diff --git a/vllm/distributed/ec_transfer/__init__.py b/vllm/distributed/ec_transfer/__init__.py index 8320564818e3..9fb784268183 100644 --- a/vllm/distributed/ec_transfer/__init__.py +++ b/vllm/distributed/ec_transfer/__init__.py @@ -2,12 +2,10 @@ # SPDX-FileCopyrightText: Copyright contributors to the vLLM project from vllm.distributed.ec_transfer.ec_transfer_state import ( - get_ec_transfer, - ensure_ec_transfer_initialized, - has_ec_transfer) + ensure_ec_transfer_initialized, get_ec_transfer, has_ec_transfer) __all__ = [ - "get_ec_transfer", + "get_ec_transfer", "ensure_ec_transfer_initialized", - "has_ec_transfer", + "has_ec_transfer", ] diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 54b5cda2afd1..3b87d6ab4028 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -1,7 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project """ -ECConnectorBase Class for Distributed Encoder Cache & P2P Encoder cache communication in V1 +ECConnectorBase Class for Distributed Encoder Cache & +P2P Encoder cache communication in V1 The class provides the following primitives: Scheduler-side: runs in the scheduler, binds metadata, which @@ -9,8 +10,8 @@ check_caches_exist() - Check whether Encoder cache of requests exist update_state_after_alloc() - update ECConnector state after allocate. This will decide to load the cache or not - request_finished() - called when a request is finished, free the cache with - the requests + request_finished() - called when a request is finished, + free the cache with the requests Worker-side: runs in each worker, loads/saves Encoder Cache to/from the Connector based on the metadata. @@ -23,21 +24,16 @@ import enum from abc import ABC, abstractmethod -from collections.abc import Iterable -from typing import TYPE_CHECKING, Any, Callable, Literal, Optional +from typing import TYPE_CHECKING, Any, Optional import torch from vllm.logger import init_logger from vllm.v1.core.sched.output import SchedulerOutput -from vllm.v1.outputs import (KVConnectorOutput, ECConnectorOutput) +from vllm.v1.outputs import ECConnectorOutput if TYPE_CHECKING: - from vllm.attention.backends.abstract import AttentionMetadata from vllm.config import VllmConfig - from vllm.distributed.kv_events import KVCacheEvent - from vllm.forward_context import ForwardContext - from vllm.v1.core.kv_cache_manager import KVCacheBlocks from vllm.v1.request import Request logger = init_logger(__name__) @@ -113,7 +109,10 @@ def _get_connector_metadata(self) -> ECConnectorMetadata: assert self._connector_metadata is not None return self._connector_metadata - def register_caches(self, ec_caches: dict[str, torch.Tensor],): + def register_caches( + self, + ec_caches: dict[str, torch.Tensor], + ): """ Initialize with the EC caches. Args: @@ -219,11 +218,9 @@ def update_connector_output(self, connector_output: ECConnectorOutput): return def request_finished( - self, - request: "Request" - ) -> tuple[bool, Optional[dict[str, Any]]]: + self, request: "Request") -> tuple[bool, Optional[dict[str, Any]]]: """ - Called when a request has finished, before its freed the local encoder cached. + Called when a request has finished, before its encoder cache is freed. Returns: True if the request is being saved/sent asynchronously and cached @@ -231,4 +228,3 @@ def request_finished( get_finished(). """ return False, None - diff --git a/vllm/distributed/ec_transfer/ec_connector/factory.py b/vllm/distributed/ec_transfer/ec_connector/factory.py index 0bca7e2a30d5..3d9030686c2a 100644 --- a/vllm/distributed/ec_transfer/ec_connector/factory.py +++ b/vllm/distributed/ec_transfer/ec_connector/factory.py @@ -5,8 +5,8 @@ from typing import TYPE_CHECKING, Callable # yapf: disable -import vllm.envs as envs -from vllm.distributed.ec_transfer.ec_connector.base import (ECConnectorRole,ECConnectorBase) +from vllm.distributed.ec_transfer.ec_connector.base import (ECConnectorBase, + ECConnectorRole) from vllm.logger import init_logger # yapf: enable @@ -53,8 +53,8 @@ def create_connector( @classmethod def get_connector_class( - cls, ec_transfer_config: "ECTransferConfig" - ) -> type[ECConnectorBase]: + cls, + ec_transfer_config: "ECTransferConfig") -> type[ECConnectorBase]: """Get the connector class by name.""" connector_name = ec_transfer_config.ec_connector if connector_name in cls._registry: @@ -77,4 +77,3 @@ def get_connector_class( "ECSharedStorageConnector", "vllm.distributed.ec_transfer.ec_connector.shared_storage_connector", "ECSharedStorageConnector") - diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 512953b3eed0..3e6c35744c4e 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -1,12 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project -import hashlib import os from dataclasses import dataclass from typing import TYPE_CHECKING import safetensors -import torch from vllm.config import VllmConfig from vllm.distributed.ec_transfer.ec_connector.base import ( @@ -15,7 +13,6 @@ from vllm.v1.core.sched.output import SchedulerOutput if TYPE_CHECKING: - from vllm.forward_context import ForwardContext from vllm.v1.request import Request logger = init_logger(__name__) @@ -28,12 +25,8 @@ class MMMeta: @staticmethod def make_meta(mm_hash, num_token) -> "MMMeta": - return MMMeta( - mm_hash=mm_hash, - num_token=num_token - ) + return MMMeta(mm_hash=mm_hash, num_token=num_token) - @dataclass class ECSharedStorageConnectorMetadata(ECConnectorMetadata): @@ -42,7 +35,7 @@ class ECSharedStorageConnectorMetadata(ECConnectorMetadata): def __init__(self): self.mm_datas = [] - def add_mm_data(self, mm_data:MMMeta): + def add_mm_data(self, mm_data: MMMeta): self.mm_datas.append(mm_data) @@ -55,7 +48,8 @@ def __init__(self, vllm_config: "VllmConfig", role: ECConnectorRole): # req_id -> index self._mm_datas_need_loads: dict[str, int] = {} transfer_config = vllm_config.ec_transfer_config - self._storage_path = transfer_config.get_from_extra_config("shared_storage_path", "/tmp") + self._storage_path = transfer_config.get_from_extra_config( + "shared_storage_path", "/tmp") logger.debug(transfer_config) logger.debug("Shared storage path is %s", self._storage_path) @@ -67,24 +61,24 @@ def start_load_caches(self, **kwargs) -> None: **kwargs: additional arguments for the load operation """ - # Get the metadata + # Get the metadata metadata: ECConnectorMetadata = self._get_connector_metadata() assert isinstance(metadata, ECSharedStorageConnectorMetadata) - encoder_cache = kwargs.get("encoder_cache") # returns None if missing + encoder_cache = kwargs.get("encoder_cache") # returns None if missing assert encoder_cache is not None if metadata is None: - logger.warning( - "In connector.start_load_caches, but the connector metadata is None" - ) + logger.warning(("In connector.start_load_caches, ", + "but the connector metadata is None")) return - # Load the EC for each mm datas + # Load the EC for each mm data for mm_data in metadata.mm_datas: if mm_data.mm_hash in encoder_cache: continue filename = self._generate_filename_debug(mm_data.mm_hash) ec_cache = safetensors.torch.load_file(filename)["ec_cache"].cuda() encoder_cache[mm_data.mm_hash] = ec_cache - logger.debug(f"Success load encoder cache for hash {mm_data.mm_hash}") + logger.debug("Success load encoder cache for hash %s", + mm_data.mm_hash) def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: """Start saving the EC cache for each mm_datas from encoder cache @@ -99,7 +93,7 @@ def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: ec_cache = encoder_cache[mm_hash] tensors = {"ec_cache": ec_cache.detach().cpu()} safetensors.torch.save_file(tensors, filename) - logger.debug(f"Save cache successful for mm_hash {mm_hash}") + logger.debug("Save cache successful for mm_hash %s", mm_hash) def has_caches( self, @@ -119,10 +113,11 @@ def has_caches( result.append(self._found_match_for_mm_data(mm_hash)) return result - def update_state_after_alloc(self, - request: "Request", - index: int, - ) -> None: + def update_state_after_alloc( + self, + request: "Request", + index: int, + ) -> None: """ Update ECConnector state after encoder cache allocation. """ @@ -153,19 +148,16 @@ def build_connector_meta( # Helper functions # ============================== - def _found_match_for_mm_data( - self, - mm_hash - ) -> bool: + def _found_match_for_mm_data(self, mm_hash) -> bool: """Check if the cache is hit for the request. """ filename = self._generate_filename_debug(mm_hash) return os.path.exists(filename) def _generate_foldername_debug( - self, - mm_hash: str, - create_folder: bool = True, # <- now defaults to True + self, + mm_hash: str, + create_folder: bool = True, # <- now defaults to True ) -> str: """ Return the folder in which the cache for this mm_hash lives. @@ -184,6 +176,6 @@ def _generate_filename_debug(self, mm_hash: str) -> str: `_generate_foldername_debug` is called with its default (`create_folder=True`). """ - foldername = self._generate_foldername_debug(mm_hash) # <- folder auto-created + foldername = self._generate_foldername_debug( + mm_hash) # <- folder auto-created return os.path.join(foldername, "encoder_cache.safetensors") - diff --git a/vllm/distributed/ec_transfer/ec_transfer_state.py b/vllm/distributed/ec_transfer/ec_transfer_state.py index 8f35c25f1c3d..91a8c80d1e96 100644 --- a/vllm/distributed/ec_transfer/ec_transfer_state.py +++ b/vllm/distributed/ec_transfer/ec_transfer_state.py @@ -23,13 +23,14 @@ def get_ec_transfer() -> ECConnectorBase: def has_ec_transfer() -> bool: return _EC_CONNECTOR_AGENT is not None + def ensure_ec_transfer_initialized(vllm_config: "VllmConfig") -> None: """ Initialize EC cache connector. """ global _EC_CONNECTOR_AGENT - + if vllm_config.ec_transfer_config is None: return diff --git a/vllm/engine/arg_utils.py b/vllm/engine/arg_utils.py index 53ff59c56542..d2a864e564a1 100644 --- a/vllm/engine/arg_utils.py +++ b/vllm/engine/arg_utils.py @@ -24,15 +24,16 @@ from vllm.config import (BlockSize, CacheConfig, CacheDType, CompilationConfig, ConfigFormat, ConfigType, ConvertOption, DecodingConfig, DetailedTraceModules, Device, - DeviceConfig, DistributedExecutorBackend, ECTransferConfig, EPLBConfig, - GuidedDecodingBackend, HfOverrides, KVEventsConfig, - KVTransferConfig, LoadConfig, LogprobsMode, - LoRAConfig, MambaDType, MMEncoderTPMode, ModelConfig, - ModelDType, ModelImpl, MultiModalConfig, - ObservabilityConfig, ParallelConfig, PoolerConfig, - PrefixCachingHashAlgo, RunnerOption, SchedulerConfig, - SchedulerPolicy, SpeculativeConfig, TaskOption, - TokenizerMode, VllmConfig, get_attr_docs, get_field) + DeviceConfig, DistributedExecutorBackend, + ECTransferConfig, EPLBConfig, GuidedDecodingBackend, + HfOverrides, KVEventsConfig, KVTransferConfig, + LoadConfig, LogprobsMode, LoRAConfig, MambaDType, + MMEncoderTPMode, ModelConfig, ModelDType, ModelImpl, + MultiModalConfig, ObservabilityConfig, ParallelConfig, + PoolerConfig, PrefixCachingHashAlgo, RunnerOption, + SchedulerConfig, SchedulerPolicy, SpeculativeConfig, + TaskOption, TokenizerMode, VllmConfig, get_attr_docs, + get_field) from vllm.logger import init_logger from vllm.platforms import CpuArchEnum, current_platform from vllm.plugins import load_general_plugins @@ -888,11 +889,11 @@ def add_cli_args(parser: FlexibleArgumentParser) -> FlexibleArgumentParser: vllm_group.add_argument("--speculative-config", **vllm_kwargs["speculative_config"]) vllm_group.add_argument("--kv-transfer-config", - **vllm_kwargs["kv_transfer_config"]) + **vllm_kwargs["kv_transfer_config"]) vllm_group.add_argument('--kv-events-config', **vllm_kwargs["kv_events_config"]) vllm_group.add_argument("--ec-transfer-config", - **vllm_kwargs["ec_transfer_config"]) + **vllm_kwargs["ec_transfer_config"]) vllm_group.add_argument("--compilation-config", "-O", **vllm_kwargs["compilation_config"]) vllm_group.add_argument("--additional-config", diff --git a/vllm/v1/core/sched/output.py b/vllm/v1/core/sched/output.py index 5894dcd36f25..67c0dda9a77c 100644 --- a/vllm/v1/core/sched/output.py +++ b/vllm/v1/core/sched/output.py @@ -6,16 +6,14 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Optional - - if TYPE_CHECKING: import numpy as np import numpy.typing as npt - from vllm.distributed.kv_transfer.kv_connector.v1.base import ( - KVConnectorMetadata) from vllm.distributed.ec_transfer.ec_connector.base import ( ECConnectorMetadata) + from vllm.distributed.kv_transfer.kv_connector.v1.base import ( + KVConnectorMetadata) from vllm.lora.request import LoRARequest from vllm.multimodal.inputs import MultiModalKwargsItem, PlaceholderRange from vllm.pooling_params import PoolingParams @@ -159,6 +157,6 @@ class SchedulerOutput: # KV Cache Connector metadata. kv_connector_metadata: Optional[KVConnectorMetadata] = None - + # EC Cache Connector metadata ec_connector_metadata: Optional[ECConnectorMetadata] = None diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index fa1f90f5e687..5e72e4bc7df1 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -11,7 +11,8 @@ from vllm.config import VllmConfig from vllm.distributed.ec_transfer.ec_connector.base import ECConnectorRole -from vllm.distributed.ec_transfer.ec_connector.factory import ECConnectorFactory +from vllm.distributed.ec_transfer.ec_connector.factory import ( + ECConnectorFactory) from vllm.distributed.kv_events import EventPublisherFactory, KVEventBatch from vllm.distributed.kv_transfer.kv_connector.factory import ( KVConnectorFactory) @@ -99,8 +100,7 @@ def __init__( self.ec_connector = None if self.vllm_config.ec_transfer_config is not None: self.ec_connector = ECConnectorFactory.create_connector( - config=self.vllm_config, role=ECConnectorRole.SCHEDULER - ) + config=self.vllm_config, role=ECConnectorRole.SCHEDULER) num_gpu_blocks = self.cache_config.num_gpu_blocks assert num_gpu_blocks is not None and num_gpu_blocks > 0 @@ -222,7 +222,7 @@ def schedule(self) -> SchedulerOutput: # Schedule encoder inputs. encoder_inputs_to_schedule = None - external_load_encoder_input = [] + external_load_encoder_input: list[int] = [] new_encoder_compute_budget = encoder_compute_budget if request.has_encoder_inputs: (encoder_inputs_to_schedule, num_new_tokens, @@ -317,7 +317,8 @@ def schedule(self) -> SchedulerOutput: if external_load_encoder_input: for i in external_load_encoder_input: self.encoder_cache_manager.allocate(request, i) - self.ec_connector.update_state_after_alloc(request, i) + if self.ec_connector is not None: + self.ec_connector.update_state_after_alloc(request, i) # Record the LoRAs in scheduled_running_reqs scheduled_loras: set[int] = set() @@ -433,7 +434,8 @@ def schedule(self) -> SchedulerOutput: # Schedule encoder inputs. if request.has_encoder_inputs: (encoder_inputs_to_schedule, num_new_tokens, - new_encoder_compute_budget, external_load_encoder_input + new_encoder_compute_budget, + external_load_encoder_input ) = self._try_schedule_encoder_inputs( request, num_computed_tokens, num_new_tokens, encoder_compute_budget) @@ -537,7 +539,9 @@ def schedule(self) -> SchedulerOutput: if external_load_encoder_input: for i in external_load_encoder_input: self.encoder_cache_manager.allocate(request, i) - self.ec_connector.update_state_after_alloc(request, i) + if self.ec_connector is not None: + self.ec_connector.update_state_after_alloc( + request, i) # Put back any skipped requests at the head of the waiting queue if skipped_waiting_requests: self.waiting.prepend_requests(skipped_waiting_requests) @@ -606,7 +610,7 @@ def schedule(self) -> SchedulerOutput: if self.connector is not None: meta = self.connector.build_connector_meta(scheduler_output) scheduler_output.kv_connector_metadata = meta - + events = self.kv_cache_manager.take_events() if events: batch = KVEventBatch(ts=time.time(), events=events) @@ -618,7 +622,7 @@ def schedule(self) -> SchedulerOutput: self._update_after_schedule(scheduler_output) return scheduler_output - + def _update_after_schedule( self, scheduler_output: SchedulerOutput, @@ -811,23 +815,18 @@ def _try_schedule_encoder_inputs( num_new_tokens = 0 break - if self.ec_connector is not None: - if remote_cache_has_item[i]: - mm_hashes_to_schedule.add(request.mm_hashes[i]) - external_load_encoder_input.append(i) - continue + if self.ec_connector is not None and remote_cache_has_item[i]: + mm_hashes_to_schedule.add(request.mm_hashes[i]) + external_load_encoder_input.append(i) + continue num_tokens_to_schedule += num_encoder_tokens encoder_compute_budget -= num_encoder_tokens mm_hashes_to_schedule.add(request.mm_hashes[i]) encoder_inputs_to_schedule.append(i) - return ( - encoder_inputs_to_schedule, - num_new_tokens, - encoder_compute_budget, - external_load_encoder_input - ) + return (encoder_inputs_to_schedule, num_new_tokens, + encoder_compute_budget, external_load_encoder_input) def get_grammar_bitmask( self, diff --git a/vllm/v1/outputs.py b/vllm/v1/outputs.py index aab17993d70a..fd980894a03b 100644 --- a/vllm/v1/outputs.py +++ b/vllm/v1/outputs.py @@ -5,6 +5,7 @@ from typing import NamedTuple, Optional import torch + from vllm.v1.core.sched.output import SchedulerOutput @@ -78,6 +79,7 @@ class KVConnectorOutput: finished_sending: Optional[set[str]] = None finished_recving: Optional[set[str]] = None + @dataclass class ECConnectorOutput: # [mm_hash] @@ -131,9 +133,9 @@ class DraftTokenIds: # num_reqs x num_draft_tokens draft_token_ids: list[list[int]] + def make_empty_encoder_model_runner_output( - scheduler_output: "SchedulerOutput", -) -> ModelRunnerOutput: + scheduler_output: "SchedulerOutput", ) -> ModelRunnerOutput: """ Create a ModelRunnerOutput stub that contains the correct per-request bookkeeping but no generated data yet. @@ -145,7 +147,10 @@ def make_empty_encoder_model_runner_output( req_ids: list[str] = list(scheduler_output.num_scheduled_tokens.keys()) # Give every request its own contiguous index - req_id_to_index: dict[str, int] = {rid: idx for idx, rid in enumerate(req_ids)} + req_id_to_index: dict[str, int] = { + rid: idx + for idx, rid in enumerate(req_ids) + } # No tokens generated yet ⇒ one empty list per request sampled_token_ids: list[list[int]] = [[0] for _ in req_ids] @@ -165,6 +170,7 @@ def make_empty_encoder_model_runner_output( num_nans_in_logits=None, ) + EMPTY_MODEL_RUNNER_OUTPUT = ModelRunnerOutput(req_ids=[], req_id_to_index={}, sampled_token_ids=[], diff --git a/vllm/v1/worker/ec_connector_model_runner_mixin.py b/vllm/v1/worker/ec_connector_model_runner_mixin.py index 8827bcfc8a98..24d65b3665cf 100644 --- a/vllm/v1/worker/ec_connector_model_runner_mixin.py +++ b/vllm/v1/worker/ec_connector_model_runner_mixin.py @@ -3,18 +3,17 @@ """ Define EC connector functionality mixin for model runners. """ -import copy from contextlib import AbstractContextManager, contextmanager, nullcontext from typing import Generator # noqa: UP035 from typing import TYPE_CHECKING, Optional -from vllm.config import VllmConfig -from vllm.distributed.ec_transfer import (get_ec_transfer, - has_ec_transfer) +import torch + +from vllm.distributed.ec_transfer import get_ec_transfer, has_ec_transfer from vllm.distributed.ec_transfer.ec_connector.base import ECConnectorBase from vllm.logger import init_logger from vllm.v1.outputs import ECConnectorOutput -import torch + if TYPE_CHECKING: from vllm.v1.core.sched.output import SchedulerOutput @@ -23,7 +22,7 @@ # Defined as a EC connector functionality mixin for ModelRunner (GPU, TPU) class ECConnectorModelRunnerMixin: - + @staticmethod def maybe_save_ec_to_connector( encoder_cache: dict[str, torch.Tensor], @@ -33,7 +32,7 @@ def maybe_save_ec_to_connector( logger.debug("Not have ec transfer please check") return connector = get_ec_transfer() - connector.save_caches(encoder_cache=encoder_cache,mm_hash=mm_hash) + connector.save_caches(encoder_cache=encoder_cache, mm_hash=mm_hash) @staticmethod def get_finished_ec_transfers( @@ -50,7 +49,8 @@ def maybe_get_ec_connector_output( **kwargs, ) -> AbstractContextManager[Optional[ECConnectorOutput]]: return ECConnectorModelRunnerMixin._get_ec_connector_output( - scheduler_output, **kwargs) if has_ec_transfer() else nullcontext() + scheduler_output, ** + kwargs) if has_ec_transfer() else nullcontext() # This context manager must be used within an active forward context. # It encapsulates the entire EC conector lifecycle within execute_model diff --git a/vllm/v1/worker/gpu_model_runner.py b/vllm/v1/worker/gpu_model_runner.py index 1ad01b41af9a..4b7c9df6b2cb 100644 --- a/vllm/v1/worker/gpu_model_runner.py +++ b/vllm/v1/worker/gpu_model_runner.py @@ -23,13 +23,12 @@ from vllm.compilation.counter import compilation_counter from vllm.compilation.cuda_graph import CUDAGraphWrapper from vllm.compilation.monitor import set_cudagraph_capturing_enabled -from vllm.config import (CompilationLevel, CUDAGraphMode, ECProducer, VllmConfig, +from vllm.config import (CompilationLevel, CUDAGraphMode, VllmConfig, get_layers_from_vllm_config, update_config) +from vllm.distributed.ec_transfer import get_ec_transfer, has_ec_transfer from vllm.distributed.eplb.eplb_state import EplbState from vllm.distributed.kv_transfer import (get_kv_transfer_group, has_kv_transfer_group) -from vllm.distributed.ec_transfer import (get_ec_transfer, - has_ec_transfer) from vllm.distributed.parallel_state import ( get_pp_group, get_tp_group, graph_capture, is_global_first_rank, prepare_communication_buffer_for_model) @@ -68,8 +67,10 @@ FullAttentionSpec, KVCacheConfig, KVCacheGroupSpec, KVCacheSpec, MambaSpec, SlidingWindowSpec) -from vllm.v1.outputs import (EMPTY_MODEL_RUNNER_OUTPUT, DraftTokenIds, ECConnectorOutput, - LogprobsTensors, ModelRunnerOutput, make_empty_encoder_model_runner_output) +from vllm.v1.outputs import (EMPTY_MODEL_RUNNER_OUTPUT, DraftTokenIds, + ECConnectorOutput, LogprobsTensors, + ModelRunnerOutput, + make_empty_encoder_model_runner_output) from vllm.v1.pool.metadata import PoolingMetadata from vllm.v1.sample.logits_processor import LogitsProcessors, build_logitsprocs from vllm.v1.sample.metadata import SamplingMetadata @@ -80,7 +81,8 @@ from vllm.v1.spec_decode.metadata import SpecDecodeMetadata from vllm.v1.spec_decode.ngram_proposer import NgramProposer from vllm.v1.utils import CpuGpuBuffer -from vllm.v1.worker.ec_connector_model_runner_mixin import ECConnectorModelRunnerMixin +from vllm.v1.worker.ec_connector_model_runner_mixin import ( + ECConnectorModelRunnerMixin) from vllm.v1.worker.gpu_input_batch import CachedRequestState, InputBatch from vllm.v1.worker.kv_connector_model_runner_mixin import ( KVConnectorModelRunnerMixin, KVConnectorOutput) @@ -106,7 +108,7 @@ logger = init_logger(__name__) -class GPUModelRunner(LoRAModelRunnerMixin, KVConnectorModelRunnerMixin, +class GPUModelRunner(LoRAModelRunnerMixin, KVConnectorModelRunnerMixin, ECConnectorModelRunnerMixin): def __init__( @@ -1167,7 +1169,7 @@ def _execute_mm_encoder(self, scheduler_output: "SchedulerOutput"): output, is_embed=pos_info.is_embed, ) - logger.debug(f"Finish execute for mm hash {mm_hash}") + logger.debug("Finish execute for mm hash %s", mm_hash) self.maybe_save_ec_to_connector(self.encoder_cache, mm_hash) def _gather_mm_embeddings( @@ -1418,12 +1420,10 @@ def get_dp_padding(self, return max_tokens_across_dp_cpu - num_tokens, num_tokens_after_padding def _pool( - self, - hidden_states: torch.Tensor, - num_scheduled_tokens: int, - num_scheduled_tokens_np: np.ndarray, - kv_connector_output: Optional[KVConnectorOutput], - ec_connector_output: Optional[ECConnectorOutput] + self, hidden_states: torch.Tensor, num_scheduled_tokens: int, + num_scheduled_tokens_np: np.ndarray, + kv_connector_output: Optional[KVConnectorOutput], + ec_connector_output: Optional[ECConnectorOutput] ) -> ModelRunnerOutput: assert self.input_batch.num_reqs ==\ len(self.input_batch.pooling_params), \ @@ -1455,8 +1455,7 @@ def _pool( prompt_logprobs_dict={}, pooler_output=pooler_output, kv_connector_output=kv_connector_output, - ec_connector_output=ec_connector_output - ) + ec_connector_output=ec_connector_output) @torch.inference_mode() def execute_model( @@ -1467,15 +1466,14 @@ def execute_model( self._update_states(scheduler_output) - if has_ec_transfer(): - if get_ec_transfer().is_producer: - with self.maybe_get_ec_connector_output( - scheduler_output, - encoder_cache=self.encoder_cache, - ) as ec_connector_output: - self._execute_mm_encoder(scheduler_output) - return make_empty_encoder_model_runner_output(scheduler_output) - + if has_ec_transfer() and get_ec_transfer().is_producer: + with self.maybe_get_ec_connector_output( + scheduler_output, + encoder_cache=self.encoder_cache, + ) as ec_connector_output: + self._execute_mm_encoder(scheduler_output) + return make_empty_encoder_model_runner_output(scheduler_output) + if not scheduler_output.total_num_scheduled_tokens: if not has_kv_transfer_group(): # Return empty ModelRunnerOutput if there's no work to do. @@ -1488,7 +1486,7 @@ def execute_model( "--kv-sharing-fast-prefill produces incorrect logprobs for " "prompt tokens, tokens, please disable it when the requests " "need prompt logprobs") - + # Prepare the decoder inputs. (attn_metadata, logits_indices, spec_decode_metadata, num_scheduled_tokens_np, spec_decode_common_attn_metadata, @@ -1520,7 +1518,7 @@ def execute_model( if self.supports_mm_inputs: with self.maybe_get_ec_connector_output( scheduler_output, - encoder_cache=self.encoder_cache, + encoder_cache=self.encoder_cache, ) as ec_connector_output: # Run the multimodal encoder if any. self._execute_mm_encoder(scheduler_output) @@ -1618,7 +1616,8 @@ def execute_model( else: if self.input_batch.pooling_params: return self._pool(hidden_states, num_scheduled_tokens, - num_scheduled_tokens_np, kv_connector_output) + num_scheduled_tokens_np, kv_connector_output, + ec_connector_output) sample_hidden_states = hidden_states[logits_indices] logits = self.model.compute_logits(sample_hidden_states, None) @@ -1766,7 +1765,7 @@ def execute_model( prompt_logprobs_dict=prompt_logprobs_dict, pooler_output=[], kv_connector_output=kv_connector_output, - ec_connector_output=ec_connector_output + ec_connector_output=ec_connector_output if self.supports_mm_inputs else None, num_nans_in_logits=num_nans_in_logits, ) @@ -3192,9 +3191,8 @@ def get_kv_cache_spec(self) -> dict[str, KVCacheSpec]: format. Layers that do not need KV cache are not included. """ - if has_ec_transfer(): - if get_ec_transfer().is_producer: - return {} + if has_ec_transfer() and get_ec_transfer().is_producer: + return {} block_size = self.vllm_config.cache_config.block_size use_mla = self.vllm_config.model_config.use_mla diff --git a/vllm/v1/worker/gpu_worker.py b/vllm/v1/worker/gpu_worker.py index f282875e0244..2851aca725e2 100644 --- a/vllm/v1/worker/gpu_worker.py +++ b/vllm/v1/worker/gpu_worker.py @@ -16,8 +16,8 @@ from vllm.distributed import (ensure_model_parallel_initialized, init_distributed_environment, set_custom_all_reduce) -from vllm.distributed.kv_transfer import ensure_kv_transfer_initialized from vllm.distributed.ec_transfer import ensure_ec_transfer_initialized +from vllm.distributed.kv_transfer import ensure_kv_transfer_initialized from vllm.distributed.parallel_state import get_pp_group, get_tp_group from vllm.logger import init_logger from vllm.lora.request import LoRARequest From a08d1d5a820c1b46ac4ea4c1efa065a70c1cf264 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Fri, 17 Oct 2025 11:51:36 +0800 Subject: [PATCH 31/57] [Bugfix] Fix ec_connector_output for non multimodal model Signed-off-by: knlnguyen1802 --- vllm/v1/worker/gpu_model_runner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/vllm/v1/worker/gpu_model_runner.py b/vllm/v1/worker/gpu_model_runner.py index 4b7c9df6b2cb..f686a491621a 100644 --- a/vllm/v1/worker/gpu_model_runner.py +++ b/vllm/v1/worker/gpu_model_runner.py @@ -1515,6 +1515,7 @@ def execute_model( # _prepare_inputs may reorder the batch, so we must gather multi # modal outputs after that to ensure the correct order + ec_connector_output = None if self.supports_mm_inputs: with self.maybe_get_ec_connector_output( scheduler_output, From ff050c709aabf2eacb4ba2dcdd9a11a8bfd80ef1 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Tue, 21 Oct 2025 16:50:16 +0800 Subject: [PATCH 32/57] Fix pre-commit Signed-off-by: knlnguyen1802 --- vllm/v1/worker/gpu_model_runner.py | 1 - 1 file changed, 1 deletion(-) diff --git a/vllm/v1/worker/gpu_model_runner.py b/vllm/v1/worker/gpu_model_runner.py index feb21f21fb45..197ca2c39dad 100644 --- a/vllm/v1/worker/gpu_model_runner.py +++ b/vllm/v1/worker/gpu_model_runner.py @@ -4645,7 +4645,6 @@ def get_kv_cache_spec(self) -> dict[str, KVCacheSpec]: """ if has_ec_transfer() and get_ec_transfer().is_producer: return {} - kv_cache_spec: dict[str, KVCacheSpec] = {} attn_layers = get_layers_from_vllm_config(self.vllm_config, AttentionLayerBase) for layer_name, attn_module in attn_layers.items(): From 7968f617b9ed86bf1abe2adc1c81705a8b862e12 Mon Sep 17 00:00:00 2001 From: Khuong Le Date: Tue, 21 Oct 2025 03:28:15 -0700 Subject: [PATCH 33/57] [Misc] Fix/add documentation Signed-off-by: Khuong Le --- examples/online_serving/disaggregated_encoder/README.md | 2 +- vllm/distributed/ec_transfer/ec_connector/__init__.py | 0 vllm/model_executor/warmup/kernel_warmup.py | 4 ++++ 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 vllm/distributed/ec_transfer/ec_connector/__init__.py diff --git a/examples/online_serving/disaggregated_encoder/README.md b/examples/online_serving/disaggregated_encoder/README.md index fd11ff88ace6..60dfae24552f 100644 --- a/examples/online_serving/disaggregated_encoder/README.md +++ b/examples/online_serving/disaggregated_encoder/README.md @@ -2,7 +2,7 @@ This example contains scripts that demonstrate the disaggregated encoder (EPD) features of vLLM. -Please refer to [Disaggregated Encoder Feature](../../features/disagg_encoder.md) for the detailed explanation for the EPD features. +Please refer to [Disaggregated Encoder Feature](../../../docs/features/disagg_encoder.md) for the detailed explanation for the EPD features. ## Files diff --git a/vllm/distributed/ec_transfer/ec_connector/__init__.py b/vllm/distributed/ec_transfer/ec_connector/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/vllm/model_executor/warmup/kernel_warmup.py b/vllm/model_executor/warmup/kernel_warmup.py index 2977666133b5..2b29e0003f3d 100644 --- a/vllm/model_executor/warmup/kernel_warmup.py +++ b/vllm/model_executor/warmup/kernel_warmup.py @@ -68,6 +68,10 @@ def _is_flashinfer_backend(backend): except NotImplementedError: return False + # NOTE: we add check for empty attn_groups to avoid errors when + # deploying models such as E instances and encoder-only models. + # As for those models, worker.model_runner.attn_groups is empty. + # This change is made during EPD feature development. if ( not worker.model_runner.is_pooling_model and worker.model_runner.attn_groups From ec4e701eed6f1ee255263d4c574f61d5227a67f5 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Wed, 22 Oct 2025 09:23:17 +0800 Subject: [PATCH 34/57] Fix docs Signed-off-by: knlnguyen1802 --- vllm/distributed/ec_transfer/ec_connector/base.py | 5 ++--- .../ec_connector/shared_storage_connector.py | 13 ++++++++----- vllm/v1/worker/ec_connector_model_runner_mixin.py | 6 ++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 74eb5c2243a1..2981354de910 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -124,15 +124,14 @@ def register_caches( return @abstractmethod - def start_load_caches(self, **kwargs) -> None: + def start_load_caches(self, encoder_cache, **kwargs) -> None: """ Start loading the cache from the connector to vLLM's encoder cache. This is called before _gather_mm_embeddings for EC Connector For EC the encoder_cache and mm_hash is store in kwargs Args: - **kwargs: additional arguments for the load operation - + encoder_cache: Reference to encoder cache storage inside worker """ pass diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 8fb723ee77a0..6e91efa56630 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -60,18 +60,18 @@ def __init__(self, vllm_config: "VllmConfig", role: ECConnectorRole): else: raise ValueError("ec_transfer_config must be set for ECConnectorBase") - def start_load_caches(self, **kwargs) -> None: + def start_load_caches(self, encoder_cache, **kwargs) -> None: """Start loading the EC cache from the connector buffer to worker encoder_cache Args: - **kwargs: additional arguments for the load operation + encoder_cache (dict[str, torch.Tensor]): A dictionary that maps + mm_hash identifiers to their corresponding encoder cache tensors. """ # Get the metadata metadata: ECConnectorMetadata = self._get_connector_metadata() assert isinstance(metadata, ECSharedStorageConnectorMetadata) - encoder_cache = kwargs.get("encoder_cache") # returns None if missing assert encoder_cache is not None if metadata is None: logger.warning( @@ -91,10 +91,13 @@ def start_load_caches(self, **kwargs) -> None: logger.debug("Success load encoder cache for hash %s", mm_data.mm_hash) def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: - """Start saving the EC cache for each mm_datas from encoder cache + """ + Start saving the EC cache for each mm_data from the encoder cache. Args: - **kwargs: additional arguments for the save operation. + encoder_cache (dict[str, torch.Tensor]): A dictionary that maps + mm_hash identifiers to their corresponding encoder cache tensors. + mm_hash (str): The mm_hash identifier for the cache to be saved. """ # Return if it is PD Instance if not self.is_producer: diff --git a/vllm/v1/worker/ec_connector_model_runner_mixin.py b/vllm/v1/worker/ec_connector_model_runner_mixin.py index 09ae985dd4c3..00bc909df297 100644 --- a/vllm/v1/worker/ec_connector_model_runner_mixin.py +++ b/vllm/v1/worker/ec_connector_model_runner_mixin.py @@ -47,11 +47,12 @@ def get_finished_ec_transfers( @staticmethod def maybe_get_ec_connector_output( scheduler_output: "SchedulerOutput", + encoder_cache: dict[str, torch.Tensor], **kwargs, ) -> AbstractContextManager[ECConnectorOutput | None]: return ( ECConnectorModelRunnerMixin._get_ec_connector_output( - scheduler_output, **kwargs + scheduler_output, encoder_cache, **kwargs ) if has_ec_transfer() else nullcontext() @@ -63,6 +64,7 @@ def maybe_get_ec_connector_output( @contextmanager def _get_ec_connector_output( scheduler_output: "SchedulerOutput", + encoder_cache: dict[str, torch.Tensor], **kwargs, ) -> Generator[ECConnectorOutput, None, None]: output = ECConnectorOutput() @@ -73,7 +75,7 @@ def _get_ec_connector_output( ec_connector.bind_connector_metadata(scheduler_output.ec_connector_metadata) if not ec_connector.is_producer: - ec_connector.start_load_caches(**kwargs) + ec_connector.start_load_caches(encoder_cache, **kwargs) try: yield output From 3cc166ff97944a985845f029cc5538125441c8ac Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Wed, 22 Oct 2025 09:53:54 +0800 Subject: [PATCH 35/57] Fix test and clean code Signed-off-by: knlnguyen1802 --- tests/v1/core/test_scheduler.py | 2 +- vllm/config/vllm.py | 7 +++++-- vllm/engine/arg_utils.py | 3 ++- vllm/v1/worker/gpu_model_runner.py | 17 +++++++---------- vllm/v1/worker/gpu_worker.py | 3 +++ 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/v1/core/test_scheduler.py b/tests/v1/core/test_scheduler.py index a753bbdd1810..49e8e277da3b 100644 --- a/tests/v1/core/test_scheduler.py +++ b/tests/v1/core/test_scheduler.py @@ -21,7 +21,7 @@ PlaceholderRange, ) from vllm.sampling_params import SamplingParams, StructuredOutputsParams -from vllm.utils import sha256 +from vllm.utils.hashing import sha256 from vllm.v1.core.kv_cache_utils import get_request_block_hasher, init_none_hash from vllm.v1.core.sched.output import CachedRequestData, SchedulerOutput from vllm.v1.core.sched.scheduler import Scheduler diff --git a/vllm/config/vllm.py b/vllm/config/vllm.py index f29309fd6ea3..ba4826ccc739 100644 --- a/vllm/config/vllm.py +++ b/vllm/config/vllm.py @@ -769,10 +769,13 @@ def try_verify_and_update_config(self): "Overriding `load_format` to 'runai_streamer'" ) self.load_config.load_format = "runai_streamer" - elif self.load_config.load_format != "runai_streamer": + elif self.load_config.load_format not in ( + "runai_streamer", + "runai_streamer_sharded", + ): raise ValueError( f"To load a model from S3, 'load_format' " - f"must be 'runai_streamer', " + f"must be 'runai_streamer' or 'runai_streamer_sharded', " f"but got '{self.load_config.load_format}'. " f"Model: {self.model_config.model}" ) diff --git a/vllm/engine/arg_utils.py b/vllm/engine/arg_utils.py index c962cb328906..aa69e21c3574 100644 --- a/vllm/engine/arg_utils.py +++ b/vllm/engine/arg_utils.py @@ -1619,6 +1619,7 @@ def create_engine_config( otlp_traces_endpoint=self.otlp_traces_endpoint, collect_detailed_traces=self.collect_detailed_traces, ) + config = VllmConfig( model_config=model_config, cache_config=cache_config, @@ -1739,7 +1740,7 @@ def _set_default_args( ) -> None: """Set Default Arguments for V1 Engine.""" - # V1 always uses chunked prefills and prefix caching + # V1 uses chunked prefills and prefix caching by default # for non-pooling tasks. # For pooling tasks the default is False if model_config.runner_type != "pooling": diff --git a/vllm/v1/worker/gpu_model_runner.py b/vllm/v1/worker/gpu_model_runner.py index 197ca2c39dad..e275d3db2cff 100644 --- a/vllm/v1/worker/gpu_model_runner.py +++ b/vllm/v1/worker/gpu_model_runner.py @@ -235,9 +235,6 @@ def __init__( from vllm.model_executor.models.utils import set_cpu_offload_max_bytes set_cpu_offload_max_bytes(int(self.cache_config.cpu_offload_gb * 1024**3)) - from vllm.model_executor.layers.batch_invariant import init_batch_invariance - - init_batch_invariance() model_config = self.model_config cache_config = self.cache_config @@ -1949,15 +1946,16 @@ def get_supported_pooling_tasks(self) -> list[PoolingTask]: supported_tasks = list(model.pooler.get_supported_tasks()) - if ( - self.scheduler_config.chunked_prefill_enabled - and "encode" in supported_tasks - ): - supported_tasks.remove("encode") + if self.scheduler_config.chunked_prefill_enabled: + if "token_embed" in supported_tasks: + supported_tasks.remove("token_embed") + if "token_classify" in supported_tasks: + supported_tasks.remove("token_classify") logger.debug_once( "Chunked prefill is not supported with " - "encode task which using ALL pooling. " + "token_embed and token_classify tasks " + "which using ALL pooling. " "Please turn off chunked prefill by " "`--no-enable-chunked-prefill` before using it." ) @@ -4575,7 +4573,6 @@ def initialize_kv_cache(self, kv_cache_config: KVCacheConfig) -> None: kv_cache_config: Configuration for the KV cache, including the KV cache size of each layer """ - # TODO skip this for encoder model runner kv_cache_config = deepcopy(kv_cache_config) self.kv_cache_config = kv_cache_config self.may_add_encoder_only_layers_to_kv_cache_config() diff --git a/vllm/v1/worker/gpu_worker.py b/vllm/v1/worker/gpu_worker.py index 53c4f0586a64..712163ade036 100644 --- a/vllm/v1/worker/gpu_worker.py +++ b/vllm/v1/worker/gpu_worker.py @@ -766,6 +766,9 @@ def init_worker_distributed_environment( ) -> None: """Initialize the distributed environment.""" parallel_config = vllm_config.parallel_config + from vllm.model_executor.layers.batch_invariant import init_batch_invariance + + init_batch_invariance() set_custom_all_reduce(not parallel_config.disable_custom_all_reduce) init_distributed_environment( From 67b502e143c5c7b437226f9408c2679e49d58c66 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Wed, 22 Oct 2025 11:01:51 +0800 Subject: [PATCH 36/57] Fix docs Signed-off-by: knlnguyen1802 --- .../ec_transfer/ec_connector/base.py | 17 ++++++++++++----- .../ec_connector/shared_storage_connector.py | 8 ++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 2981354de910..fd5417a5fc6c 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -124,24 +124,31 @@ def register_caches( return @abstractmethod - def start_load_caches(self, encoder_cache, **kwargs) -> None: + def start_load_caches(self, + encoder_cache: dict[str, torch.Tensor], + **kwargs) -> None: """ Start loading the cache from the connector to vLLM's encoder cache. This is called before _gather_mm_embeddings for EC Connector For EC the encoder_cache and mm_hash is store in kwargs Args: - encoder_cache: Reference to encoder cache storage inside worker + encoder_cache (dict[str, torch.Tensor]): Reference + to encoder cache storage inside worker """ pass @abstractmethod - def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: + def save_caches(self, + encoder_cache: dict[str, torch.Tensor], + mm_hash: str, + **kwargs) -> None: """ Save caches into connector Args: - encoder_cache: Reference to encoder cache storage inside worker - mm_hash: Hash of the multimodal data + encoder_cache (dict[str, torch.Tensor]): Reference + to encoder cache storage inside worker. + mm_hash (str): Hash of the multimodal data. """ pass diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 6e91efa56630..e8035b4e99ce 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -65,8 +65,8 @@ def start_load_caches(self, encoder_cache, **kwargs) -> None: encoder_cache Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary that maps - mm_hash identifiers to their corresponding encoder cache tensors. + encoder_cache (dict[str, torch.Tensor]): Reference + to encoder cache storage inside worker. """ # Get the metadata @@ -95,8 +95,8 @@ def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: Start saving the EC cache for each mm_data from the encoder cache. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary that maps - mm_hash identifiers to their corresponding encoder cache tensors. + encoder_cache (dict[str, torch.Tensor]): Reference + to encoder cache storage inside worker. mm_hash (str): The mm_hash identifier for the cache to be saved. """ # Return if it is PD Instance From 84d99c7132a0e37035fb5a442ed45556ae00b2ee Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Wed, 22 Oct 2025 11:05:55 +0800 Subject: [PATCH 37/57] Fix docs Signed-off-by: knlnguyen1802 --- .../ec_transfer/ec_connector/base.py | 17 ++++++++--------- .../ec_connector/shared_storage_connector.py | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index fd5417a5fc6c..7eccba0bcae6 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -124,29 +124,28 @@ def register_caches( return @abstractmethod - def start_load_caches(self, - encoder_cache: dict[str, torch.Tensor], - **kwargs) -> None: + def start_load_caches( + self, encoder_cache: dict[str, torch.Tensor], **kwargs + ) -> None: """ Start loading the cache from the connector to vLLM's encoder cache. This is called before _gather_mm_embeddings for EC Connector For EC the encoder_cache and mm_hash is store in kwargs Args: - encoder_cache (dict[str, torch.Tensor]): Reference + encoder_cache (dict[str, torch.Tensor]): Reference to encoder cache storage inside worker """ pass @abstractmethod - def save_caches(self, - encoder_cache: dict[str, torch.Tensor], - mm_hash: str, - **kwargs) -> None: + def save_caches( + self, encoder_cache: dict[str, torch.Tensor], mm_hash: str, **kwargs + ) -> None: """ Save caches into connector Args: - encoder_cache (dict[str, torch.Tensor]): Reference + encoder_cache (dict[str, torch.Tensor]): Reference to encoder cache storage inside worker. mm_hash (str): Hash of the multimodal data. """ diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index e8035b4e99ce..8c910b602e84 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -65,7 +65,7 @@ def start_load_caches(self, encoder_cache, **kwargs) -> None: encoder_cache Args: - encoder_cache (dict[str, torch.Tensor]): Reference + encoder_cache (dict[str, torch.Tensor]): Reference to encoder cache storage inside worker. """ @@ -95,7 +95,7 @@ def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: Start saving the EC cache for each mm_data from the encoder cache. Args: - encoder_cache (dict[str, torch.Tensor]): Reference + encoder_cache (dict[str, torch.Tensor]): Reference to encoder cache storage inside worker. mm_hash (str): The mm_hash identifier for the cache to be saved. """ From a5fc6fe79cbee43dc45e0e527f2665aa352e4877 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Wed, 22 Oct 2025 11:48:36 +0800 Subject: [PATCH 38/57] Fix docs again Signed-off-by: knlnguyen1802 --- .../ec_transfer/ec_connector/base.py | 26 ++++++++++++------- .../ec_connector/shared_storage_connector.py | 25 ++++++++++++------ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 7eccba0bcae6..670207d30d00 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -128,13 +128,16 @@ def start_load_caches( self, encoder_cache: dict[str, torch.Tensor], **kwargs ) -> None: """ - Start loading the cache from the connector to vLLM's encoder cache. - This is called before _gather_mm_embeddings for EC Connector - For EC the encoder_cache and mm_hash is store in kwargs + Start loading the cache from the connector into vLLM's encoder cache. + + This method loads the encoder cache based on metadata provided by the scheduler. + It is called before `_gather_mm_embeddings` for the EC Connector. For EC, + the `encoder_cache` and `mm_hash` are stored in `kwargs`. Args: - encoder_cache (dict[str, torch.Tensor]): Reference - to encoder cache storage inside worker + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes + (`mm_hash`) to encoder cache tensors. + kwargs (dict): Additional keyword arguments for the connector. """ pass @@ -143,11 +146,16 @@ def save_caches( self, encoder_cache: dict[str, torch.Tensor], mm_hash: str, **kwargs ) -> None: """ - Save caches into connector + Save the encoder cache to the connector. + + This method saves the encoder cache from the worker's local storage + to shared storage or another external connector. + Args: - encoder_cache (dict[str, torch.Tensor]): Reference - to encoder cache storage inside worker. - mm_hash (str): Hash of the multimodal data. + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes + (`mm_hash`) to encoder cache tensors. + mm_hash (str): The hash of the multimodal data whose cache is being saved. + kwargs (dict): Additional keyword arguments for the connector. """ pass diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 8c910b602e84..bb9b867491d5 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -61,12 +61,17 @@ def __init__(self, vllm_config: "VllmConfig", role: ECConnectorRole): raise ValueError("ec_transfer_config must be set for ECConnectorBase") def start_load_caches(self, encoder_cache, **kwargs) -> None: - """Start loading the EC cache from the connector buffer to worker - encoder_cache + """ + Start loading the cache from the connector into vLLM's encoder cache. + + This method loads the encoder cache based on metadata provided by the scheduler. + It is called before `_gather_mm_embeddings` for the EC Connector. For EC, + the `encoder_cache` and `mm_hash` are stored in `kwargs`. Args: - encoder_cache (dict[str, torch.Tensor]): Reference - to encoder cache storage inside worker. + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes + (`mm_hash`) to encoder cache tensors. + kwargs (dict): Additional keyword arguments for the connector. """ # Get the metadata @@ -92,12 +97,16 @@ def start_load_caches(self, encoder_cache, **kwargs) -> None: def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: """ - Start saving the EC cache for each mm_data from the encoder cache. + Save the encoder cache to the connector. + + This method saves the encoder cache from the worker's local storage + to shared storage or another external connector. Args: - encoder_cache (dict[str, torch.Tensor]): Reference - to encoder cache storage inside worker. - mm_hash (str): The mm_hash identifier for the cache to be saved. + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes + (`mm_hash`) to encoder cache tensors. + mm_hash (str): The hash of the multimodal data whose cache is being saved. + kwargs (dict): Additional keyword arguments for the connector. """ # Return if it is PD Instance if not self.is_producer: From 30888ba79fe2d8dd9e710fbd9ebbb3c05d242b36 Mon Sep 17 00:00:00 2001 From: herotai214 Date: Wed, 22 Oct 2025 10:10:50 +0000 Subject: [PATCH 39/57] [Misc] Script to verify EPD correctness Signed-off-by: herotai214 --- docs/features/disagg_encoder.md | 6 +- tests/v1/ec_connector/integration/README.md | 167 ++++++ .../integration/run_epd_correctness_test.sh | 478 ++++++++++++++++++ .../integration/test_epd_correctness.py | 317 ++++++++++++ 4 files changed, 967 insertions(+), 1 deletion(-) create mode 100644 tests/v1/ec_connector/integration/README.md create mode 100644 tests/v1/ec_connector/integration/run_epd_correctness_test.sh create mode 100644 tests/v1/ec_connector/integration/test_epd_correctness.py diff --git a/docs/features/disagg_encoder.md b/docs/features/disagg_encoder.md index 46a5848b2e1c..7d40af706982 100644 --- a/docs/features/disagg_encoder.md +++ b/docs/features/disagg_encoder.md @@ -43,7 +43,11 @@ Below ready-to-run scripts shows the workflow: --- -## 3 Development +## 3 Test Script + +Please refer to the directories `tests/v1/ec_connector` + +## 4 Development Disaggregated encoding is implemented by running two parts: diff --git a/tests/v1/ec_connector/integration/README.md b/tests/v1/ec_connector/integration/README.md new file mode 100644 index 000000000000..fe41fc7b382c --- /dev/null +++ b/tests/v1/ec_connector/integration/README.md @@ -0,0 +1,167 @@ +# EPD Correctness Test + +This test verifies that EPD (Encoder-Prefill-Decode) disaggregation produces identical outputs to a baseline single instance. + +## What It Tests + +- **Baseline**: Single vLLM instance serving a multimodal model +- **EPD (1E+1PD)**: 1 Encoder + 1 Prefill-Decode instance +- **Baseline (1P+1D)**: 1 Prefill + 1 Decode instance +- **EPD (1E+1P+1D)**: 1 Encoder + 1 Prefill + 1 Decode instance + +The test ensures that disaggregated encoding produces **identical** outputs to the baseline. + +Note that currently PD disaggregation set up may give slightly different results from a single instance. Therefore, we need the result from 1P+1D as the baseline for 1E+1P+1D + +Please refer to [Disaggregated Encoder Feature](../../../docs/features/disagg_encoder.md) for the detailed explanation for the EPD features. + +## Files + +- `run_epd_correctness_test.sh` - Main test script (starts all instances and runs tests) +- `test_epd_correctness.py` - Python test script (compares outputs) + +## Usage + +### Text-Only Prompts + +```bash +cd vllm +USE_MM_PROMPTS=0 ./tests/v1/ec_connector/integration/run_epd_correctness_test.sh +``` + +This runs a quick test with text-only prompts to verify the setup works. + +### Full Test (With Multimodal Prompts) + +```bash +cd vllm +./tests/v1/ec_connector/integration/run_epd_correctness_test.sh +``` + +This runs the full test with actual multimodal (image) prompts. + +### Custom Configuration + +```bash +# Use specific GPUs +GPU_E=0 GPU_PD=1 GPU_P=1 GPU_D=2 ./tests/v1/ec_connector/integration/run_epd_correctness_test.sh + +# Use specific ports +ENDPOINT_PORT=10001 ./tests/v1/ec_connector/integration/run_epd_correctness_test.sh + +# Use specific model +MODEL="Qwen/Qwen2.5-VL-3B-Instruct" ./tests/v1/ec_connector/integration/run_epd_correctness_test.sh + +# Use specific storage path +EC_SHARED_STORAGE_PATH="/tmp/my_ec_cache" ./tests/v1/ec_connector/integration/run_epd_correctness_test.sh +``` + +## How It Works + +### Step 1: Baseline + +1. Start single vLLM instance on GPU +2. Run test prompts (multimodal or text-only) +3. Save outputs to `.vllm_epd_baseline.txt` +4. Shutdown instance + +### Step 2: EPD (1E + 1PD) + +1. Clear encoder cache storage +2. Start instances and proxy +3. Run same test prompts +4. Assert outputs match baseline exactly +5. Shutdown instances + +### Step 3: EPD (1E + 1P + 1D) + +1. Clear encoder cache storage +2. Start instances and proxy +3. Run same test prompts +4. Assert outputs match baseline exactly +5. Shutdown instances + +## Test Scenarios + +### Multimodal Prompts (--use_mm_prompts) + +Tests encoder cache transfer: +- Single image query +- Multiple images in one request +- Mixed image and text +- Image with detailed questions + +### Text-Only Prompts (default) + +Quick sanity check: +- Simple text queries +- Text-only explanations +- Verifies proxy routing works + +## Expected Behavior + +### ✅ Test Passes When: +- All disagg outputs match baseline outputs exactly +- No errors during instance startup +- Encoder cache is properly saved and loaded +- Proxy correctly routes requests + +### ❌ Test Fails When: +- Outputs differ between baseline and disagg +- Server startup fails +- Encoder cache not found (should fallback to local execution) +- Proxy routing errors + +## Notes + +- The test uses deterministic generation (`temperature=0.0`, `seed=42`) +- Encoder cache should enable exact output reproduction +- Test cleans up all instances and cache files after completion +- Safe to run multiple times (idempotent) +- We setup the PD disagg part with NixlConnector. Please read details about EPD in `examples/online_serving/disaggregated_encoder/README.md` + +## Requirements + +- Multiple GPUs (3 for 1E+1P+1D, 2 for 1E+1PD, 1 for baseline) + - 1E+1P+1D is runnable with 2 GPU by assign E and P on the same GPU now. +- Multimodal model (e.g., Qwen2.5-VL-3B-Instruct) +- Internet access (for accessing vllm test images) + - + +## Debugging + +### Check Logs +Logs and baseline output are saved in `/tmp/` by default. +Can be customized by changing the environment variables. + +### Check Encoder Cache + +```bash +# Verify cache files are created +ls -la $EC_SHARED_STORAGE_PATH/ + +# Should see directories with mm_hash names +# Each containing encoder_cache.safetensors +``` + +### Manual Testing + +Run individual components: + +```bash +# Baseline only +python test_epd_correctness.py \ + --service_url http://localhost:8000 \ + --model_name Qwen/Qwen2.5-VL-3B-Instruct \ + --mode baseline \ + --baseline_file test_output.txt + +# Disagg only (requires baseline output file) +python test_epd_correctness.py \ + --service_url http://localhost:8000 \ + --model_name Qwen/Qwen2.5-VL-3B-Instruct \ + --mode disagg \ + --baseline_file test_output.txt +``` + + diff --git a/tests/v1/ec_connector/integration/run_epd_correctness_test.sh b/tests/v1/ec_connector/integration/run_epd_correctness_test.sh new file mode 100644 index 000000000000..ba8afd86caaf --- /dev/null +++ b/tests/v1/ec_connector/integration/run_epd_correctness_test.sh @@ -0,0 +1,478 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# +# EPD (Encoder-Prefill-Decode) Correctness Test +# +# This script tests that EPD disaggregation produces the same outputs as baseline. +# It runs: +# 1. Baseline: Single vLLM instance +# 2. EPD: 1E + 1PD setup +# 3. Baseline for (E + P + D): 1P + 1D vLLM instances disagg +# 4. EPD: 1E + 1P + 1D setup + +# For GPU usage + +# set -xe + +# Find the git repository root directory +GIT_ROOT=$(git rev-parse --show-toplevel) + +# Model to test +MODEL="${MODEL:-Qwen/Qwen2.5-VL-3B-Instruct}" + +# Set 1 to use multimodal prompts; else to use text-only +USE_MM_PROMPTS="${USE_MM_PROMPTS:-1}" + +# GPU configuration +GPU_E="${GPU_E:-0}" +GPU_P="${GPU_P:-1}" +GPU_D="${GPU_D:-2}" +GPU_SINGLE="${GPU_SINGLE:-$GPU_E}" +GPU_PD="${GPU_PD:-$GPU_P}" + +# Port +ENCODE_PORT="${ENCODE_PORT:-19534}" +PREFILL_PORT="${PREFILL_PORT:-19535}" +DECODE_PORT="${DECODE_PORT:-19536}" +PREFILL_DECODE_PORT="${PREFILL_DECODE_PORT:-19537}" +ENDPOINT_PORT="${ENDPOINT_PORT:-10001}" + +# Storage path for encoder cache +EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/ec_cache_test}" +TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-600}" + +# Output file for baseline comparison and logs +LOG_PATH="${LOG_PATH:-/tmp}" +BASELINE_FILE="${BASELINE_FILE:-/tmp/vllm_baseline.txt}" +BASELINE_PD_FILE="${BASELINE_PD_FILE:-/tmp/vllm_epd_baseline.txt}" + +mkdir -p $LOG_PATH + +# Trap the SIGINT signal (triggered by Ctrl+C) +trap 'kill $(jobs -pr)' SIGINT SIGTERM EXIT + +# Wait for server to be ready +wait_for_server() { + local port=$1 + timeout "$TIMEOUT_SECONDS" bash -c " + until curl -s localhost:${port}/v1/chat/completions > /dev/null; do + sleep 1 + done" && return 0 || return 1 +} + +# Cleanup function +cleanup_instances() { + echo "Cleaning up any running vLLM instances..." + pkill -f "vllm serve" || true + pkill -f "disagg_epd_proxy.py" || true + sleep 2 +} + +# Function to run baseline (single instance) +run_baseline() { + echo "================================" + echo "Running BASELINE (single instance)" + echo "================================" + + cleanup_instances + rm -rf "$EC_SHARED_STORAGE_PATH" + + local PORT=$ENDPOINT_PORT + + # Start baseline instance + echo "Starting baseline instance on GPU $GPU_SINGLE, port $PORT" + CUDA_VISIBLE_DEVICES="$GPU_SINGLE" vllm serve "$MODEL" \ + --port $PORT \ + --enforce-eager \ + --gpu-memory-utilization 0.7 \ + --max-num-seqs 128 \ + > $LOG_PATH/baseline.log 2>&1 & + + local BASELINE_PID=$! + + # Wait for baseline to start + echo "Waiting for baseline instance to start..." + wait_for_server $PORT + + curl http://127.0.0.1:$PORT/v1/models + echo "" + + # Run test in baseline mode + echo "Running baseline correctness test..." + MM_FLAG="" + if [ $USE_MM_PROMPTS = "1" ]; then + MM_FLAG="--use_mm_prompts" + fi + + python "${GIT_ROOT}/tests/v1/ec_connector/integration/test_epd_correctness.py" \ + --service_url "http://localhost:$PORT" \ + --model_name "$MODEL" \ + --mode baseline \ + --baseline_file "$BASELINE_FILE" \ + $MM_FLAG + + # Cleanup baseline + echo "Stopping baseline instance..." + kill $BASELINE_PID 2>/dev/null || true + sleep 2 + cleanup_instances +} + +# Function to run EPD with 1E + 1PD +run_epd_1e_1pd() { + echo "================================" + echo "Running EPD (1E + 1PD)" + echo "================================" + + cleanup_instances + rm -rf "$EC_SHARED_STORAGE_PATH" + mkdir -p "$EC_SHARED_STORAGE_PATH" + + local ENCODE_PORT=$ENCODE_PORT + local PREFILL_DECODE_PORT=$PREFILL_DECODE_PORT + local PROXY_PORT=$ENDPOINT_PORT + + declare -a PIDS=() + + # Start encoder instance + echo "Starting encoder instance on GPU $GPU_E, port $ENCODE_PORT" + CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ + --port $ENCODE_PORT \ + --enforce-eager \ + --gpu-memory-utilization 0.7 \ + --enable-request-id-headers \ + --no-enable-prefix-caching \ + --max-num-seqs 128 \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_producer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'" + } + }' \ + > $LOG_PATH/1e1pd_encoder.log 2>&1 & + PIDS+=($!) + + # Start prefill+decode instance + echo "Starting PD instance on GPU $GPU_PD, port $PREFILL_DECODE_PORT" + CUDA_VISIBLE_DEVICES="$GPU_PD" vllm serve "$MODEL" \ + --port $PREFILL_DECODE_PORT \ + --enforce-eager \ + --gpu-memory-utilization 0.7 \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_consumer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'" + } + }' \ + > $LOG_PATH/1e1pd_pd.log 2>&1 & + PIDS+=($!) + + # Wait for instances to start + echo "Waiting for encoder instance..." + wait_for_server $ENCODE_PORT + echo "Waiting for PD instance..." + wait_for_server $PREFILL_DECODE_PORT + + # Start proxy + echo "Starting EPD proxy on port $PROXY_PORT" + python "${GIT_ROOT}/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py" \ + --host "0.0.0.0" \ + --port $PROXY_PORT \ + --encode-servers-urls "http://localhost:$ENCODE_PORT" \ + --prefill-servers-urls "disable" \ + --decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT" \ + > $LOG_PATH/1e1pd_proxy.log 2>&1 & + PIDS+=($!) + + # Wait for proxy + echo "Waiting for proxy..." + wait_for_server $PROXY_PORT + + curl http://127.0.0.1:$PROXY_PORT/v1/models + curl http://127.0.0.1:$PROXY_PORT/health + echo "" + + echo "All EPD (1E+1PD) services are up!" + + # Run test in disagg mode + echo "Running EPD (1E+1PD) correctness test..." + MM_FLAG="" + if [ $USE_MM_PROMPTS = "1" ]; then + MM_FLAG="--use_mm_prompts" + fi + + python "${GIT_ROOT}/tests/v1/ec_connector/integration/test_epd_correctness.py" \ + --service_url "http://localhost:$PROXY_PORT" \ + --model_name "$MODEL" \ + --mode disagg \ + --baseline_file "$BASELINE_FILE" \ + $MM_FLAG + + # Cleanup + echo "✅✅ 1E+1PD Correctness Test PASSED" + echo "Stopping EPD (1E+1PD) instances..." + for pid in "${PIDS[@]}"; do + kill $pid 2>/dev/null || true + done + sleep 2 + cleanup_instances +} + +# Function to run baseline for 1E + 1P + 1D (PD disagg) +run_baseline_1p_1d() { + echo "================================" + echo "Running PD BASELINE (1P + 1D)" + echo "================================" + + cleanup_instances + rm -rf "$EC_SHARED_STORAGE_PATH" + mkdir -p "$EC_SHARED_STORAGE_PATH" + + local PREFILL_PORT=$PREFILL_PORT + local DECODE_PORT=$DECODE_PORT + local PROXY_PORT=$ENDPOINT_PORT + + declare -a PIDS=() + + # Start prefill instance + echo "Starting prefill instance on GPU $GPU_P, port $PREFILL_PORT" + CUDA_VISIBLE_DEVICES="$GPU_P" \ + VLLM_NIXL_SIDE_CHANNEL_PORT=5559 \ + vllm serve "$MODEL" \ + --port $PREFILL_PORT \ + --enforce-eager \ + --gpu-memory-utilization 0.7 \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --kv-transfer-config '{ + "kv_connector": "NixlConnector", + "kv_role": "kv_producer" + }' \ + > $LOG_PATH/1p1d_prefill.log 2>&1 & + PIDS+=($!) + + # Start decode instance + echo "Starting decode instance on GPU $GPU_D, port $DECODE_PORT" + CUDA_VISIBLE_DEVICES="$GPU_D" \ + VLLM_NIXL_SIDE_CHANNEL_PORT=6000 \ + vllm serve "$MODEL" \ + --port $DECODE_PORT \ + --enforce-eager \ + --gpu-memory-utilization 0.7 \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --kv-transfer-config '{ + "kv_connector": "NixlConnector", + "kv_role": "kv_consumer" + }' \ + > $LOG_PATH/1p1d_decode.log 2>&1 & + PIDS+=($!) + + # Wait for instances to start + echo "Waiting for prefill instance..." + wait_for_server $PREFILL_PORT + echo "Waiting for decode instance..." + wait_for_server $DECODE_PORT + + # Start proxy + echo "Starting EPD proxy on port $PROXY_PORT" + python "${GIT_ROOT}/tests/v1/kv_connector/nixl_integration/toy_proxy_server.py" \ + --host "0.0.0.0" \ + --port $PROXY_PORT \ + --prefiller-ports $PREFILL_PORT \ + --decoder-ports $DECODE_PORT \ + > $LOG_PATH/1p1d_proxy.log 2>&1 & + PIDS+=($!) + + # Wait for proxy + echo "Waiting for proxy..." + wait_for_server $PROXY_PORT + + curl http://127.0.0.1:$PROXY_PORT/healthcheck + echo "" + + echo "All PD (1P+1D) services are up!" + + # Run test in baseline mode + echo "Running EPD (1E+1P+1D) correctness test..." + MM_FLAG="" + if [ $USE_MM_PROMPTS = "1" ]; then + MM_FLAG="--use_mm_prompts" + fi + + python "${GIT_ROOT}/tests/v1/ec_connector/integration/test_epd_correctness.py" \ + --service_url "http://localhost:$PROXY_PORT" \ + --model_name "$MODEL" \ + --mode baseline_pd \ + --baseline_file "$BASELINE_PD_FILE" \ + $MM_FLAG + + # Cleanup + echo "Stopping PD (1P+1D) instances..." + for pid in "${PIDS[@]}"; do + kill $pid 2>/dev/null || true + done + sleep 2 + cleanup_instances +} + +# Function to run EPD with 1E + 1P + 1D +run_epd_1e_1p_1d() { + echo "================================" + echo "Running EPD (1E + 1P + 1D)" + echo "================================" + + cleanup_instances + rm -rf "$EC_SHARED_STORAGE_PATH" + mkdir -p "$EC_SHARED_STORAGE_PATH" + + local ENCODE_PORT=$ENCODE_PORT + local PREFILL_PORT=$PREFILL_PORT + local DECODE_PORT=$DECODE_PORT + local PROXY_PORT=$ENDPOINT_PORT + + declare -a PIDS=() + + # Start encoder instance + echo "Starting encoder instance on GPU $GPU_E, port $ENCODE_PORT" + CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ + --port $ENCODE_PORT \ + --enforce-eager \ + --gpu-memory-utilization 0.7 \ + --enable-request-id-headers \ + --no-enable-prefix-caching \ + --max-num-seqs 128 \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_producer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'" + } + }' \ + > $LOG_PATH/1e1p1d_encoder.log 2>&1 & + PIDS+=($!) + + # Start prefill instance + echo "Starting prefill instance on GPU $GPU_P, port $PREFILL_PORT" + CUDA_VISIBLE_DEVICES="$GPU_P" \ + VLLM_NIXL_SIDE_CHANNEL_PORT=5559 \ + vllm serve "$MODEL" \ + --port $PREFILL_PORT \ + --enforce-eager \ + --gpu-memory-utilization 0.7 \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --ec-transfer-config '{ + "ec_connector": "ECSharedStorageConnector", + "ec_role": "ec_consumer", + "ec_connector_extra_config": { + "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'" + } + }' \ + --kv-transfer-config '{ + "kv_connector": "NixlConnector", + "kv_role": "kv_producer" + }' \ + > $LOG_PATH/1e1p1d_prefill.log 2>&1 & + PIDS+=($!) + + # Start decode instance + echo "Starting decode instance on GPU $GPU_D, port $DECODE_PORT" + CUDA_VISIBLE_DEVICES="$GPU_D" \ + VLLM_NIXL_SIDE_CHANNEL_PORT=6000 \ + vllm serve "$MODEL" \ + --port $DECODE_PORT \ + --enforce-eager \ + --gpu-memory-utilization 0.7 \ + --enable-request-id-headers \ + --max-num-seqs 128 \ + --kv-transfer-config '{ + "kv_connector": "NixlConnector", + "kv_role": "kv_consumer" + }' \ + > $LOG_PATH/1e1p1d_decode.log 2>&1 & + PIDS+=($!) + + # Wait for instances to start + echo "Waiting for encoder instance..." + wait_for_server $ENCODE_PORT + echo "Waiting for prefill instance..." + wait_for_server $PREFILL_PORT + echo "Waiting for decode instance..." + wait_for_server $DECODE_PORT + + # Start proxy + echo "Starting EPD proxy on port $PROXY_PORT" + python "${GIT_ROOT}/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py" \ + --host "0.0.0.0" \ + --port $PROXY_PORT \ + --encode-servers-urls "http://localhost:$ENCODE_PORT" \ + --prefill-servers-urls "http://localhost:$PREFILL_PORT" \ + --decode-servers-urls "http://localhost:$DECODE_PORT" \ + > $LOG_PATH/1e1p1d_proxy.log 2>&1 & + PIDS+=($!) + + # Wait for proxy + echo "Waiting for proxy..." + wait_for_server $PROXY_PORT + + curl http://127.0.0.1:$PROXY_PORT/v1/models + curl http://127.0.0.1:$PROXY_PORT/health + echo "" + + echo "All EPD (1E+1P+1D) services are up!" + + # Run test in disagg mode + echo "Running EPD (1E+1P+1D) correctness test..." + MM_FLAG="" + if [ $USE_MM_PROMPTS = "1" ]; then + MM_FLAG="--use_mm_prompts" + fi + + python "${GIT_ROOT}/tests/v1/ec_connector/integration/test_epd_correctness.py" \ + --service_url "http://localhost:$PROXY_PORT" \ + --model_name "$MODEL" \ + --mode disagg \ + --baseline_file "$BASELINE_PD_FILE" \ + $MM_FLAG + + # Cleanup + echo "✅✅ 1E+1P+1D Correctness Test PASSED" + echo "Stopping EPD (1E+1P+1D) instances..." + for pid in "${PIDS[@]}"; do + kill $pid 2>/dev/null || true + done + sleep 2 + cleanup_instances +} + +# Main execution +echo "================================" +echo "EPD Correctness Test Suite" +echo "Model: $MODEL" +echo "================================" + +# Step 1: Run baseline +run_baseline + +# Step 2: Test 1E + 1PD +run_epd_1e_1pd + +# Step 3: Test baseline 1P + 1D +run_baseline_1p_1d + +# Step 4: Test 1E + 1P + 1D +run_epd_1e_1p_1d + +# Cleanup output file +rm -f "$BASELINE_FILE" +rm -f "$BASELINE_PD_FILE" + +echo "================================" +echo "✅✅✅ All EPD correctness tests passed!" +echo "================================" diff --git a/tests/v1/ec_connector/integration/test_epd_correctness.py b/tests/v1/ec_connector/integration/test_epd_correctness.py new file mode 100644 index 000000000000..7d9b88c63bbc --- /dev/null +++ b/tests/v1/ec_connector/integration/test_epd_correctness.py @@ -0,0 +1,317 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +""" +EPD Correctness Test + +Tests that EPD (Encoder-Prefill-Decode) disaggregation produces the same +outputs as a baseline single instance. + +Usage: + # Baseline mode (saves outputs): + python test_epd_correctness.py \ + --service_url http://localhost:8000 \ + --model_name Qwen/Qwen2.5-VL-3B-Instruct \ + --mode baseline \ + --baseline_file .vllm_epd_baseline.txt + + # Disagg mode (compares outputs): + python test_epd_correctness.py \ + --service_url http://localhost:8000 \ + --model_name Qwen/Qwen2.5-VL-3B-Instruct \ + --mode disagg \ + --baseline_file .vllm_epd_baseline.txt +""" + +import argparse +import json +import os +import time + +import openai +import requests + +from vllm.assets.image import ImageAsset +from vllm.multimodal.utils import encode_image_base64 + +MAX_OUTPUT_LEN = 256 + +# Sample prompts with multimodal content +image_1 = ImageAsset("stop_sign").pil_image.resize((1280, 720)) +image_2 = ImageAsset("cherry_blossom").pil_image.resize((1280, 720)) + +SAMPLE_PROMPTS_MM = [ + { + "messages": [ + { + "role": "user", + "content": [ + { + "type": "image_url", + "image_url": { + "url": f"data:image;base64,{encode_image_base64(image_1)}" + } + }, + { + "type": "text", + "text": "What's in this image?" + } + ] + } + ], + "description": "Single image query" + }, + { + "messages": [ + { + "role": "user", + "content": [ + { + "type": "image_url", + "image_url": { + "url": f"data:image;base64,{encode_image_base64(image_2)}" + } + }, + { + "type": "image_url", + "image_url": { + "url": f"data:image;base64,{encode_image_base64(image_1)}" + } + }, + { + "type": "text", + "text": "Describe these 2 images in detail." + } + ] + } + ], + "description": "2 images with detailed query" + }, +] + +# Text-only prompts for mixed testing +SAMPLE_PROMPTS_TEXT = [ + { + "messages": [ + { + "role": "user", + "content": "What is the capital of France?" + } + ], + "description": "Simple text-only query" + }, + { + "messages": [ + { + "role": "user", + "content": "Explain quantum computing in simple terms." + } + ], + "description": "Text-only explanation request" + }, +] + + +def check_vllm_server(url: str, timeout=5, retries=10) -> bool: + """Check if the vLLM server is ready. + + Args: + url: The URL to check (usually /health or /healthcheck endpoint) + timeout: Timeout in seconds for each request + retries: Number of retries if the server is not ready + + Returns: + True if the server is ready, False otherwise + """ + for attempt in range(retries): + try: + response = requests.get(url, timeout=timeout) + if response.status_code == 200: + print(f"Server is ready at {url}") + return True + else: + print( + f"Attempt {attempt + 1}/{retries}: Server returned " + f"status code {response.status_code}" + ) + except requests.exceptions.RequestException as e: + print(f"Attempt {attempt + 1}/{retries}: Error connecting: {e}") + time.sleep(2) # Wait before retrying + return False + + +def run_chat_completion( + base_url: str, + model_name: str, + messages: list, + max_tokens: int = MAX_OUTPUT_LEN, +) -> str: + """Run a chat completion request. + + Args: + base_url: Base URL of the vLLM server + model_name: Name of the model + messages: Messages for chat completion + max_tokens: Maximum tokens to generate + + Returns: + Generated text content + """ + client = openai.OpenAI(api_key="EMPTY", base_url=base_url) + + completion = client.chat.completions.create( + model=model_name, + messages=messages, + max_tokens=max_tokens, + temperature=0.0, + seed=42, + ) + + return completion.choices[0].message.content + + +def main(): + """Main test function.""" + parser = argparse.ArgumentParser( + description="EPD correctness test - compare disagg vs baseline" + ) + + parser.add_argument( + "--service_url", + type=str, + required=True, + help="The vLLM service URL (e.g., http://localhost:8000)", + ) + + parser.add_argument( + "--model_name", + type=str, + required=True, + help="Model name", + ) + + parser.add_argument( + "--mode", + type=str, + default="baseline", + choices=["baseline","baseline_pd", "disagg"], + help="Mode: baseline/baseline_pd (saves outputs) or disagg (compares outputs)", + ) + + parser.add_argument( + "--baseline_file", + type=str, + default=".vllm_epd_baseline.txt", + help="File to save/load baseline outputs", + ) + + parser.add_argument( + "--use_mm_prompts", + action="store_true", + help="Use multimodal prompts (default: use text-only for quick testing)", + ) + + args = parser.parse_args() + + print(f"Service URL: {args.service_url}") + print(f"Model: {args.model_name}") + print(f"Mode: {args.mode}") + print(f"Output file: {args.baseline_file}") + print(f"Use MM prompts: {args.use_mm_prompts}") + + # Determine health check endpoint + if args.mode == "baseline": + health_check_url = f"{args.service_url}/health" + elif args.mode == "baseline_pd": + # Nixl toy proxy use /healthcheck + health_check_url = f"{args.service_url}/healthcheck" + else: + # Disagg proxy uses /health + health_check_url = f"{args.service_url}/health" + if not os.path.exists(args.baseline_file): + raise ValueError( + f"In disagg mode, the output file {args.baseline_file} from " + "baseline does not exist. Run baseline mode first." + ) + + # Check if server is ready + if not check_vllm_server(health_check_url): + raise RuntimeError( + f"vLLM server at {args.service_url} is not ready!" + ) + + # Select prompts to use + if args.use_mm_prompts: + test_prompts = SAMPLE_PROMPTS_MM + print("Using multimodal prompts") + else: + test_prompts = SAMPLE_PROMPTS_TEXT + print("Using text-only prompts for quick testing") + + # Run completions + service_url = f"{args.service_url}/v1" + output_strs = {} + + for i, prompt_data in enumerate(test_prompts): + print(f"\nRunning prompt {i+1}/{len(test_prompts)}: {prompt_data['description']}") + + output_str = run_chat_completion( + base_url=service_url, + model_name=args.model_name, + messages=prompt_data["messages"], + max_tokens=MAX_OUTPUT_LEN, + ) + + # Use description as key for comparison + key = prompt_data["description"] + output_strs[key] = output_str + print(f"Output: {output_str}") + + if args.mode in ("baseline", "baseline_pd"): + # Baseline mode: Save outputs + print(f"\nSaving baseline outputs to {args.baseline_file}") + try: + with open(args.baseline_file, "w") as json_file: + json.dump(output_strs, json_file, indent=4) + print("✅ Baseline outputs saved successfully") + except OSError as e: + print(f"Error writing to file: {e}") + raise + else: + # Disagg mode: Load and compare outputs + print(f"\nLoading baseline outputs from {args.baseline_file}") + baseline_outputs = None + try: + with open(args.baseline_file) as json_file: + baseline_outputs = json.load(json_file) + except OSError as e: + print(f"Error reading from file: {e}") + raise + + # Verify outputs match + print("\nComparing disagg outputs with baseline...") + assert isinstance(baseline_outputs, dict), \ + "Baseline outputs should be a dict" + assert len(baseline_outputs) == len(output_strs), \ + f"Length mismatch: baseline has {len(baseline_outputs)}, " \ + f"disagg has {len(output_strs)}" + + all_match = True + for key, baseline_output in baseline_outputs.items(): + assert key in output_strs, f"{key} not in disagg outputs" + + disagg_output = output_strs[key] + if baseline_output == disagg_output: + print(f"✓ {key}: MATCH") + else: + print(f"✗ {key}: MISMATCH") + print(f" Baseline: {baseline_output}") + print(f" Disagg: {disagg_output}") + all_match = False + + assert all_match, "Disagg outputs do not match baseline!" + print("\n✅ All outputs match! Test PASSED") + + +if __name__ == "__main__": + main() + From eabfe7efcbc49731411ef81d0cb5313724ab3511 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Thu, 23 Oct 2025 09:28:44 +0800 Subject: [PATCH 40/57] Fix pre-commit Signed-off-by: knlnguyen1802 --- .../integration/test_epd_correctness.py | 73 ++++++++----------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/tests/v1/ec_connector/integration/test_epd_correctness.py b/tests/v1/ec_connector/integration/test_epd_correctness.py index 7d9b88c63bbc..46645e4333c2 100644 --- a/tests/v1/ec_connector/integration/test_epd_correctness.py +++ b/tests/v1/ec_connector/integration/test_epd_correctness.py @@ -49,16 +49,13 @@ "type": "image_url", "image_url": { "url": f"data:image;base64,{encode_image_base64(image_1)}" - } + }, }, - { - "type": "text", - "text": "What's in this image?" - } - ] + {"type": "text", "text": "What's in this image?"}, + ], } ], - "description": "Single image query" + "description": "Single image query", }, { "messages": [ @@ -69,44 +66,33 @@ "type": "image_url", "image_url": { "url": f"data:image;base64,{encode_image_base64(image_2)}" - } + }, }, { "type": "image_url", "image_url": { "url": f"data:image;base64,{encode_image_base64(image_1)}" - } + }, }, - { - "type": "text", - "text": "Describe these 2 images in detail." - } - ] + {"type": "text", "text": "Describe these 2 images in detail."}, + ], } ], - "description": "2 images with detailed query" + "description": "2 images with detailed query", }, ] # Text-only prompts for mixed testing SAMPLE_PROMPTS_TEXT = [ { - "messages": [ - { - "role": "user", - "content": "What is the capital of France?" - } - ], - "description": "Simple text-only query" + "messages": [{"role": "user", "content": "What is the capital of France?"}], + "description": "Simple text-only query", }, { "messages": [ - { - "role": "user", - "content": "Explain quantum computing in simple terms." - } + {"role": "user", "content": "Explain quantum computing in simple terms."} ], - "description": "Text-only explanation request" + "description": "Text-only explanation request", }, ] @@ -157,7 +143,7 @@ def run_chat_completion( Generated text content """ client = openai.OpenAI(api_key="EMPTY", base_url=base_url) - + completion = client.chat.completions.create( model=model_name, messages=messages, @@ -165,7 +151,7 @@ def run_chat_completion( temperature=0.0, seed=42, ) - + return completion.choices[0].message.content @@ -193,7 +179,7 @@ def main(): "--mode", type=str, default="baseline", - choices=["baseline","baseline_pd", "disagg"], + choices=["baseline", "baseline_pd", "disagg"], help="Mode: baseline/baseline_pd (saves outputs) or disagg (compares outputs)", ) @@ -235,9 +221,7 @@ def main(): # Check if server is ready if not check_vllm_server(health_check_url): - raise RuntimeError( - f"vLLM server at {args.service_url} is not ready!" - ) + raise RuntimeError(f"vLLM server at {args.service_url} is not ready!") # Select prompts to use if args.use_mm_prompts: @@ -250,17 +234,19 @@ def main(): # Run completions service_url = f"{args.service_url}/v1" output_strs = {} - + for i, prompt_data in enumerate(test_prompts): - print(f"\nRunning prompt {i+1}/{len(test_prompts)}: {prompt_data['description']}") - + print( + f"\nRunning prompt {i + 1}/{len(test_prompts)}: {prompt_data['description']}" + ) + output_str = run_chat_completion( base_url=service_url, model_name=args.model_name, messages=prompt_data["messages"], max_tokens=MAX_OUTPUT_LEN, ) - + # Use description as key for comparison key = prompt_data["description"] output_strs[key] = output_str @@ -289,16 +275,16 @@ def main(): # Verify outputs match print("\nComparing disagg outputs with baseline...") - assert isinstance(baseline_outputs, dict), \ - "Baseline outputs should be a dict" - assert len(baseline_outputs) == len(output_strs), \ - f"Length mismatch: baseline has {len(baseline_outputs)}, " \ + assert isinstance(baseline_outputs, dict), "Baseline outputs should be a dict" + assert len(baseline_outputs) == len(output_strs), ( + f"Length mismatch: baseline has {len(baseline_outputs)}, " f"disagg has {len(output_strs)}" + ) all_match = True for key, baseline_output in baseline_outputs.items(): assert key in output_strs, f"{key} not in disagg outputs" - + disagg_output = output_strs[key] if baseline_output == disagg_output: print(f"✓ {key}: MATCH") @@ -307,11 +293,10 @@ def main(): print(f" Baseline: {baseline_output}") print(f" Disagg: {disagg_output}") all_match = False - + assert all_match, "Disagg outputs do not match baseline!" print("\n✅ All outputs match! Test PASSED") if __name__ == "__main__": main() - From 5120f76b7083a80172415b417e1713c1bcfdc6c1 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Thu, 23 Oct 2025 09:42:33 +0800 Subject: [PATCH 41/57] Fix pre-commit Signed-off-by: knlnguyen1802 --- vllm/distributed/ec_transfer/ec_connector/base.py | 8 ++++---- .../ec_transfer/ec_connector/shared_storage_connector.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index 670207d30d00..b4a1858cd644 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -135,8 +135,8 @@ def start_load_caches( the `encoder_cache` and `mm_hash` are stored in `kwargs`. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes - (`mm_hash`) to encoder cache tensors. + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal + data hashes (`mm_hash`) to encoder cache tensors. kwargs (dict): Additional keyword arguments for the connector. """ pass @@ -152,8 +152,8 @@ def save_caches( to shared storage or another external connector. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes - (`mm_hash`) to encoder cache tensors. + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal + data hashes (`mm_hash`) to encoder cache tensors. mm_hash (str): The hash of the multimodal data whose cache is being saved. kwargs (dict): Additional keyword arguments for the connector. """ diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index bb9b867491d5..856270bd9ec0 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -69,8 +69,8 @@ def start_load_caches(self, encoder_cache, **kwargs) -> None: the `encoder_cache` and `mm_hash` are stored in `kwargs`. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes - (`mm_hash`) to encoder cache tensors. + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal + data hashes (`mm_hash`) to encoder cache tensors. kwargs (dict): Additional keyword arguments for the connector. """ @@ -103,8 +103,8 @@ def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: to shared storage or another external connector. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes - (`mm_hash`) to encoder cache tensors. + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal + data hashes (`mm_hash`) to encoder cache tensors. mm_hash (str): The hash of the multimodal data whose cache is being saved. kwargs (dict): Additional keyword arguments for the connector. """ From 7e7a26986f1a4a219d3c35ec2638f1b50d8f4657 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Thu, 23 Oct 2025 09:50:34 +0800 Subject: [PATCH 42/57] Fix pre-commit Signed-off-by: knlnguyen1802 --- vllm/distributed/ec_transfer/ec_connector/base.py | 4 ++-- .../ec_transfer/ec_connector/shared_storage_connector.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index b4a1858cd644..aa082539ae61 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -135,7 +135,7 @@ def start_load_caches( the `encoder_cache` and `mm_hash` are stored in `kwargs`. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes (`mm_hash`) to encoder cache tensors. kwargs (dict): Additional keyword arguments for the connector. """ @@ -152,7 +152,7 @@ def save_caches( to shared storage or another external connector. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes (`mm_hash`) to encoder cache tensors. mm_hash (str): The hash of the multimodal data whose cache is being saved. kwargs (dict): Additional keyword arguments for the connector. diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 856270bd9ec0..0c2dcb1e72f0 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -69,7 +69,7 @@ def start_load_caches(self, encoder_cache, **kwargs) -> None: the `encoder_cache` and `mm_hash` are stored in `kwargs`. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes (`mm_hash`) to encoder cache tensors. kwargs (dict): Additional keyword arguments for the connector. """ @@ -103,7 +103,7 @@ def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: to shared storage or another external connector. Args: - encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal + encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal data hashes (`mm_hash`) to encoder cache tensors. mm_hash (str): The hash of the multimodal data whose cache is being saved. kwargs (dict): Additional keyword arguments for the connector. From 37545efe060679d54337e3bb8585138c53daefd2 Mon Sep 17 00:00:00 2001 From: Khuong Le Date: Thu, 23 Oct 2025 02:20:17 +0000 Subject: [PATCH 43/57] [Fix] fix pre-commit Signed-off-by: Khuong Le --- tests/v1/ec_connector/integration/README.md | 14 ++++++++------ .../integration/test_epd_correctness.py | 8 +++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/v1/ec_connector/integration/README.md b/tests/v1/ec_connector/integration/README.md index fe41fc7b382c..03cb2e9a178d 100644 --- a/tests/v1/ec_connector/integration/README.md +++ b/tests/v1/ec_connector/integration/README.md @@ -86,6 +86,7 @@ EC_SHARED_STORAGE_PATH="/tmp/my_ec_cache" ./tests/v1/ec_connector/integration/ru ### Multimodal Prompts (--use_mm_prompts) Tests encoder cache transfer: + - Single image query - Multiple images in one request - Mixed image and text @@ -94,19 +95,22 @@ Tests encoder cache transfer: ### Text-Only Prompts (default) Quick sanity check: + - Simple text queries - Text-only explanations - Verifies proxy routing works ## Expected Behavior -### ✅ Test Passes When: +### ✅ Test Passes When + - All disagg outputs match baseline outputs exactly - No errors during instance startup - Encoder cache is properly saved and loaded - Proxy correctly routes requests -### ❌ Test Fails When: +### ❌ Test Fails When + - Outputs differ between baseline and disagg - Server startup fails - Encoder cache not found (should fallback to local execution) @@ -123,14 +127,14 @@ Quick sanity check: ## Requirements - Multiple GPUs (3 for 1E+1P+1D, 2 for 1E+1PD, 1 for baseline) - - 1E+1P+1D is runnable with 2 GPU by assign E and P on the same GPU now. + - 1E+1P+1D is runnable with 2 GPU by assign E and P on the same GPU now. - Multimodal model (e.g., Qwen2.5-VL-3B-Instruct) - Internet access (for accessing vllm test images) - - ## Debugging ### Check Logs + Logs and baseline output are saved in `/tmp/` by default. Can be customized by changing the environment variables. @@ -163,5 +167,3 @@ python test_epd_correctness.py \ --mode disagg \ --baseline_file test_output.txt ``` - - diff --git a/tests/v1/ec_connector/integration/test_epd_correctness.py b/tests/v1/ec_connector/integration/test_epd_correctness.py index 46645e4333c2..d946d72ff3e6 100644 --- a/tests/v1/ec_connector/integration/test_epd_correctness.py +++ b/tests/v1/ec_connector/integration/test_epd_correctness.py @@ -39,7 +39,7 @@ image_1 = ImageAsset("stop_sign").pil_image.resize((1280, 720)) image_2 = ImageAsset("cherry_blossom").pil_image.resize((1280, 720)) -SAMPLE_PROMPTS_MM = [ +SAMPLE_PROMPTS_MM: list[dict] = [ { "messages": [ { @@ -83,7 +83,7 @@ ] # Text-only prompts for mixed testing -SAMPLE_PROMPTS_TEXT = [ +SAMPLE_PROMPTS_TEXT: list[dict] = [ { "messages": [{"role": "user", "content": "What is the capital of France?"}], "description": "Simple text-only query", @@ -237,7 +237,9 @@ def main(): for i, prompt_data in enumerate(test_prompts): print( - f"\nRunning prompt {i + 1}/{len(test_prompts)}: {prompt_data['description']}" + f"\nRunning prompt {i + 1}/{len(test_prompts)}: { + prompt_data['description'] + }" ) output_str = run_chat_completion( From f1ee67ce705242dbfa52f091d14cecfead44b2b2 Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Thu, 23 Oct 2025 11:50:40 +0800 Subject: [PATCH 44/57] Fix docs Signed-off-by: knlnguyen1802 --- vllm/distributed/ec_transfer/ec_connector/base.py | 4 ++-- .../ec_transfer/ec_connector/shared_storage_connector.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vllm/distributed/ec_transfer/ec_connector/base.py b/vllm/distributed/ec_transfer/ec_connector/base.py index aa082539ae61..2b7b14d89b8a 100644 --- a/vllm/distributed/ec_transfer/ec_connector/base.py +++ b/vllm/distributed/ec_transfer/ec_connector/base.py @@ -136,7 +136,7 @@ def start_load_caches( Args: encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal - data hashes (`mm_hash`) to encoder cache tensors. + data hashes (`mm_hash`) to encoder cache tensors. kwargs (dict): Additional keyword arguments for the connector. """ pass @@ -153,7 +153,7 @@ def save_caches( Args: encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal - data hashes (`mm_hash`) to encoder cache tensors. + data hashes (`mm_hash`) to encoder cache tensors. mm_hash (str): The hash of the multimodal data whose cache is being saved. kwargs (dict): Additional keyword arguments for the connector. """ diff --git a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py index 0c2dcb1e72f0..c8388141dcc9 100644 --- a/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py +++ b/vllm/distributed/ec_transfer/ec_connector/shared_storage_connector.py @@ -70,7 +70,7 @@ def start_load_caches(self, encoder_cache, **kwargs) -> None: Args: encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal - data hashes (`mm_hash`) to encoder cache tensors. + data hashes (`mm_hash`) to encoder cache tensors. kwargs (dict): Additional keyword arguments for the connector. """ @@ -104,7 +104,7 @@ def save_caches(self, encoder_cache, mm_hash, **kwargs) -> None: Args: encoder_cache (dict[str, torch.Tensor]): A dictionary mapping multimodal - data hashes (`mm_hash`) to encoder cache tensors. + data hashes (`mm_hash`) to encoder cache tensors. mm_hash (str): The hash of the multimodal data whose cache is being saved. kwargs (dict): Additional keyword arguments for the connector. """ From a8f5dad4893ed78cab63c1ca28c12c304be3e60a Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Fri, 24 Oct 2025 13:54:11 +0800 Subject: [PATCH 45/57] Fix whisper bug Signed-off-by: knlnguyen1802 --- vllm/v1/worker/gpu_model_runner.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/vllm/v1/worker/gpu_model_runner.py b/vllm/v1/worker/gpu_model_runner.py index 27121c55e181..a1a93144d8e3 100644 --- a/vllm/v1/worker/gpu_model_runner.py +++ b/vllm/v1/worker/gpu_model_runner.py @@ -2124,22 +2124,21 @@ def _preprocess( # _prepare_inputs may reorder the batch, so we must gather multi # modal outputs after that to ensure the correct order - if self.supports_mm_inputs: + ec_connector_output = None + + if ( + self.supports_mm_inputs + and is_first_rank + and not self.model_config.is_encoder_decoder + ): + # Run the multimodal encoder if any. with self.maybe_get_ec_connector_output( scheduler_output, encoder_cache=self.encoder_cache, ) as ec_connector_output: - # Run the multimodal encoder if any. self._execute_mm_encoder(scheduler_output) mm_embeds, is_mm_embed = self._gather_mm_embeddings(scheduler_output) - else: - mm_embeds, is_mm_embed = [], None - if ( - self.supports_mm_inputs - and is_first_rank - and not self.model_config.is_encoder_decoder - ): # NOTE(woosuk): To unify token ids and soft tokens (vision # embeddings), we always use embeddings (rather than token ids) # as input to the multimodal model, even when the input is text. @@ -2219,7 +2218,7 @@ def _preprocess( positions, intermediate_tensors, model_kwargs, - ec_connector_output if self.supports_mm_inputs else None, + ec_connector_output, ) def _sample( From 42f43fb86b169718ba629f394196ba6ed154dbef Mon Sep 17 00:00:00 2001 From: knlnguyen1802 Date: Fri, 24 Oct 2025 14:47:24 +0800 Subject: [PATCH 46/57] Fix pre-commit Signed-off-by: knlnguyen1802 --- tests/v1/core/test_scheduler.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/v1/core/test_scheduler.py b/tests/v1/core/test_scheduler.py index bcaec1d7648b..22ba263df5f2 100644 --- a/tests/v1/core/test_scheduler.py +++ b/tests/v1/core/test_scheduler.py @@ -1019,6 +1019,7 @@ def test_kv_connector_basic(): scheduler.kv_cache_manager.block_pool.get_num_free_blocks() == NUM_TOTAL_BLOCKS ) + def test_external_prefix_cache_metrics(): """ Verify connector prefix cache metrics are updated @@ -1078,6 +1079,7 @@ def test_external_prefix_cache_metrics(): assert external_stats.requests == NUM_REQUESTS assert external_stats.preempted_requests == 0 + @pytest.mark.parametrize( "use_ec_connector, ec_role", [(False, None), (True, "ec_consumer")] ) From 563cdd42ecfb03523ab90cf2db124cb784071097 Mon Sep 17 00:00:00 2001 From: herotai214 Date: Mon, 27 Oct 2025 03:42:35 +0000 Subject: [PATCH 47/57] [CI/Build] Fix test_scheduler disable_hybrid_kv_cache_manager flag Signed-off-by: herotai214 --- tests/v1/core/test_scheduler.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/v1/core/test_scheduler.py b/tests/v1/core/test_scheduler.py index e024952b780f..01e90d6ce07f 100644 --- a/tests/v1/core/test_scheduler.py +++ b/tests/v1/core/test_scheduler.py @@ -2387,6 +2387,7 @@ def test_ec_connector_text_only_request(use_kv_connector): use_kv_connector=use_kv_connector, use_ec_connector=True, ec_role="ec_consumer", + disable_hybrid_kv_cache_manager=use_kv_connector, ) NUM_PROMPT_TOKENS = 100 @@ -2431,6 +2432,7 @@ def test_ec_connector_cache_hit_external_load(use_kv_connector): use_kv_connector=use_kv_connector, use_ec_connector=True, ec_role="ec_consumer", + disable_hybrid_kv_cache_manager=use_kv_connector, ) # Create MM request @@ -2483,6 +2485,7 @@ def test_ec_connector_cache_miss_computes_locally(use_kv_connector): use_kv_connector=use_kv_connector, use_ec_connector=True, ec_role="ec_consumer", + disable_hybrid_kv_cache_manager=use_kv_connector, ) # Verify consumer role @@ -2537,6 +2540,7 @@ def test_ec_connector_with_partial_cache_hit_multi_round(use_kv_connector): use_kv_connector=use_kv_connector, use_ec_connector=True, ec_role="ec_consumer", + disable_hybrid_kv_cache_manager=use_kv_connector, ) # Create MM request @@ -2679,6 +2683,7 @@ def test_ec_connector_schedule_multiple_requests(cache_exist, use_kv_connector): use_kv_connector=use_kv_connector, use_ec_connector=True, ec_role="ec_consumer", + disable_hybrid_kv_cache_manager=use_kv_connector, ) mm_hashes_list = [[f"hash_{i}"] for i in range(10)] mm_positions = [[PlaceholderRange(offset=i, length=100)] for i in range(10)] @@ -2770,6 +2775,7 @@ def test_ec_connector_unable_to_allocate(use_kv_connector): num_blocks=NUM_BLOCKS, use_ec_connector=True, ec_role="ec_consumer", + disable_hybrid_kv_cache_manager=use_kv_connector, ) # Mock ec_connector load external cache behavior @@ -2867,6 +2873,7 @@ def test_priority_scheduling_ec_connector_preemption_and_resumption( block_size=16, # standard block size use_ec_connector=True, ec_role="ec_consumer", + disable_hybrid_kv_cache_manager=use_kv_connector, ) # Mock cache hit: Both cache exist in connector (at E->PD initially) From 1c7632894f5107e4b63a35eb6ece3b0bbb83ea2c Mon Sep 17 00:00:00 2001 From: herotai214 Date: Tue, 28 Oct 2025 09:41:38 +0000 Subject: [PATCH 48/57] [CI/Build][Bugfix] Fix and add test ensure init ECConnector before KV cache init Signed-off-by: herotai214 --- .../disagg_1e1p1d_example.sh | 9 +- .../integration/run_epd_correctness_test.sh | 28 ++-- tests/v1/engine/test_engine_core.py | 146 ++++++++++++++++++ vllm/v1/worker/gpu_worker.py | 7 +- 4 files changed, 168 insertions(+), 22 deletions(-) diff --git a/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh index dc103b28bf51..2430719c38ee 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh @@ -90,12 +90,13 @@ mkdir -p $EC_SHARED_STORAGE_PATH # Encoder worker ############################################################################### CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ - --gpu-memory-utilization 0.0 \ + --gpu-memory-utilization 0.01 \ --port "$ENCODE_PORT" \ + --enforce-eager \ --enable-request-id-headers \ --no-enable-prefix-caching \ - --max-num-seqs 128 \ --max-num-batched-tokens 4096 \ + --max-num-seqs 128 \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_producer", @@ -116,7 +117,9 @@ VLLM_NIXL_SIDE_CHANNEL_PORT=5559 \ vllm serve "$MODEL" \ --gpu-memory-utilization 0.7 \ --port "$PREFILL_PORT" \ + --enforce-eager \ --enable-request-id-headers \ + --disable-hybrid-kv-cache-manager \ --max-num-seqs 128 \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", @@ -142,7 +145,9 @@ VLLM_NIXL_SIDE_CHANNEL_PORT=6000 \ vllm serve "$MODEL" \ --gpu-memory-utilization 0.7 \ --port "$DECODE_PORT" \ + --enforce-eager \ --enable-request-id-headers \ + --disable-hybrid-kv-cache-manager \ --max-num-seqs 128 \ --kv-transfer-config '{ "kv_connector": "NixlConnector", diff --git a/tests/v1/ec_connector/integration/run_epd_correctness_test.sh b/tests/v1/ec_connector/integration/run_epd_correctness_test.sh index ba8afd86caaf..3833deceacd0 100644 --- a/tests/v1/ec_connector/integration/run_epd_correctness_test.sh +++ b/tests/v1/ec_connector/integration/run_epd_correctness_test.sh @@ -23,6 +23,10 @@ MODEL="${MODEL:-Qwen/Qwen2.5-VL-3B-Instruct}" # Set 1 to use multimodal prompts; else to use text-only USE_MM_PROMPTS="${USE_MM_PROMPTS:-1}" +MM_FLAG="" +if [ $USE_MM_PROMPTS = "1" ]; then + MM_FLAG="--use_mm_prompts" +fi # GPU configuration GPU_E="${GPU_E:-0}" @@ -99,11 +103,7 @@ run_baseline() { echo "" # Run test in baseline mode - echo "Running baseline correctness test..." - MM_FLAG="" - if [ $USE_MM_PROMPTS = "1" ]; then - MM_FLAG="--use_mm_prompts" - fi + echo "Running baseline..." python "${GIT_ROOT}/tests/v1/ec_connector/integration/test_epd_correctness.py" \ --service_url "http://localhost:$PORT" \ @@ -201,10 +201,6 @@ run_epd_1e_1pd() { # Run test in disagg mode echo "Running EPD (1E+1PD) correctness test..." - MM_FLAG="" - if [ $USE_MM_PROMPTS = "1" ]; then - MM_FLAG="--use_mm_prompts" - fi python "${GIT_ROOT}/tests/v1/ec_connector/integration/test_epd_correctness.py" \ --service_url "http://localhost:$PROXY_PORT" \ @@ -248,6 +244,7 @@ run_baseline_1p_1d() { --enforce-eager \ --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ + --disable-hybrid-kv-cache-manager \ --max-num-seqs 128 \ --kv-transfer-config '{ "kv_connector": "NixlConnector", @@ -265,6 +262,7 @@ run_baseline_1p_1d() { --enforce-eager \ --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ + --disable-hybrid-kv-cache-manager \ --max-num-seqs 128 \ --kv-transfer-config '{ "kv_connector": "NixlConnector", @@ -299,11 +297,7 @@ run_baseline_1p_1d() { echo "All PD (1P+1D) services are up!" # Run test in baseline mode - echo "Running EPD (1E+1P+1D) correctness test..." - MM_FLAG="" - if [ $USE_MM_PROMPTS = "1" ]; then - MM_FLAG="--use_mm_prompts" - fi + echo "Running PD disagg baseline..." python "${GIT_ROOT}/tests/v1/ec_connector/integration/test_epd_correctness.py" \ --service_url "http://localhost:$PROXY_PORT" \ @@ -366,6 +360,7 @@ run_epd_1e_1p_1d() { --enforce-eager \ --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ + --disable-hybrid-kv-cache-manager \ --max-num-seqs 128 \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", @@ -390,6 +385,7 @@ run_epd_1e_1p_1d() { --enforce-eager \ --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ + --disable-hybrid-kv-cache-manager \ --max-num-seqs 128 \ --kv-transfer-config '{ "kv_connector": "NixlConnector", @@ -429,10 +425,6 @@ run_epd_1e_1p_1d() { # Run test in disagg mode echo "Running EPD (1E+1P+1D) correctness test..." - MM_FLAG="" - if [ $USE_MM_PROMPTS = "1" ]; then - MM_FLAG="--use_mm_prompts" - fi python "${GIT_ROOT}/tests/v1/ec_connector/integration/test_epd_correctness.py" \ --service_url "http://localhost:$PROXY_PORT" \ diff --git a/tests/v1/engine/test_engine_core.py b/tests/v1/engine/test_engine_core.py index becedb59f644..9412685c7b51 100644 --- a/tests/v1/engine/test_engine_core.py +++ b/tests/v1/engine/test_engine_core.py @@ -10,6 +10,14 @@ from transformers import AutoTokenizer from vllm import SamplingParams +from vllm.config import ( + CacheConfig, + ECTransferConfig, + KVTransferConfig, + ModelConfig, + SchedulerConfig, + VllmConfig, +) from vllm.engine.arg_utils import EngineArgs from vllm.platforms import current_platform from vllm.utils.torch_utils import set_default_torch_num_threads @@ -431,3 +439,141 @@ def test_engine_core_invalid_request_id_type(): engine_core.add_request(*engine_core.preprocess_add_request(valid_request)) assert len(engine_core.scheduler.waiting) == 1 assert len(engine_core.scheduler.running) == 0 + + +@create_new_process_for_each_test() +@pytest.mark.parametrize( + ("ec_role", "gpu_memory_utilization", "enable_prefix_caching"), + [ + ("ec_producer", 0.01, False), + # NOTE: ec_producer never allows prefix caching + ("ec_consumer", 0.7, True), + ("ec_consumer", 0.7, False), + ], +) +@pytest.mark.parametrize("use_kv_connector", [False, True]) +def test_encoder_instance_zero_kv_cache( + ec_role: str, + gpu_memory_utilization: float, + enable_prefix_caching: bool, + use_kv_connector: bool, +): + """EPD (Encoder-Prefill-Decode) Encoder-cache-specific tests + + This test verifies encoder-only instance initializes with 0 KV cache blocks. + Under EPD disagg mode, Encoder instances (EC producer role) only execute + vision encoder, so they don't need KV cache for text generation. + """ + # Form vllm config + scheduler_config = SchedulerConfig( + max_num_seqs=10, + max_num_batched_tokens=512, + max_model_len=512, + disable_hybrid_kv_cache_manager=True, + ) + model_config = ModelConfig( + model="llava-hf/llava-1.5-7b-hf", # Multimodal model + enforce_eager=True, + trust_remote_code=True, + dtype="float16", + seed=42, + ) + cache_config = CacheConfig( + block_size=16, + gpu_memory_utilization=gpu_memory_utilization, + swap_space=0, + cache_dtype="auto", + enable_prefix_caching=enable_prefix_caching, + ) + kv_transfer_config = ( + KVTransferConfig( + kv_connector="SharedStorageConnector", + kv_role="kv_both", + kv_connector_extra_config={"shared_storage_path": "local_storage"}, + ) + if use_kv_connector + else None + ) + ec_transfer_config = ECTransferConfig( + ec_connector="ECSharedStorageConnector", + ec_role=ec_role, + ec_connector_extra_config={"shared_storage_path": "/tmp/ec_test_encoder"}, + ) + + vllm_config = VllmConfig( + model_config=model_config, + cache_config=cache_config, + scheduler_config=scheduler_config, + kv_transfer_config=kv_transfer_config, + ec_transfer_config=ec_transfer_config, + ) + + executor_class = Executor.get_class(vllm_config) + print(f"executor_class: {executor_class}") + + with set_default_torch_num_threads(1): + engine_core = EngineCore( + vllm_config=vllm_config, executor_class=executor_class, log_stats=True + ) + + # Check encoder cache manager exists + assert engine_core.scheduler.encoder_cache_manager is not None, ( + "encoder_cache_manager should exist" + ) + + if ec_role == "ec_producer": + # Check 1: num_blocks should be 0 + # NOTE: num_blocks=1 as BlockPool always needs a null_block. + kv_cache_config = engine_core.scheduler.kv_cache_manager.kv_cache_config + print(f"kv_cache_config: {kv_cache_config}") + assert kv_cache_config.num_blocks == 1, ( + f"ec_producer should only have 1 KV blocks, " + f"got {kv_cache_config.num_blocks}" + ) + + # Check 2: kv_cache_groups should be empty + assert len(kv_cache_config.kv_cache_groups) == 0, ( + f"ec_producer should have 0 KV cache groups, " + f"got {len(kv_cache_config.kv_cache_groups)}" + ) + + # Check 3: kv_cache_tensors should be empty + assert len(kv_cache_config.kv_cache_tensors) == 0, ( + f"Encoder instance should have 0 KV cache tensors, " + f"got {len(kv_cache_config.kv_cache_tensors)}" + ) + + # Check 4: Verify EC connector is initialized and is producer + assert engine_core.scheduler.ec_connector is not None, ( + "Encoder instance should have EC connector" + ) + assert engine_core.scheduler.ec_connector.is_producer, ( + "Encoder instance EC connector should be producer" + ) + + # Check 5: Verify chunked prefill is disabled + assert not vllm_config.scheduler_config.chunked_prefill_enabled, ( + "Encoder instance should disable chunked prefill (no KV cache)" + ) + + elif ec_role == "ec_consumer": + # Check 1: num_blocks should be > 1 + kv_cache_config = engine_core.scheduler.kv_cache_manager.kv_cache_config + print(f"kv_cache_config: {kv_cache_config}") + assert kv_cache_config.num_blocks > 1, ( + f"ec_consumer should have >1 KV blocks, got {kv_cache_config.num_blocks}" + ) + + # Check 2: kv_cache_groups should NOT be empty + assert len(kv_cache_config.kv_cache_groups) > 0, ( + f"ec_consumer should have KV cache groups, " + f"got {len(kv_cache_config.kv_cache_groups)}" + ) + + # Check 3: Verify EC connector is consumer + assert engine_core.scheduler.ec_connector is not None, ( + "Consumer instance should have EC connector" + ) + assert not engine_core.scheduler.ec_connector.is_producer, ( + "Consumer instance EC connector should be consumer" + ) diff --git a/vllm/v1/worker/gpu_worker.py b/vllm/v1/worker/gpu_worker.py index 904a7d1efd15..908310d64496 100644 --- a/vllm/v1/worker/gpu_worker.py +++ b/vllm/v1/worker/gpu_worker.py @@ -340,8 +340,7 @@ def initialize_from_config(self, kv_cache_config: KVCacheConfig) -> None: connector_vllm_config = copy.copy(self.vllm_config) connector_vllm_config.kv_cache_config = copy.copy(kv_cache_config) ensure_kv_transfer_initialized(connector_vllm_config) - # Init ec connector here - ensure_ec_transfer_initialized(connector_vllm_config) + if self.vllm_config.model_config.enable_sleep_mode: from vllm.device_allocator.cumem import CuMemAllocator @@ -794,3 +793,7 @@ def init_worker_distributed_environment( parallel_config.pipeline_parallel_size, parallel_config.decode_context_parallel_size, ) + + # Init ec connector here before KV caches caches init + # NOTE: We do not init KV caches for Encoder-only instance in EPD disagg mode + ensure_ec_transfer_initialized(vllm_config) From 5e79b0bf86d9462d70995f0ce67c02fade3aeddc Mon Sep 17 00:00:00 2001 From: herotai214 Date: Tue, 4 Nov 2025 17:51:17 +0800 Subject: [PATCH 49/57] Fix scheduler pre-commit Signed-off-by: herotai214 --- vllm/v1/core/sched/scheduler.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index f873f4b13cc8..d8fa5081ad8f 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -8,7 +8,10 @@ from typing import Any from vllm.config import VllmConfig -from vllm.distributed.ec_transfer.ec_connector.base import ECConnectorRole +from vllm.distributed.ec_transfer.ec_connector.base import ( + ECConnectorMetadata, + ECConnectorRole, +) from vllm.distributed.ec_transfer.ec_connector.factory import ECConnectorFactory from vllm.distributed.kv_events import EventPublisherFactory, KVEventBatch from vllm.distributed.kv_transfer.kv_connector.factory import KVConnectorFactory @@ -17,6 +20,7 @@ KVConnectorRole, SupportsHMA, ) +from vllm.distributed.kv_transfer.kv_connector.v1.base import KVConnectorMetadata from vllm.distributed.kv_transfer.kv_connector.v1.metrics import KVConnectorStats from vllm.logger import init_logger from vllm.multimodal import MULTIMODAL_REGISTRY, MultiModalRegistry @@ -668,13 +672,17 @@ def schedule(self) -> SchedulerOutput: # 2. Wrap up all the KV cache load / save ops into an opaque object # 3. Clear the internal states of the connector if self.connector is not None: - meta = self.connector.build_connector_meta(scheduler_output) + meta: KVConnectorMetadata = self.connector.build_connector_meta( + scheduler_output + ) scheduler_output.kv_connector_metadata = meta # Build the connector meta for ECConnector if self.ec_connector is not None: - meta = self.ec_connector.build_connector_meta(scheduler_output) - scheduler_output.ec_connector_metadata = meta + ec_meta: ECConnectorMetadata = self.ec_connector.build_connector_meta( + scheduler_output + ) + scheduler_output.ec_connector_metadata = ec_meta self._update_after_schedule(scheduler_output) return scheduler_output From 2665ff626b1c47510717188cf0cedd998924da6f Mon Sep 17 00:00:00 2001 From: herotai214 Date: Wed, 5 Nov 2025 18:17:02 +0800 Subject: [PATCH 50/57] [Bugfix] Fix num_tokens_to_schedule & Add unit test Signed-off-by: herotai214 --- tests/v1/core/test_scheduler.py | 177 +++++++++++++++++++++++++++++++- tests/v1/core/utils.py | 8 +- vllm/v1/core/sched/scheduler.py | 1 + 3 files changed, 180 insertions(+), 6 deletions(-) diff --git a/tests/v1/core/test_scheduler.py b/tests/v1/core/test_scheduler.py index c53d4010b096..2e450b733c07 100644 --- a/tests/v1/core/test_scheduler.py +++ b/tests/v1/core/test_scheduler.py @@ -22,6 +22,7 @@ ) from vllm.sampling_params import SamplingParams, StructuredOutputsParams from vllm.utils.hashing import sha256 +from vllm.v1.core.encoder_cache_manager import EncoderCacheManager from vllm.v1.core.kv_cache_utils import get_request_block_hasher, init_none_hash from vllm.v1.core.sched.output import CachedRequestData, SchedulerOutput from vllm.v1.core.sched.scheduler import Scheduler @@ -1518,6 +1519,7 @@ def create_requests_with_priority( starting_idx: int = 0, same_prompt: bool = False, block_size: int = 16, + req_ids: list[int] | None = None, ): """Create requests with specified priorities and arrival times.""" assert len(priorities) == num_requests @@ -1553,6 +1555,11 @@ def create_requests_with_priority( # Verify mm items with identical identifier are having mm_position.length seen_hashes: dict[str, int] = {} + if req_ids: + assert len(req_ids) == num_requests + else: + req_ids = [f"{i + starting_idx}" for i in range(num_requests)] + for i in range(num_requests): mm_features = [] @@ -1589,7 +1596,7 @@ def create_requests_with_priority( else [i + starting_idx] * num_tokens ) request = Request( - request_id=f"{i + starting_idx}", + request_id=req_ids[i], prompt_token_ids=prompt_token_ids, sampling_params=sampling_params, pooling_params=None, @@ -2273,6 +2280,7 @@ def _validate_chunked_prefill_settings_for_encoder_decoder( def _assert_right_encoder_cache_allocated( scheduler: Scheduler, + hashes_to_check: list[str] | None = None, requests: list[Request] | None = None, expected_total_allocated: int | None = None, ): @@ -2291,6 +2299,13 @@ def _assert_right_encoder_cache_allocated( # Verify each request with MM data is in cache cached_hashes = set(encoder_cache_manager.cached.keys()) + if hashes_to_check: + missed_hashes = set(hashes_to_check) - cached_hashes + assert not missed_hashes, ( + f"Miss hashes: {missed_hashes} " + f"Existing encoder cache: {encoder_cache_manager.cached}" + ) + for req in requests if requests is not None else []: if req.mm_features: mm_hashes = [f.identifier for f in req.mm_features] @@ -2572,7 +2587,7 @@ def test_ec_connector_with_partial_cache_hit_multi_round(use_kv_connector): # Encoder cache should contain all mm items from request _assert_right_encoder_cache_allocated(scheduler, requests=[request1]) - # Should call update_state_after_alloc for external load + # Should have called update_state_after_alloc for external load scheduler.ec_connector.update_state_after_alloc.assert_called() scheduler.ec_connector.update_state_after_alloc.reset_mock() @@ -2716,7 +2731,7 @@ def test_ec_connector_schedule_multiple_requests(cache_exist, use_kv_connector): ## Encoder-cache-specific checks: # mm_hashes of requests exist in cache after scheduling for all scenario - _assert_right_encoder_cache_allocated(scheduler, requests) + _assert_right_encoder_cache_allocated(scheduler, requests=requests) # Should only call update_state_after_alloc when loaded externally if cache_exist == "connector_only": @@ -2814,7 +2829,7 @@ def test_ec_connector_unable_to_allocate(use_kv_connector): assert len(scheduler.running) == 1 assert len(scheduler.waiting) == 1 - # Should call update_state_after_alloc for external load + # Should have called update_state_after_alloc for external load scheduler.ec_connector.update_state_after_alloc.assert_called_with( scheduler.running[0], 0 ) @@ -3051,7 +3066,7 @@ def test_priority_scheduling_ec_connector_preemption_and_resumption( ## Encoder-cache-specific checks: # mm_hash of request_low exists in cache after scheduling for all scenario - _assert_right_encoder_cache_allocated(scheduler, [request_low]) + _assert_right_encoder_cache_allocated(scheduler, requests=[request_low]) # Should only call update_state_after_alloc when loaded externally if cache_exist == "connector_only": @@ -3080,6 +3095,158 @@ def test_priority_scheduling_ec_connector_preemption_and_resumption( _assert_right_encoder_inputs(output, expected_total_reqs=0) +@pytest.mark.parametrize("use_kv_connector", [False, True]) +def test_ec_connector_allocate_encoder_tokens_with_external_load(use_kv_connector): + """ + Scenario: + - Encoder cache size: 32 + - Request A: 1 feature (12 tokens) → NOT cached remotely. + - Request B: 3 features (3 x 10 tokens) → ALL cached remotely. + + Steps: + 1. Schedule Request A (locally uses 12 tokens). + 2. Schedule Request B (remote cache — no local tokens used) - only schedule 1st and 2nd + 3. Free A's cache, then schedule B again (continuation) - schedule 3rd image + """ + scheduler = create_scheduler( + model="llava-hf/llava-1.5-7b-hf", + max_num_batched_tokens=1024, + enable_prefix_caching=True, + use_kv_connector=use_kv_connector, + block_size=16, + num_blocks=11, # Can hold 160 tokens (first block is null) + use_ec_connector=True, + ec_role="ec_consumer", + disable_hybrid_kv_cache_manager=use_kv_connector, + ) + + # Limit the + scheduler.encoder_cache_manager = EncoderCacheManager(cache_size=32) + + # Create MM request1 + NUM_TOKENS_1 = 50 # NOTE: includes mm tokens + NUM_ENCODER_TOKENS_1 = 12 + mm_hashes_list_1 = [["hash1_1"]] + mm_positions_1 = [[PlaceholderRange(offset=0, length=NUM_ENCODER_TOKENS_1)]] + + request1 = create_requests( + num_requests=1, + num_tokens=NUM_TOKENS_1, + mm_hashes_list=mm_hashes_list_1, + mm_positions=mm_positions_1, + max_tokens=1, # For simplicity + req_ids=["req1"], + )[0] + + # Create MM request1 with 3 MM items + NUM_TOKENS_2 = 40 + NUM_ENCODER_TOKENS_2 = 10 + mm_hashes_list_2 = [["hash2_1", "hash2_2", "hash2_3"]] + mm_positions_2 = [ + [ + PlaceholderRange(offset=0, length=NUM_ENCODER_TOKENS_2), + PlaceholderRange(offset=12, length=NUM_ENCODER_TOKENS_2), + PlaceholderRange(offset=24, length=NUM_ENCODER_TOKENS_2), + ] + ] + + request2 = create_requests( + num_requests=1, + num_tokens=NUM_TOKENS_2, + mm_hashes_list=mm_hashes_list_2, + mm_positions=mm_positions_2, + max_tokens=10, + req_ids=["req2"], + )[0] + + # Mock cache hit: MM of request1 NOT cached remotely, request2 cached remotely + scheduler.ec_connector.has_caches = Mock( + side_effect=lambda req: [True, True, True] if req == request2 else [False] + ) + scheduler.ec_connector.update_state_after_alloc = Mock( + wraps=scheduler.ec_connector.update_state_after_alloc + ) + + scheduler.add_request(request1) + scheduler.add_request(request2) + output = scheduler.schedule() + + # Now, since encoder cache manager can only store 32 tokens + # It should allocated mm item hash1_1, hash2_1 and hash2_2 + scheduled_tokens = output.num_scheduled_tokens[request1.request_id] + assert scheduled_tokens == NUM_TOKENS_1 + assert scheduler.get_num_unfinished_requests() == 2 + + # Encoder cache should contain mm item from request1 + _assert_right_encoder_cache_allocated( + scheduler, hashes_to_check=['hash1_1', 'hash2_1', 'hash2_2'] + ) + + # request2's 2nd mm item is the last call of update_state_after_alloc + scheduler.ec_connector.update_state_after_alloc.assert_called_with(request2, 1) + scheduler.ec_connector.update_state_after_alloc.reset_mock() + + # ECConnector should carry metadata of hash2_1 and hash2_2 ONLY + _assert_right_ec_connector_metadata( + output, mm_features_list=[request2.mm_features[0], request2.mm_features[1]] + ) + + # Should schedule ONLY 1 encoder input + _assert_right_encoder_inputs( + output, + requests=[request1], + expected_encoder_inputs=[[0]], # index 0 of the mm item of request1 + expected_total_reqs=1, + ) + + # Simulate model execution 1 step + model_output = ModelRunnerOutput( + req_ids=[request1.request_id, request2.request_id], + req_id_to_index={request1.request_id: 0, request2.request_id: 1}, + sampled_token_ids=[[100], [121]], + # spec_token_ids=None, + logprobs=None, + prompt_logprobs_dict={}, + pooler_output=[], + ) + scheduler.update_from_output(output, model_output) + + # request1 is finished after outputing 1 token + # Finish request + scheduler.finish_requests(request1.request_id, RequestStatus.FINISHED_LENGTH_CAPPED) + assert scheduler.get_num_unfinished_requests() == 1 + + # Schedule again + # Now request1's encoder cache should be freed -> hash2_3 can be scheduled and allocated + output = scheduler.schedule() + + # Check + # Should schedule all tokens + scheduled_tokens = output.num_scheduled_tokens[request2.request_id] + print(f"Hero: scheduled_tokens for req2: {scheduled_tokens}") + print(f"hero: num_scheduled_tokens 2: {output.num_scheduled_tokens}") + + # Encoder cache should contain all mm items from request2 + _assert_right_encoder_cache_allocated(scheduler, requests=[request2]) + + # request2's 3rd mm item is the ONLY call of update_state_after_alloc + scheduler.ec_connector.update_state_after_alloc.assert_called_with(request2, 2) + scheduler.ec_connector.update_state_after_alloc.assert_called_once() + + scheduler.ec_connector.update_state_after_alloc.reset_mock() + + # ECConnector should carry metadata for hash2_3 ONLY + _assert_right_ec_connector_metadata( + output, mm_features_list=[request2.mm_features[2]] + ) + + # Should schedule no encoder input + _assert_right_encoder_inputs( + output, + expected_total_reqs=0, + ) + + # ============================================================================== # EPD (Encoder-Prefill-Decode) Encoder-cache-specific tests end # ============================================================================== diff --git a/tests/v1/core/utils.py b/tests/v1/core/utils.py index 926c6fa260be..00a370b7517f 100644 --- a/tests/v1/core/utils.py +++ b/tests/v1/core/utils.py @@ -163,6 +163,7 @@ def create_requests( prompt_logprobs: int | None = None, same_prompt: bool = False, block_size: int = 16, + req_ids: list[int] | None = None, ) -> list[Request]: global _none_hash_initialized if not _none_hash_initialized: @@ -191,6 +192,11 @@ def create_requests( # Verify mm items with identical identifier are having mm_position.length seen_hashes: dict[str, int] = {} + if req_ids: + assert len(req_ids) == num_requests + else: + req_ids = [f"{i}" for i in range(num_requests)] + for i in range(num_requests): mm_features = [] @@ -223,7 +229,7 @@ def create_requests( prompt_token_ids = [0] * num_tokens if same_prompt else [i] * num_tokens request = Request( - request_id=f"{i}", + request_id=req_ids[i], prompt_token_ids=prompt_token_ids, sampling_params=sampling_params, pooling_params=None, diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index d8fa5081ad8f..d347cffe6277 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -898,6 +898,7 @@ def _try_schedule_encoder_inputs( if self.ec_connector is not None and remote_cache_has_item[i]: mm_hashes_to_schedule.add(request.mm_features[i].identifier) external_load_encoder_input.append(i) + num_tokens_to_schedule += num_encoder_tokens continue num_tokens_to_schedule += num_encoder_tokens From 8e04ca93c1b19df3e695cc40e0143e11ae04ae52 Mon Sep 17 00:00:00 2001 From: herotai214 Date: Thu, 6 Nov 2025 09:58:40 +0800 Subject: [PATCH 51/57] Fix pre-commit Signed-off-by: herotai214 --- tests/v1/core/test_scheduler.py | 16 ++++++++-------- tests/v1/core/utils.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/v1/core/test_scheduler.py b/tests/v1/core/test_scheduler.py index 2e450b733c07..aea6a62a6aae 100644 --- a/tests/v1/core/test_scheduler.py +++ b/tests/v1/core/test_scheduler.py @@ -1519,7 +1519,7 @@ def create_requests_with_priority( starting_idx: int = 0, same_prompt: bool = False, block_size: int = 16, - req_ids: list[int] | None = None, + req_ids: list[str] | None = None, ): """Create requests with specified priorities and arrival times.""" assert len(priorities) == num_requests @@ -2304,8 +2304,8 @@ def _assert_right_encoder_cache_allocated( assert not missed_hashes, ( f"Miss hashes: {missed_hashes} " f"Existing encoder cache: {encoder_cache_manager.cached}" - ) - + ) + for req in requests if requests is not None else []: if req.mm_features: mm_hashes = [f.identifier for f in req.mm_features] @@ -3105,7 +3105,7 @@ def test_ec_connector_allocate_encoder_tokens_with_external_load(use_kv_connecto Steps: 1. Schedule Request A (locally uses 12 tokens). - 2. Schedule Request B (remote cache — no local tokens used) - only schedule 1st and 2nd + 2. Schedule Request B (remote cache) - only schedule 1st and 2nd 3. Free A's cache, then schedule B again (continuation) - schedule 3rd image """ scheduler = create_scheduler( @@ -3120,7 +3120,7 @@ def test_ec_connector_allocate_encoder_tokens_with_external_load(use_kv_connecto disable_hybrid_kv_cache_manager=use_kv_connector, ) - # Limit the + # Limit the number of availiable slots of EncoderCacheManager scheduler.encoder_cache_manager = EncoderCacheManager(cache_size=32) # Create MM request1 @@ -3179,7 +3179,7 @@ def test_ec_connector_allocate_encoder_tokens_with_external_load(use_kv_connecto # Encoder cache should contain mm item from request1 _assert_right_encoder_cache_allocated( - scheduler, hashes_to_check=['hash1_1', 'hash2_1', 'hash2_2'] + scheduler, hashes_to_check=["hash1_1", "hash2_1", "hash2_2"] ) # request2's 2nd mm item is the last call of update_state_after_alloc @@ -3216,8 +3216,8 @@ def test_ec_connector_allocate_encoder_tokens_with_external_load(use_kv_connecto scheduler.finish_requests(request1.request_id, RequestStatus.FINISHED_LENGTH_CAPPED) assert scheduler.get_num_unfinished_requests() == 1 - # Schedule again - # Now request1's encoder cache should be freed -> hash2_3 can be scheduled and allocated + # Schedule again; Now request1's encoder cache should be freed + # -> hash2_3 can be scheduled and allocated output = scheduler.schedule() # Check diff --git a/tests/v1/core/utils.py b/tests/v1/core/utils.py index 00a370b7517f..eccfefc8ea6e 100644 --- a/tests/v1/core/utils.py +++ b/tests/v1/core/utils.py @@ -163,7 +163,7 @@ def create_requests( prompt_logprobs: int | None = None, same_prompt: bool = False, block_size: int = 16, - req_ids: list[int] | None = None, + req_ids: list[str] | None = None, ) -> list[Request]: global _none_hash_initialized if not _none_hash_initialized: From 2353348a21c721b0840775af13e904433f2f9d17 Mon Sep 17 00:00:00 2001 From: herotai214 Date: Thu, 6 Nov 2025 03:39:42 +0000 Subject: [PATCH 52/57] [Bugfix] Add logs to EPD proxy at during runtime Signed-off-by: herotai214 --- .../disaggregated_encoder/disagg_epd_proxy.py | 221 +++++++++++++----- 1 file changed, 163 insertions(+), 58 deletions(-) diff --git a/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py index 70b9538a2f66..3c6769484e62 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py +++ b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py @@ -87,17 +87,22 @@ def extract_mm_items(request_data: dict) -> list[dict]: async def fanout_encoder_primer( orig_request: dict, e_urls: list[str], - request_id: str, + req_id: str, ) -> None: """ 1. Build one request *per MM item* with all text removed. 2. Send them concurrently to the encode cluster. 3. Raise if any of them fails. """ + logger.info("[%s] Processing multimodal items...", req_id) + mm_items = extract_mm_items(orig_request) if not mm_items: + logger.info("[%s] No multimodal items, skipping encoder", req_id) return # nothing to do + logger.info("[%s] got %d multimodal items...", req_id, len(mm_items)) + tasks = [] # Round-robin over encode servers to distribute load a bit @@ -105,7 +110,7 @@ async def fanout_encoder_primer( for idx, (item, target_url) in enumerate(zip(mm_items, url_cycle)): # Derive a *child* request id: :: - child_req_id = f"{request_id}:{idx}:{uuid.uuid4().hex[:6]}" + child_req_id = f"{req_id}:{idx}:{uuid.uuid4().hex[:6]}" headers = {"x-request-id": child_req_id} encoder_req = { @@ -129,21 +134,39 @@ async def fanout_encoder_primer( results = await asyncio.gather(*tasks, return_exceptions=True) # Fail fast if any sub-request failed - for r in results: + for idx, r in enumerate(results): if isinstance(r, Exception): - logger.error("Encoder request raised: %s", r) - raise HTTPException(status_code=502, detail=str(r)) + logger.error( + "[%s] Encoder request #%d raised exception: %s", + req_id, + idx, + r, + exc_info=r, + ) + raise HTTPException( + status_code=502, detail=f"Encoder request failed: {str(r)}" + ) if r.status != 200: try: detail = await r.text() except Exception: detail = "" - logger.error("Encoder request returned %s: %s", r.status, detail) + logger.error( + "[%s] Encoder request #%d returned status %s: %s", + req_id, + idx, + r.status, + detail, + ) raise HTTPException( status_code=r.status, detail=f"Encoder request failed: {detail}", ) + logger.info( + "[%s] All %d encoder requests completed successfully", req_id, len(mm_items) + ) + async def maybe_prefill( req_data: dict, @@ -156,13 +179,15 @@ async def maybe_prefill( - Else, skip and return the original request data for decode """ if p_url: + logger.info("[%s] Processing through prefill: %s", req_id, p_url) + prefill_response = await process_prefill_stage(req_data, p_url, req_id) # for nixl connector to facilitate kv transfer... prefill_response_json = await prefill_response.json() kv_transfer_params = prefill_response_json.get("kv_transfer_params", {}) if kv_transfer_params: req_data["kv_transfer_params"] = kv_transfer_params - logger.debug("kv_transfer_params: %s", kv_transfer_params) + # logger.info("[%s] Received kv_transfer_params from prefill: %s", req_id, kv_transfer_params) return req_data else: @@ -175,7 +200,7 @@ async def process_prefill_stage( req_id: str, ) -> dict: """Process request through Prefill stage and return kv_transfer_params""" - logger.debug("Processing through prefill for req_id: %s/ url: %s", req_id, p_url) + logger.info("[%s] Sending prefill request to: %s", req_id, p_url) prefill_request = req_data.copy() prefill_request["kv_transfer_params"] = { @@ -202,11 +227,17 @@ async def process_prefill_stage( if prefill_response.status != 200: error_text = await prefill_response.text() + logger.error( + "[%s] Prefill request failed with status %d: %s", + req_id, + prefill_response.status, + error_text, + ) raise HTTPException( status_code=prefill_response.status, detail={"error": "Prefill request failed", "message": error_text}, ) - logger.debug("Prefill processing completed successfully for req_id: %s", req_id) + logger.info("[%s] Prefill request completed successfully", req_id) return prefill_response @@ -218,6 +249,52 @@ async def process_prefill_stage( ) from e +############################################################################### +# Middleware for request/response logging +############################################################################### + + +@app.middleware("http") +async def log_requests(request: Request, call_next): + """Middleware to log all incoming requests and responses""" + req_id = request.headers.get("x-request-id", str(uuid.uuid4())) + + # Log incoming request + logger.info( + ">>> [%s] %s %s from %s", + req_id, + request.method, + request.url.path, + request.client.host if request.client else "unknown", + ) + + try: + # Process request + response = await call_next(request) + + # Log response + logger.info( + "<<< [%s] %s %s completed with status %d", + req_id, + request.method, + request.url.path, + response.status_code, + ) + + return response + except Exception as e: + # Log errors + logger.error( + "!!! [%s] %s %s failed with error: %s", + req_id, + request.method, + request.url.path, + str(e), + exc_info=True, + ) + raise + + ############################################################################### # FastAPI lifecycle ############################################################################### @@ -254,49 +331,68 @@ async def on_shutdown() -> None: async def forward_non_stream( req_data: dict, req_id: str, e_urls: list[str], p_url: str, d_url: str ) -> dict: - # Step 1: Process through Encoder instance (if has MM input) - await fanout_encoder_primer(req_data, e_urls, req_id) + try: + # Step 1: Process through Encoder instance (if has MM input) + await fanout_encoder_primer(req_data, e_urls, req_id) - # Step 2: Process through Prefill instance - req_data = await maybe_prefill(req_data, p_url, req_id) + # Step 2: Process through Prefill instance + req_data = await maybe_prefill(req_data, p_url, req_id) - # Step 3: Process through Decode instance - logger.debug("Getting response from decode for req_id: %s/ url: %s", req_id, d_url) - headers = {"x-request-id": req_id} + # Step 3: Process through Decode instance + logger.info("[%s] Forwarding to decode: %s", req_id, d_url) + headers = {"x-request-id": req_id} - # Non-streaming response - async with decode_session.post( - f"{d_url}/v1/chat/completions", json=req_data, headers=headers - ) as resp: - resp.raise_for_status() - return await resp.json() + # Non-streaming response + async with decode_session.post( + f"{d_url}/v1/chat/completions", json=req_data, headers=headers + ) as resp: + resp.raise_for_status() + return await resp.json() + + except HTTPException: + raise + except Exception as e: + logger.error( + "[%s] Error in forward_non_stream: %s", req_id, str(e), exc_info=True + ) + raise HTTPException(status_code=500, detail=f"Proxy error: {str(e)}") from e async def forward_stream( req_data: dict, req_id: str, e_urls: list[str], p_url: str, d_url: str ) -> AsyncIterator[str]: - # Step 1: Process through Encoder instance (if has MM input) - await fanout_encoder_primer(req_data, e_urls, req_id) - - # Step 2: Process through Prefill instance - req_data = await maybe_prefill(req_data, p_url, req_id) - - # Step 3: Process through Decode instance - logger.debug( - "Streaming response from decode for req_id: %s/ url: %s", req_id, d_url - ) - headers = {"x-request-id": req_id} - - # Streaming response - async with decode_session.post( - f"{d_url}/v1/chat/completions", - json=req_data, - headers=headers, - ) as resp: - resp.raise_for_status() - async for chunk in resp.content.iter_chunked(1024): - if chunk: - yield chunk.decode("utf-8", errors="ignore") + try: + # Step 1: Process through Encoder instance (if has MM input) + await fanout_encoder_primer(req_data, e_urls, req_id) + + # Step 2: Process through Prefill instance + req_data = await maybe_prefill(req_data, p_url, req_id) + + # Step 3: Process through Decode instance + logger.info("[%s] Starting streaming from decode: %s", req_id, d_url) + headers = {"x-request-id": req_id} + + # Streaming response + async with decode_session.post( + f"{d_url}/v1/chat/completions", + json=req_data, + headers=headers, + ) as resp: + resp.raise_for_status() + async for chunk in resp.content.iter_chunked(1024): + if chunk: + yield chunk.decode("utf-8", errors="ignore") + + logger.info("[%s] Streaming completed", req_id) + + except HTTPException: + logger.error("[%s] HTTPException in forward_stream", req_id, exc_info=True) + raise + except Exception as e: + logger.error("[%s] Error in forward_stream: %s", req_id, str(e), exc_info=True) + raise HTTPException( + status_code=500, detail=f"Proxy streaming error: {str(e)}" + ) from e ############################################################################### @@ -306,22 +402,31 @@ async def forward_stream( @app.post("/v1/chat/completions") async def chat_completions(request: Request): - req_data = await request.json() - req_id = request.headers.get("x-request-id", str(uuid.uuid4())) + try: + req_data = await request.json() + req_id = request.headers.get("x-request-id", str(uuid.uuid4())) - e_urls = app.state.e_urls # we want the full list for fan-out - p_url = random.choice(app.state.p_urls) if app.state.p_urls else None - d_url = random.choice(app.state.d_urls) + e_urls = app.state.e_urls # we want the full list for fan-out + p_url = random.choice(app.state.p_urls) if app.state.p_urls else None + d_url = random.choice(app.state.d_urls) - is_streaming = req_data.get("stream", False) + is_streaming = req_data.get("stream", False) - if is_streaming: - return StreamingResponse( - forward_stream(req_data, req_id, e_urls, p_url, d_url), - media_type="text/event-stream", - ) - result = await forward_non_stream(req_data, req_id, e_urls, p_url, d_url) - return JSONResponse(content=result) + if is_streaming: + return StreamingResponse( + forward_stream(req_data, req_id, e_urls, p_url, d_url), + media_type="text/event-stream", + ) + result = await forward_non_stream(req_data, req_id, e_urls, p_url, d_url) + return JSONResponse(content=result) + + except HTTPException: + raise + except Exception as e: + logger.error("Error in chat_completions endpoint: %s", str(e), exc_info=True) + raise HTTPException( + status_code=500, detail=f"Request processing error: {str(e)}" + ) from e @app.get("/v1/models") @@ -512,5 +617,5 @@ async def stop_profile(request: Request): port=args.port, log_level="info", loop="uvloop", - access_log=False, + access_log=True, ) From 69515d876ec0f2bcf125e3338a9c25b0e7ece21b Mon Sep 17 00:00:00 2001 From: herotai214 Date: Thu, 6 Nov 2025 06:27:36 +0000 Subject: [PATCH 53/57] Edit Readme & comments Signed-off-by: herotai214 --- tests/v1/ec_connector/integration/README.md | 20 ++++++++++--------- .../integration/run_epd_correctness_test.sh | 8 ++++---- .../integration/test_epd_correctness.py | 9 +++++---- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/tests/v1/ec_connector/integration/README.md b/tests/v1/ec_connector/integration/README.md index 03cb2e9a178d..c38f80f4dd58 100644 --- a/tests/v1/ec_connector/integration/README.md +++ b/tests/v1/ec_connector/integration/README.md @@ -22,23 +22,23 @@ Please refer to [Disaggregated Encoder Feature](../../../docs/features/disagg_en ## Usage -### Text-Only Prompts +### Multimodal Prompts (Default) ```bash cd vllm -USE_MM_PROMPTS=0 ./tests/v1/ec_connector/integration/run_epd_correctness_test.sh +./tests/v1/ec_connector/integration/run_epd_correctness_test.sh ``` -This runs a quick test with text-only prompts to verify the setup works. +This runs the test with actual multimodal (image) prompts. -### Full Test (With Multimodal Prompts) +### Text-Only Prompts ```bash cd vllm -./tests/v1/ec_connector/integration/run_epd_correctness_test.sh +USE_MM_PROMPTS=0 ./tests/v1/ec_connector/integration/run_epd_correctness_test.sh ``` -This runs the full test with actual multimodal (image) prompts. +This runs a quick test with text-only prompts to verify the setup works. ### Custom Configuration @@ -158,12 +158,14 @@ python test_epd_correctness.py \ --service_url http://localhost:8000 \ --model_name Qwen/Qwen2.5-VL-3B-Instruct \ --mode baseline \ - --baseline_file test_output.txt + --baseline_file test_output.txt \ + --use_mm_prompts -# Disagg only (requires baseline output file) +# Disagg only (requires baseline output file!) python test_epd_correctness.py \ --service_url http://localhost:8000 \ --model_name Qwen/Qwen2.5-VL-3B-Instruct \ --mode disagg \ - --baseline_file test_output.txt + --baseline_file test_output.txt \ + --use_mm_prompts ``` diff --git a/tests/v1/ec_connector/integration/run_epd_correctness_test.sh b/tests/v1/ec_connector/integration/run_epd_correctness_test.sh index 3833deceacd0..5bc4afe258e1 100644 --- a/tests/v1/ec_connector/integration/run_epd_correctness_test.sh +++ b/tests/v1/ec_connector/integration/run_epd_correctness_test.sh @@ -32,7 +32,7 @@ fi GPU_E="${GPU_E:-0}" GPU_P="${GPU_P:-1}" GPU_D="${GPU_D:-2}" -GPU_SINGLE="${GPU_SINGLE:-$GPU_E}" +GPU_SINGLE="${GPU_SINGLE:-$GPU_P}" GPU_PD="${GPU_PD:-$GPU_P}" # Port @@ -210,7 +210,7 @@ run_epd_1e_1pd() { $MM_FLAG # Cleanup - echo "✅✅ 1E+1PD Correctness Test PASSED" + echo "✓✓ 1E+1PD Correctness Test finished" echo "Stopping EPD (1E+1PD) instances..." for pid in "${PIDS[@]}"; do kill $pid 2>/dev/null || true @@ -434,7 +434,7 @@ run_epd_1e_1p_1d() { $MM_FLAG # Cleanup - echo "✅✅ 1E+1P+1D Correctness Test PASSED" + echo "✓✓ 1E+1P+1D Correctness Test finished" echo "Stopping EPD (1E+1P+1D) instances..." for pid in "${PIDS[@]}"; do kill $pid 2>/dev/null || true @@ -466,5 +466,5 @@ rm -f "$BASELINE_FILE" rm -f "$BASELINE_PD_FILE" echo "================================" -echo "✅✅✅ All EPD correctness tests passed!" +echo "✓✓ All EPD correctness tests finished!" echo "================================" diff --git a/tests/v1/ec_connector/integration/test_epd_correctness.py b/tests/v1/ec_connector/integration/test_epd_correctness.py index d946d72ff3e6..fafa60a5308e 100644 --- a/tests/v1/ec_connector/integration/test_epd_correctness.py +++ b/tests/v1/ec_connector/integration/test_epd_correctness.py @@ -289,15 +289,16 @@ def main(): disagg_output = output_strs[key] if baseline_output == disagg_output: - print(f"✓ {key}: MATCH") + print(f"✅ {key}: MATCH") else: - print(f"✗ {key}: MISMATCH") + print(f"❌ {key}: MISMATCH") print(f" Baseline: {baseline_output}") print(f" Disagg: {disagg_output}") all_match = False - assert all_match, "Disagg outputs do not match baseline!" - print("\n✅ All outputs match! Test PASSED") + assert all_match, "❌❌Disagg outputs do not match baseline!❌❌" + if all_match: + print("\n✅ All outputs match! Test PASSED") if __name__ == "__main__": From 9f71ddfd2af4b7fa0d514d106e07348e3695bb95 Mon Sep 17 00:00:00 2001 From: herotai214 Date: Thu, 6 Nov 2025 07:30:52 +0000 Subject: [PATCH 54/57] fix pre-commit Signed-off-by: herotai214 --- .../disaggregated_encoder/disagg_epd_proxy.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py index 3c6769484e62..40b2fb84d1f8 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py +++ b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py @@ -187,7 +187,6 @@ async def maybe_prefill( kv_transfer_params = prefill_response_json.get("kv_transfer_params", {}) if kv_transfer_params: req_data["kv_transfer_params"] = kv_transfer_params - # logger.info("[%s] Received kv_transfer_params from prefill: %s", req_id, kv_transfer_params) return req_data else: @@ -284,13 +283,12 @@ async def log_requests(request: Request, call_next): return response except Exception as e: # Log errors - logger.error( + logger.exception( "!!! [%s] %s %s failed with error: %s", req_id, request.method, request.url.path, str(e), - exc_info=True, ) raise @@ -352,9 +350,7 @@ async def forward_non_stream( except HTTPException: raise except Exception as e: - logger.error( - "[%s] Error in forward_non_stream: %s", req_id, str(e), exc_info=True - ) + logger.exception("[%s] Error in forward_non_stream: %s", req_id, str(e)) raise HTTPException(status_code=500, detail=f"Proxy error: {str(e)}") from e @@ -386,10 +382,10 @@ async def forward_stream( logger.info("[%s] Streaming completed", req_id) except HTTPException: - logger.error("[%s] HTTPException in forward_stream", req_id, exc_info=True) + logger.exception("[%s] HTTPException in forward_stream", req_id) raise except Exception as e: - logger.error("[%s] Error in forward_stream: %s", req_id, str(e), exc_info=True) + logger.exception("[%s] Error in forward_stream: %s", req_id, str(e)) raise HTTPException( status_code=500, detail=f"Proxy streaming error: {str(e)}" ) from e @@ -423,7 +419,7 @@ async def chat_completions(request: Request): except HTTPException: raise except Exception as e: - logger.error("Error in chat_completions endpoint: %s", str(e), exc_info=True) + logger.exception("Error in chat_completions endpoint: %s", str(e)) raise HTTPException( status_code=500, detail=f"Request processing error: {str(e)}" ) from e From 1659fc4a74c0f1f2d80ecd0ac0fec5a50645e540 Mon Sep 17 00:00:00 2001 From: herotai214 Date: Fri, 7 Nov 2025 16:50:35 +0800 Subject: [PATCH 55/57] [Misc] Support local mm, Increase encoder budget in test & better error handling Signed-off-by: herotai214 --- .../disaggregated_encoder/disagg_epd_proxy.py | 4 ++- tests/v1/ec_connector/integration/hato.jpg | Bin 0 -> 841034 bytes .../integration/run_epd_correctness_test.sh | 14 ++++++++-- .../integration/test_epd_correctness.py | 10 ++++---- vllm/v1/core/sched/scheduler.py | 24 ++++++++++++++++++ 5 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 tests/v1/ec_connector/integration/hato.jpg diff --git a/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py index 40b2fb84d1f8..a150514d5e9f 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py +++ b/examples/online_serving/disaggregated_encoder/disagg_epd_proxy.py @@ -49,7 +49,9 @@ # FastAPI app & global state ############################################################################### -logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s") +logging.basicConfig( + level=logging.DEBUG, format="%(asctime)s %(levelname)s: %(message)s" +) logger = logging.getLogger("proxy") app = FastAPI() diff --git a/tests/v1/ec_connector/integration/hato.jpg b/tests/v1/ec_connector/integration/hato.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9c7e390e7d7f68824cfa198d8ceb57f9174a1137 GIT binary patch literal 841034 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

K91Am+`;mV94d_{xWdn( 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%0Dclb!t>c~)gbRICnbjVI4rv5h$r{%e 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

kVf?gpvbGlSw}7Ok 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®qHD$OE(&lSp}TPJ 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�E-mRXZNpTe0HAD2OpQ=NIgjaZ*D@ZY>H_s+o&!TH$}HvaNfM848xE&IaqF8?sYWK~oz|_Jjf4 z$K&p-;UV1jQBP0YDk)JqA&OE(flp+Pz0lGJM(lY~#Bc2?k!0qmHIfHlpP^1IHa*bH zu>#*!J0#B1oyX`^D-!m-l+eyafx2th(l2|co$NkPaZLqDrdR+Z2eM%fXu=v9oYQNN zj%g2XKUL2p;&etzLPIGWlk`PK{hsEG*#=q%8B#IMu>R_82c}!m*8^rd{I0BHWgCY! zD!M$Ii(GkA!%?*DH_7goj_nP|uc&L9;@!DGRnsy?Tm___7EID?E~{pxb8*>HG7-ki ztkF6*6Juo7O5oreuWIS{Hvv@CQkD{IZ`pLlX`J$n3de3276nfXrGx@X02eUW;Y}Ow z&vit}wd}NxYud#V9M;9kscVaHrewGmAQWr`xR5vkQeQU)!2=xE9N*}tWT5>Ppr#bk z2)Q^)K*1S2sN*-lDa_Bo`XyrzWS0Fx{{U3&!N6fL#F5?NnJ%MB{3td|>rrf*D_KzF#4;DxY=K?^Jh7*N#LLmY3r zhab9UNofhmv&=R97C1xi+q%T+x^!TY2tP&Wn(Xq{N?RLA7bBIMpGuGd=U<-dnl4L^iGl0Om5isZLsp4)m=`=#?v6&MV5O~ zZ{$5arrU-7t0}5WC03{D4a9EZ=u*h-0j9QF$31STP~#To8xxNKEhR+s?)O|+_gXH4 zp==}G20~t;(&B86djPTQ6{8mta+-Q(b6M)@`04#P-D=HXN_lvCBU%>vh1$*`iwNTzKxLgPKwgGiXgICM`S-?FNP8C@A6q_lTj%A)}n z#gBEd$)P6@zr?LzRZB>JOwfBt2auCNtCpa)NnS{>!7DYdO8Wgzdv02;w8H2jX#n6M zIV%cHMvqC-by%W`&mzMgMKpDA$uKQ=H}bsr)=2%#+;VP-qpgw+u5pZS^lA@rHr-3%>lt@H7#;yM&<%=eDboIhN)Xx^AjBBStR7ELq;qoTGb+C z&H#cgfYLR6lFB!GU4eB>>S~IbhY1M|1zc%bNo#IFxa6siUq+iwtbE0-Wx#P4UXRim z92GBXrWqr@V!Yc*V0d~kxRqk>F`ZS92Z>tZC)N7SYkQ^_k1S{IzltjPwT=Q+n|7CBei z{-oy_TGw)N786+|&Gj-ap*6FjFH~AdtFzYM8@M>ig1Vww<`Nu9;3_Q;3aY^y&JSg& zq0`MMVUQnp3n&WZOv*)1HBC{2hYP4Gs3c>+u|9CMRTPecsT(|TpH09z!{u4CM)lhy zfu7yhzrxQ<%1N!2y)mOQX2SBpyOOuBlu%O$z_Ht6v-(!uGf-n+mfwZ2)~Mptsl<>x z2RWm_5`l+;vXy~S%pKr0l3X_M?ILyrH z`n1i1b4d0$|`H^Ff>@PU#WMcr$=c6SK}!)LR@e_JwuxI|9Ys+EJuy3gAZ2*ZTy+?J_?qk^ddsXt z%zGntIOmn+I=-U%iCp4IP{}_?tRgIRE`57Tdll*ZDOll7);Q;oyt6n&Q1jK`}>0_FND}+PrJ2s)*GGrfp|jEw@JN2hb7DZvD3z zMi<7$npS!Z0b^jht+*TnbQ+9pdr2dUWn<*jBzY1rkkV{a#yMnRa~yBT%HOjWiVo_X zT9Qbljlf^IUS&q+zo{7nM|5&KB^}i*t&BLhlih1NA4t=yDB!E~hpIU?@7*ThwmfT~ zO=XVhy6Bx48z*Jk^;Ei>^=(RbJhjbhhi>cAy6Z)TzJ`&_XeI{&4}?t~l}^f0c7O=R z72%uo*(u{nT09F@ps$2Wa_fLdy3AA4RoA_tmpQS|3)*`2nwBOL85@DI1H#8>G!Vs9 z@Yap4cI04vj9rBgPN2bPWPuqvvGYHB93M_U0!s`Vs0 zOJa5{Pe6i3 zh>eKCt<-DdiNqIJ9ED5%xYkA-96mrRHLvStR#}eAcsEs)v`#B#f{LlNx{S2g!*_i` zt*(jm)kaV()@JI5q;*Ld)G)o-X**rw#cj3Pc1Rq~{MmVV@xFF;VU_5t)jEZarG`jb zx!{0L{Hwh`U;NII>Pq`Ljp2FbusXq($&T({2U~q`Za(4@=x_DhvHrEVryEyFUS|p~VnyM1!u#yf>!Zw1L)YCMR z!B_n|PT1oub3q$yR9cRoJD%YaPTQLsau${$qmjQ(Ff-CMxR(W9~Lp z;-JYObB_mv?bwPaHYUq6_KT3Y`gD)x_wKYBB_wi<%mDl=p+E~R;4#Ru$yhAOXgXu5 z>#i^yJ0;iLX>Qix&F;02iWnl?0J}~8RyV9_;tg|!ujk4Vidz{?^k?cTWvMNXeZ}lW z&>F{2nuhw(--J(3HMKH0+dHtgG&J!3P_|GqKV(Xb7`DyEL?pR zKjD;O3W}#&_;NHg!9}Xloj<6mjX67R9M+EnDCGT}7sXLldZVk^H36x=xC<5M-ASoQ z43C%)1O1^xNvzcv9b!WWvw-ZXx{7yIQZ=j>wlJCyuEoha(Vo>0=IeySf=(UswS5&s z>AkXya8_Q5neCabm$|a^4FhCUb|ep~=*JX7O_FLsrSEf2-NPYMM>AUT$9s=uKEGY* z?hQHMtmo#Bsl1f>h>qE+b$6&osB#5`(ACnl(Ks^3!wQ;e!0LU?we4lvRa51YZTaUM zq?T30XyauLtn(E>oHz8GtL~lG8vtwCN1jxDMWr~zNFLb-?5JpHB&Vc#bII6vQCU>V zyly9;S9LgbJDk^ht>t;=Qfm&WbB64bHK&HU#k{MDbn)Yk6?G9U$f1%q#UyWFL{HIGq=GVFaEH`BNQ&MlTttHSGPH93aF!0a?tOC5G)O{!(COcgpA4FXY zErLHu_`X8Vbx;wK8;!=vr3zXl$+xnfsJfmv)Cj=@Uf1xcE2>MOE-&7DXN6C%Q^+a{ z#|U~VtHfC$wY;hPRkDgn=)2MSjDRD1tU$LY9Y(mChe^Bj8?5%COfs1xBWsUjB-N8R z2Aud*Skvg6n@rLF0IL=>k-#05Gpl`Cg3xYUZmjxhh*d-HXmhW@Ruz3W=r{8bGxX-b zCUf)%!uEo?YPGGWAXNHsS3GvsZ+cxPnLm_D7Ot<3%p* zm4)BR<8`W{_tG`-+i(jdHb*%J!nV7P9y?A+>AJQNi`O>QZ1*WU8icba7}XK=}G%6=U8gN^@afAcVi0fo|;$Ex(%d} z`bx~|T5E=)B$!^t!t0(8joHxV>Wx25P>RhoHRA3K?uMspw92y6a4xhR3mBE{g{IdA z-&7x8Kw%DeZJg6%WFa@th+J0-E;Q|S(F;q!QrA?SLV?q<#67pqb&lz}I*O@1!NI+} z6|~ay^1xv?5xnQ%s?G5w7M{;E)ufsAE{*pGaz9VeWH9=~W1phg^)E?7`D0xH21XBX z@)R91(fMan%rHlFd@3?TGPaqFs(5y%8CY0j(ut7NID88|y^dxXUWDiQP$xs0{ zH~z`gcSdbijRj0DsE*^CEN;6+By}6ZZ04Ka%Jh+^x*#QJC8zr;y?ad$fXdcgGLD3D zuy4bvh^oPYKsU5^TlyG$LqNCld=*bu>B`f^!l$U}kIO>v7+)NNXwL;>wVtNbX)1k#b03iJDwdhQ zWNoSg9^Nw5H4Q9PEG@QHCrs)`)mzlNNabjBooSKPTMfUS>ytDR+B$Jby)#Qs0f1~d z2pwjKNeO#KM`Tm0PLx$D4C*lzhL^s+Ay|Z!QYhO<7M@eR*O5?TS_6TE>Of!n2x2*Jk zR(NYE#^{N(jUVMwRp~7dx+gaTU4?0MJytm${W_@oh7JD!$}XmoC$aH1+nbjBh0x>6 zaUiE!XOq5?NGg56hcy1-8$7ZyFzelpR~=6S8pgZ}Ij1W;XZ53eB!GJ>#kU=jlu~*k zj<82LaktS$Uijw);0ydJJyNCc65IQSZzwulTY2w(;U8kjFG14EBg2Z3vV&%xJfY@j zsBfy$4YOpSzrnD<84EEJMw_K|K~Ev0p2jEPw^q80EsdsD+he;dRV=q{?`JoKa_wK$ zp!8gB`&mj@?`2_H>O^H^R zGP~Jvtx%S{kQQ=y_PW-}+||B0wDR{6xCM=@7MmjngzhxNQcVNF86<2M9n&XljU~J| zBlOEQYd+gI5!J_5J|j>ioIJy zcje2P!d%gNfQQiHouR}F82+I z*gh6W(*{D?i2cBeyTWxfXQKNPXvxpQgrc8Cl$tKOmW~RBmP!D1uGcJGOeW8T->sYw zv>LTkj$pg)&@ig0+9!M5{B zFRbFm0zt?MwyKHoN<)BY1$4!xj%I)#6I=;z2O&*MF7M$#kf)L@vF>Lb{t$9Bmu_Yx zZyzbZPc=6DxAt8~(;3I?jiQy3G+&W|6Xu1Fys-YE$Uq9nO^62eJg#%D8sKh1kj5V# z=H|#-mLW#4s)}(WUc6j)3bsZP7fGA&1rUL z$qQN;OJ$CuNcwu8%)|(hzo>R_R+RMAx}6YvGm8*=9|$U{_~vV&bH9qwc9MAtmrBym&!`xasQO%IXbaH;LFGdOai~(`=0(vE9P*ts=&? zvB})>y-%i`TN7bM5fw_ctr! zqn>bjJ#HzLpOK1I7QL4|EWWqXqtq^BX2-(a3rO5y%a~Z>>B`afUZ08iESTkXbLGIK zk0Pzn>S;fV8%Z77qBMr0p1@i_Fuj7WM}~OInj2!V+Qx+?1ja@%>^$52ucyKJKapAH zPsiOJX&{oGQql`t4sfJpK@Kkf-@4RmS~uq66%jVlv}Ac%DPxi+xvvBfI}G(1I}4gXaO58786$LK)nU7Pgxi*#&B5-aiRAl$+)2xPg>9l_Oq3D1pLHx! zg8O#vp_zfF)Qj|<$*eZ9X}7{Xfs@q6ZR$pD6g!Cb54c3ZF4tQG9?6vu*!qm`*$W7; zOm_|02fu`S?O}Z1gXL8QoxY=Z?h%xA7xqb({{Vzo6B}1ZHW_1XIdDTq`nDgkvx-v_ z?D9(p!BJIGw|4mWJ(jTl0ATxE%=Y@Ekl>qh%90anG2D&{d*c?ku_KVOW(3?1B}yB1 z?*TG+iw5S4j_awPv;cAnHUvDDyAB_91Fjvk-y9TMqOiMtz^I(v!v6sMg{;&zCy;ru z3UM@qi=2cruEXU>$8NAZ`AWitnc`RH2fAU6!vr0@ihPaSJUhyDG{88rP72AHp@(&V zJoYKTwnqlYGv!G3HYZz{&-PKx9}a21i+4uA$faS0`55?5hGQ7oKy+ua=Exl1PEWD$ zn&uWbi`*U%4Hk3;INToJb9^H;8VIVO^&tY_c2rQx=uO*^+$%~7=C#8(JcNxqu&U{m zG6yjFQr_bLsIFM@3Bm5P+JyvFu==rEb(VUf86qW*7#tMQX_@GTcIM;vOB=8+%4-Xl zY~gmPgGI0Wr85C5NOMb1*$X^wjn`@*0@Ju;c~ZHomAOAeEFhSXmjccSp~a)+J@J-2 zf(qgZ!p0gs+3u0R_bZDFNFw&|k;dJw698+P*I=8WZ#b0XMR71N8t_Fc0Oz zb0aN0qHYf&$;}NoKe`t{@3J^$vCk;COX@Rg@`jQt{+lMT#g_yetx21q(?;IcKPoMt z{1qTQ!NNk(x5^l1;WM>}BpfNtp4-~RLt@kL zl)^E^gtU@d=fZirPBPSmm*a%imqy|pa^BwvGYjrxgpq;>&K1s|s+X`bU)AMQ<-X>h zX-(RH+-KcRQBSgwl`R()GYpYqbyrw-pH?GhG-W-GCOcmtKuHfL_X|QaX-I=}rIP#+ zk`YwzzqQyuM4pB}~I{oFrjsusq!^T5s794Rm)0 zvTF%$4<1y%H(h4PYZqPzjGG{p0_fdc?&n0&I5(-HO4ZW_V zB+5mNCfWI29L|lvgO2JT@Lon!gAMKl!dfY1gJo>2#tMpCwE03uA&vJOBU>Y7X9DXj z0$V_?b8@xPJf}+Ct|s>hrNCPGT?y!gP{KYF0K19#Qkx56{{Shr`yvezQ_f;` z4T`j;)L8Fp^V;f}z#i$I;CcO&rv%50+BB_u9N#}G3aVzjTw6I+G}SUkVYrs77;3?` z>nZVQt*I50(U9Ur!T3-*H#gerkgs30{{W)a?uVWRxNt70rbl!7KWALTW&n3O-u+R8=$7pyl=AwS4ctQx(vkTT#J>qtJA?Q zHv6ht+9J|@y}4J0TO~YSMMQ7La-?Bxl1%|&yKkQ9fRW0)WSI#n2xHLpZ~?&iv_IXi-hj!R_o@`;lT4;S*5{@;W6Eb@5|zu*sY~ zp>v3^%0h4n@S0D>(zFwg7x0ie_CG0iW4+T`#nwXfN**}EQseNW{z3AQr?u{d44Ct4 l5p>hoT_APZQgdK@VG})zcC?&bHs|_^L&poZAL>}g|Jk!$A)5dI literal 0 HcmV?d00001 diff --git a/tests/v1/ec_connector/integration/run_epd_correctness_test.sh b/tests/v1/ec_connector/integration/run_epd_correctness_test.sh index 125fc8fff96b..d1150fe0cf36 100644 --- a/tests/v1/ec_connector/integration/run_epd_correctness_test.sh +++ b/tests/v1/ec_connector/integration/run_epd_correctness_test.sh @@ -91,6 +91,7 @@ run_baseline() { --enforce-eager \ --gpu-memory-utilization 0.7 \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ > $LOG_PATH/baseline.log 2>&1 & local BASELINE_PID=$! @@ -140,10 +141,12 @@ run_epd_1e_1pd() { CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ --port $ENCODE_PORT \ --enforce-eager \ - --gpu-memory-utilization 0.7 \ + --gpu-memory-utilization 0.01 \ --enable-request-id-headers \ --no-enable-prefix-caching \ + --max-num-batched-tokens 65536 \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_producer", @@ -162,6 +165,7 @@ run_epd_1e_1pd() { --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_consumer", @@ -245,6 +249,7 @@ run_baseline_1p_1d() { --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --kv-transfer-config '{ "kv_connector": "NixlConnector", "kv_role": "kv_producer" @@ -262,6 +267,7 @@ run_baseline_1p_1d() { --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --kv-transfer-config '{ "kv_connector": "NixlConnector", "kv_role": "kv_consumer" @@ -335,10 +341,12 @@ run_epd_1e_1p_1d() { CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ --port $ENCODE_PORT \ --enforce-eager \ - --gpu-memory-utilization 0.7 \ + --gpu-memory-utilization 0.01 \ --enable-request-id-headers \ --no-enable-prefix-caching \ + --max-num-batched-tokens 65536 \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_producer", @@ -359,6 +367,7 @@ run_epd_1e_1p_1d() { --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_consumer", @@ -383,6 +392,7 @@ run_epd_1e_1p_1d() { --gpu-memory-utilization 0.7 \ --enable-request-id-headers \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --kv-transfer-config '{ "kv_connector": "NixlConnector", "kv_role": "kv_consumer" diff --git a/tests/v1/ec_connector/integration/test_epd_correctness.py b/tests/v1/ec_connector/integration/test_epd_correctness.py index fafa60a5308e..69c4c58e349b 100644 --- a/tests/v1/ec_connector/integration/test_epd_correctness.py +++ b/tests/v1/ec_connector/integration/test_epd_correctness.py @@ -39,6 +39,8 @@ image_1 = ImageAsset("stop_sign").pil_image.resize((1280, 720)) image_2 = ImageAsset("cherry_blossom").pil_image.resize((1280, 720)) +image_local_path = f"{os.path.dirname(os.path.abspath(__file__))}/hato.jpg" + SAMPLE_PROMPTS_MM: list[dict] = [ { "messages": [ @@ -70,9 +72,7 @@ }, { "type": "image_url", - "image_url": { - "url": f"data:image;base64,{encode_image_base64(image_1)}" - }, + "image_url": {"url": f"file://{image_local_path}"}, }, {"type": "text", "text": "Describe these 2 images in detail."}, ], @@ -208,10 +208,10 @@ def main(): if args.mode == "baseline": health_check_url = f"{args.service_url}/health" elif args.mode == "baseline_pd": - # Nixl toy proxy use /healthcheck + # Nixl toy proxy use /healthcheck health_check_url = f"{args.service_url}/healthcheck" else: - # Disagg proxy uses /health + # Disagg EPD proxy uses /health health_check_url = f"{args.service_url}/health" if not os.path.exists(args.baseline_file): raise ValueError( diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index 8f3aa5d9f354..22932ef9b368 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -479,6 +479,30 @@ def schedule(self) -> SchedulerOutput: not self.scheduler_config.chunked_prefill_enabled and num_new_tokens > token_budget ): + enable_prefix_caching = self.cache_config.enable_prefix_caching + kv_role = getattr(self.connector, "kv_role", None) + + can_reduce_token: bool = enable_prefix_caching or kv_role in ( + "kv_consumer", + "kv_both", + ) + + # If no prefix caching or external load + # then impossible to further reduce num_new_tokens: + if ( + num_new_tokens > self.max_num_scheduled_tokens + and not can_reduce_token + ): + logger.warning( + "enable_prefix_caching is %s", enable_prefix_caching + ) + logger.warning("kv_role is %s", kv_role) + raise RuntimeError( + f"num_new_tokens ({num_new_tokens}) exceeds " + f"self.max_num_scheduled_tokens " + f"({self.max_num_scheduled_tokens}), and cannot be " + f"further reduced. Request impossible to be scheduled!" + ) self.waiting.pop_request() skipped_waiting_requests.prepend_request(request) continue From dc6a0bc9756409a24c46612415c43f1af955502d Mon Sep 17 00:00:00 2001 From: herotai214 Date: Mon, 10 Nov 2025 03:27:07 +0000 Subject: [PATCH 56/57] [Misc] Add single request example Signed-off-by: herotai214 --- .../disagg_1e1p1d_example.sh | 27 ++++++++++++++++- .../disagg_1e1pd_example.sh | 30 +++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh index 1d8280a790b8..a3314be269ae 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1p1d_example.sh @@ -30,6 +30,9 @@ export UCX_NET_DEVICES=all ############################################################################### # Helpers ############################################################################### +# Find the git repository root directory +GIT_ROOT=$(git rev-parse --show-toplevel) + START_TIME=$(date +"%Y%m%d_%H%M%S") ENC_LOG=$LOG_PATH/encoder_${START_TIME}.log P_LOG=$LOG_PATH/p_${START_TIME}.log @@ -95,8 +98,9 @@ CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ --enforce-eager \ --enable-request-id-headers \ --no-enable-prefix-caching \ - --max-num-batched-tokens 4096 \ + --max-num-batched-tokens 65536 \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_producer", @@ -120,6 +124,7 @@ vllm serve "$MODEL" \ --enforce-eager \ --enable-request-id-headers \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_consumer", @@ -147,6 +152,7 @@ vllm serve "$MODEL" \ --enforce-eager \ --enable-request-id-headers \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --kv-transfer-config '{ "kv_connector": "NixlConnector", "kv_role": "kv_consumer" @@ -178,6 +184,8 @@ echo "All services are up!" ############################################################################### # Benchmark +############################################################################### +echo "Running benchmark (stream)..." vllm bench serve \ --model $MODEL \ --backend openai-chat \ @@ -189,7 +197,24 @@ vllm bench serve \ --port $PROXY_PORT PIDS+=($!) + ############################################################################### +# Single request with local image +############################################################################### +echo "Running single request with local image (non-stream)..." +curl http://127.0.0.1:${PROXY_PORT}/v1/chat/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "'${MODEL}'", + "messages": [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": [ + {"type": "image_url", "image_url": {"url": "file://'"${GIT_ROOT}"'/tests/v1/ec_connector/integration/hato.jpg"}}, + {"type": "text", "text": "What is in this image?"} + ]} + ] + }' + # cleanup echo "cleanup..." diff --git a/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh index ecc8f9b5a86c..479b20fef3c4 100644 --- a/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh +++ b/examples/online_serving/disaggregated_encoder/disagg_1e1pd_example.sh @@ -25,6 +25,9 @@ NUM_PROMPTS="${NUM_PROMPTS:-100}" # number of prompts to send in benchmark ############################################################################### # Helpers ############################################################################### +# Find the git repository root directory +GIT_ROOT=$(git rev-parse --show-toplevel) + START_TIME=$(date +"%Y%m%d_%H%M%S") ENC_LOG=$LOG_PATH/encoder_${START_TIME}.log PD_LOG=$LOG_PATH/pd_${START_TIME}.log @@ -84,13 +87,14 @@ mkdir -p $EC_SHARED_STORAGE_PATH # Encoder worker ############################################################################### CUDA_VISIBLE_DEVICES="$GPU_E" vllm serve "$MODEL" \ - --gpu-memory-utilization 0.7 \ + --gpu-memory-utilization 0.01 \ --port "$ENCODE_PORT" \ --enforce-eager \ --enable-request-id-headers \ --no-enable-prefix-caching \ - --max-num-batched-tokens 4096 \ + --max-num-batched-tokens 65536 \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_producer", @@ -105,12 +109,13 @@ PIDS+=($!) ############################################################################### # Prefill+Decode worker ############################################################################### -CUDA_VISIBLE_DEVICES="$GPU_PD" VLLM_NIXL_SIDE_CHANNEL_PORT=6000 vllm serve "$MODEL" \ +CUDA_VISIBLE_DEVICES="$GPU_PD" vllm serve "$MODEL" \ --gpu-memory-utilization 0.7 \ --port "$PREFILL_DECODE_PORT" \ --enforce-eager \ --enable-request-id-headers \ --max-num-seqs 128 \ + --allowed-local-media-path ${GIT_ROOT}/tests/v1/ec_connector/integration \ --ec-transfer-config '{ "ec_connector": "ECSharedStorageConnector", "ec_role": "ec_consumer", @@ -144,6 +149,8 @@ echo "All services are up!" ############################################################################### # Benchmark +############################################################################### +echo "Running benchmark (stream)..." vllm bench serve \ --model $MODEL \ --backend openai-chat \ @@ -155,7 +162,24 @@ vllm bench serve \ --port $PROXY_PORT PIDS+=($!) + +############################################################################### +# Single request with local image ############################################################################### +echo "Running single request with local image (non-stream)..." +curl http://127.0.0.1:${PROXY_PORT}/v1/chat/completions \ + -H "Content-Type: application/json" \ + -d '{ + "model": "'${MODEL}'", + "messages": [ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": [ + {"type": "image_url", "image_url": {"url": "file://'"${GIT_ROOT}"'/tests/v1/ec_connector/integration/hato.jpg"}}, + {"type": "text", "text": "What is in this image?"} + ]} + ] + }' + # cleanup echo "cleanup..." From c8215d912d0abf58b268587fbd610415450dbe9c Mon Sep 17 00:00:00 2001 From: herotai214 Date: Mon, 10 Nov 2025 06:38:15 +0000 Subject: [PATCH 57/57] Revert num_new_tokens bug handling changes in scheduler Signed-off-by: herotai214 --- vllm/v1/core/sched/scheduler.py | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/vllm/v1/core/sched/scheduler.py b/vllm/v1/core/sched/scheduler.py index 6a9d2f932b40..f1ffc9ccd7d5 100644 --- a/vllm/v1/core/sched/scheduler.py +++ b/vllm/v1/core/sched/scheduler.py @@ -482,30 +482,6 @@ def schedule(self) -> SchedulerOutput: not self.scheduler_config.chunked_prefill_enabled and num_new_tokens > token_budget ): - enable_prefix_caching = self.cache_config.enable_prefix_caching - kv_role = getattr(self.connector, "kv_role", None) - - can_reduce_token: bool = enable_prefix_caching or kv_role in ( - "kv_consumer", - "kv_both", - ) - - # If no prefix caching or external load - # then impossible to further reduce num_new_tokens: - if ( - num_new_tokens > self.max_num_scheduled_tokens - and not can_reduce_token - ): - logger.warning( - "enable_prefix_caching is %s", enable_prefix_caching - ) - logger.warning("kv_role is %s", kv_role) - raise RuntimeError( - f"num_new_tokens ({num_new_tokens}) exceeds " - f"self.max_num_scheduled_tokens " - f"({self.max_num_scheduled_tokens}), and cannot be " - f"further reduced. Request impossible to be scheduled!" - ) self.waiting.pop_request() skipped_waiting_requests.prepend_request(request) continue