Skip to content

EngineArgs: コマンドライン引数から VllmConfig まで

源码版本v0.25.1

役割

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 serveLLM(...)、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 SDK LLM(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 は pydantic TypeAdapter.validate_json、list/tuple は nargs="+"、int フィールドの max_model_lenhuman_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: 定義、docstring Arguments 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-1602dataclasses.fields(cls) で EngineArgs フィールド名を逆推し、argparse Namespace から EngineArgs インスタンスを逆構築。
  • create_engine_config 先頭:1822-1828pre_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_pluginspre_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 の最も重要な組み立て処理:

python
# 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_configarg_utils.py:1875-1894CacheConfig(...) を現場で組み立て、parallel_config の前には nnodes > 1 に基づいて inferred_data_parallel_rank(arg_utils.py:1943-1977)を算出する。つまり create_engine_config は単なる代入ではなく、一連の依存計算である:ModelConfig が先行し(続く CacheConfig.sliding_windowis_attention_free がすべてこれを読むため)、その後 CacheConfigParallelConfigSchedulerConfig が順に算出され、最後にすべて 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_lbdata_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/clivllm serve が CLI から EngineArgs をどう組み立てるかを見るか、/startup/llm-classLLM / AsyncLLMVllmConfig をどうやって実際に推論可能なオブジェクトにするかを見る。/engine/engine-core では VllmConfig が EngineCore でどう消費されるかを取り上げる。

公式資料: vLLM ドキュメント · README