122 lines
3.8 KiB
Python
122 lines
3.8 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
import argparse
|
|
import asyncio
|
|
import signal
|
|
import socket
|
|
from argparse import Namespace
|
|
|
|
from vllm import AsyncEngineArgs, envs
|
|
from vllm.config import VllmConfig
|
|
from vllm.logger import init_logger
|
|
|
|
from ..app import build_app
|
|
from ..launcher import serve_http, setup_server
|
|
from ..utils.server_utils import get_uvicorn_log_config
|
|
from .app_state import init_render_app_state
|
|
|
|
logger = init_logger("vllm.entrypoints.launchers.render.entry")
|
|
|
|
|
|
async def build_and_serve_renderer(
|
|
vllm_config: VllmConfig,
|
|
listen_address: str,
|
|
sock: socket.socket,
|
|
args: Namespace,
|
|
**uvicorn_kwargs,
|
|
) -> asyncio.Task:
|
|
"""Build FastAPI app for a CPU-only render server, initialize state, and
|
|
start serving.
|
|
|
|
Returns the shutdown task for the caller to await.
|
|
"""
|
|
|
|
# Get uvicorn log config (from file or with endpoint filter)
|
|
log_config = get_uvicorn_log_config(args)
|
|
if log_config is not None:
|
|
uvicorn_kwargs["log_config"] = log_config
|
|
|
|
app = build_app(args, ("render",))
|
|
await init_render_app_state(vllm_config, app.state, args)
|
|
|
|
logger.info("Starting vLLM server on %s", listen_address)
|
|
|
|
return await serve_http(
|
|
app,
|
|
sock=sock,
|
|
enable_ssl_refresh=args.enable_ssl_refresh,
|
|
host=args.host,
|
|
port=args.port,
|
|
log_level=args.uvicorn_log_level,
|
|
# NOTE: When the 'disable_uvicorn_access_log' value is True,
|
|
# no access log will be output.
|
|
access_log=not args.disable_uvicorn_access_log,
|
|
timeout_keep_alive=envs.VLLM_HTTP_TIMEOUT_KEEP_ALIVE,
|
|
ssl_keyfile=args.ssl_keyfile,
|
|
ssl_certfile=args.ssl_certfile,
|
|
ssl_ca_certs=args.ssl_ca_certs,
|
|
ssl_cert_reqs=args.ssl_cert_reqs,
|
|
ssl_ciphers=args.ssl_ciphers,
|
|
h11_max_incomplete_event_size=args.h11_max_incomplete_event_size,
|
|
h11_max_header_count=args.h11_max_header_count,
|
|
**uvicorn_kwargs,
|
|
)
|
|
|
|
|
|
async def run_launch_fastapi(args: argparse.Namespace) -> None:
|
|
"""Run the online serving layer with FastAPI (no GPU inference)."""
|
|
|
|
# Interrupt initialization if SIGTERM arrives before uvicorn installs
|
|
# its own signal handlers. Once uvicorn is running it replaces this.
|
|
def _interrupt_init(*_) -> None:
|
|
raise KeyboardInterrupt("terminated")
|
|
|
|
signal.signal(signal.SIGTERM, _interrupt_init)
|
|
|
|
# 1. Socket binding
|
|
listen_address, sock = setup_server(args, reuse_port=False)
|
|
|
|
# 2. Build and serve the API server
|
|
engine_args = AsyncEngineArgs.from_cli_args(args)
|
|
model_config = engine_args.create_model_config()
|
|
|
|
# Render servers preprocess data only — no inference, no quantized kernels.
|
|
# Clear quantization so VllmConfig skips quant dtype/capability validation.
|
|
model_config.quantization = None
|
|
|
|
# Render servers never allocate KV cache; suppress the spurious CPU KV
|
|
# cache space warning from CpuPlatform.check_and_update_config.
|
|
envs.VLLM_CPU_KVCACHE_SPACE = 0
|
|
|
|
vllm_config = VllmConfig(model_config=model_config)
|
|
shutdown_task = await build_and_serve_renderer(
|
|
vllm_config, listen_address, sock, args
|
|
)
|
|
try:
|
|
await shutdown_task
|
|
finally:
|
|
sock.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import uvloop
|
|
|
|
from vllm.entrypoints.serve.utils.api_utils import cli_env_setup
|
|
from vllm.utils.argparse_utils import FlexibleArgumentParser
|
|
|
|
from ..cli_args import (
|
|
make_arg_parser,
|
|
validate_parsed_serve_args,
|
|
)
|
|
|
|
cli_env_setup()
|
|
parser = FlexibleArgumentParser(
|
|
description="Starts a GPU-less rendering server "
|
|
"for preprocessing and postprocessing only"
|
|
)
|
|
parser = make_arg_parser(parser)
|
|
args = parser.parse_args()
|
|
validate_parsed_serve_args(args)
|
|
|
|
uvloop.run(run_launch_fastapi(args))
|