diff --git a/docs/docs/sglang-diffusion/api/cli.mdx b/docs/docs/sglang-diffusion/api/cli.mdx index a869f96b2..316bfcca9 100644 --- a/docs/docs/sglang-diffusion/api/cli.mdx +++ b/docs/docs/sglang-diffusion/api/cli.mdx @@ -143,10 +143,14 @@ For a native text encoder: The same contract applies to every weighted component: path routing is generic, while quantized materialization is capability-based. Native auxiliary loaders -that only understand unquantized state dicts reject quantization metadata before -model construction. See [Quantized Component Repositories](../quantization#quantized-component-repositories) +whose current materializer expects plain state dicts reject unsupported +quantization metadata before model construction. See +[Quantized Component Repositories](../quantization#quantized-component-repositories) for the current component matrix. +Component overrides accept a local component directory, a standalone Hub +repository, or a Hub component subfolder written as `owner/repo/subfolder`. + For supported realtime causal video models, `--kv-cache-quant {off|int4|int2}` compresses completed KV-cache chunks independently of transformer weight quantization. It is lossy and disabled by default. diff --git a/python/sglang/multimodal_gen/runtime/pipelines_core/composed_pipeline_base.py b/python/sglang/multimodal_gen/runtime/pipelines_core/composed_pipeline_base.py index 9641f5795..5c6b0c201 100644 --- a/python/sglang/multimodal_gen/runtime/pipelines_core/composed_pipeline_base.py +++ b/python/sglang/multimodal_gen/runtime/pipelines_core/composed_pipeline_base.py @@ -53,6 +53,7 @@ from sglang.multimodal_gen.runtime.platforms import current_platform from sglang.multimodal_gen.runtime.server_args import ServerArgs from sglang.multimodal_gen.runtime.utils.hf_diffusers_utils import ( maybe_download_model, + prepare_diffusers_component_path_for_loading, verify_model_config_and_directory, ) from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger @@ -349,8 +350,9 @@ class ComposedPipelineBase(ABC): ) -> str: override_path = server_args.component_paths.get(module_name) if override_path is not None: - # overridden with args like --vae-path - component_model_path = maybe_download_model(override_path) + component_model_path = prepare_diffusers_component_path_for_loading( + override_path + ) else: component_model_path = os.path.join(self.model_path, load_module_name) diff --git a/python/sglang/multimodal_gen/test/unit/test_hf_diffusers_utils.py b/python/sglang/multimodal_gen/test/unit/test_hf_diffusers_utils.py index 408cc5599..bffa1e2f8 100644 --- a/python/sglang/multimodal_gen/test/unit/test_hf_diffusers_utils.py +++ b/python/sglang/multimodal_gen/test/unit/test_hf_diffusers_utils.py @@ -1,9 +1,14 @@ import json +from types import SimpleNamespace +from unittest.mock import patch import modelscope import pytest from huggingface_hub.errors import LocalEntryNotFoundError +from sglang.multimodal_gen.runtime.pipelines_core.composed_pipeline_base import ( + ComposedPipelineBase, +) from sglang.multimodal_gen.runtime.utils import hf_diffusers_utils from sglang.multimodal_gen.runtime.utils.hf_diffusers_utils import ( _check_index_files_for_missing_shards, @@ -14,6 +19,35 @@ from sglang.multimodal_gen.runtime.utils.hf_diffusers_utils import ( from sglang.srt.environ import envs +def test_component_override_resolves_hub_subfolder_before_loading(tmp_path): + repo_root = tmp_path / "FLUX.1-dev-bnb-4bit" + component_root = repo_root / "text_encoder_2" + component_root.mkdir(parents=True) + pipeline = SimpleNamespace(model_path="/base") + server_args = SimpleNamespace( + component_paths={ + "text_encoder_2": "diffusers/FLUX.1-dev-bnb-4bit/text_encoder_2" + } + ) + + with patch( + "sglang.multimodal_gen.runtime.utils.hf_diffusers_utils.maybe_download_model", + return_value=str(repo_root), + ) as download: + component_path = ComposedPipelineBase._resolve_component_path( + pipeline, + server_args, + "text_encoder_2", + "text_encoder_2", + ) + + assert component_path == str(component_root) + download.assert_called_once_with( + "diffusers/FLUX.1-dev-bnb-4bit", + allow_patterns=["text_encoder_2/**", "text_encoder_2/*"], + ) + + def _write_model_index(root): (root / "model_index.json").write_text( json.dumps(