diff --git a/.buildkite/test-amd.yaml b/.buildkite/test-amd.yaml index 156b501257c..b1ed31b1eee 100644 --- a/.buildkite/test-amd.yaml +++ b/.buildkite/test-amd.yaml @@ -1004,11 +1004,13 @@ steps: - tests/entrypoints/unit_tests - tests/entrypoints/rl/weight_transfer - tests/entrypoints/launchers + - tests/entrypoints/common - vllm/platforms/rocm.py commands: - pytest -v -s entrypoints/unit_tests - pytest -v -s entrypoints/rl/weight_transfer - pytest -v -s entrypoints/launchers + - pytest -v -s entrypoints/common - label: ":amd: (MI300) Entrypoints Integration (Responses API)" # TBD timeout_in_minutes: 50 diff --git a/.buildkite/test_areas/entrypoints.yaml b/.buildkite/test_areas/entrypoints.yaml index f23a51577c5..428852a870e 100644 --- a/.buildkite/test_areas/entrypoints.yaml +++ b/.buildkite/test_areas/entrypoints.yaml @@ -34,9 +34,11 @@ steps: - vllm/utils/flashinfer.py - tests/entrypoints/unit_tests - tests/entrypoints/launchers + - tests/entrypoints/common commands: - pytest -v -s entrypoints/unit_tests - pytest -v -s entrypoints/launchers + - pytest -v -s entrypoints/common mirror: amd: label: ":amd: (MI355 DPX) Entrypoints Unit" diff --git a/docs/mkdocs/gen_files/generate_argparse.py b/docs/mkdocs/gen_files/generate_argparse.py index 8e71d13ae08..3c61de01a45 100644 --- a/docs/mkdocs/gen_files/generate_argparse.py +++ b/docs/mkdocs/gen_files/generate_argparse.py @@ -183,7 +183,7 @@ DownloadKernelsSubcommand = auto_mock( "vllm.entrypoints.cli.download_kernels", "DownloadKernelsSubcommand" ) sweep_subcommands = auto_mock("vllm.benchmarks.sweep.cli", "SUBCOMMANDS") -openai_cli_args = auto_mock("vllm.entrypoints.launchers", "cli_args") +openai_cli_args = auto_mock("vllm.entrypoints.common", "cli_args") run_batch = auto_mock("vllm.entrypoints.launchers", "run_batch") if TYPE_CHECKING: diff --git a/rust/src/cmd/src/cli/unsupported.rs b/rust/src/cmd/src/cli/unsupported.rs index 02e1377ff01..c31994c1f8e 100644 --- a/rust/src/cmd/src/cli/unsupported.rs +++ b/rust/src/cmd/src/cli/unsupported.rs @@ -137,7 +137,7 @@ Remove these arguments to continue." /// recognizes but does not support yet. /// /// Source of truth in Python vLLM: -/// - `vllm.entrypoints.openai.cli_args.make_arg_parser(...)` +/// - `vllm.entrypoints.common.cli_args.make_arg_parser(...)` /// - `vllm.entrypoints.cli.serve.ServeSubcommand.subparser_init(...)` /// /// These are not part of `EngineArgs`, `AsyncEngineArgs`, `BaseFrontendArgs`, @@ -384,8 +384,8 @@ pub struct EngineUnsupportedArgs { /// does not support yet. /// /// Source of truth in Python vLLM: -/// - `vllm.entrypoints.openai.cli_args.BaseFrontendArgs` -/// - `vllm.entrypoints.openai.cli_args.FrontendArgs` +/// - `vllm.entrypoints.common.cli_args.BaseFrontendArgs` +/// - `vllm.entrypoints.common.cli_args.FrontendArgs` /// /// These are not engine args. They belong to the Python OpenAI-compatible /// frontend / API-server layer itself, for example chat-template configuration, diff --git a/tests/engine/test_arg_utils.py b/tests/engine/test_arg_utils.py index 81587c652df..27d4493475f 100644 --- a/tests/engine/test_arg_utils.py +++ b/tests/engine/test_arg_utils.py @@ -481,7 +481,7 @@ def test_compilation_config(): def test_trust_request_mm_kwargs_cli(): - from vllm.entrypoints.launchers.cli_args import FrontendArgs + from vllm.entrypoints.common.cli_args import FrontendArgs parser = FrontendArgs.add_cli_args(FlexibleArgumentParser()) diff --git a/tests/entrypoints/cohere/test_registry_and_args.py b/tests/entrypoints/cohere/test_registry_and_args.py index 71d6be27303..62bde8bb154 100644 --- a/tests/entrypoints/cohere/test_registry_and_args.py +++ b/tests/entrypoints/cohere/test_registry_and_args.py @@ -6,7 +6,7 @@ by the Cohere v2 chat API: * ``vllm/renderers/registry.py``: new ``"cohere"`` renderer entry. * ``vllm/tokenizers/registry.py``: new ``"cohere"`` tokenizer entry (aliased to the cached HF tokenizer). -* ``vllm/entrypoints/openai/cli_args.py``: new +* ``vllm/entrypoints/common/cli_args.py``: new ``cohere_is_reasoning_model`` field. * ``vllm/config/model.py``: ``"cohere"`` added to ``TokenizerMode`` Literal. @@ -18,7 +18,7 @@ import typing import pytest from vllm.config.model import TokenizerMode -from vllm.entrypoints.launchers.cli_args import BaseFrontendArgs, make_arg_parser +from vllm.entrypoints.common.cli_args import BaseFrontendArgs, make_arg_parser from vllm.renderers.registry import RENDERER_REGISTRY from vllm.tokenizers.registry import TokenizerRegistry from vllm.utils.argparse_utils import FlexibleArgumentParser diff --git a/tests/entrypoints/common/__init__.py b/tests/entrypoints/common/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/entrypoints/launchers/test_cli_args.py b/tests/entrypoints/common/test_cli_args.py similarity index 99% rename from tests/entrypoints/launchers/test_cli_args.py rename to tests/entrypoints/common/test_cli_args.py index 7fb555c1413..5face353f1f 100644 --- a/tests/entrypoints/launchers/test_cli_args.py +++ b/tests/entrypoints/common/test_cli_args.py @@ -6,10 +6,10 @@ from types import SimpleNamespace import pytest -import vllm.entrypoints.launchers.cli_args as cli_args_module +import vllm.entrypoints.common.cli_args as cli_args_module from tests.utils import VLLM_PATH from vllm.engine.arg_utils import AsyncEngineArgs -from vllm.entrypoints.launchers.cli_args import ( +from vllm.entrypoints.common.cli_args import ( make_arg_parser, validate_parsed_serve_args, ) diff --git a/tests/entrypoints/unit_tests/test_offline_utils.py b/tests/entrypoints/common/test_offline.py similarity index 100% rename from tests/entrypoints/unit_tests/test_offline_utils.py rename to tests/entrypoints/common/test_offline.py diff --git a/tests/entrypoints/common/test_startup.py b/tests/entrypoints/common/test_startup.py new file mode 100644 index 00000000000..9717ff9fcd8 --- /dev/null +++ b/tests/entrypoints/common/test_startup.py @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +from argparse import Namespace + +from vllm.entrypoints.common import startup +from vllm.entrypoints.common.startup import redact_sensitive_args + + +class TestRedactSensitiveArgs: + API_KEY = "sk-test-secret-12345" + + def test_redact_replaces_sensitive_values_only(self): + args = { + "api_key": self.API_KEY, + "hf_token": "hf_secret", + "watermark_config": {"algorithm": "gumbel", "key": 42}, + "other": "visible", + } + redacted = redact_sensitive_args(args) + assert redacted == { + "api_key": "***", + "hf_token": "***", + "watermark_config": "***", + "other": "visible", + } + # original dict must not be mutated + assert args == { + "api_key": self.API_KEY, + "hf_token": "hf_secret", + "watermark_config": {"algorithm": "gumbel", "key": 42}, + "other": "visible", + } + + def test_no_sensitive_fields_returns_original(self): + args = {"model_tag": "org/model", "other": "visible"} + assert redact_sensitive_args(args) is args + + def test_api_key_not_in_log(self, monkeypatch, caplog): + non_default = { + "model_tag": "org/model", + "default_chat_template_kwargs": {"enable_thinking": False}, + "api_key": self.API_KEY, + "enable_auto_tool_choice": True, + "tool_call_parser": "qwen3_coder", + } + monkeypatch.setattr(startup, "get_non_default_args", lambda args: non_default) + with caplog.at_level("INFO", logger="vllm.entrypoints.common.startup"): + startup.log_non_default_args(args=Namespace()) + message = caplog.text + assert self.API_KEY not in message + assert "'api_key': '***'" in message + # non-sensitive args are still logged + assert "org/model" in message + assert "qwen3_coder" in message + + def test_hf_token_not_in_log(self, monkeypatch, caplog): + hf_token = "hf_TESTTOKENVALUE123" + non_default = { + "model_tag": "org/model", + "hf_token": hf_token, + "tool_call_parser": "qwen3_coder", + } + monkeypatch.setattr(startup, "get_non_default_args", lambda args: non_default) + with caplog.at_level("INFO", logger="vllm.entrypoints.common.startup"): + startup.log_non_default_args(args=Namespace()) + message = caplog.text + assert hf_token not in message + assert "'hf_token': '***'" in message + assert "org/model" in message diff --git a/tests/entrypoints/launchers/api_server/test_api_server_process_manager.py b/tests/entrypoints/launchers/api_server/test_api_server_process_manager.py index 318f57b86ff..e90f8d0a7fb 100644 --- a/tests/entrypoints/launchers/api_server/test_api_server_process_manager.py +++ b/tests/entrypoints/launchers/api_server/test_api_server_process_manager.py @@ -417,7 +417,7 @@ def test_rust_frontend_launch_log_redacts_credentials(monkeypatch): Credentials must not reach the log line.""" import subprocess as subprocess_mod - from vllm.entrypoints.launchers.cli_args import make_arg_parser + from vllm.entrypoints.common.cli_args import make_arg_parser from vllm.utils.argparse_utils import FlexibleArgumentParser from vllm.v1.utils import RustFrontendProcessManager @@ -469,7 +469,7 @@ def test_rust_frontend_uses_config_model_as_model_tag(monkeypatch, caplog, tmp_p """Config-only model selection must be forwarded to the Rust frontend.""" import subprocess as subprocess_mod - from vllm.entrypoints.launchers.cli_args import make_arg_parser + from vllm.entrypoints.common.cli_args import make_arg_parser from vllm.utils.argparse_utils import FlexibleArgumentParser from vllm.v1.utils import RustFrontendProcessManager @@ -517,7 +517,7 @@ def test_rust_frontend_inherits_grpc_listener(monkeypatch): """The Python-bound gRPC socket is passed to Rust like the HTTP one.""" import subprocess as subprocess_mod - from vllm.entrypoints.launchers.cli_args import make_arg_parser + from vllm.entrypoints.common.cli_args import make_arg_parser from vllm.utils.argparse_utils import FlexibleArgumentParser from vllm.v1.utils import RustFrontendProcessManager @@ -577,7 +577,7 @@ def test_rust_frontend_inherits_grpc_listener(monkeypatch): def test_rust_frontend_spawn_failure_cleans_up_listeners(tmp_path): """No child owns the listeners when Popen fails, so the parent removes them.""" - from vllm.entrypoints.launchers.cli_args import make_arg_parser + from vllm.entrypoints.common.cli_args import make_arg_parser from vllm.utils.argparse_utils import FlexibleArgumentParser from vllm.v1.utils import RustFrontendProcessManager diff --git a/tests/entrypoints/launchers/render/test_app_state.py b/tests/entrypoints/launchers/render/test_app_state.py index f0f54d9bafd..424b7eb112b 100644 --- a/tests/entrypoints/launchers/render/test_app_state.py +++ b/tests/entrypoints/launchers/render/test_app_state.py @@ -7,7 +7,7 @@ from starlette.datastructures import State import vllm.entrypoints.launchers.render.app_state as app_state_mod from vllm.config import ModelConfig, VllmConfig -from vllm.entrypoints.launchers.cli_args import make_arg_parser +from vllm.entrypoints.common.cli_args import make_arg_parser from vllm.utils.argparse_utils import FlexibleArgumentParser diff --git a/tests/entrypoints/launchers/test_launch_cli.py b/tests/entrypoints/launchers/test_launch_cli.py index 55093c5685d..3464e99ae8a 100644 --- a/tests/entrypoints/launchers/test_launch_cli.py +++ b/tests/entrypoints/launchers/test_launch_cli.py @@ -24,6 +24,7 @@ from vllm.entrypoints.cli.launch import ( RenderSubcommand, cmd_init, ) +from vllm.entrypoints.common import startup from vllm.snapshot.controller import ( LocalSnapshotTools, SnapshotCreateError, @@ -159,9 +160,7 @@ def test_snapshot_environment_contract( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], ): - from vllm.entrypoints.serve.utils import api_utils - - monkeypatch.setattr(api_utils, "cli_env_setup", pytest.fail) + monkeypatch.setattr(startup, "cli_env_setup", pytest.fail) secret = "snapshot-secret" monkeypatch.setenv("VLLM_API_KEY", secret) monkeypatch.setenv("VLLM_USER_SETTING", secret) diff --git a/tests/entrypoints/serve/middleware/test_cors_middleware.py b/tests/entrypoints/serve/middleware/test_cors_middleware.py index 543c101a930..a63c2db831b 100644 --- a/tests/entrypoints/serve/middleware/test_cors_middleware.py +++ b/tests/entrypoints/serve/middleware/test_cors_middleware.py @@ -4,7 +4,7 @@ from fastapi import FastAPI from starlette.testclient import TestClient -from vllm.entrypoints.launchers.cli_args import FrontendArgs +from vllm.entrypoints.common.cli_args import FrontendArgs from vllm.entrypoints.serve.middleware.register import init_entrypoints_middleware diff --git a/tests/entrypoints/serve/utils/test_api_utils.py b/tests/entrypoints/serve/utils/test_api_utils.py index 4dcf2dcffed..e9f8ce34f27 100644 --- a/tests/entrypoints/serve/utils/test_api_utils.py +++ b/tests/entrypoints/serve/utils/test_api_utils.py @@ -1,8 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project - import asyncio -from argparse import Namespace import pytest from fastapi import FastAPI, Request @@ -11,7 +9,6 @@ from vllm.entrypoints.generate.base.protocol import StreamOptions from vllm.entrypoints.serve.utils import api_utils from vllm.entrypoints.serve.utils.api_utils import ( get_max_tokens, - redact_sensitive_args, should_include_usage, ) @@ -165,66 +162,3 @@ class TestGetMaxTokens: input_length=150, default_sampling_params={"max_tokens": 2048}, ) - - -class TestRedactSensitiveArgs: - API_KEY = "sk-test-secret-12345" - - def test_redact_replaces_sensitive_values_only(self): - args = { - "api_key": self.API_KEY, - "hf_token": "hf_secret", - "watermark_config": {"algorithm": "gumbel", "key": 42}, - "other": "visible", - } - redacted = redact_sensitive_args(args) - assert redacted == { - "api_key": "***", - "hf_token": "***", - "watermark_config": "***", - "other": "visible", - } - # original dict must not be mutated - assert args == { - "api_key": self.API_KEY, - "hf_token": "hf_secret", - "watermark_config": {"algorithm": "gumbel", "key": 42}, - "other": "visible", - } - - def test_no_sensitive_fields_returns_original(self): - args = {"model_tag": "org/model", "other": "visible"} - assert redact_sensitive_args(args) is args - - def test_api_key_not_in_log(self, monkeypatch, caplog): - non_default = { - "model_tag": "org/model", - "default_chat_template_kwargs": {"enable_thinking": False}, - "api_key": self.API_KEY, - "enable_auto_tool_choice": True, - "tool_call_parser": "qwen3_coder", - } - monkeypatch.setattr(api_utils, "get_non_default_args", lambda args: non_default) - with caplog.at_level("INFO", logger="vllm.entrypoints.serve.utils.api_utils"): - api_utils.log_non_default_args(args=Namespace()) - message = caplog.text - assert self.API_KEY not in message - assert "'api_key': '***'" in message - # non-sensitive args are still logged - assert "org/model" in message - assert "qwen3_coder" in message - - def test_hf_token_not_in_log(self, monkeypatch, caplog): - hf_token = "hf_TESTTOKENVALUE123" - non_default = { - "model_tag": "org/model", - "hf_token": hf_token, - "tool_call_parser": "qwen3_coder", - } - monkeypatch.setattr(api_utils, "get_non_default_args", lambda args: non_default) - with caplog.at_level("INFO", logger="vllm.entrypoints.serve.utils.api_utils"): - api_utils.log_non_default_args(args=Namespace()) - message = caplog.text - assert hf_token not in message - assert "'hf_token': '***'" in message - assert "org/model" in message diff --git a/tests/plugins_tests/test_endpoint_plugins.py b/tests/plugins_tests/test_endpoint_plugins.py index 864c915fe08..41d00884692 100644 --- a/tests/plugins_tests/test_endpoint_plugins.py +++ b/tests/plugins_tests/test_endpoint_plugins.py @@ -17,8 +17,8 @@ import pytest from fastapi import APIRouter, FastAPI from vllm_add_dummy_endpoint_plugin import DummyAdminEndpointPlugin +from vllm.entrypoints.common.cli_args import make_arg_parser from vllm.entrypoints.launchers.app import build_app -from vllm.entrypoints.launchers.cli_args import make_arg_parser from vllm.plugins import load_endpoint_plugins from vllm.plugins.endpoint_plugins.interface import ( EndpointPlugin, diff --git a/tools/pre_commit/mypy.py b/tools/pre_commit/mypy.py index 876e19e1fdb..1823052f6c4 100755 --- a/tools/pre_commit/mypy.py +++ b/tools/pre_commit/mypy.py @@ -42,6 +42,7 @@ SILENT_GROUPS = [ "tests/entrypoints/serve", "tests/entrypoints/tool_parsers", "tests/entrypoints/unit_tests", + "tests/entrypoints/common", "tests/kernels/attention", "tests/kernels/core", "tests/kernels/helion", diff --git a/vllm/benchmarks/sweep/cli.py b/vllm/benchmarks/sweep/cli.py index 96d26c47539..fb8f746323f 100644 --- a/vllm/benchmarks/sweep/cli.py +++ b/vllm/benchmarks/sweep/cli.py @@ -2,7 +2,7 @@ # SPDX-FileCopyrightText: Copyright contributors to the vLLM project import argparse -from vllm.entrypoints.serve.utils.api_utils import VLLM_SUBCMD_PARSER_EPILOG +from vllm.entrypoints.common.startup import VLLM_SUBCMD_PARSER_EPILOG from vllm.utils.argparse_utils import FlexibleArgumentParser from .plot import SweepPlotArgs diff --git a/vllm/entrypoints/cli/benchmark/main.py b/vllm/entrypoints/cli/benchmark/main.py index d540c9ddded..c71e8bf0756 100644 --- a/vllm/entrypoints/cli/benchmark/main.py +++ b/vllm/entrypoints/cli/benchmark/main.py @@ -9,7 +9,7 @@ import typing from vllm import envs from vllm.entrypoints.cli.benchmark.base import BenchmarkSubcommandBase from vllm.entrypoints.cli.types import CLISubcommand -from vllm.entrypoints.serve.utils.api_utils import VLLM_SUBCMD_PARSER_EPILOG +from vllm.entrypoints.common.startup import VLLM_SUBCMD_PARSER_EPILOG from vllm.logger import init_logger if typing.TYPE_CHECKING: diff --git a/vllm/entrypoints/cli/launch.py b/vllm/entrypoints/cli/launch.py index bde58aabf57..442becf87d0 100644 --- a/vllm/entrypoints/cli/launch.py +++ b/vllm/entrypoints/cli/launch.py @@ -7,12 +7,12 @@ import inspect import uvloop from vllm.entrypoints.cli.types import CLISubcommand -from vllm.entrypoints.launchers.cli_args import ( +from vllm.entrypoints.common.cli_args import ( make_arg_parser, validate_parsed_serve_args, ) +from vllm.entrypoints.common.startup import VLLM_SUBCMD_PARSER_EPILOG from vllm.entrypoints.launchers.render.entry import run_launch_fastapi -from vllm.entrypoints.serve.utils.api_utils import VLLM_SUBCMD_PARSER_EPILOG from vllm.logger import init_logger from vllm.utils.argparse_utils import FlexibleArgumentParser diff --git a/vllm/entrypoints/cli/main.py b/vllm/entrypoints/cli/main.py index c85bec4f180..a07d8a754c5 100644 --- a/vllm/entrypoints/cli/main.py +++ b/vllm/entrypoints/cli/main.py @@ -49,10 +49,7 @@ def main(): import vllm.entrypoints.cli.run_batch import vllm.entrypoints.cli.serve import vllm.entrypoints.cli.snapshot - from vllm.entrypoints.serve.utils.api_utils import ( - VLLM_SUBCMD_PARSER_EPILOG, - cli_env_setup, - ) + from vllm.entrypoints.common.startup import VLLM_SUBCMD_PARSER_EPILOG, cli_env_setup from vllm.utils.argparse_utils import FlexibleArgumentParser CMD_MODULES = [ diff --git a/vllm/entrypoints/cli/preload.py b/vllm/entrypoints/cli/preload.py index 90e746fdb68..f8912a29483 100644 --- a/vllm/entrypoints/cli/preload.py +++ b/vllm/entrypoints/cli/preload.py @@ -34,7 +34,7 @@ from fastapi.responses import Response from vllm.engine.arg_utils import EngineArgs from vllm.entrypoints.cli.types import CLISubcommand -from vllm.entrypoints.serve.utils.api_utils import VLLM_SUBCMD_PARSER_EPILOG +from vllm.entrypoints.common.startup import VLLM_SUBCMD_PARSER_EPILOG from vllm.logger import init_logger from vllm.model_executor.model_loader.weight_cache.protocol import ( check_ipc_platform_support, diff --git a/vllm/entrypoints/cli/run_batch.py b/vllm/entrypoints/cli/run_batch.py index 5fa626a6a57..a8be4cee8a9 100644 --- a/vllm/entrypoints/cli/run_batch.py +++ b/vllm/entrypoints/cli/run_batch.py @@ -7,7 +7,7 @@ import importlib.metadata import typing from vllm.entrypoints.cli.types import CLISubcommand -from vllm.entrypoints.serve.utils.api_utils import VLLM_SUBCMD_PARSER_EPILOG +from vllm.entrypoints.common.startup import VLLM_SUBCMD_PARSER_EPILOG from vllm.logger import init_logger if typing.TYPE_CHECKING: diff --git a/vllm/entrypoints/cli/serve.py b/vllm/entrypoints/cli/serve.py index 94e6545c089..40f116514d3 100644 --- a/vllm/entrypoints/cli/serve.py +++ b/vllm/entrypoints/cli/serve.py @@ -10,15 +10,15 @@ import uvloop import vllm import vllm.envs as envs from vllm.entrypoints.cli.types import CLISubcommand -from vllm.entrypoints.launchers.api_server.entry import run_server, setup_server -from vllm.entrypoints.launchers.cli_args import ( +from vllm.entrypoints.common.cli_args import ( make_arg_parser, propagate_flash_late_interaction, validate_parsed_serve_args, ) +from vllm.entrypoints.common.startup import VLLM_SUBCMD_PARSER_EPILOG +from vllm.entrypoints.launchers.api_server.entry import run_server, setup_server from vllm.entrypoints.launchers.dp_supervisor import run_dp_supervisor from vllm.entrypoints.launchers.launcher import create_server_socket -from vllm.entrypoints.serve.utils.api_utils import VLLM_SUBCMD_PARSER_EPILOG from vllm.logger import init_logger from vllm.reasoning import ReasoningParserManager from vllm.usage.usage_lib import UsageContext diff --git a/vllm/entrypoints/cli/snapshot.py b/vllm/entrypoints/cli/snapshot.py index f5201675d40..36d6728ca8f 100644 --- a/vllm/entrypoints/cli/snapshot.py +++ b/vllm/entrypoints/cli/snapshot.py @@ -114,7 +114,7 @@ class SnapshotSubcommand(CLISubcommand): "create", help="Create a snapshot from an initialized TP1 engine." ) if self.create_requested: - from vllm.entrypoints.launchers.cli_args import make_arg_parser + from vllm.entrypoints.common.cli_args import make_arg_parser create_parser = make_arg_parser(create_parser) else: diff --git a/vllm/entrypoints/launchers/cli_args.py b/vllm/entrypoints/common/cli_args.py similarity index 95% rename from vllm/entrypoints/launchers/cli_args.py rename to vllm/entrypoints/common/cli_args.py index 34475a3a610..38bb3468ddc 100644 --- a/vllm/entrypoints/launchers/cli_args.py +++ b/vllm/entrypoints/common/cli_args.py @@ -17,6 +17,10 @@ from vllm.engine.arg_utils import AsyncEngineArgs, optional_type from vllm.entrypoints.anthropic.protocol import ( AnthropicDisabledThinkingEffortOption, ) +from vllm.entrypoints.launchers.utils.constants import ( + H11_MAX_HEADER_COUNT_DEFAULT, + H11_MAX_INCOMPLETE_EVENT_SIZE_DEFAULT, +) from vllm.entrypoints.openai.models.protocol import LoRAModulePath from vllm.logger import init_logger from vllm.renderers.chat_utils import ( @@ -27,11 +31,6 @@ from vllm.tool_parsers import ToolParserManager from vllm.tool_parsers.tool_strict_level import ToolStrictLevelName from vllm.utils.argparse_utils import FlexibleArgumentParser -from .utils.constants import ( - H11_MAX_HEADER_COUNT_DEFAULT, - H11_MAX_INCOMPLETE_EVENT_SIZE_DEFAULT, -) - logger = init_logger(__name__) @@ -571,3 +570,33 @@ def propagate_flash_late_interaction(args, engine_args) -> None: engine_args.pooler_config = PoolerConfig(enable_flash_late_interaction=False) else: engine_args.pooler_config.enable_flash_late_interaction = False + + +def init_parser_plugin(args: argparse.Namespace): + from vllm.reasoning import ReasoningParserManager + + if args.tool_parser_plugin and len(args.tool_parser_plugin) > 3: + ToolParserManager.import_tool_parser(args.tool_parser_plugin) + + if args.reasoning_parser_plugin and len(args.reasoning_parser_plugin) > 3: + ReasoningParserManager.import_reasoning_parser(args.reasoning_parser_plugin) + + +def validate_api_server_args(args: argparse.Namespace): + from vllm.reasoning import ReasoningParserManager + + valid_tool_parses = ToolParserManager.list_registered() + if args.enable_auto_tool_choice and args.tool_call_parser not in valid_tool_parses: + raise KeyError( + f"invalid tool call parser: {args.tool_call_parser} " + f"(chose from {{ {','.join(valid_tool_parses)} }})" + ) + + valid_reasoning_parsers = ReasoningParserManager.list_registered() + if ( + reasoning_parser := args.structured_outputs_config.reasoning_parser + ) and reasoning_parser not in valid_reasoning_parsers: + raise KeyError( + f"invalid reasoning parser: {reasoning_parser} " + f"(chose from {{ {','.join(valid_reasoning_parsers)} }})" + ) diff --git a/vllm/entrypoints/common/startup.py b/vllm/entrypoints/common/startup.py new file mode 100644 index 00000000000..a40be680d0a --- /dev/null +++ b/vllm/entrypoints/common/startup.py @@ -0,0 +1,149 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +import dataclasses +import os +from argparse import Namespace +from logging import Logger +from string import Template +from typing import Any + +from vllm import EngineArgs, envs +from vllm.logger import current_formatter_type, init_logger + +logger = init_logger(__name__) + + +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[1m", # bold, default foreground + "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) + + +VLLM_SUBCMD_PARSER_EPILOG = ( + "For full list: vllm {subcmd} --help=all\n" + "For a section: vllm {subcmd} --help=ModelConfig (case-insensitive)\n" # noqa: E501 + "For a flag: vllm {subcmd} --help=max-model-len (_ or - accepted)\n" # noqa: E501 + "Documentation: https://docs.vllm.ai\n" +) + + +# Fields whose values must never be logged verbatim. +_SENSITIVE_ARG_FIELDS = frozenset({"api_key", "hf_token", "watermark_config"}) + + +def redact_sensitive_args(args: dict[str, Any]) -> dict[str, Any]: + """Return a copy of `args` with sensitive values redacted for logging.""" + if not any(key in _SENSITIVE_ARG_FIELDS for key in args): + return args + return { + key: ("***" if key in _SENSITIVE_ARG_FIELDS else value) + for key, value in args.items() + } + + +def get_non_default_args(args: Namespace | EngineArgs) -> dict[str, Any]: + from vllm.entrypoints.common.cli_args import make_arg_parser + from vllm.utils.argparse_utils import FlexibleArgumentParser + + non_default_args = {} + + # Handle Namespace + if isinstance(args, Namespace): + parser = make_arg_parser(FlexibleArgumentParser()) + for arg, default in vars(parser.parse_args([])).items(): + if default != getattr(args, arg): + non_default_args[arg] = getattr(args, arg) + + # Handle EngineArgs instance + elif isinstance(args, EngineArgs): + default_args = EngineArgs(model=args.model) # Create default instance + for field in dataclasses.fields(args): + current_val = getattr(args, field.name) + default_val = getattr(default_args, field.name) + if current_val != default_val: + non_default_args[field.name] = current_val + if default_args.model != EngineArgs.model: + non_default_args["model"] = default_args.model + else: + raise TypeError( + "Unsupported argument type. Must be Namespace or EngineArgs instance." + ) + + return non_default_args + + +def log_non_default_args(args: Namespace | EngineArgs): + non_default_args = get_non_default_args(args) + logger.info("non-default args: %s", redact_sensitive_args(non_default_args)) + + +def _jsonify_arg_value(value: Any) -> Any: + if value is None or isinstance(value, bool | int | float | str): + return value + if dataclasses.is_dataclass(value) and not isinstance(value, type): + return { + key: _jsonify_arg_value(val) + for key, val in dataclasses.asdict(value).items() + } + if isinstance(value, dict): + return {str(key): _jsonify_arg_value(val) for key, val in value.items()} + if isinstance(value, tuple | list): + return [_jsonify_arg_value(item) for item in value] + if (model_dump := getattr(value, "model_dump", None)) is not None: + return _jsonify_arg_value(model_dump(mode="json")) + if (to_dict := getattr(value, "dict", None)) is not None: + return _jsonify_arg_value(to_dict()) + return repr(value) + + +def jsonify_non_default_args( + args: Namespace | EngineArgs, + *, + exclude: set[str] | None = None, +) -> dict[str, Any]: + non_default_args = get_non_default_args(args) + if exclude is not None: + for key in exclude: + non_default_args.pop(key, None) + + return {key: _jsonify_arg_value(value) for key, value in non_default_args.items()} + + +def cli_env_setup(): + # The safest multiprocessing method is `spawn`, as the default `fork` method + # is not compatible with some accelerators. The default method will be + # changing in future versions of Python, so we should use it explicitly when + # possible. + # + # We only set it here in the CLI entrypoint, because changing to `spawn` + # could break some existing code using vLLM as a library. `spawn` will cause + # unexpected behavior if the code is not protected by + # `if __name__ == "__main__":`. + # + # References: + # - https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods + # - https://pytorch.org/docs/stable/notes/multiprocessing.html#cuda-in-multiprocessing + # - https://pytorch.org/docs/stable/multiprocessing.html#sharing-cuda-tensors + # - https://docs.habana.ai/en/latest/PyTorch/Getting_Started_with_PyTorch_and_Gaudi/Getting_Started_with_PyTorch.html?highlight=multiprocessing#torch-multiprocessing-for-dataloaders + if "VLLM_WORKER_MULTIPROC_METHOD" not in os.environ: + logger.debug("Setting VLLM_WORKER_MULTIPROC_METHOD to 'spawn'") + os.environ["VLLM_WORKER_MULTIPROC_METHOD"] = "spawn" diff --git a/vllm/entrypoints/launchers/api_server/app_state.py b/vllm/entrypoints/launchers/api_server/app_state.py index ff87dbea491..567fded4ea1 100644 --- a/vllm/entrypoints/launchers/api_server/app_state.py +++ b/vllm/entrypoints/launchers/api_server/app_state.py @@ -7,7 +7,7 @@ from typing import cast from starlette.datastructures import State from vllm.engine.protocol import EngineClient -from vllm.entrypoints.launchers.cli_args import resolve_default_chat_template_kwargs +from vllm.entrypoints.common.cli_args import resolve_default_chat_template_kwargs from vllm.entrypoints.mcp.tool_server import init_tool_server from vllm.entrypoints.openai.models.protocol import BaseModelPath from vllm.entrypoints.openai.models.serving import OpenAIServingModels diff --git a/vllm/entrypoints/launchers/api_server/entry.py b/vllm/entrypoints/launchers/api_server/entry.py index e5ba536e112..a856ac0d93f 100644 --- a/vllm/entrypoints/launchers/api_server/entry.py +++ b/vllm/entrypoints/launchers/api_server/entry.py @@ -15,9 +15,8 @@ from typing import Any import vllm.envs as envs from vllm.engine.arg_utils import AsyncEngineArgs from vllm.engine.protocol import EngineClient +from vllm.entrypoints.common.cli_args import init_parser_plugin from vllm.logger import configure_logging_from_args, init_logger -from vllm.reasoning import ReasoningParserManager -from vllm.tool_parsers import ToolParserManager from vllm.usage.usage_lib import UsageContext from vllm.utils.system_utils import decorate_logs @@ -51,7 +50,7 @@ async def build_async_engine_client( # Context manager to handle engine_client lifecycle # Ensures everything is shutdown and cleaned up on error/exit engine_args = AsyncEngineArgs.from_cli_args(args) - from ..cli_args import propagate_flash_late_interaction + from vllm.entrypoints.common.cli_args import propagate_flash_late_interaction propagate_flash_late_interaction(args, engine_args) if client_config: @@ -181,11 +180,7 @@ async def run_server_worker( listen_address, sock, args, client_config=None, **uvicorn_kwargs ) -> None: """Run a single API server worker.""" - if args.tool_parser_plugin and len(args.tool_parser_plugin) > 3: - ToolParserManager.import_tool_parser(args.tool_parser_plugin) - - if args.reasoning_parser_plugin and len(args.reasoning_parser_plugin) > 3: - ReasoningParserManager.import_reasoning_parser(args.reasoning_parser_plugin) + init_parser_plugin(args) peer_loads = None if client_config and "api_server_loads" in client_config: @@ -209,13 +204,12 @@ async def run_server_worker( def 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 ( + from vllm.entrypoints.common.cli_args import ( make_arg_parser, validate_parsed_serve_args, ) + from vllm.entrypoints.common.startup import cli_env_setup + from vllm.utils.argparse_utils import FlexibleArgumentParser # NOTE(simon): # This section should be in sync with vllm/entrypoints/cli/main.py for CLI diff --git a/vllm/entrypoints/launchers/grpc_server.py b/vllm/entrypoints/launchers/grpc_server.py index 2f3808526a0..9cdb18b6bc7 100644 --- a/vllm/entrypoints/launchers/grpc_server.py +++ b/vllm/entrypoints/launchers/grpc_server.py @@ -43,7 +43,7 @@ import uvloop from vllm import envs from vllm.engine.arg_utils import AsyncEngineArgs -from vllm.entrypoints.serve.utils.api_utils import log_version_and_model +from vllm.entrypoints.common.startup import log_version_and_model from vllm.logger import configure_logging_from_args, init_logger from vllm.usage.usage_lib import UsageContext from vllm.utils.argparse_utils import FlexibleArgumentParser diff --git a/vllm/entrypoints/launchers/launcher.py b/vllm/entrypoints/launchers/launcher.py index 1db294cfc6f..ebaf2f3cad0 100644 --- a/vllm/entrypoints/launchers/launcher.py +++ b/vllm/entrypoints/launchers/launcher.py @@ -14,14 +14,16 @@ from fastapi import FastAPI from vllm import envs from vllm.engine.protocol import EngineClient -from vllm.entrypoints.launchers.utils.ssl import SSLCertRefresher -from vllm.entrypoints.serve.utils.api_utils import ( +from vllm.entrypoints.common.cli_args import ( + init_parser_plugin, + validate_api_server_args, +) +from vllm.entrypoints.common.startup import ( log_non_default_args, log_version_and_model, ) +from vllm.entrypoints.launchers.utils.ssl import SSLCertRefresher from vllm.logger import init_logger -from vllm.reasoning import ReasoningParserManager -from vllm.tool_parsers import ToolParserManager from vllm.tracing import instrument from vllm.utils.network_utils import find_process_using_port, is_valid_ipv6_address from vllm.utils.system_utils import set_ulimit @@ -359,36 +361,12 @@ def create_server_unix_socket(path: str) -> socket.socket: return sock -def validate_api_server_args(args): - valid_tool_parses = ToolParserManager.list_registered() - if args.enable_auto_tool_choice and args.tool_call_parser not in valid_tool_parses: - raise KeyError( - f"invalid tool call parser: {args.tool_call_parser} " - f"(chose from {{ {','.join(valid_tool_parses)} }})" - ) - - valid_reasoning_parsers = ReasoningParserManager.list_registered() - if ( - reasoning_parser := args.structured_outputs_config.reasoning_parser - ) and reasoning_parser not in valid_reasoning_parsers: - raise KeyError( - f"invalid reasoning parser: {reasoning_parser} " - f"(chose from {{ {','.join(valid_reasoning_parsers)} }})" - ) - - @instrument(span_name="API server setup") def setup_server(args, *, reuse_port: bool): """Validate API server args and create the server socket.""" 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: - ToolParserManager.import_tool_parser(args.tool_parser_plugin) - - if args.reasoning_parser_plugin and len(args.reasoning_parser_plugin) > 3: - ReasoningParserManager.import_reasoning_parser(args.reasoning_parser_plugin) - + init_parser_plugin(args) validate_api_server_args(args) # workaround to make sure that we bind the port before the engine is set up. diff --git a/vllm/entrypoints/launchers/render/app_state.py b/vllm/entrypoints/launchers/render/app_state.py index d25263f56b5..b498e394312 100644 --- a/vllm/entrypoints/launchers/render/app_state.py +++ b/vllm/entrypoints/launchers/render/app_state.py @@ -5,7 +5,7 @@ from argparse import Namespace from starlette.datastructures import State from vllm.config import VllmConfig -from vllm.entrypoints.launchers.cli_args import resolve_default_chat_template_kwargs +from vllm.entrypoints.common.cli_args import resolve_default_chat_template_kwargs from vllm.entrypoints.mcp.tool_server import init_tool_server from vllm.entrypoints.openai.models.protocol import BaseModelPath from vllm.entrypoints.openai.models.serving import OpenAIModelRegistry diff --git a/vllm/entrypoints/launchers/render/entry.py b/vllm/entrypoints/launchers/render/entry.py index 92c29ea320d..77040a8f68f 100644 --- a/vllm/entrypoints/launchers/render/entry.py +++ b/vllm/entrypoints/launchers/render/entry.py @@ -108,13 +108,12 @@ async def run_launch_fastapi(args: argparse.Namespace) -> None: 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 ( + from vllm.entrypoints.common.cli_args import ( make_arg_parser, validate_parsed_serve_args, ) + from vllm.entrypoints.common.startup import cli_env_setup + from vllm.utils.argparse_utils import FlexibleArgumentParser cli_env_setup() parser = FlexibleArgumentParser( diff --git a/vllm/entrypoints/launchers/run_batch.py b/vllm/entrypoints/launchers/run_batch.py index 266592a731a..5a7f9f3d93d 100644 --- a/vllm/entrypoints/launchers/run_batch.py +++ b/vllm/entrypoints/launchers/run_batch.py @@ -31,6 +31,7 @@ from vllm.config import config from vllm.connections import HTTPResponseSizeExceededError, global_http_connection from vllm.engine.arg_utils import AsyncEngineArgs from vllm.engine.protocol import EngineClient +from vllm.entrypoints.common.cli_args import BaseFrontendArgs from vllm.entrypoints.openai.chat_completion.protocol import ( ChatCompletionRequest, ChatCompletionResponse, @@ -69,7 +70,6 @@ from vllm.utils.mem_constants import MiB_bytes from vllm.version import __version__ as VLLM_VERSION from .api_server.entry import init_app_state -from .cli_args import BaseFrontendArgs logger = init_logger(__name__) diff --git a/vllm/entrypoints/llm.py b/vllm/entrypoints/llm.py index 6b7f91d08e4..8c605d84c66 100644 --- a/vllm/entrypoints/llm.py +++ b/vllm/entrypoints/llm.py @@ -29,16 +29,17 @@ from vllm.config.model import ( from vllm.config.quantization import QuantizationConfigArgs from vllm.engine.arg_utils import EngineArgs from vllm.entrypoints.common.offline import _O, _R, OfflineInferenceMixin +from vllm.entrypoints.common.startup import log_non_default_args from vllm.entrypoints.generate.beam_search.offline import BeamSearchOfflineMixin from vllm.entrypoints.pooling.offline import PoolingOfflineMixin from vllm.entrypoints.rl.offline import RLOfflineMixin -from vllm.entrypoints.serve.utils.api_utils import log_non_default_args from vllm.inputs import PromptType from vllm.logger import configure_logging_if_needed, init_logger from vllm.lora.request import LoRARequest from vllm.model_executor.layers.quantization import QuantizationMethods from vllm.outputs import PoolingRequestOutput, RequestOutput from vllm.platforms import current_platform +from vllm.renderers import ChatParams from vllm.renderers.chat_utils import ( ChatCompletionMessageParam, ChatTemplateContentFormatOption, @@ -52,8 +53,6 @@ from vllm.v1.engine import PauseMode from vllm.v1.engine.llm_engine import LLMEngine from vllm.v1.sample.logits_processor import LogitsProcessor -from ..renderers import ChatParams - if TYPE_CHECKING: from vllm.v1.metrics.reader import Metric diff --git a/vllm/entrypoints/serve/utils/api_utils.py b/vllm/entrypoints/serve/utils/api_utils.py index 14de8b558a5..6ddec1d6f64 100644 --- a/vllm/entrypoints/serve/utils/api_utils.py +++ b/vllm/entrypoints/serve/utils/api_utils.py @@ -2,13 +2,8 @@ # SPDX-FileCopyrightText: Copyright contributors to the vLLM project import asyncio -import dataclasses import functools -import os -from argparse import Namespace from http import HTTPStatus -from logging import Logger -from string import Template from typing import Any from fastapi import Request @@ -17,23 +12,13 @@ from fastapi.responses import JSONResponse, Response, StreamingResponse from pydantic import BaseModel from starlette.background import BackgroundTask, BackgroundTasks -from vllm import envs -from vllm.engine.arg_utils import EngineArgs from vllm.entrypoints.generate.base.protocol import StreamOptions from vllm.entrypoints.openai.models.protocol import LoRAModulePath -from vllm.logger import current_formatter_type, init_logger +from vllm.logger import init_logger from vllm.platforms import current_platform -from vllm.utils.argparse_utils import FlexibleArgumentParser logger = init_logger(__name__) -VLLM_SUBCMD_PARSER_EPILOG = ( - "For full list: vllm {subcmd} --help=all\n" - "For a section: vllm {subcmd} --help=ModelConfig (case-insensitive)\n" # noqa: E501 - "For a flag: vllm {subcmd} --help=max-model-len (_ or - accepted)\n" # noqa: E501 - "Documentation: https://docs.vllm.ai\n" -) - async def listen_for_disconnect(request: Request) -> None: """Returns if a disconnect message is received.""" @@ -216,27 +201,6 @@ def load_aware_call(func): return wrapper -def cli_env_setup(): - # The safest multiprocessing method is `spawn`, as the default `fork` method - # is not compatible with some accelerators. The default method will be - # changing in future versions of Python, so we should use it explicitly when - # possible. - # - # We only set it here in the CLI entrypoint, because changing to `spawn` - # could break some existing code using vLLM as a library. `spawn` will cause - # unexpected behavior if the code is not protected by - # `if __name__ == "__main__":`. - # - # References: - # - https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods - # - https://pytorch.org/docs/stable/notes/multiprocessing.html#cuda-in-multiprocessing - # - https://pytorch.org/docs/stable/multiprocessing.html#sharing-cuda-tensors - # - https://docs.habana.ai/en/latest/PyTorch/Getting_Started_with_PyTorch_and_Gaudi/Getting_Started_with_PyTorch.html?highlight=multiprocessing#torch-multiprocessing-for-dataloaders - if "VLLM_WORKER_MULTIPROC_METHOD" not in os.environ: - logger.debug("Setting VLLM_WORKER_MULTIPROC_METHOD to 'spawn'") - os.environ["VLLM_WORKER_MULTIPROC_METHOD"] = "spawn" - - def get_max_tokens( max_model_len: int, max_tokens: int | None, @@ -276,87 +240,6 @@ def get_max_tokens( ) -def get_non_default_args(args: Namespace | EngineArgs) -> dict[str, Any]: - from vllm.entrypoints.launchers.cli_args import make_arg_parser - - non_default_args = {} - - # Handle Namespace - if isinstance(args, Namespace): - parser = make_arg_parser(FlexibleArgumentParser()) - for arg, default in vars(parser.parse_args([])).items(): - if default != getattr(args, arg): - non_default_args[arg] = getattr(args, arg) - - # Handle EngineArgs instance - elif isinstance(args, EngineArgs): - default_args = EngineArgs(model=args.model) # Create default instance - for field in dataclasses.fields(args): - current_val = getattr(args, field.name) - default_val = getattr(default_args, field.name) - if current_val != default_val: - non_default_args[field.name] = current_val - if default_args.model != EngineArgs.model: - non_default_args["model"] = default_args.model - else: - raise TypeError( - "Unsupported argument type. Must be Namespace or EngineArgs instance." - ) - - return non_default_args - - -def _jsonify_arg_value(value: Any) -> Any: - if value is None or isinstance(value, bool | int | float | str): - return value - if dataclasses.is_dataclass(value) and not isinstance(value, type): - return { - key: _jsonify_arg_value(val) - for key, val in dataclasses.asdict(value).items() - } - if isinstance(value, dict): - return {str(key): _jsonify_arg_value(val) for key, val in value.items()} - if isinstance(value, tuple | list): - return [_jsonify_arg_value(item) for item in value] - if (model_dump := getattr(value, "model_dump", None)) is not None: - return _jsonify_arg_value(model_dump(mode="json")) - if (to_dict := getattr(value, "dict", None)) is not None: - return _jsonify_arg_value(to_dict()) - return repr(value) - - -def jsonify_non_default_args( - args: Namespace | EngineArgs, - *, - exclude: set[str] | None = None, -) -> dict[str, Any]: - non_default_args = get_non_default_args(args) - if exclude is not None: - for key in exclude: - non_default_args.pop(key, None) - - return {key: _jsonify_arg_value(value) for key, value in non_default_args.items()} - - -# Fields whose values must never be logged verbatim. -_SENSITIVE_ARG_FIELDS = frozenset({"api_key", "hf_token", "watermark_config"}) - - -def redact_sensitive_args(args: dict[str, Any]) -> dict[str, Any]: - """Return a copy of `args` with sensitive values redacted for logging.""" - if not any(key in _SENSITIVE_ARG_FIELDS for key in args): - return args - return { - key: ("***" if key in _SENSITIVE_ARG_FIELDS else value) - for key, value in args.items() - } - - -def log_non_default_args(args: Namespace | EngineArgs): - non_default_args = get_non_default_args(args) - logger.info("non-default args: %s", redact_sensitive_args(non_default_args)) - - def should_include_usage( stream_options: StreamOptions | None, enable_force_include_usage: bool ) -> tuple[bool, bool]: @@ -393,31 +276,6 @@ def process_lora_modules( return lora_modules -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[1m", # bold, default foreground - "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) - - async def validate_json_request(raw_request: Request): content_type = raw_request.headers.get("content-type", "").lower() media_type = content_type.split(";", maxsplit=1)[0] diff --git a/vllm/snapshot/server.py b/vllm/snapshot/server.py index 2dc0f3384ae..724739e6d6d 100644 --- a/vllm/snapshot/server.py +++ b/vllm/snapshot/server.py @@ -176,7 +176,7 @@ async def wait_for_release_marker( def parse_vllm_args(argv: list[str]) -> Any: - from vllm.entrypoints.launchers.cli_args import ( + from vllm.entrypoints.common.cli_args import ( make_arg_parser, validate_parsed_serve_args, ) diff --git a/vllm/v1/utils.py b/vllm/v1/utils.py index b8d98ff1cf7..4a3a09d5a7f 100644 --- a/vllm/v1/utils.py +++ b/vllm/v1/utils.py @@ -331,7 +331,7 @@ class RustFrontendProcessManager: inherited_fds.append(grpc_fd) if stats_update_address is not None: cmd.extend(["--coordinator-address", stats_update_address]) - from vllm.entrypoints.serve.utils.api_utils import jsonify_non_default_args + from vllm.entrypoints.common.startup import jsonify_non_default_args args_dict = jsonify_non_default_args( args, @@ -366,7 +366,7 @@ class RustFrontendProcessManager: # The subprocess needs the real values, but the log must not carry # credentials such as api_key or hf_token. - from vllm.entrypoints.serve.utils.api_utils import redact_sensitive_args + from vllm.entrypoints.common.startup import redact_sensitive_args redacted_json = json.dumps(redact_sensitive_args(args_dict), sort_keys=True) logger.info("Launching Rust frontend: %s", " ".join(cmd[:-1] + [redacted_json]))