diff --git a/vllm/entrypoints/grpc_server.py b/vllm/entrypoints/grpc_server.py index 2778385c99..1fc3354a41 100755 --- a/vllm/entrypoints/grpc_server.py +++ b/vllm/entrypoints/grpc_server.py @@ -30,6 +30,7 @@ from grpc_reflection.v1alpha import reflection from vllm import SamplingParams, TextPrompt, TokensPrompt from vllm.engine.arg_utils import AsyncEngineArgs +from vllm.entrypoints.utils import log_version_and_model from vllm.grpc import vllm_engine_pb2, vllm_engine_pb2_grpc from vllm.logger import init_logger from vllm.outputs import RequestOutput @@ -408,8 +409,8 @@ async def serve_grpc(args: argparse.Namespace): Args: args: Parsed command line arguments """ - logger.info("vLLM gRPC server version %s", VLLM_VERSION) - logger.info("args: %s", args) + log_version_and_model(logger, VLLM_VERSION, args.model) + logger.info("vLLM gRPC server args: %s", args) start_time = time.time() diff --git a/vllm/entrypoints/openai/api_server.py b/vllm/entrypoints/openai/api_server.py index c7941bf256..d6b910193c 100644 --- a/vllm/entrypoints/openai/api_server.py +++ b/vllm/entrypoints/openai/api_server.py @@ -63,6 +63,7 @@ from vllm.entrypoints.serve.tokenize.serving import OpenAIServingTokenization from vllm.entrypoints.utils import ( cli_env_setup, log_non_default_args, + log_version_and_model, process_lora_modules, sanitize_message, ) @@ -867,7 +868,7 @@ def setup_server(args): """Validate API server args, set up signal handler, create socket ready to serve.""" - logger.info("vLLM API server version %s", VLLM_VERSION) + log_version_and_model(logger, VLLM_VERSION, args.model) log_non_default_args(args) if args.tool_parser_plugin and len(args.tool_parser_plugin) > 3: diff --git a/vllm/entrypoints/utils.py b/vllm/entrypoints/utils.py index 64cbb6ed44..a42f08f7f0 100644 --- a/vllm/entrypoints/utils.py +++ b/vllm/entrypoints/utils.py @@ -6,6 +6,8 @@ import dataclasses import functools import os from argparse import Namespace +from logging import Logger +from string import Template from typing import TYPE_CHECKING, Any import regex as re @@ -13,8 +15,9 @@ from fastapi import Request from fastapi.responses import JSONResponse, StreamingResponse from starlette.background import BackgroundTask, BackgroundTasks +from vllm import envs from vllm.engine.arg_utils import EngineArgs -from vllm.logger import init_logger +from vllm.logger import current_formatter_type, init_logger from vllm.platforms import current_platform from vllm.utils.argparse_utils import FlexibleArgumentParser @@ -295,3 +298,28 @@ def process_lora_modules( def sanitize_message(message: str) -> str: # Avoid leaking memory address from object reprs return re.sub(r" at 0x[0-9a-f]+>", ">", message) + + +def log_version_and_model(lgr: Logger, version: str, model_name: str) -> None: + if envs.VLLM_DISABLE_LOG_LOGO or (formatter := current_formatter_type(lgr)) is None: + message = "vLLM server version %s, serving model %s" + else: + logo_template = Template( + "\n ${w}█ █ █▄ ▄█${r}\n" + " ${o}▄▄${r} ${b}▄█${r} ${w}█ █ █ ▀▄▀ █${r} version ${w}%s${r}\n" + " ${o}█${r}${b}▄█▀${r} ${w}█ █ █ █${r} model ${w}%s${r}\n" + " ${b}▀▀${r} ${w}▀▀▀▀▀ ▀▀▀▀▀ ▀ ▀${r}\n" + ) + colors = { + "w": "\033[97;1m", # white + "o": "\033[93m", # orange + "b": "\033[94m", # blue + "r": "\033[0m", # reset + } + if formatter != "color": + # monochrome logo (no ansi escape codes) + colors = dict.fromkeys(colors, "") + + message = logo_template.substitute(colors) + + lgr.info(message, version, model_name) diff --git a/vllm/envs.py b/vllm/envs.py index 9ffb79fb70..e28f9c4319 100755 --- a/vllm/envs.py +++ b/vllm/envs.py @@ -249,6 +249,7 @@ if TYPE_CHECKING: VLLM_USE_V2_MODEL_RUNNER: bool = False VLLM_LOG_MODEL_INSPECTION: bool = False VLLM_DEBUG_MFU_METRICS: bool = False + VLLM_DISABLE_LOG_LOGO: bool = False def get_default_cache_root(): @@ -1610,6 +1611,8 @@ environment_variables: dict[str, Callable[[], Any]] = { "VLLM_DEBUG_MFU_METRICS": lambda: bool( int(os.getenv("VLLM_DEBUG_MFU_METRICS", "0")) ), + # Disable logging of vLLM logo at server startup time. + "VLLM_DISABLE_LOG_LOGO": lambda: bool(int(os.getenv("VLLM_DISABLE_LOG_LOGO", "0"))), } # --8<-- [end:env-vars-definition] diff --git a/vllm/logger.py b/vllm/logger.py index 5506e09b8a..e6e3807946 100644 --- a/vllm/logger.py +++ b/vllm/logger.py @@ -17,6 +17,7 @@ from types import MethodType from typing import Any, Literal, cast import vllm.envs as envs +from vllm.logging_utils import ColoredFormatter, NewLineFormatter _FORMAT = ( f"{envs.VLLM_LOGGING_PREFIX}%(levelname)s %(asctime)s " @@ -224,6 +225,18 @@ def suppress_logging(level: int = logging.INFO) -> Generator[None, Any, None]: logging.disable(current_level) +def current_formatter_type(lgr: Logger) -> Literal["color", "newline", None]: + while lgr is not None: + if lgr.handlers and len(lgr.handlers) == 1 and lgr.handlers[0].name == "vllm": + formatter = lgr.handlers[0].formatter + if isinstance(formatter, ColoredFormatter): + return "color" + if isinstance(formatter, NewLineFormatter): + return "newline" + lgr = lgr.parent + return None + + # The root logger is initialized when the module is imported. # This is thread-safe as the module is only imported once, # guaranteed by the Python GIL.