diff --git a/tests/benchmarks/test_accuracy_bench_utils.py b/tests/benchmarks/test_accuracy_bench_utils.py index ab539234616..8d78da2b2da 100644 --- a/tests/benchmarks/test_accuracy_bench_utils.py +++ b/tests/benchmarks/test_accuracy_bench_utils.py @@ -1,9 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + # ruff: noqa: E402, I001 import argparse import math import os import sys -import types from pathlib import Path import pytest @@ -106,11 +108,9 @@ def fake_snapshot_download(*, repo_id, repo_type, allow_patterns): captured["allow_patterns"] = allow_patterns return str(downloaded_root) - monkeypatch.setitem( - sys.modules, - "huggingface_hub", - types.SimpleNamespace(snapshot_download=fake_snapshot_download), - ) + from vllm_omni.transformers_utils import repo_utils + + monkeypatch.setattr(repo_utils.hf_api(), "snapshot_download", fake_snapshot_download) resolved = resolve_seed_tts_root( "zhaochenyang20/seed-tts-eval", diff --git a/tests/dfx/perf/scripts/run_diffusion_benchmark.py b/tests/dfx/perf/scripts/run_diffusion_benchmark.py index bb69391fdf1..ffcfc45b721 100644 --- a/tests/dfx/perf/scripts/run_diffusion_benchmark.py +++ b/tests/dfx/perf/scripts/run_diffusion_benchmark.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + """ Performance benchmark CI runner for diffusion models. @@ -356,6 +359,8 @@ def _resolve_offline_model(model: str) -> str: """ import huggingface_hub + from vllm_omni.transformers_utils.repo_utils import hf_api + if not model or os.path.isdir(model): return model @@ -380,9 +385,7 @@ def _resolve_offline_model(model: str) -> str: if len(parts) >= 3: repo_id = "/".join(parts[:2]) subfolder = "/".join(parts[2:]) - from huggingface_hub import snapshot_download - - snapshot_root = snapshot_download( + snapshot_root = hf_api().snapshot_download( repo_id, allow_patterns=[f"{subfolder}/**"], local_files_only=huggingface_hub.constants.HF_HUB_OFFLINE, @@ -391,9 +394,7 @@ def _resolve_offline_model(model: str) -> str: if not huggingface_hub.constants.HF_HUB_OFFLINE: return model - from huggingface_hub import snapshot_download - - return snapshot_download(model, local_files_only=True) + return hf_api().snapshot_download(model, local_files_only=True) class DiffusionServer: diff --git a/tests/diffusion/model_loader/test_diffusers_loader.py b/tests/diffusion/model_loader/test_diffusers_loader.py index 555cb19bb4d..565949ff616 100644 --- a/tests/diffusion/model_loader/test_diffusers_loader.py +++ b/tests/diffusion/model_loader/test_diffusers_loader.py @@ -13,7 +13,6 @@ import pytest import torch import torch.nn as nn -from huggingface_hub import snapshot_download from safetensors.torch import save_file from vllm.config.load import LoadConfig @@ -32,6 +31,7 @@ from vllm_omni.diffusion.models.host_weight_contract import FinalLayoutModelContract from vllm_omni.diffusion.registry import initialize_model from vllm_omni.quantization.component_config import ComponentQuantizationConfig +from vllm_omni.transformers_utils.repo_utils import hf_api pytestmark = [pytest.mark.core_model, pytest.mark.diffusion, pytest.mark.cpu] @@ -41,7 +41,7 @@ @pytest.fixture(scope="module") def prefetch_helios_model(): """Downloads the tiny helios model prior to running a test.""" - snapshot_download(model_path) + hf_api().snapshot_download(model_path) @pytest.fixture(scope="function") diff --git a/tests/diffusion/model_loader/test_hub_prefetch.py b/tests/diffusion/model_loader/test_hub_prefetch.py index 39eb2b27711..94170edcc3f 100644 --- a/tests/diffusion/model_loader/test_hub_prefetch.py +++ b/tests/diffusion/model_loader/test_hub_prefetch.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project import contextlib @@ -14,10 +14,10 @@ def test_prefetch_subfolders_propagates_revision(monkeypatch): calls = [] - def fake_snapshot_download(**kwargs): + def fake_snapshot_download(self, **kwargs): calls.append(kwargs) - monkeypatch.setattr(huggingface_hub, "snapshot_download", fake_snapshot_download) + monkeypatch.setattr(huggingface_hub.HfApi, "snapshot_download", fake_snapshot_download) monkeypatch.setattr(hub_prefetch, "_repo_prefetch_lock", lambda _model: contextlib.nullcontext()) hub_prefetch.prefetch_subfolders( diff --git a/tests/diffusion/models/cosmos3/test_cosmos3_sound_tokenizer.py b/tests/diffusion/models/cosmos3/test_cosmos3_sound_tokenizer.py index 7ab04cc212f..1aa653d4a37 100644 --- a/tests/diffusion/models/cosmos3/test_cosmos3_sound_tokenizer.py +++ b/tests/diffusion/models/cosmos3/test_cosmos3_sound_tokenizer.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project from __future__ import annotations @@ -81,9 +81,8 @@ def test_from_config_loads_local_diffusers_component(tmp_path, monkeypatch: pyte def test_from_config_downloads_component_from_hf_repo(tmp_path, monkeypatch: pytest.MonkeyPatch) -> None: - import huggingface_hub - from vllm_omni.diffusion.models.cosmos3 import sound_tokenizer + from vllm_omni.transformers_utils import repo_utils cache_dir = tmp_path / "hf" _write_component(cache_dir, checkpoint_name=DIFFUSERS_SOUND_TOKENIZER_CHECKPOINT_NAME) @@ -95,7 +94,7 @@ def fake_snapshot_download(repo_id: str, *, revision: str | None, allow_patterns calls.append((repo_id, revision, allow_patterns)) return str(cache_dir) - monkeypatch.setattr(huggingface_hub, "snapshot_download", fake_snapshot_download) + monkeypatch.setattr(repo_utils.hf_api(), "snapshot_download", fake_snapshot_download) sound_tokenizer.Cosmos3SoundTokenizer.from_config( SimpleNamespace( diff --git a/tests/diffusion/models/ltx2/test_ltx2_pipeline.py b/tests/diffusion/models/ltx2/test_ltx2_pipeline.py index 3e630d8ddd6..a7f6b95dfb8 100644 --- a/tests/diffusion/models/ltx2/test_ltx2_pipeline.py +++ b/tests/diffusion/models/ltx2/test_ltx2_pipeline.py @@ -10,6 +10,7 @@ from types import SimpleNamespace from typing import Any +import huggingface_hub import numpy as np import pytest import torch @@ -302,11 +303,11 @@ def test_ltx_artifact_uses_source_revision_and_hub_fallback( filename = "ltx-sidecar.safetensors" calls = [] - def fake_download(**kwargs): + def fake_download(self, **kwargs): calls.append(kwargs) return "/cache/ltx-sidecar.safetensors" - monkeypatch.setattr(ltx2_components, "hf_hub_download", fake_download) + monkeypatch.setattr(huggingface_hub.HfApi, "hf_hub_download", fake_download) assert ( resolve_ltx_artifact( @@ -331,7 +332,9 @@ def test_ltx_artifact_prefers_model_root(tmp_path, monkeypatch): filename = "ltx-sidecar.safetensors" expected = tmp_path / filename expected.write_bytes(b"sidecar") - monkeypatch.setattr(ltx2_components, "hf_hub_download", lambda **_kwargs: pytest.fail("unexpected Hub lookup")) + monkeypatch.setattr( + huggingface_hub.HfApi, "hf_hub_download", lambda *_args, **_kwargs: pytest.fail("unexpected Hub lookup") + ) assert resolve_ltx_artifact( str(tmp_path), @@ -345,11 +348,11 @@ def test_ltx_artifact_prefers_model_root(tmp_path, monkeypatch): def test_ltx_artifact_local_model_missing_sidecar_falls_back_to_hub(tmp_path, monkeypatch): calls = [] - def fake_download(**kwargs): + def fake_download(self, **kwargs): calls.append(kwargs) return "/cache/ltx-sidecar.safetensors" - monkeypatch.setattr(ltx2_components, "hf_hub_download", fake_download) + monkeypatch.setattr(huggingface_hub.HfApi, "hf_hub_download", fake_download) assert ( resolve_ltx_artifact( diff --git a/tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py b/tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py index 0fb043a1ec5..a45631f7dce 100644 --- a/tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py +++ b/tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py @@ -42,10 +42,10 @@ def _resolve_fl2va_model_ref() -> str: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api repo_root = Path( - snapshot_download( + hf_api().snapshot_download( repo_id=_MINIMAX_H3_REPO, revision=_MINIMAX_H3_REVISION, allow_patterns=["FL2VA/**"], @@ -253,13 +253,13 @@ def test_resolve_fl2va_model_ref(tmp_path, monkeypatch): fl2va_root.mkdir() (fl2va_root / "model_index.json").write_text("{}", encoding="utf-8") - def fake_snapshot_download(*, repo_id, revision, allow_patterns): + def fake_snapshot_download(self, *, repo_id, revision, allow_patterns): assert repo_id == _MINIMAX_H3_REPO assert revision == _MINIMAX_H3_REVISION assert allow_patterns == ["FL2VA/**"] return str(tmp_path) - monkeypatch.setattr("huggingface_hub.snapshot_download", fake_snapshot_download) + monkeypatch.setattr("huggingface_hub.HfApi.snapshot_download", fake_snapshot_download) assert _resolve_fl2va_model_ref() == str(fl2va_root) diff --git a/tests/e2e/accuracy/ltx/test_ltx_official_similarity.py b/tests/e2e/accuracy/ltx/test_ltx_official_similarity.py index 63ce7392371..c1b083495e9 100644 --- a/tests/e2e/accuracy/ltx/test_ltx_official_similarity.py +++ b/tests/e2e/accuracy/ltx/test_ltx_official_similarity.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """E2E accuracy guard against a pinned Lightricks LTX pipeline revision. @@ -22,11 +22,11 @@ import numpy as np import pytest import torch -from huggingface_hub import hf_hub_download, snapshot_download from torchmetrics.image import PeakSignalNoiseRatio, StructuralSimilarityIndexMeasure from tests.e2e.accuracy.helpers import reset_artifact_dir from tests.helpers.mark import hardware_test +from vllm_omni.transformers_utils.repo_utils import hf_api OFFICIAL_REPOSITORY = "https://github.com/Lightricks/LTX-2.git" OFFICIAL_REVISION = "9377758131b1ffde4b7f766804590a6617bf2ab9" @@ -326,7 +326,7 @@ def _resolve_model(case: LTXAccuracyCase) -> Path: if revision is None and model_id == case.model_id: revision = case.model_revision return Path( - snapshot_download( + hf_api().snapshot_download( repo_id=model_id, revision=revision, allow_patterns=[ @@ -359,7 +359,7 @@ def _resolve_gemma_root(case: LTXAccuracyCase, model: Path) -> Path: if configured_model and Path(configured_model).is_dir(): return Path(configured_model) return Path( - snapshot_download( + hf_api().snapshot_download( repo_id=case.gemma_model_id, revision=case.gemma_model_revision, allow_patterns=[ @@ -383,7 +383,7 @@ def _resolve_artifact(artifact: LTXArtifact, model: Path | None = None) -> Path: if model_path.is_file(): return model_path return Path( - hf_hub_download( + hf_api().hf_hub_download( repo_id=artifact.repo_id, repo_type=None if artifact.repo_type == "model" else artifact.repo_type, filename=artifact.filename, diff --git a/tests/e2e/features/rlhf_test/test_verl_omni_e2e.py b/tests/e2e/features/rlhf_test/test_verl_omni_e2e.py index dab5feef1f8..8d8062092a1 100644 --- a/tests/e2e/features/rlhf_test/test_verl_omni_e2e.py +++ b/tests/e2e/features/rlhf_test/test_verl_omni_e2e.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """E2E test that follows the EXACT same flow as ``verl-omni/tests/workers/rollout/rollout_vllm/test_vllm_omni_generate.py`` @@ -35,7 +35,6 @@ import pytest import ray import torch -from huggingface_hub import snapshot_download from omegaconf import OmegaConf from transformers import AutoTokenizer @@ -46,6 +45,7 @@ vLLMOmniHttpServerLocal, ) from tests.helpers.mark import hardware_test +from vllm_omni.transformers_utils.repo_utils import hf_api MODEL = "tiny-random/Qwen-Image" TOKENIZER_MODEL = "Qwen/Qwen2-1.5B-Instruct" @@ -55,7 +55,7 @@ def _resolve_model_path(repo_id: str) -> str: if os.path.isdir(repo_id): return repo_id - return snapshot_download(repo_id=repo_id) + return hf_api().snapshot_download(repo_id=repo_id) @lru_cache(maxsize=1) diff --git a/tests/e2e/offline_inference/test_cosyvoice3_expansion.py b/tests/e2e/offline_inference/test_cosyvoice3_expansion.py index 7e57433ef5c..dd7c8ec8509 100644 --- a/tests/e2e/offline_inference/test_cosyvoice3_expansion.py +++ b/tests/e2e/offline_inference/test_cosyvoice3_expansion.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """ Offline E2E smoke test for CosyVoice3 zero-shot reference inference. @@ -20,7 +20,6 @@ import numpy as np import pytest import soundfile as sf -from huggingface_hub import snapshot_download from vllm.sampling_params import SamplingParams from tests.helpers.mark import hardware_test @@ -29,6 +28,7 @@ from tests.helpers.stage_config import get_deploy_config_path from vllm_omni.model_executor.models.cosyvoice3.tokenizer import get_qwen_tokenizer from vllm_omni.transformers_utils.configs.cosyvoice3 import CosyVoice3Config +from vllm_omni.transformers_utils.repo_utils import hf_api MODEL = "FunAudioLLM/Fun-CosyVoice3-0.5B-2512" MODEL_DIR_ENV = "VLLM_OMNI_COSYVOICE3_MODEL_DIR" @@ -58,7 +58,7 @@ def _resolve_model_dir() -> Path: override = os.environ.get(MODEL_DIR_ENV) if override: return Path(override).expanduser().resolve() - return Path(snapshot_download(MODEL, allow_patterns=["*"])) + return Path(hf_api().snapshot_download(MODEL, allow_patterns=["*"])) def _reference_zero_shot_stage0_sampling(*, text: str) -> SamplingParams: diff --git a/tests/e2e/offline_inference/test_mammoth_moda2_expansion.py b/tests/e2e/offline_inference/test_mammoth_moda2_expansion.py index f570a6ea717..4f21dd1c485 100644 --- a/tests/e2e/offline_inference/test_mammoth_moda2_expansion.py +++ b/tests/e2e/offline_inference/test_mammoth_moda2_expansion.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + """ End-to-end test for MammothModa2 text-to-image generation. @@ -19,12 +22,12 @@ import pytest import torch -from huggingface_hub import snapshot_download from vllm.sampling_params import SamplingParams from tests.helpers.mark import hardware_test from tests.helpers.runtime import OmniRunner from tests.helpers.stage_config import get_deploy_config_path +from vllm_omni.transformers_utils.repo_utils import hf_api # --------------------------------------------------------------------------- # Constants @@ -64,7 +67,7 @@ # Helpers # --------------------------------------------------------------------------- def _load_t2i_gen_config(repo_id: str) -> dict: - weights_dir = Path(snapshot_download(repo_id)) + weights_dir = Path(hf_api().snapshot_download(repo_id)) cfg_path = weights_dir / "t2i_generation_config.json" if not cfg_path.exists(): pytest.skip(f"t2i_generation_config.json not found at {cfg_path}") diff --git a/tests/e2e/offline_inference/test_moss_tts_realtime.py b/tests/e2e/offline_inference/test_moss_tts_realtime.py index 34d36118d99..81d97cd743c 100644 --- a/tests/e2e/offline_inference/test_moss_tts_realtime.py +++ b/tests/e2e/offline_inference/test_moss_tts_realtime.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """E2E offline inference tests for MOSS-TTS-Realtime (MossTTSRealtime, 1.7B). Uses the standard omni_runner + pytestmark pattern (one module-scoped engine @@ -160,12 +160,13 @@ def _build_request(ref_audio_path: str, text: str) -> dict: Frees the codec model before returning to avoid competing with the running vllm engine for GPU/CPU memory. """ - from huggingface_hub import snapshot_download from transformers import AutoModel, AutoTokenizer + from vllm_omni.transformers_utils.repo_utils import hf_api + # Step 1: locate the realtime processor module in the snapshot. try: - snap_dir = Path(snapshot_download(repo_id=MODEL)) + snap_dir = Path(hf_api().snapshot_download(repo_id=MODEL)) except Exception as exc: msg = f"Cannot locate snapshot for {MODEL}: {exc}" if os.environ.get("MOSS_TTS_SKIP_ON_NET_FAIL"): diff --git a/tests/e2e/online_serving/helpers/minicpmo_4_5_duplex.py b/tests/e2e/online_serving/helpers/minicpmo_4_5_duplex.py index 432124e76ff..66f8be616f6 100644 --- a/tests/e2e/online_serving/helpers/minicpmo_4_5_duplex.py +++ b/tests/e2e/online_serving/helpers/minicpmo_4_5_duplex.py @@ -12,7 +12,6 @@ from types import SimpleNamespace import pytest -from huggingface_hub import snapshot_download from tests.helpers.runtime import OmniServerParams, get_model_prefix from tests.helpers.stage_config import ( @@ -20,6 +19,7 @@ get_deploy_duplex_max_sessions, modify_stage_config, ) +from vllm_omni.transformers_utils.repo_utils import hf_api MODEL = "openbmb/MiniCPM-o-4_5" DEPLOY_CONFIG_REL = "minicpmo_4_5.yaml" @@ -111,7 +111,7 @@ def resolve_ref_audio() -> Path: model_prefix = get_model_prefix() model_root = Path(model_prefix) / MODEL if model_prefix else Path(MODEL) if not model_root.is_dir(): - model_root = Path(snapshot_download(MODEL, local_files_only=True)) + model_root = Path(hf_api().snapshot_download(MODEL, local_files_only=True)) ref_audio = model_root / REF_AUDIO_RELATIVE_PATH if not ref_audio.is_file(): raise FileNotFoundError(f"MiniCPM-o checkpoint ref audio is missing: {ref_audio}") diff --git a/tests/engine/test_arg_utils.py b/tests/engine/test_arg_utils.py index fb8231a75c6..0e88a00ef88 100644 --- a/tests/engine/test_arg_utils.py +++ b/tests/engine/test_arg_utils.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + """ Tests for Omni config utils. For stability, these tests should largely be invariant to the specific attributes of vLLM config except in cases where we @@ -63,7 +66,7 @@ class ConnectorRunner(OmniConnectorModelRunnerMixin): class ConnectorWorker: model_runner_cls = ConnectorRunner - worker_module.ConnectorWorker = ConnectorWorker + setattr(worker_module, "ConnectorWorker", ConnectorWorker) monkeypatch.setitem(sys.modules, worker_module.__name__, worker_module) monkeypatch.setattr(OmniEngineArgs, "_ensure_omni_models_registered", lambda _self: None) @@ -95,7 +98,7 @@ def test_stage_without_connector_configuration_accepts_plain_runner(monkeypatch) class WorkerWithoutConnector: model_runner_cls = object - worker_module.WorkerWithoutConnector = WorkerWithoutConnector + setattr(worker_module, "WorkerWithoutConnector", WorkerWithoutConnector) monkeypatch.setitem(sys.modules, worker_module.__name__, worker_module) args = OmniEngineArgs( @@ -113,7 +116,7 @@ def test_full_payload_capability_requires_selected_worker_connector(monkeypatch) class WorkerWithoutConnector: model_runner_cls = object - worker_module.WorkerWithoutConnector = WorkerWithoutConnector + setattr(worker_module, "WorkerWithoutConnector", WorkerWithoutConnector) monkeypatch.setitem(sys.modules, worker_module.__name__, worker_module) with pytest.raises(ValueError, match="does not provide an Omni connector model runner"): @@ -130,7 +133,7 @@ def test_full_payload_capability_validates_platform_selected_worker(monkeypatch) class WorkerWithoutConnector: model_runner_cls = object - worker_module.WorkerWithoutConnector = WorkerWithoutConnector + setattr(worker_module, "WorkerWithoutConnector", WorkerWithoutConnector) monkeypatch.setitem(sys.modules, worker_module.__name__, worker_module) monkeypatch.setattr( current_omni_platform, @@ -293,7 +296,7 @@ def test_remote_tokenizer_subfolder_download_does_not_report_failure(tmp_path, m baseline_config = Mock() warning = mocker.patch("vllm_omni.engine.arg_utils.logger.warning") - monkeypatch.setattr("huggingface_hub.snapshot_download", lambda *args, **kwargs: str(tmp_path)) + monkeypatch.setattr("huggingface_hub.HfApi.snapshot_download", lambda *args, **kwargs: str(tmp_path)) monkeypatch.setattr(OmniEngineArgs, "_patch_empty_hf_config", lambda *args, **kwargs: None) monkeypatch.setattr(EngineArgs, "create_model_config", lambda _self: baseline_config) monkeypatch.setattr( @@ -339,6 +342,7 @@ def test_patch_missing_local_hf_config(tmp_path): def test_non_missing_local_hf_config_error_reaches_parent_loader(tmp_path, monkeypatch, config_entry): """Non-missing config errors must reach vLLM's normal loader.""" config_path = tmp_path / "config.json" + loader_error: Exception if config_entry == "malformed": config_path.write_text("{not valid json", encoding="utf-8") loader_error = json.JSONDecodeError("invalid config", "{not valid json", 1) diff --git a/tests/helpers/__init__.py b/tests/helpers/__init__.py index a4e641a571a..9120e183f8d 100644 --- a/tests/helpers/__init__.py +++ b/tests/helpers/__init__.py @@ -29,12 +29,13 @@ def skip_if_gated_repo_inaccessible( and we skip cleanly. """ try: - from huggingface_hub import hf_hub_download from huggingface_hub.errors import GatedRepoError, RepositoryNotFoundError + + from vllm_omni.transformers_utils.repo_utils import hf_api except Exception: return try: - hf_hub_download(repo_id=repo_id, filename=filename, revision=revision) + hf_api().hf_hub_download(repo_id=repo_id, filename=filename, revision=revision) except GatedRepoError as exc: import pytest diff --git a/tests/model_executor/models/minicpmo_4_5/test_code2wav_model_dir.py b/tests/model_executor/models/minicpmo_4_5/test_code2wav_model_dir.py index 5aa78262ae8..8d5aeade657 100644 --- a/tests/model_executor/models/minicpmo_4_5/test_code2wav_model_dir.py +++ b/tests/model_executor/models/minicpmo_4_5/test_code2wav_model_dir.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """Unit tests for MiniCPM-o 4.5 code2wav model-dir resolution (#5442). In hub/CI deployments ``model_config.model`` is a repo id rather than a local @@ -27,7 +27,7 @@ def _no_hub(monkeypatch): def _fail(*args, **kwargs): # pragma: no cover - must not be reached raise AssertionError("snapshot_download must not be called here") - monkeypatch.setattr(huggingface_hub, "snapshot_download", _fail) + monkeypatch.setattr(huggingface_hub.HfApi, "snapshot_download", _fail) def test_local_directory_is_returned_unchanged(tmp_path, monkeypatch): @@ -38,13 +38,13 @@ def test_local_directory_is_returned_unchanged(tmp_path, monkeypatch): def test_repo_id_resolves_via_snapshot_download(tmp_path, monkeypatch): calls = {} - def _fake_snapshot_download(model_ref, revision=None, allow_patterns=None): + def _fake_snapshot_download(self, model_ref, revision=None, allow_patterns=None): calls["model_ref"] = model_ref calls["revision"] = revision calls["allow_patterns"] = allow_patterns return str(tmp_path / "snapshot") - monkeypatch.setattr(huggingface_hub, "snapshot_download", _fake_snapshot_download) + monkeypatch.setattr(huggingface_hub.HfApi, "snapshot_download", _fake_snapshot_download) resolved = _resolve_model_dir("openbmb/MiniCPM-o-4_5", revision="abc123") assert resolved == str(tmp_path / "snapshot") assert calls["model_ref"] == "openbmb/MiniCPM-o-4_5" @@ -56,7 +56,7 @@ def test_snapshot_download_failure_propagates(monkeypatch): def _raise(*args, **kwargs): raise FileNotFoundError("offline and not cached") - monkeypatch.setattr(huggingface_hub, "snapshot_download", _raise) + monkeypatch.setattr(huggingface_hub.HfApi, "snapshot_download", _raise) with pytest.raises(FileNotFoundError): _resolve_model_dir("openbmb/MiniCPM-o-4_5") diff --git a/tests/model_executor/models/omnivoice/test_nonverbal_tags_tokenize.py b/tests/model_executor/models/omnivoice/test_nonverbal_tags_tokenize.py index fbf5ac0b010..95524fdced3 100644 --- a/tests/model_executor/models/omnivoice/test_nonverbal_tags_tokenize.py +++ b/tests/model_executor/models/omnivoice/test_nonverbal_tags_tokenize.py @@ -1,12 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + from __future__ import annotations import pytest -from huggingface_hub import hf_hub_download from tokenizers import Tokenizer as HFTokenizer from vllm_omni.diffusion.models.omnivoice.pipeline_omnivoice import ( _tokenize_with_nonverbal_tags, ) +from vllm_omni.transformers_utils.repo_utils import hf_api pytestmark = [pytest.mark.core_model, pytest.mark.cpu] @@ -18,7 +21,7 @@ def _ids(tok: HFTokenizer, s: str) -> list[int]: class TestNonVerbalTags: @classmethod def setup_class(cls): - tokenizer_path = hf_hub_download(repo_id="k2-fsa/OmniVoice", filename="tokenizer.json") + tokenizer_path = hf_api().hf_hub_download(repo_id="k2-fsa/OmniVoice", filename="tokenizer.json") cls.tokenizer = HFTokenizer.from_file(tokenizer_path) def test_plain_text_fallback(self): diff --git a/tools/pre_commit/check_forbidden_imports.py b/tools/pre_commit/check_forbidden_imports.py index 22ba693d4f2..c5a96148ea2 100644 --- a/tools/pre_commit/check_forbidden_imports.py +++ b/tools/pre_commit/check_forbidden_imports.py @@ -17,7 +17,7 @@ _HF_NAMES = ( r"HfApi|HfFileSystem|hf_hub_download|snapshot_download" r"|list_repo_files|file_exists|try_to_load_from_cache" - r"|list_repo_refs|repo_exists" + r"|list_repo_refs|repo_exists|get_safetensors_metadata" ) # Non-library trees: examples, tests, and tooling may keep stdlib imports. @@ -169,56 +169,20 @@ class ForbiddenImport: r"^\s*from\s+huggingface_hub\s+import\b[^\n]*\b(?:" + _HF_NAMES + r")\b" ), tip=( - "Use the shared, vLLM-tagged helpers from " - "vllm.transformers_utils.repo_utils (e.g. hf_api(), hf_fs(), " - "list_repo_files, file_exists) instead of calling " - "huggingface_hub directly." + "Use 'hf_api()' from 'vllm_omni.transformers_utils.repo_utils' (or " + "add a tagged helper there) instead, so requests are tagged with " + "vLLM-Omni's library info." ), allowed_dirs=_NON_LIBRARY_DIRS, allowed_files={ - "vllm_omni/benchmarks/data_modules/daily_omni_dataset.py", - "vllm_omni/benchmarks/data_modules/seed_tts_dataset.py", - "vllm_omni/benchmarks/data_modules/seed_tts_eval.py", - "vllm_omni/diffusion/lora/loader.py", - "vllm_omni/diffusion/model_loader/hub_prefetch.py", - "vllm_omni/diffusion/models/cosmos3/sound_tokenizer.py", - "vllm_omni/diffusion/models/dreamzero/pipeline_dreamzero.py", - "vllm_omni/diffusion/models/helios/pipeline_helios.py", - "vllm_omni/diffusion/models/longcat_video/pipeline_longcat_video_avatar.py", - "vllm_omni/diffusion/models/ltx2/ltx2_components.py", - "vllm_omni/diffusion/models/magi_human/pipeline_magi_human.py", - "vllm_omni/diffusion/models/omnivoice/pipeline_omnivoice.py", - "vllm_omni/diffusion/models/pi0/pipeline_pi0.py", - "vllm_omni/diffusion/models/sensenova_u1/pipeline_sensenova_u1.py", - "vllm_omni/diffusion/models/soulx_singer/utils.py", - "vllm_omni/diffusion/models/utils.py", - "vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py", - "vllm_omni/engine/arg_utils.py", - "vllm_omni/entrypoints/openai/api_server.py", - "vllm_omni/entrypoints/openai/serving_speech.py", - "vllm_omni/entrypoints/openai/tts_adapters/cosyvoice3.py", - "vllm_omni/model_executor/model_loader/weight_utils.py", - "vllm_omni/model_executor/models/audex/checkpoint.py", - "vllm_omni/model_executor/models/bagel/bagel.py", - "vllm_omni/model_executor/models/cosyvoice3/cosyvoice3.py", - "vllm_omni/model_executor/models/covo_audio/covo_audio_code2wav.py", - "vllm_omni/model_executor/models/dots_tts/dots_tts_talker.py", - "vllm_omni/model_executor/models/dynin_omni/dynin_omni_common.py", - "vllm_omni/model_executor/models/dynin_omni/dynin_omni_token2audio.py", - "vllm_omni/model_executor/models/glm_tts/glm_tts.py", + # ``try_to_load_from_cache`` is a local cache lookup that issues no + # Hub request, so there is nothing for ``hf_api()`` to tag. "vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_code2wav.py", "vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_tokenizer.py", "vllm_omni/model_executor/models/higgs_audio_v3/higgs_audio_v3_code2wav.py", - "vllm_omni/model_executor/models/indextts2/preprocess_utils.py", - "vllm_omni/model_executor/models/indextts2/s2mel/modules/bigvgan.py", - "vllm_omni/model_executor/models/indextts2/tokenizer_v2_5.py", - "vllm_omni/model_executor/models/ming_tts/speaker_extractor.py", - "vllm_omni/model_executor/models/minicpmo_4_5/minicpmo_4_5_code2wav.py", - "vllm_omni/model_executor/models/omnivoice/omnivoice.py", - "vllm_omni/model_executor/models/personaplex/personaplex_mimi.py", - "vllm_omni/model_executor/models/step_audio2/step_audio2_token2wav.py", - "vllm_omni/model_executor/models/voxtral_tts/voxtral_tts.py", "vllm_omni/transformers_utils/configs/higgs_audio_v3.py", + # Defines the tagged helper itself. + "vllm_omni/transformers_utils/repo_utils.py", }, ), } @@ -330,6 +294,7 @@ def matches(rule: str, content: str) -> bool: ("from huggingface_hub import HfFileSystem", True), ("from huggingface_hub import list_repo_files", True), ("from huggingface_hub import try_to_load_from_cache", True), + ("from huggingface_hub import get_safetensors_metadata", True), (" from huggingface_hub import snapshot_download", True), ("from huggingface_hub import PyTorchModelHubMixin, hf_hub_download", True), ("from huggingface_hub import (snapshot_download)", True), @@ -346,6 +311,7 @@ def matches(rule: str, content: str) -> bool: ("from huggingface_hub.constants import HF_HUB_CACHE", False), ("from huggingface_hub.utils import EntryNotFoundError", False), ("from vllm.transformers_utils.repo_utils import hf_api", False), + ("from vllm_omni.transformers_utils.repo_utils import hf_api", False), ("from huggingface_hub import (\n PyTorchModelHubMixin,\n)", False), ("# from huggingface_hub import snapshot_download", False), ] diff --git a/vllm_omni/benchmarks/data_modules/daily_omni_dataset.py b/vllm_omni/benchmarks/data_modules/daily_omni_dataset.py index abb02b1d500..3bf852e8c54 100644 --- a/vllm_omni/benchmarks/data_modules/daily_omni_dataset.py +++ b/vllm_omni/benchmarks/data_modules/daily_omni_dataset.py @@ -170,7 +170,7 @@ def ensure_daily_omni_hub_videos_dir(repo_id: str) -> Path: raise ValueError("repo_id is required to download Daily-Omni Videos.tar") try: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api except ImportError as e: raise ImportError( "Daily-Omni Hub media download requires huggingface_hub. " @@ -180,7 +180,7 @@ def ensure_daily_omni_hub_videos_dir(repo_id: str) -> Path: tar_path: Path | None = None for fname in ("Videos.tar", "videos.tar"): try: - tar_path = Path(hf_hub_download(repo_id=rid, filename=fname, repo_type="dataset")) + tar_path = Path(hf_api().hf_hub_download(repo_id=rid, filename=fname, repo_type="dataset")) break except Exception: continue @@ -237,14 +237,14 @@ def ensure_daily_omni_hub_root(repo_id: str) -> Path: raise ValueError("repo_id is required to download Daily-Omni from Hugging Face") try: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api except ImportError as e: raise ImportError( "Install huggingface_hub to load Daily-Omni from the Hub, or pass a local " "--daily-omni-qa-json / --daily-omni-video-dir mirror." ) from e - cache = snapshot_download( + cache = hf_api().snapshot_download( repo_id=rid, repo_type="dataset", allow_patterns=_DAILY_OMNI_QA_ALLOW_PATTERNS, diff --git a/vllm_omni/benchmarks/data_modules/seed_tts_dataset.py b/vllm_omni/benchmarks/data_modules/seed_tts_dataset.py index 23e8b8ade63..996f4f24865 100644 --- a/vllm_omni/benchmarks/data_modules/seed_tts_dataset.py +++ b/vllm_omni/benchmarks/data_modules/seed_tts_dataset.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + """Seed-TTS zero-shot evaluation-style prompts for ``vllm bench serve``. Loads rows from the `meta.lst` format used in `BytedanceSpeech/seed-tts-eval`_ (or any @@ -121,7 +124,7 @@ def resolve_seed_tts_root(dataset_path: str | None, *, explicit_root: str | None repo_id = dataset_path.strip() try: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api except ImportError as e: raise ImportError( "Install huggingface_hub to download Seed-TTS from the Hub, or clone the dataset " @@ -130,7 +133,7 @@ def resolve_seed_tts_root(dataset_path: str | None, *, explicit_root: str | None # Download only the requested locale subtree instead of the whole dataset # repo. This avoids large, flaky nightly downloads when we only need e.g. # ``en/meta.lst`` + ``en/prompt-wavs/**``. - cache = snapshot_download( + cache = hf_api().snapshot_download( repo_id=repo_id, repo_type="dataset", allow_patterns=[f"{locale}/**"], diff --git a/vllm_omni/benchmarks/data_modules/seed_tts_eval.py b/vllm_omni/benchmarks/data_modules/seed_tts_eval.py index ddfbbd63058..9dc99548aeb 100644 --- a/vllm_omni/benchmarks/data_modules/seed_tts_eval.py +++ b/vllm_omni/benchmarks/data_modules/seed_tts_eval.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + """Seed-TTS WER aligned with Bytedance ``seed-tts-eval`` / ``run_wer.py``. Matches the published protocol (see Hugging Face dataset card and @@ -329,7 +332,8 @@ def _ensure_utmos_jit_model() -> Any | None: return _utmos_jit_model try: import torch - from huggingface_hub import hf_hub_download + + from vllm_omni.transformers_utils.repo_utils import hf_api repo = os.environ.get("SEED_TTS_UTMOS_HF_REPO", "balacoon/utmos").strip() or "balacoon/utmos" fname = os.environ.get("SEED_TTS_UTMOS_JIT_FILE", "utmos.jit").strip() or "utmos.jit" @@ -338,7 +342,7 @@ def _ensure_utmos_jit_model() -> Any | None: repo, fname, ) - path = hf_hub_download(repo_id=repo, filename=fname, repo_type="model") + path = hf_api().hf_hub_download(repo_id=repo, filename=fname, repo_type="model") # TODO The model weights in UTMOS must be loaded in cuda:0; otherwise, the model execution will fail. want = "cuda:0" diff --git a/vllm_omni/diffusion/lora/loader.py b/vllm_omni/diffusion/lora/loader.py index 3f74b4853a2..a13363c7a77 100644 --- a/vllm_omni/diffusion/lora/loader.py +++ b/vllm_omni/diffusion/lora/loader.py @@ -10,11 +10,11 @@ _convert_non_diffusers_qwen_lora_to_diffusers, _convert_non_diffusers_wan_lora_to_diffusers, ) -from huggingface_hub import hf_hub_download from safetensors.torch import load_file from vllm.logger import init_logger from vllm_omni.diffusion.utils.tf_utils import get_transformer_from_pipeline +from vllm_omni.transformers_utils.repo_utils import hf_api logger = init_logger(__name__) @@ -131,7 +131,7 @@ def _load_lora_state_dict( # finally, we try to load it from the internet try: - model_file = hf_hub_download( + model_file = hf_api().hf_hub_download( pretrained_model_name_or_path, filename=weights_name, subfolder=subfolder, diff --git a/vllm_omni/diffusion/model_loader/hub_prefetch.py b/vllm_omni/diffusion/model_loader/hub_prefetch.py index 3594aa4e1c0..a1e893b3be6 100644 --- a/vllm_omni/diffusion/model_loader/hub_prefetch.py +++ b/vllm_omni/diffusion/model_loader/hub_prefetch.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """Best-effort HuggingFace Hub prefetch for multi-subfolder pipelines. @@ -297,7 +297,7 @@ def prefetch_subfolders( logger.info("Prefetching %s subfolders: %s", model, subfolders) try: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api except ImportError: # pragma: no cover - huggingface_hub is a hard dep logger.debug("huggingface_hub unavailable; skipping prefetch of %s", model) return @@ -334,7 +334,7 @@ def prefetch_subfolders( for attempt in range(1, _PREFETCH_MAX_ATTEMPTS + 1): try: with _repo_prefetch_lock(model): - snapshot_download( + hf_api().snapshot_download( repo_id=model, revision=revision, allow_patterns=allow_patterns, diff --git a/vllm_omni/diffusion/models/cosmos3/sound_tokenizer.py b/vllm_omni/diffusion/models/cosmos3/sound_tokenizer.py index 5d6ff8dd968..8c1337ec90d 100644 --- a/vllm_omni/diffusion/models/cosmos3/sound_tokenizer.py +++ b/vllm_omni/diffusion/models/cosmos3/sound_tokenizer.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """Cosmos3 sound tokenizer integration. The tokenizer decodes model-generated sound latents for video+audio output. It @@ -338,9 +338,9 @@ def from_config(cls, od_config: OmniDiffusionConfig) -> Cosmos3SoundTokenizer: model_root = str(model_path) if model_path and os.path.isdir(model_path) else None if model_root is None and model_path and not explicit_avae_path: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - model_root = snapshot_download( + model_root = hf_api().snapshot_download( repo_id=str(model_path), revision=getattr(od_config, "revision", None), allow_patterns=[ diff --git a/vllm_omni/diffusion/models/dreamzero/pipeline_dreamzero.py b/vllm_omni/diffusion/models/dreamzero/pipeline_dreamzero.py index bf19f0a0fc0..09bd536cd7f 100644 --- a/vllm_omni/diffusion/models/dreamzero/pipeline_dreamzero.py +++ b/vllm_omni/diffusion/models/dreamzero/pipeline_dreamzero.py @@ -21,7 +21,6 @@ import numpy as np import torch import torch.nn as nn -from huggingface_hub import hf_hub_download from transformers import AutoTokenizer, UMT5Config, UMT5EncoderModel from vllm.model_executor.model_loader.weight_utils import default_weight_loader @@ -67,6 +66,7 @@ resolve_session_state_config, ) from vllm_omni.inputs.data import OmniDiffusionSamplingParams +from vllm_omni.transformers_utils.repo_utils import hf_api logger = logging.getLogger(__name__) MAX_DREAMZERO_SESSIONS = 64 @@ -581,7 +581,7 @@ def _load_repo_json(model_path: str, relative_path: str, local_files_only: bool) return json.load(f) try: - json_path = hf_hub_download(model_path, relative_path) + json_path = hf_api().hf_hub_download(model_path, relative_path) with open(json_path) as f: return json.load(f) except Exception: diff --git a/vllm_omni/diffusion/models/helios/pipeline_helios.py b/vllm_omni/diffusion/models/helios/pipeline_helios.py index 820f9a1d98a..610fb2b8fbe 100644 --- a/vllm_omni/diffusion/models/helios/pipeline_helios.py +++ b/vllm_omni/diffusion/models/helios/pipeline_helios.py @@ -76,9 +76,9 @@ def load_json_config(model_path: str, subfolder: str, filename: str, local_files return json.load(f) else: try: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api - config_path = hf_hub_download( + config_path = hf_api().hf_hub_download( repo_id=model_path, filename=f"{subfolder}/{filename}", ) diff --git a/vllm_omni/diffusion/models/longcat_video/pipeline_longcat_video_avatar.py b/vllm_omni/diffusion/models/longcat_video/pipeline_longcat_video_avatar.py index 33b0e2a458a..6cb2dd7fb50 100644 --- a/vllm_omni/diffusion/models/longcat_video/pipeline_longcat_video_avatar.py +++ b/vllm_omni/diffusion/models/longcat_video/pipeline_longcat_video_avatar.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project from __future__ import annotations @@ -376,9 +376,9 @@ def _ensure_local_dir(model: str | os.PathLike[str], allow_patterns: list[str] | model_path = Path(model) if model_path.exists(): return model_path - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - return Path(snapshot_download(str(model), allow_patterns=allow_patterns)) + return Path(hf_api().snapshot_download(str(model), allow_patterns=allow_patterns)) def _ensure_avatar_model_index(model_dir: Path, use_int8: bool) -> None: diff --git a/vllm_omni/diffusion/models/ltx2/ltx2_components.py b/vllm_omni/diffusion/models/ltx2/ltx2_components.py index c00fdd8355a..72e63a22f3b 100644 --- a/vllm_omni/diffusion/models/ltx2/ltx2_components.py +++ b/vllm_omni/diffusion/models/ltx2/ltx2_components.py @@ -20,7 +20,6 @@ from diffusers.pipelines.ltx2.latent_upsampler import LTX2LatentUpsamplerModel from diffusers.pipelines.ltx2.vocoder import LTX2Vocoder from diffusers.video_processor import VideoProcessor -from huggingface_hub import hf_hub_download from safetensors import safe_open from safetensors.torch import load_file from transformers import AutoModelForImageTextToText, AutoTokenizer, Gemma3ForConditionalGeneration @@ -32,6 +31,7 @@ from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders from vllm_omni.diffusion.offloader.module_collector import ModuleDiscovery +from vllm_omni.transformers_utils.repo_utils import hf_api if TYPE_CHECKING: from vllm.model_executor.layers.quantization.base_config import QuantizationConfig @@ -279,7 +279,7 @@ def resolve_ltx_artifact( # independently pinned artifact revision. revision = model_revision if model == repo_id else artifact_revision try: - return hf_hub_download( + return hf_api().hf_hub_download( repo_id=repo_id, filename=filename, revision=revision, @@ -351,7 +351,7 @@ def _load_ltx_metadata_json(model: str, filename: str, revision: str | None = No return {} else: try: - path = hf_hub_download(repo_id=model, filename=filename, revision=revision) + path = hf_api().hf_hub_download(repo_id=model, filename=filename, revision=revision) except Exception: return {} try: @@ -529,7 +529,7 @@ def _detect_vocoder_output_sample_rate(model: str, revision: str | None = None) vocoder_config_path = os.path.join(model, "vocoder", "config.json") if not os.path.exists(vocoder_config_path): try: - vocoder_config_path = hf_hub_download(model, "vocoder/config.json", revision=revision) + vocoder_config_path = hf_api().hf_hub_download(model, "vocoder/config.json", revision=revision) except Exception: return None try: @@ -839,7 +839,7 @@ def load_transformer_config( if not os.path.exists(config_path): raise FileNotFoundError(f"LTX transformer config not found: {config_path}") else: - config_path = hf_hub_download( + config_path = hf_api().hf_hub_download( repo_id=model_path, filename=f"{subfolder}/config.json", revision=revision, diff --git a/vllm_omni/diffusion/models/omnivoice/pipeline_omnivoice.py b/vllm_omni/diffusion/models/omnivoice/pipeline_omnivoice.py index 62ac027ca8b..cfc40fcb6bc 100644 --- a/vllm_omni/diffusion/models/omnivoice/pipeline_omnivoice.py +++ b/vllm_omni/diffusion/models/omnivoice/pipeline_omnivoice.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """ OmniVoice TTS Pipeline for vLLM-Omni diffusion engine. @@ -141,9 +141,9 @@ def __init__(self, *, od_config: OmniDiffusionConfig, prefix: str = ""): # Resolve model path (HF hub ID → local cache) if not os.path.isdir(self.model_path): - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - self.model_path = snapshot_download(self.model_path) + self.model_path = hf_api().snapshot_download(self.model_path) # Load OmniVoice config config_path = os.path.join(self.model_path, "config.json") diff --git a/vllm_omni/diffusion/models/pi0/pipeline_pi0.py b/vllm_omni/diffusion/models/pi0/pipeline_pi0.py index 1eeca29692c..a03801c8d4e 100644 --- a/vllm_omni/diffusion/models/pi0/pipeline_pi0.py +++ b/vllm_omni/diffusion/models/pi0/pipeline_pi0.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """π0 (Pi-Zero) VLA pipeline for vllm-omni. Entry point for ``DiffusionEngine.step() → pipeline.forward(req)``. Mirrors the @@ -94,9 +94,9 @@ def _resolve_model_dir(model: str | None) -> str | None: return None if os.path.isdir(model): return model - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - return snapshot_download( + return hf_api().snapshot_download( repo_id=model, allow_patterns=["*.json", "*.safetensors", "*.model", "tokenizer*"], ) diff --git a/vllm_omni/diffusion/models/sensenova_u1/pipeline_sensenova_u1.py b/vllm_omni/diffusion/models/sensenova_u1/pipeline_sensenova_u1.py index de636fb6dca..2be1a9c7a39 100644 --- a/vllm_omni/diffusion/models/sensenova_u1/pipeline_sensenova_u1.py +++ b/vllm_omni/diffusion/models/sensenova_u1/pipeline_sensenova_u1.py @@ -27,7 +27,6 @@ import torch import torch.nn as nn import torchvision.transforms as T -from huggingface_hub import snapshot_download from PIL import Image from transformers import AutoTokenizer from vllm.logger import init_logger @@ -109,7 +108,9 @@ def _resolve_model_path(model_path: str) -> str: """Resolve a HuggingFace model ID or local path to a local directory.""" if os.path.isdir(model_path): return model_path - return snapshot_download(model_path) + from vllm_omni.transformers_utils.repo_utils import hf_api + + return hf_api().snapshot_download(model_path) def _round_by_factor(number: float, factor: int) -> int: diff --git a/vllm_omni/diffusion/models/utils.py b/vllm_omni/diffusion/models/utils.py index 2d783d90712..429c34b9d5c 100644 --- a/vllm_omni/diffusion/models/utils.py +++ b/vllm_omni/diffusion/models/utils.py @@ -168,8 +168,8 @@ def _load_json(model_path: str, filename: str, local_files_only: bool = True) -> with open(path) as f: return json.load(f) else: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api - cached = hf_hub_download(repo_id=model_path, filename=filename) + cached = hf_api().hf_hub_download(repo_id=model_path, filename=filename) with open(cached) as f: return json.load(f) diff --git a/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py b/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py index 2383fc6fd09..c9ef325c4ee 100644 --- a/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py +++ b/vllm_omni/diffusion/models/wan2_2/pipeline_wan2_2.py @@ -156,9 +156,9 @@ def load_transformer_config(model_path: str, subfolder: str = "transformer", loc else: # Try to download config from HF Hub try: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api - config_path = hf_hub_download( + config_path = hf_api().hf_hub_download( repo_id=model_path, filename=f"{subfolder}/config.json", ) @@ -364,9 +364,9 @@ def __init__( else: # For remote models, download and read model_index.json try: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api - model_index_path = hf_hub_download(repo_id=model, filename="model_index.json") + model_index_path = hf_api().hf_hub_download(repo_id=model, filename="model_index.json") with open(model_index_path) as f: model_index = json.load(f) self.expand_timesteps = model_index.get("expand_timesteps", False) diff --git a/vllm_omni/engine/arg_utils.py b/vllm_omni/engine/arg_utils.py index f9ee40cbbff..bd6a7156215 100644 --- a/vllm_omni/engine/arg_utils.py +++ b/vllm_omni/engine/arg_utils.py @@ -381,9 +381,9 @@ def create_model_config(self) -> OmniModelConfig: if tokenizer_subfolder: # Download just the tokenizer files from the subfolder try: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - local_dir = snapshot_download( + local_dir = hf_api().snapshot_download( model_path, allow_patterns=[ f"{tokenizer_subfolder}/tokenizer*", diff --git a/vllm_omni/engine/stage_init_utils.py b/vllm_omni/engine/stage_init_utils.py index eed686837a6..5645d2a366c 100644 --- a/vllm_omni/engine/stage_init_utils.py +++ b/vllm_omni/engine/stage_init_utils.py @@ -31,7 +31,6 @@ from vllm.renderers import BaseRenderer from vllm.sampling_params import SamplingParams from vllm.tokenizers import cached_tokenizer_from_config -from vllm.transformers_utils.repo_utils import hf_api from vllm.transformers_utils.runai_utils import is_runai_obj_uri from vllm.usage.usage_lib import UsageContext from vllm.v1.engine.input_processor import InputProcessor @@ -59,6 +58,7 @@ from vllm_omni.outputs.output_processor import MultimodalOutputProcessor from vllm_omni.platforms import current_omni_platform from vllm_omni.quantization.inc_config import OmniINCConfig +from vllm_omni.transformers_utils.repo_utils import hf_api logger = init_logger(__name__) diff --git a/vllm_omni/entrypoints/openai/api_server.py b/vllm_omni/entrypoints/openai/api_server.py index d49d95175b5..1d53c387094 100644 --- a/vllm_omni/entrypoints/openai/api_server.py +++ b/vllm_omni/entrypoints/openai/api_server.py @@ -201,9 +201,9 @@ def _load_model_chat_template_json(model: str) -> str | None: if template_path is None: try: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api - template_path = hf_hub_download( + template_path = hf_api().hf_hub_download( repo_id=model, filename="chat_template.json", local_files_only=True, diff --git a/vllm_omni/entrypoints/openai/tts_adapters/cosyvoice3.py b/vllm_omni/entrypoints/openai/tts_adapters/cosyvoice3.py index 25993ed6e3e..1196c5c709d 100644 --- a/vllm_omni/entrypoints/openai/tts_adapters/cosyvoice3.py +++ b/vllm_omni/entrypoints/openai/tts_adapters/cosyvoice3.py @@ -116,9 +116,9 @@ def apply_sampling_overrides( if tokenizer is None: model_path = server.engine_client.model_config.model if not os.path.isdir(model_path): - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - model_path = snapshot_download(model_path) + model_path = hf_api().snapshot_download(model_path) tokenizer = get_qwen_tokenizer( token_path=os.path.join(model_path, hf_cfg.qwen_pretrain_path), skip_special_tokens=hf_cfg.skip_special_tokens, diff --git a/vllm_omni/model_executor/model_loader/weight_utils.py b/vllm_omni/model_executor/model_loader/weight_utils.py index 59c2cd86022..559a90b5062 100644 --- a/vllm_omni/model_executor/model_loader/weight_utils.py +++ b/vllm_omni/model_executor/model_loader/weight_utils.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + import os import time from pathlib import Path @@ -10,7 +13,11 @@ if envs.VLLM_USE_MODELSCOPE: from modelscope.hub.snapshot_download import snapshot_download else: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api + + def snapshot_download(*args, **kwargs): + return hf_api().snapshot_download(*args, **kwargs) + logger = init_logger(__name__) diff --git a/vllm_omni/model_executor/models/audex/checkpoint.py b/vllm_omni/model_executor/models/audex/checkpoint.py index 38b0531e660..ae8230e05d6 100644 --- a/vllm_omni/model_executor/models/audex/checkpoint.py +++ b/vllm_omni/model_executor/models/audex/checkpoint.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """Audex checkpoint layout preparation. The nvidia/Nemotron-Labs-Audex-2B repo deduplicates weights: the @@ -57,12 +57,12 @@ def _download_audiogen_index(model: str) -> str: metadata round trip per stage-engine boot; a cache miss falls back to the network. """ - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api try: - return hf_hub_download(model, _AUDIOGEN_INDEX_FILE, local_files_only=True) + return hf_api().hf_hub_download(model, _AUDIOGEN_INDEX_FILE, local_files_only=True) except Exception: - return hf_hub_download(model, _AUDIOGEN_INDEX_FILE) + return hf_api().hf_hub_download(model, _AUDIOGEN_INDEX_FILE) def _dedup_shard_patterns(model: str) -> list[str]: @@ -111,13 +111,13 @@ def ensure_audex_snapshot(model: str, profile: str = "tts") -> str: if profile in ("tts", "tta"): patterns += _dedup_shard_patterns(model) - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api try: - return snapshot_download(model, allow_patterns=patterns) + return hf_api().snapshot_download(model, allow_patterns=patterns) except Exception as download_exc: try: - return snapshot_download(model, allow_patterns=patterns, local_files_only=True) + return hf_api().snapshot_download(model, allow_patterns=patterns, local_files_only=True) except Exception: raise RuntimeError( f"Could not resolve the Audex repo {model!r} (profile {profile!r}): the download " @@ -135,13 +135,13 @@ def ensure_xcodec1_snapshot(model: str | None) -> str: if os.path.isdir(model): return model - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api try: - return snapshot_download(model) + return hf_api().snapshot_download(model) except Exception as download_exc: try: - return snapshot_download(model, local_files_only=True) + return hf_api().snapshot_download(model, local_files_only=True) except Exception: raise RuntimeError( f"Could not resolve the XCodec1 checkpoint {model!r}: the download failed and " diff --git a/vllm_omni/model_executor/models/bagel/bagel.py b/vllm_omni/model_executor/models/bagel/bagel.py index a3dfd7bf151..495e0037f29 100644 --- a/vllm_omni/model_executor/models/bagel/bagel.py +++ b/vllm_omni/model_executor/models/bagel/bagel.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + from collections.abc import Iterable, Mapping, Sequence from math import isqrt from typing import Any @@ -122,9 +125,9 @@ def _patch_max_latent_size(self, config): if p.is_dir(): index_path = p / "model.safetensors.index.json" else: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api - index_path = Path(hf_hub_download(model_name, "model.safetensors.index.json")) + index_path = Path(hf_api().hf_hub_download(model_name, "model.safetensors.index.json")) if not index_path.exists(): return diff --git a/vllm_omni/model_executor/models/cosyvoice3/cosyvoice3.py b/vllm_omni/model_executor/models/cosyvoice3/cosyvoice3.py index 81bae6d6c2b..84652cadabf 100644 --- a/vllm_omni/model_executor/models/cosyvoice3/cosyvoice3.py +++ b/vllm_omni/model_executor/models/cosyvoice3/cosyvoice3.py @@ -10,7 +10,6 @@ import onnxruntime import torch import torch.nn as nn -from huggingface_hub import snapshot_download from scipy.signal import resample_poly from transformers import Qwen2Config from transformers.feature_extraction_utils import BatchFeature @@ -52,6 +51,7 @@ from vllm_omni.model_executor.models.output_templates import OmniOutput from vllm_omni.platforms import current_omni_platform from vllm_omni.transformers_utils.configs.cosyvoice3 import CosyVoice3Config +from vllm_omni.transformers_utils.repo_utils import hf_api from vllm_omni.utils.speaker_cache import get_speaker_cache logger = init_logger(__name__) @@ -137,7 +137,7 @@ def _build_runtime_components(self, model_dir: str, config: CosyVoice3Config) -> """Build the per-model runtime components once (cached process-wide).""" # If model_dir is an HF repo ID (not a local path), resolve to cache. if not os.path.isdir(model_dir): - model_dir = snapshot_download(model_dir) + model_dir = hf_api().snapshot_download(model_dir) tokenizer = get_qwen_tokenizer( token_path=os.path.join(model_dir, config.qwen_pretrain_path), @@ -463,7 +463,7 @@ def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""): self.model_stage = vllm_config.model_config.model_stage model_dir = vllm_config.model_config.model if not os.path.isdir(model_dir): - model_dir = snapshot_download(model_dir) + model_dir = hf_api().snapshot_download(model_dir) self.model_dir = model_dir self.model = None if self.model_stage == "cosyvoice3_talker": @@ -918,7 +918,7 @@ def _resolve_flow_estimator_onnx(self) -> str | None: repo = getattr(self.config, "flow_estimator_onnx_repo", None) if repo: try: - fetched_dir = snapshot_download(repo, allow_patterns=[fp16_name]) + fetched_dir = hf_api().snapshot_download(repo, allow_patterns=[fp16_name]) fetched = os.path.join(fetched_dir, fp16_name) if os.path.exists(fetched): return fetched diff --git a/vllm_omni/model_executor/models/covo_audio/covo_audio_code2wav.py b/vllm_omni/model_executor/models/covo_audio/covo_audio_code2wav.py index 4b0b2fe4bea..15cd0875e64 100644 --- a/vllm_omni/model_executor/models/covo_audio/covo_audio_code2wav.py +++ b/vllm_omni/model_executor/models/covo_audio/covo_audio_code2wav.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + # Copyright 2026 Tencent. import os from collections.abc import Iterable @@ -25,9 +28,9 @@ def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""): if os.path.isdir(model_name): model_path = model_name else: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - model_path = snapshot_download(model_name) + model_path = hf_api().snapshot_download(model_name) token2wav_path = os.path.join(model_path, "token2wav") code2wav_config = CovoAudioCode2WavConfig() diff --git a/vllm_omni/model_executor/models/dots_tts/dots_tts_talker.py b/vllm_omni/model_executor/models/dots_tts/dots_tts_talker.py index ff2f460d637..862af8e17cf 100644 --- a/vllm_omni/model_executor/models/dots_tts/dots_tts_talker.py +++ b/vllm_omni/model_executor/models/dots_tts/dots_tts_talker.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """dots.tts talker — vLLM-native AR base LM + audio side path. Mirrors upstream rednote-hilab/dots.tts (pinned @ a393d2e): @@ -516,9 +516,9 @@ def _resolve_latent_stats_path(model_arg: str) -> str | None: if os.path.exists(local): return local try: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api - return hf_hub_download( + return hf_api().hf_hub_download( repo_id=model_arg, filename="latent_stats.pt", local_files_only=True, diff --git a/vllm_omni/model_executor/models/dynin_omni/dynin_omni_common.py b/vllm_omni/model_executor/models/dynin_omni/dynin_omni_common.py index 5c67decaa56..125822c1ef4 100644 --- a/vllm_omni/model_executor/models/dynin_omni/dynin_omni_common.py +++ b/vllm_omni/model_executor/models/dynin_omni/dynin_omni_common.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + from __future__ import annotations import hashlib @@ -20,9 +23,9 @@ logger = init_logger(__name__) try: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api except Exception: # pragma: no cover - snapshot_download = None + hf_api = None class DetokTarget(IntEnum): @@ -397,13 +400,13 @@ def _find_dynin_config_under_root(root: Path) -> Path | None: @lru_cache(maxsize=16) def _resolve_dynin_config_from_hf_repo(repo_id: str) -> str | None: - if not _looks_like_hf_repo_id(repo_id) or snapshot_download is None: + if not _looks_like_hf_repo_id(repo_id) or hf_api is None: return None try: snapshot_dir = ( Path( - snapshot_download( + hf_api().snapshot_download( repo_id=repo_id, repo_type="model", allow_patterns=list(_DYNIN_CONFIG_CANDIDATE_RELPATHS), @@ -719,7 +722,7 @@ def _resolve_remote_snapshot_dir( if source_path.is_dir(): return str(source_path.resolve()) - if snapshot_download is None: + if hf_api is None: raise RuntimeError("huggingface_hub is required to load remote code.") kwargs: dict[str, Any] = { @@ -732,10 +735,10 @@ def _resolve_remote_snapshot_dir( kwargs["revision"] = revision try: - return str(snapshot_download(**kwargs)) + return str(hf_api().snapshot_download(**kwargs)) except TypeError: kwargs.pop("local_files_only", None) - return str(snapshot_download(**kwargs)) + return str(hf_api().snapshot_download(**kwargs)) def _ensure_remote_package(snapshot_dir: str) -> str: diff --git a/vllm_omni/model_executor/models/dynin_omni/dynin_omni_token2audio.py b/vllm_omni/model_executor/models/dynin_omni/dynin_omni_token2audio.py index 80bc0a78b47..dbbb635245f 100644 --- a/vllm_omni/model_executor/models/dynin_omni/dynin_omni_token2audio.py +++ b/vllm_omni/model_executor/models/dynin_omni/dynin_omni_token2audio.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + from __future__ import annotations import os @@ -80,7 +83,7 @@ def _ensure_remote_s2u_vendor_root( return str(existing_path) try: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api except Exception as e: logger.warning("huggingface_hub unavailable; cannot fetch s2u_vendor from %s: %s", repo_id, e) return None @@ -91,7 +94,7 @@ def _ensure_remote_s2u_vendor_root( for revision in revisions: try: - snapshot_dir = snapshot_download( + snapshot_dir = hf_api().snapshot_download( repo_id=repo_id, revision=revision, allow_patterns=["s2u_vendor/**"], @@ -99,7 +102,7 @@ def _ensure_remote_s2u_vendor_root( ) except TypeError: try: - snapshot_dir = snapshot_download( + snapshot_dir = hf_api().snapshot_download( repo_id=repo_id, revision=revision, allow_patterns=["s2u_vendor/**"], diff --git a/vllm_omni/model_executor/models/glm_tts/glm_tts.py b/vllm_omni/model_executor/models/glm_tts/glm_tts.py index 664a794c4c0..fb3517036d0 100644 --- a/vllm_omni/model_executor/models/glm_tts/glm_tts.py +++ b/vllm_omni/model_executor/models/glm_tts/glm_tts.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """GLM-TTS AR Model (Stage 0): Text → Speech Tokens. Based on Llama architecture, generates speech token sequences from input text. @@ -113,9 +113,9 @@ def resolve_glm_tts_tokenizer_path(model_name_or_path: Any) -> str: return candidate return model_path - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - local_dir = snapshot_download( + local_dir = hf_api().snapshot_download( model_path, allow_patterns=[ f"{_GLM_TTS_TOKENIZER_SUBDIR}/tokenizer*", @@ -169,9 +169,9 @@ def _has_files(root: str) -> bool: except Exception: pass - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - return snapshot_download(model_name_or_path) + return hf_api().snapshot_download(model_name_or_path) def _first_glm_tts_value(value: Any) -> Any: diff --git a/vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_code2wav.py b/vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_code2wav.py index 91609e1a4ee..c6a54a39350 100644 --- a/vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_code2wav.py +++ b/vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_code2wav.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """Stage 1 (codec decoder) for higgs-audio v2. Two surfaces exposed: @@ -231,9 +231,9 @@ def _resolve_hf_id_to_local(repo_id: str) -> str: if os.path.isfile(os.path.join(candidate, "config.json")): return candidate - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - return snapshot_download(repo_id=repo_id) + return hf_api().snapshot_download(repo_id=repo_id) # ------------------------------------------------------ direct decode API @torch.inference_mode() diff --git a/vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_tokenizer.py b/vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_tokenizer.py index c3f5024b3bc..587bcda6718 100755 --- a/vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_tokenizer.py +++ b/vllm_omni/model_executor/models/higgs_audio_v2/higgs_audio_v2_tokenizer.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """TTS prompt builder + scope validators for higgs-audio v2. vllm-omni's higgs path supports two request shapes: @@ -248,9 +248,9 @@ def _load_audio_tokenizer(): audio_tokenizer_dir = _resolve_audio_tokenizer_dir() if audio_tokenizer_dir is None: - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - repo_path = snapshot_download( + repo_path = hf_api().snapshot_download( _K2_OMNIVOICE_REPO, allow_patterns=[f"{_K2_OMNIVOICE_SUBDIR}/*"], ) diff --git a/vllm_omni/model_executor/models/indextts2/preprocess_utils.py b/vllm_omni/model_executor/models/indextts2/preprocess_utils.py index 88e9a063952..82729160270 100644 --- a/vllm_omni/model_executor/models/indextts2/preprocess_utils.py +++ b/vllm_omni/model_executor/models/indextts2/preprocess_utils.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """External model loading, audio I/O, and emotion conditioning for IndexTTS2.""" from __future__ import annotations @@ -171,9 +171,10 @@ def load_semantic_codec( codec.load_state_dict(state, strict=False) else: import safetensors.torch - from huggingface_hub import hf_hub_download - ckpt_path = hf_hub_download("amphion/MaskGCT", filename="semantic_codec/model.safetensors") + from vllm_omni.transformers_utils.repo_utils import hf_api + + ckpt_path = hf_api().hf_hub_download("amphion/MaskGCT", filename="semantic_codec/model.safetensors") safetensors.torch.load_model(codec, ckpt_path) _freeze(codec.to(device=device, dtype=torch.float32)) _semantic_codec_cache[cache_key] = codec @@ -198,9 +199,11 @@ def load_campplus(model_path: str, device: torch.device): if ckpt_path is not None: break if ckpt_path is None: - from huggingface_hub import hf_hub_download + if os.path.isdir(model_path): + raise FileNotFoundError(f"IndexTTS CAMPPlus checkpoint is missing from local bundle {model_path!r}") + from vllm_omni.transformers_utils.repo_utils import hf_api - ckpt_path = hf_hub_download("funasr/campplus", filename="campplus_cn_common.bin") + ckpt_path = hf_api().hf_hub_download("funasr/campplus", filename="campplus_cn_common.bin") state = torch.load(ckpt_path, map_location="cpu", weights_only=True) campplus.load_state_dict(state, strict=False) _freeze(campplus.to(device=device, dtype=torch.float32)) diff --git a/vllm_omni/model_executor/models/indextts2/s2mel/modules/bigvgan.py b/vllm_omni/model_executor/models/indextts2/s2mel/modules/bigvgan.py index 5876bb14742..048d1de2dcf 100644 --- a/vllm_omni/model_executor/models/indextts2/s2mel/modules/bigvgan.py +++ b/vllm_omni/model_executor/models/indextts2/s2mel/modules/bigvgan.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + # Copyright (c) 2024 NVIDIA CORPORATION. # Licensed under the MIT license. @@ -9,13 +12,14 @@ import torch import torch.nn as nn -from huggingface_hub import PyTorchModelHubMixin, hf_hub_download +from huggingface_hub import PyTorchModelHubMixin from torch.nn import Conv1d, ConvTranspose1d from torch.nn.utils import remove_weight_norm, weight_norm from vllm_omni.model_executor.models.common.alias_free_activation import AliasFreeActivation1d from vllm_omni.model_executor.models.common.snake_activation import Snake, SnakeBeta from vllm_omni.model_executor.models.indextts2.s2mel.modules.commons import AttrDict +from vllm_omni.transformers_utils.repo_utils import hf_api # --------------------------------------------------------------------------- # Helpers (inlined from env.py / utils.py) @@ -328,7 +332,7 @@ def _from_pretrained(cls, *, model_id: str, map_location: str = "cpu", **kwargs) def _resolve(filename): if os.path.isdir(model_id): return os.path.join(model_id, filename) - return hf_hub_download( + return hf_api().hf_hub_download( repo_id=model_id, filename=filename, **{ diff --git a/vllm_omni/model_executor/models/indextts2/tokenizer_v2_5.py b/vllm_omni/model_executor/models/indextts2/tokenizer_v2_5.py index 6eae97703a7..ba27cad6243 100644 --- a/vllm_omni/model_executor/models/indextts2/tokenizer_v2_5.py +++ b/vllm_omni/model_executor/models/indextts2/tokenizer_v2_5.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """IndexTTS 2.5 multilingual tiktoken vocabulary. The vocabulary layout mirrors the official IndexTTS 2.5 tokenizer: 58,836 @@ -234,9 +234,9 @@ def resolve_indextts25_tokenizer_file( return str(model_path) try: - from huggingface_hub import hf_hub_download + from vllm_omni.transformers_utils.repo_utils import hf_api - return hf_hub_download(repo_id=model_dir, filename=tokenizer_file) + return hf_api().hf_hub_download(repo_id=model_dir, filename=tokenizer_file) except Exception as exc: raise FileNotFoundError( f"Could not resolve IndexTTS 2.5 tokenizer {tokenizer_file!r} from {model_dir!r}" diff --git a/vllm_omni/model_executor/models/minicpmo_4_5/minicpmo_4_5_code2wav.py b/vllm_omni/model_executor/models/minicpmo_4_5/minicpmo_4_5_code2wav.py index 8b3926cc0ca..f701e8b2699 100644 --- a/vllm_omni/model_executor/models/minicpmo_4_5/minicpmo_4_5_code2wav.py +++ b/vllm_omni/model_executor/models/minicpmo_4_5/minicpmo_4_5_code2wav.py @@ -39,9 +39,9 @@ def _resolve_model_dir(model_ref: str, revision: str | None = None) -> str: """ if Path(model_ref).is_dir(): return model_ref - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - return snapshot_download(model_ref, revision=revision, allow_patterns=["assets/*"]) + return hf_api().snapshot_download(model_ref, revision=revision, allow_patterns=["assets/*"]) def _batch_error(reason: str, **details: Any) -> RuntimeError: diff --git a/vllm_omni/model_executor/models/omnivoice/omnivoice.py b/vllm_omni/model_executor/models/omnivoice/omnivoice.py index c167aa1c0a1..26a6f6b5935 100644 --- a/vllm_omni/model_executor/models/omnivoice/omnivoice.py +++ b/vllm_omni/model_executor/models/omnivoice/omnivoice.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """ OmniVoice model for vLLM-Omni two-stage TTS pipeline. @@ -487,9 +487,9 @@ def _resolve_model_dir(self) -> str: if os.path.isdir(model_dir): return model_dir # HF hub model ID — resolve to local cache - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - return snapshot_download(model_dir) + return hf_api().snapshot_download(model_dir) def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]: try: diff --git a/vllm_omni/model_executor/models/personaplex/personaplex_mimi.py b/vllm_omni/model_executor/models/personaplex/personaplex_mimi.py index 48df20fab1e..3b8813faf70 100644 --- a/vllm_omni/model_executor/models/personaplex/personaplex_mimi.py +++ b/vllm_omni/model_executor/models/personaplex/personaplex_mimi.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project """Streaming Mimi codec for PersonaPlex (moshi-free). Frame-clocked duplex needs a codec that encodes/decodes exactly one 80 ms frame @@ -288,10 +288,11 @@ class PersonaPlexMimiCodec(nn.Module): def __init__(self, hf_repo: str = DEFAULT_HF_REPO, checkpoint: str | None = None, device: str = "cuda") -> None: super().__init__() - from huggingface_hub import hf_hub_download from safetensors.torch import load_file from transformers import MimiConfig, MimiModel + from vllm_omni.transformers_utils.repo_utils import hf_api + self.device = torch.device(device) # The PersonaPlex repo ships the reference mimi checkpoint in the moshi @@ -300,7 +301,7 @@ def __init__(self, hf_repo: str = DEFAULT_HF_REPO, checkpoint: str | None = None # transformer stacks remain absent because the streaming implementations # below replace them with the checkpoint's fused QKV layout. if checkpoint is None: - checkpoint = hf_hub_download( + checkpoint = hf_api().hf_hub_download( "nvidia/personaplex-7b-v1", "tokenizer-e351c8d8-checkpoint125.safetensors", ) diff --git a/vllm_omni/model_executor/models/step_audio2/step_audio2_token2wav.py b/vllm_omni/model_executor/models/step_audio2/step_audio2_token2wav.py index e9ca78b21eb..8e3c56b327d 100644 --- a/vllm_omni/model_executor/models/step_audio2/step_audio2_token2wav.py +++ b/vllm_omni/model_executor/models/step_audio2/step_audio2_token2wav.py @@ -461,9 +461,9 @@ def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""): if model_path is None: # Resolve HF repo names to local cache path if not os.path.isdir(model_name_or_path): - from huggingface_hub import snapshot_download + from vllm_omni.transformers_utils.repo_utils import hf_api - model_name_or_path = snapshot_download(model_name_or_path) + model_name_or_path = hf_api().snapshot_download(model_name_or_path) model_path = f"{model_name_or_path}/token2wav" float16 = getattr(self.config, "token2wav_float16", False) diff --git a/vllm_omni/model_executor/models/voxtral_tts/voxtral_tts.py b/vllm_omni/model_executor/models/voxtral_tts/voxtral_tts.py index 69cfa6d2667..c61aeaaadbb 100644 --- a/vllm_omni/model_executor/models/voxtral_tts/voxtral_tts.py +++ b/vllm_omni/model_executor/models/voxtral_tts/voxtral_tts.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + from collections.abc import Iterable, Mapping from dataclasses import replace from functools import cached_property @@ -6,7 +9,6 @@ import regex as re import torch import torch.nn as nn -from huggingface_hub import hf_hub_download from vllm.config import VllmConfig from vllm.logger import init_logger from vllm.model_executor.models.interfaces import SupportsMultiModal @@ -28,6 +30,7 @@ VoxtralTTSMultiModalProcessor, VoxtralTTSProcessingInfo, ) +from vllm_omni.transformers_utils.repo_utils import hf_api logger = init_logger(__name__) @@ -133,7 +136,7 @@ def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""): self.voice_to_embedding = {} for sid in speaker_id: if self.is_hf_model: - path = hf_hub_download(repo_id=self.repo_id, filename=f"voice_embedding/{sid}.pt") + path = hf_api().hf_hub_download(repo_id=self.repo_id, filename=f"voice_embedding/{sid}.pt") else: path = Path(self.repo_id) / "voice_embedding" / f"{sid}.pt" if Path(path).exists(): diff --git a/vllm_omni/transformers_utils/repo_utils.py b/vllm_omni/transformers_utils/repo_utils.py new file mode 100644 index 00000000000..e780c4b53fc --- /dev/null +++ b/vllm_omni/transformers_utils/repo_utils.py @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project +"""Utilities for model repo interaction.""" + +from huggingface_hub import HfApi + +from vllm_omni.version import __version__ as VLLM_OMNI_VERSION + +_hf_api: HfApi | None = None + + +def hf_api() -> HfApi: + """Return a shared HfApi instance tagged with vLLM-Omni's library info.""" + global _hf_api + if _hf_api is None: + _hf_api = HfApi( + library_name="vllm-omni", + library_version=VLLM_OMNI_VERSION, + ) + return _hf_api