EngineArgs: コマンドライン引数から VllmConfig まで
役割
vLLM は調整可能なすべてのノブを一つの巨大な EngineArgs dataclass に並べている(arg_utils.py:413-414)。モデル名、tensor_parallel_size、gpu_memory_utilization、量子化方式、kv_cache_dtype、speculative config、reasoning config、各種 attention/kernel 設定……合わせて 300 近いフィールドがある。この層の役割は、散在する CLI flag・YAML 設定ファイル・Python kwargs を同一の EngineArgs インスタンスに統一し、create_engine_config()(arg_utils.py:1822-1824)で VllmConfig ——ModelConfig / CacheConfig / ParallelConfig / SchedulerConfig / CompilationConfig / KernelConfig など十数個の sub-config を一つにまとめた集約 (aggregate) コンテナ(vllm.py:287-300)——に組み立てることだ。
VllmConfig は後続の全モジュールの「憲法」である:LLMEngine、AsyncLLM、EngineCore、Scheduler、KVCacheManager、Executor はすべてこのオブジェクトからフィールドを読む。EngineArgs は唯一の書き込みパスであり——モデル重みから逆推される少数の quant_config を除き——すべての sub-config フィールドは EngineArgs の dataclass field に対応する。これにより単一の真理源 (single source of truth) が保証される:vllm serve、LLM(...)、Ray Serve LLM、run_batch のいずれも、最終的に EngineArgs.create_engine_config() に到達すれば設定は一致する。
フィールド層には注意すべき細部がある:EngineArgs の各 field のデフォルト値は = ModelConfig.model、= ParallelConfig.tensor_parallel_size のように sub-config のフィールドデフォルト値を直接参照している(arg_utils.py:417-420)。つまり EngineArgs は dataclass レベルで VllmConfig の全 sub-config を「ミラーリング」しており、これにより CLI パラメータ登録時に各 sub-config を一つの argument group としてまとめて登録でき(arg_utils.py:1504-1508)、--help 出力も ModelConfig/VllmConfig でグループ化されて表示される。
設計動機
なぜ pydantic モデル / argparse Namespace をそのまま使わず、中間に EngineArgs の層を挟むのか?
- CLI と SDK で schema を共用:
add_cli_args(arg_utils.py:790)はget_kwargs(ModelConfig)(arg_utils.py:400)で sub-config の各 field を自動的に argparse パラメータとして登録する。Python SDKLLM(model=..., tensor_parallel_size=...)は直接EngineArgs(...)dataclass の構築を経由する——二つの経路が同じ field 定義を使うため、一箇所変更すれば済む。 - 型から argparse kwargs を派生:
_compute_kwargs(arg_utils.py:288-322)は field の type hint に基づいて argparse のtype=/nargs=/action=を派生する——bool はBooleanOptionalAction、Literal はchoices、dataclass は pydanticTypeAdapter.validate_json、list/tuple はnargs="+"、int フィールドのmax_model_lenはhuman_readable_int_or_autoに特判。これにより「field を一つ追加」することが本当に dataclass フィールド一行追加だけで済む。 - 設定組み立ては段階的:
create_engine_configは無脑に構築するわけではなく、内部でまずmaybe_override_with_speculators(arg_utils.py:1839-1849)で model/tokenizer を書き換える可能性があり、次にcreate_model_config()(arg_utils.py:1604-1614)、続いて_check_feature_supported(arg_utils.py:2369)、_set_default_chunked_prefill_and_prefix_caching_args(arg_utils.py:2480-2515)、_set_default_reasoning_config_argsを呼ぶ。こうした「デフォルト値が別の config が算出された後に依存する」という依存関係を、統一されたcreate_engine_configの中でつなぐ方が、各 sub-config に__post_init__で互いに読み合うよりずっと簡単。 - プラットフォーム/プラグイン hook:
AsyncEngineArgs.add_cli_argsの中でload_general_plugins()(arg_utils.py:2695)を呼んでプラグインに parser を変更させ(例:新たな--quantizationオプションの登録)、current_platform.pre_register_and_update(parser)(arg_utils.py:2707)で CUDA/HPU/TPU/CPU 各々がプラットフォーム固有の flag を補う。create_engine_configでも冒頭でcurrent_platform.pre_register_and_update()(arg_utils.py:1828)をもう一度走らせ、プラットフォームデフォルト値を args に書き戻す。 - AsyncEngineArgs を別サブクラス化:サーバーシナリオは
enable_log_requests(arg_utils.py:2686)が一つ多い。そのためサーバーサイドではAsyncEngineArgs(EngineArgs)サブクラスで一つフィールドを補い、オフラインLLMの schema を汚染しない。
主要ファイル
EngineArgs dataclass:413-414—@dataclass class EngineArgs:定義、docstringArguments for vLLM engine.。EngineArgs フィールド:417-470— 各 field のデフォルト値がModelConfig.xxx/ParallelConfig.xxxを参照し、sub-config をミラーリング。_compute_kwargs:288-322— type hint に基づき argparse kwargs を派生、pydantic FieldInfo / default_factory を処理。get_kwargs:400-411— キャッシュ版_compute_kwargs、sub-config の field を argparse パラメータ辞書に変換。add_cli_args ModelConfig グループ:790-887— ModelConfig の field を--model/--runner/--tokenizerなどの flag として一括登録。add_cli_args VllmConfig グループ:1504-1554—--speculative-config/--compilation-config/--kernel-configなどの集約 config の flag 登録、JSON 型はoptional_type(json.loads)を使用。from_cli_args:1594-1602—dataclasses.fields(cls)で EngineArgs フィールド名を逆推し、argparse Namespace から EngineArgs インスタンスを逆構築。create_engine_config 先頭:1822-1828—pre_register_and_update+envs.validate_environ+ speculator override のエントリ。VllmConfig 組み立て:2338-2365— model_config / cache_config / parallel_config / scheduler_config / ... をすべてVllmConfig(...)に投入。_set_default_chunked_prefill_and_prefix_caching_args:2480-2515— 値が明示的に与えられなかった場合、model_config.is_chunked_prefill_supported/is_prefix_caching_supportedに基づきデフォルトを埋め戻し、runner_type が一致しない場合は warning を出す。AsyncEngineArgs:2682-2708— サーバーサイド用サブクラス、--enable-log-requestsを補い、load_general_pluginsとpre_register_and_updateを呼ぶ。VllmConfig クラス:287-346— 集約コンテナ本体、フィールド順:model/cache/parallel/scheduler/device/load/offload/attention/mamba/kernel/lora/speculative/diffusion/structured_outputs/observability/quant/compilation/profiler/kv_transfer/kv_events。
データフロー
CLI flag または Python kwarg が入ってきた後のチェーン:parser.parse_args() → EngineArgs.from_cli_args(args)(arg_utils.py:1594-1602)が Namespace の対応フィールドを dataclass に詰め、その後 create_engine_config(usage_context=...)(arg_utils.py:1822)を呼ぶ。以下が create_engine_config の最も重要な組み立て処理:
# vllm/engine/arg_utils.py L2338-L2365
config = VllmConfig(
model_config=model_config,
cache_config=cache_config,
parallel_config=parallel_config,
scheduler_config=scheduler_config,
device_config=device_config,
load_config=load_config,
offload_config=offload_config,
attention_config=attention_config,
mamba_config=mamba_config,
kernel_config=kernel_config,
lora_config=lora_config,
speculative_config=speculative_config,
diffusion_config=diffusion_config,
structured_outputs_config=self.structured_outputs_config,
observability_config=observability_config,
compilation_config=compilation_config,
kv_transfer_config=self.kv_transfer_config,
kv_events_config=self.kv_events_config,
ec_transfer_config=self.ec_transfer_config,
reasoning_config=self.reasoning_config,
profiler_config=self.profiler_config,
additional_config=self.additional_config,
optimization_level=self.optimization_level,
performance_mode=self.performance_mode,
weight_transfer_config=self.weight_transfer_config,
shutdown_timeout=self.shutdown_timeout,
)上記の各 sub-config は VllmConfig に詰め込まれる前にすべて個別に構築されている:cache_config は arg_utils.py:1875-1894 で CacheConfig(...) を現場で組み立て、parallel_config の前には nnodes > 1 に基づいて inferred_data_parallel_rank(arg_utils.py:1943-1977)を算出する。つまり create_engine_config は単なる代入ではなく、一連の依存計算である:ModelConfig が先行し(続く CacheConfig.sliding_window、is_attention_free がすべてこれを読むため)、その後 CacheConfig、ParallelConfig、SchedulerConfig が順に算出され、最後にすべて VllmConfig に投入される。
境界と失敗
- 環境変数の検証:
create_engine_configの冒頭でenvs.validate_environ(self.fail_on_environ_validation)(arg_utils.py:1832)を呼ぶ。--fail-on-environ-validationはデフォルト False で、有効にすると未認識のVLLM_*環境変数が直接 raise され、名前の打ち間違いが黙って効いてしまうのを防ぐ。 - マルチノード DP 推論:
nnodes > 1の場合、ユーザーがdata_parallel_size_localまたはdata_parallel_rankを明示的に与えなければ、コードはnode_rank * local_world_size // world_size_within_dpに基づいて逆推し(arg_utils.py:1944-1977)、外部 LB モードでのdata_parallel_rankを args に書き戻す。 - LB モードの相互排他:
data_parallel_hybrid_lbとdata_parallel_external_lbは同時に True にできない(arg_utils.py:1937-1942)。data_parallel_backend == "mp"はnnodes == 1が必須——これらの assert は argparse 段階ではなくcreate_engine_config内で直接投げられる。 - headless と hybrid_lb の相互排他:
headlessモードではnot self.data_parallel_hybrid_lbをアサート(arg_utils.py:1934-1936)する。headless は multi-node 用で、内部 LB は無意味だから。 - pipeline parallel の制限:
pipeline_parallel_size > 1の場合、_check_feature_supportedは executor backend がsupports_ppであるか、明示的にray/mp/external_launcherであることを要求(arg_utils.py:2379-2394)し、そうでなければ_raise_unsupported_error。 - chunked prefill / prefix caching の不一致:
_set_default_chunked_prefill_and_prefix_caching_argsは pooling runner が chunked prefill を強制的に有効にした(arg_utils.py:2503-2512)り、モデルが公式サポートする chunked prefill を閉じた(arg_utils.py:2493-2502)りする場合、warning_onceを出すだけで強制阻止しない——ユーザーがどうしても踏みたいなら踏ませる。 - Ray runtime env の注入:Ray actor 内で
create_engine_configを走らせるとray.get_runtime_context().runtime_env(arg_utils.py:1907-1921)を取得し、env_vars を明示的に***に置換して機密変数がログに入るのを防ぐ。
まとめ
EngineArgs は vLLM の設定エントリ層である:一つの dataclass がすべての sub-config のフィールドを平坦に並べ、add_cli_args が type hint に基づいて自動的に argparse flag として登録し、create_engine_config が段階的なデフォルト値推導・speculator override・プラットフォーム/プラグイン hook・sub-config の組み立てを一つにまとめ、最後に唯一の VllmConfig を生成して下流の全モジュールに使わせる。CLI、Python SDK、Ray Serve はすべてこの同一パスを共用するため、ターミナルで vllm serve を叩いてもコード内で LLM(...) しても、最終的にエンジンに渡る config フィールドの意味は同一。下流に進むなら /startup/cli で vllm serve が CLI から EngineArgs をどう組み立てるかを見るか、/startup/llm-class で LLM / AsyncLLM が VllmConfig をどうやって実際に推論可能なオブジェクトにするかを見る。/engine/engine-core では VllmConfig が EngineCore でどう消費されるかを取り上げる。
公式資料: vLLM ドキュメント · README