feat: enhance model loading with prefetching and retry logic
- Introduced `from_pretrained_with_prefetch` to handle racy cache scenarios by re-prefetching and retrying on failures. - Updated various model pipelines to utilize the new prefetching mechanism, ensuring robust loading of model components. - Prefetch logic added to multiple models, including HunyuanVideo, LongCatImage, and QwenImage, to mitigate issues with incomplete cache states.
This commit is contained in:
1 parent
b550709bba
commit
617c6ca55f
20 files changed
+678
-194
No files matched your search
@@ -39,7 +39,7 @@ from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import prefetch_subfolders
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders
|
||||
from vllm_omni.diffusion.models.flux2_klein.flux2_klein_transformer import (
|
||||
Flux2Transformer2DModel,
|
||||
)
|
||||
@@ -213,9 +213,10 @@ class Flux2KleinPipeline(nn.Module, CFGParallelMixin, SupportImageInput, Diffusi
|
||||
# Avoid the transformers v5 multi-worker subfolder race (see
|
||||
# ``vllm_omni/diffusion/model_loader/hub_prefetch.py`` for the full
|
||||
# analysis; L4 build #1043 hit this on FLUX.2-klein-4B's text_encoder).
|
||||
flux2_subfolders = ["scheduler", "text_encoder", "tokenizer", "vae"]
|
||||
prefetch_subfolders(
|
||||
model,
|
||||
["scheduler", "text_encoder", "tokenizer", "vae"],
|
||||
flux2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
|
||||
@@ -224,9 +225,15 @@ class Flux2KleinPipeline(nn.Module, CFGParallelMixin, SupportImageInput, Diffusi
|
||||
subfolder="scheduler",
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.text_encoder = Qwen3ForCausalLM.from_pretrained(
|
||||
# ``from_pretrained_with_prefetch`` re-prefetches and retries if a peer
|
||||
# worker left the cache half-written (missing-shard ``OSError`` or the
|
||||
# default-config size-mismatch ``RuntimeError``) instead of crashing
|
||||
# the worker - FLUX.2-klein-4B's sharded text_encoder hit this on #1043.
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen3ForCausalLM.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=flux2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self._execution_device)
|
||||
self.tokenizer = Qwen2TokenizerFast.from_pretrained(
|
||||
@@ -234,9 +241,11 @@ class Flux2KleinPipeline(nn.Module, CFGParallelMixin, SupportImageInput, Diffusi
|
||||
subfolder="tokenizer",
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.vae = AutoencoderKLFlux2.from_pretrained(
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKLFlux2.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=flux2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self._execution_device)
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.parallel_state import get_classifier_free_guidance_world_size
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.hidream_image import HiDreamImageTransformer2DModel
|
||||
from vllm_omni.diffusion.models.progress_bar import ProgressBarMixin
|
||||
from vllm_omni.diffusion.profiler.diffusion_pipeline_profiler import DiffusionPipelineProfilerMixin
|
||||
@@ -177,24 +178,55 @@ class HiDreamI1ImagePipeline(nn.Module, CFGParallelMixin, DiffusionPipelineProfi
|
||||
# Check if model is a local path
|
||||
local_files_only = os.path.exists(model)
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the in-repo component set before any from_pretrained
|
||||
# (``text_encoder_4`` lives in a separate Llama repo and is unaffected).
|
||||
hidream_subfolders = [
|
||||
"scheduler",
|
||||
"vae",
|
||||
"text_encoder",
|
||||
"tokenizer",
|
||||
"text_encoder_2",
|
||||
"tokenizer_2",
|
||||
"text_encoder_3",
|
||||
"tokenizer_3",
|
||||
]
|
||||
prefetch_subfolders(model, hidream_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
self.vae = AutoencoderKL.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self.device
|
||||
)
|
||||
self.text_encoder = CLIPTextModelWithProjection.from_pretrained(
|
||||
model, subfolder="text_encoder", local_files_only=local_files_only
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKL.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=hidream_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
CLIPTextModelWithProjection.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=hidream_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.tokenizer = CLIPTokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.text_encoder_2 = CLIPTextModelWithProjection.from_pretrained(
|
||||
model, subfolder="text_encoder_2", local_files_only=local_files_only
|
||||
self.text_encoder_2 = from_pretrained_with_prefetch(
|
||||
CLIPTextModelWithProjection.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder_2",
|
||||
prefetch_list=hidream_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.tokenizer_2 = CLIPTokenizer.from_pretrained(
|
||||
model, subfolder="tokenizer_2", local_files_only=local_files_only
|
||||
)
|
||||
self.text_encoder_3 = T5EncoderModel.from_pretrained(
|
||||
model, subfolder="text_encoder_3", local_files_only=local_files_only
|
||||
self.text_encoder_3 = from_pretrained_with_prefetch(
|
||||
T5EncoderModel.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder_3",
|
||||
prefetch_list=hidream_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.tokenizer_3 = T5Tokenizer.from_pretrained(
|
||||
model, subfolder="tokenizer_3", local_files_only=local_files_only
|
||||
|
||||
@@ -31,6 +31,7 @@ from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.parallel_state import get_classifier_free_guidance_world_size
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.hidream_image import HiDreamImageTransformer2DModel
|
||||
from vllm_omni.diffusion.models.progress_bar import ProgressBarMixin
|
||||
from vllm_omni.diffusion.profiler.diffusion_pipeline_profiler import DiffusionPipelineProfilerMixin
|
||||
@@ -177,24 +178,55 @@ class HiDreamImagePipeline(nn.Module, CFGParallelMixin, DiffusionPipelineProfile
|
||||
# Check if model is a local path
|
||||
local_files_only = os.path.exists(model)
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the in-repo component set before any from_pretrained
|
||||
# (``text_encoder_4`` lives in a separate Llama repo and is unaffected).
|
||||
hidream_subfolders = [
|
||||
"scheduler",
|
||||
"vae",
|
||||
"text_encoder",
|
||||
"tokenizer",
|
||||
"text_encoder_2",
|
||||
"tokenizer_2",
|
||||
"text_encoder_3",
|
||||
"tokenizer_3",
|
||||
]
|
||||
prefetch_subfolders(model, hidream_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
self.vae = AutoencoderKL.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self.device
|
||||
)
|
||||
self.text_encoder = CLIPTextModelWithProjection.from_pretrained(
|
||||
model, subfolder="text_encoder", local_files_only=local_files_only
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKL.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=hidream_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
CLIPTextModelWithProjection.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=hidream_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.tokenizer = CLIPTokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.text_encoder_2 = CLIPTextModelWithProjection.from_pretrained(
|
||||
model, subfolder="text_encoder_2", local_files_only=local_files_only
|
||||
self.text_encoder_2 = from_pretrained_with_prefetch(
|
||||
CLIPTextModelWithProjection.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder_2",
|
||||
prefetch_list=hidream_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.tokenizer_2 = CLIPTokenizer.from_pretrained(
|
||||
model, subfolder="tokenizer_2", local_files_only=local_files_only
|
||||
)
|
||||
self.text_encoder_3 = T5EncoderModel.from_pretrained(
|
||||
model, subfolder="text_encoder_3", local_files_only=local_files_only
|
||||
self.text_encoder_3 = from_pretrained_with_prefetch(
|
||||
T5EncoderModel.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder_3",
|
||||
prefetch_list=hidream_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.tokenizer_3 = T5Tokenizer.from_pretrained(
|
||||
model, subfolder="tokenizer_3", local_files_only=local_files_only
|
||||
|
||||
@@ -25,6 +25,7 @@ from vllm_omni.diffusion.distributed.autoencoders.autoencoder_kl_hunyuan_video_1
|
||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.hunyuan_video.hunyuan_video_15_transformer import HunyuanVideo15Transformer3DModel
|
||||
from vllm_omni.diffusion.models.progress_bar import ProgressBarMixin
|
||||
from vllm_omni.diffusion.models.t5_encoder import T5EncoderModel
|
||||
@@ -101,9 +102,20 @@ class HunyuanVideo15Pipeline(nn.Module, CFGParallelMixin, ProgressBarMixin, Diff
|
||||
model = od_config.model
|
||||
local_files_only = os.path.exists(model)
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained so
|
||||
# peer workers load from a warm, complete cache.
|
||||
hv_subfolders = ["tokenizer", "text_encoder", "tokenizer_2", "text_encoder_2", "vae", "scheduler"]
|
||||
prefetch_subfolders(model, hv_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.tokenizer = Qwen2Tokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.text_encoder = Qwen2_5_VLTextModel.from_pretrained(
|
||||
model, subfolder="text_encoder", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLTextModel.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=hv_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
self.tokenizer_2 = ByT5Tokenizer.from_pretrained(
|
||||
@@ -112,8 +124,13 @@ class HunyuanVideo15Pipeline(nn.Module, CFGParallelMixin, ProgressBarMixin, Diff
|
||||
t5_config = AutoConfig.from_pretrained(model, subfolder="text_encoder_2", local_files_only=local_files_only)
|
||||
self.text_encoder_2 = T5EncoderModel(t5_config, prefix="text_encoder_2").to(dtype=dtype, device=self.device)
|
||||
|
||||
self.vae = DistributedAutoencoderKLHunyuanVideo15.from_pretrained(
|
||||
model, subfolder="vae", torch_dtype=torch.float32, local_files_only=local_files_only
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
DistributedAutoencoderKLHunyuanVideo15.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=hv_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=torch.float32,
|
||||
).to(self.device)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
|
||||
@@ -32,6 +32,7 @@ from vllm_omni.diffusion.distributed.autoencoders.autoencoder_kl_hunyuan_video_1
|
||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.hunyuan_video.hunyuan_video_15_transformer import HunyuanVideo15Transformer3DModel
|
||||
from vllm_omni.diffusion.models.hunyuan_video.pipeline_hunyuan_video_1_5 import (
|
||||
extract_glyph_texts,
|
||||
@@ -123,9 +124,29 @@ class HunyuanVideo15I2VPipeline(
|
||||
model = od_config.model
|
||||
local_files_only = os.path.exists(model)
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained so
|
||||
# peer workers load from a warm, complete cache.
|
||||
hv_subfolders = [
|
||||
"tokenizer",
|
||||
"text_encoder",
|
||||
"tokenizer_2",
|
||||
"text_encoder_2",
|
||||
"image_encoder",
|
||||
"feature_extractor",
|
||||
"vae",
|
||||
"scheduler",
|
||||
]
|
||||
prefetch_subfolders(model, hv_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.tokenizer = Qwen2Tokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.text_encoder = Qwen2_5_VLTextModel.from_pretrained(
|
||||
model, subfolder="text_encoder", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLTextModel.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=hv_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
self.tokenizer_2 = ByT5Tokenizer.from_pretrained(
|
||||
@@ -134,15 +155,25 @@ class HunyuanVideo15I2VPipeline(
|
||||
t5_config = AutoConfig.from_pretrained(model, subfolder="text_encoder_2", local_files_only=local_files_only)
|
||||
self.text_encoder_2 = T5EncoderModel(t5_config, prefix="text_encoder_2").to(dtype=dtype, device=self.device)
|
||||
|
||||
self.image_encoder = SiglipVisionModel.from_pretrained(
|
||||
model, subfolder="image_encoder", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.image_encoder = from_pretrained_with_prefetch(
|
||||
SiglipVisionModel.from_pretrained,
|
||||
model,
|
||||
subfolder="image_encoder",
|
||||
prefetch_list=hv_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
self.feature_extractor = SiglipImageProcessor.from_pretrained(
|
||||
model, subfolder="feature_extractor", local_files_only=local_files_only
|
||||
)
|
||||
|
||||
self.vae = DistributedAutoencoderKLHunyuanVideo15.from_pretrained(
|
||||
model, subfolder="vae", torch_dtype=torch.float32, local_files_only=local_files_only
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
DistributedAutoencoderKLHunyuanVideo15.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=hv_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=torch.float32,
|
||||
).to(self.device)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
|
||||
@@ -27,6 +27,7 @@ from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.longcat_image.longcat_image_transformer import LongCatImageTransformer2DModel
|
||||
from vllm_omni.diffusion.profiler.diffusion_pipeline_profiler import DiffusionPipelineProfilerMixin
|
||||
from vllm_omni.diffusion.request import OmniDiffusionRequest
|
||||
@@ -223,19 +224,32 @@ class LongCatImagePipeline(nn.Module, CFGParallelMixin, DiffusionPipelineProfile
|
||||
model = od_config.model
|
||||
local_files_only = os.path.exists(model)
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained.
|
||||
longcat_subfolders = ["scheduler", "text_encoder", "tokenizer", "vae"]
|
||||
prefetch_subfolders(model, longcat_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
|
||||
self.text_encoder = Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
||||
model, subfolder="text_encoder", local_files_only=local_files_only
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=longcat_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.text_processor = Qwen2VLProcessor.from_pretrained(
|
||||
model, subfolder="tokenizer", local_files_only=local_files_only
|
||||
)
|
||||
self.vae = AutoencoderKL.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self.device
|
||||
)
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKL.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=longcat_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
self.transformer = LongCatImageTransformer2DModel(od_config=od_config)
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.interface import SupportImageInput
|
||||
from vllm_omni.diffusion.models.longcat_image.longcat_image_transformer import (
|
||||
LongCatImageTransformer2DModel,
|
||||
@@ -244,19 +245,32 @@ class LongCatImageEditPipeline(nn.Module, CFGParallelMixin, SupportImageInput, D
|
||||
model = od_config.model
|
||||
local_files_only = os.path.exists(model)
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained.
|
||||
longcat_subfolders = ["scheduler", "text_encoder", "text_processor", "tokenizer", "vae"]
|
||||
prefetch_subfolders(model, longcat_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
self.text_encoder = Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
||||
model, subfolder="text_encoder", local_files_only=local_files_only
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=longcat_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.text_processor = Qwen2VLProcessor.from_pretrained(
|
||||
model, subfolder="text_processor", local_files_only=local_files_only
|
||||
)
|
||||
|
||||
self.vae = AutoencoderKL.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self.device
|
||||
)
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKL.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=longcat_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
self.transformer = LongCatImageTransformer2DModel(od_config=od_config)
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ from vllm_omni.diffusion.distributed.parallel_state import (
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.lora.manager import DiffusionLoRAManager
|
||||
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.models.dmd2 import DMD2PipelineMixin
|
||||
from vllm_omni.diffusion.models.interface import SupportsComponentDiscovery
|
||||
from vllm_omni.diffusion.models.progress_bar import ProgressBarMixin
|
||||
@@ -185,6 +186,19 @@ class LTX2Pipeline(nn.Module, CFGParallelMixin, ProgressBarMixin):
|
||||
),
|
||||
]
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained.
|
||||
ltx2_subfolders = [
|
||||
"tokenizer",
|
||||
"text_encoder",
|
||||
"connectors",
|
||||
"vae",
|
||||
"audio_vae",
|
||||
"vocoder",
|
||||
"scheduler",
|
||||
]
|
||||
prefetch_subfolders(model, ltx2_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(
|
||||
model,
|
||||
subfolder="tokenizer",
|
||||
@@ -193,36 +207,46 @@ class LTX2Pipeline(nn.Module, CFGParallelMixin, ProgressBarMixin):
|
||||
# prefer mmap loading as default device is cuda, and the output of text encoder
|
||||
# could be deterministic.
|
||||
with torch.device("cpu"):
|
||||
self.text_encoder = Gemma3ForConditionalGeneration.from_pretrained(
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Gemma3ForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
self.connectors = LTX2TextConnectors.from_pretrained(
|
||||
self.connectors = from_pretrained_with_prefetch(
|
||||
LTX2TextConnectors.from_pretrained,
|
||||
model,
|
||||
subfolder="connectors",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
self.vae = AutoencoderKLLTX2Video.from_pretrained(
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKLLTX2Video.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
self.audio_vae = AutoencoderKLLTX2Audio.from_pretrained(
|
||||
self.audio_vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKLLTX2Audio.from_pretrained,
|
||||
model,
|
||||
subfolder="audio_vae",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
self.vocoder = LTX2Vocoder.from_pretrained(
|
||||
self.vocoder = from_pretrained_with_prefetch(
|
||||
LTX2Vocoder.from_pretrained,
|
||||
model,
|
||||
subfolder="vocoder",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
transformer_config = load_transformer_config(model, "transformer", local_files_only)
|
||||
|
||||
@@ -45,6 +45,7 @@ from vllm_omni.diffusion.distributed.parallel_state import (
|
||||
)
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.progress_bar import ProgressBarMixin
|
||||
from vllm_omni.diffusion.request import OmniDiffusionRequest
|
||||
|
||||
@@ -149,26 +150,59 @@ class LTX23Pipeline(nn.Module, CFGParallelMixin, ProgressBarMixin):
|
||||
),
|
||||
]
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained.
|
||||
ltx2_subfolders = [
|
||||
"tokenizer",
|
||||
"text_encoder",
|
||||
"connectors",
|
||||
"vae",
|
||||
"audio_vae",
|
||||
"vocoder",
|
||||
"scheduler",
|
||||
]
|
||||
prefetch_subfolders(model, ltx2_subfolders, local_files_only=local_files_only)
|
||||
|
||||
# --- Tokenizer (lightweight, stays wherever) ---
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
|
||||
# --- Text encoder: load on CPU, move to GPU only during encoding ---
|
||||
with torch.device("cpu"):
|
||||
self.text_encoder = Gemma3ForConditionalGeneration.from_pretrained(
|
||||
model, subfolder="text_encoder", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Gemma3ForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
)
|
||||
|
||||
# --- Connectors: CPU (LTX-2.3 connectors include caption projection) ---
|
||||
self.connectors = LTX2TextConnectors.from_pretrained(
|
||||
model, subfolder="connectors", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.connectors = from_pretrained_with_prefetch(
|
||||
LTX2TextConnectors.from_pretrained,
|
||||
model,
|
||||
subfolder="connectors",
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
)
|
||||
|
||||
# --- VAE, Audio VAE: CPU ---
|
||||
self.vae = AutoencoderKLLTX2Video.from_pretrained(
|
||||
model, subfolder="vae", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKLLTX2Video.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
)
|
||||
self.audio_vae = AutoencoderKLLTX2Audio.from_pretrained(
|
||||
model, subfolder="audio_vae", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.audio_vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKLLTX2Audio.from_pretrained,
|
||||
model,
|
||||
subfolder="audio_vae",
|
||||
prefetch_list=ltx2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
)
|
||||
|
||||
# --- Vocoder: prefer BWE vocoder (48kHz) for LTX-2.3 ---
|
||||
|
||||
@@ -32,6 +32,7 @@ from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.interface import SupportsComponentDiscovery
|
||||
from vllm_omni.diffusion.models.omnigen2.omnigen2_transformer import (
|
||||
OmniGen2RotaryPosEmbed,
|
||||
@@ -673,23 +674,40 @@ class OmniGen2Pipeline(CFGParallelMixin, nn.Module, SupportsComponentDiscovery):
|
||||
)
|
||||
]
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained.
|
||||
omnigen2_subfolders = ["scheduler", "vae", "mllm", "processor"]
|
||||
prefetch_subfolders(model, omnigen2_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
self.vae = AutoencoderKL.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self.device
|
||||
)
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKL.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=omnigen2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
|
||||
transformer_kwargs = get_transformer_config_kwargs(od_config.tf_model_config, OmniGen2Transformer2DModel)
|
||||
self.transformer = OmniGen2Transformer2DModel(
|
||||
**transformer_kwargs,
|
||||
quant_config=od_config.quantization_config,
|
||||
)
|
||||
self.mllm = Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
||||
model, subfolder="mllm", local_files_only=local_files_only
|
||||
self.mllm = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="mllm",
|
||||
prefetch_list=omnigen2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
self.processor = Qwen2_5_VLProcessor.from_pretrained(
|
||||
model, subfolder="processor", local_files_only=local_files_only
|
||||
self.processor = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLProcessor.from_pretrained,
|
||||
model,
|
||||
subfolder="processor",
|
||||
prefetch_list=omnigen2_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.vae_scale_factor = (
|
||||
2 ** (len(self.vae.config.block_out_channels) - 1) if hasattr(self, "vae") and self.vae is not None else 8
|
||||
|
||||
@@ -38,6 +38,7 @@ from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.ovis_image.ovis_image_transformer import OvisImageTransformer2DModel
|
||||
from vllm_omni.diffusion.profiler.diffusion_pipeline_profiler import DiffusionPipelineProfilerMixin
|
||||
from vllm_omni.diffusion.request import OmniDiffusionRequest
|
||||
@@ -163,20 +164,32 @@ class OvisImagePipeline(nn.Module, CFGParallelMixin, DiffusionPipelineProfilerMi
|
||||
self._execution_device = get_local_device()
|
||||
model = od_config.model
|
||||
local_files_only = os.path.exists(model)
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained.
|
||||
ovis_subfolders = ["scheduler", "text_encoder", "vae", "tokenizer"]
|
||||
prefetch_subfolders(model, ovis_subfolders, local_files_only=local_files_only)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
|
||||
self.text_encoder = Qwen3Model.from_pretrained(
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen3Model.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=ovis_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=od_config.dtype,
|
||||
)
|
||||
|
||||
self.vae = AutoencoderKL.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self._execution_device
|
||||
)
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKL.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=ovis_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self._execution_device)
|
||||
|
||||
self.tokenizer = Qwen2TokenizerFast.from_pretrained(
|
||||
model, subfolder="tokenizer", local_files_only=local_files_only
|
||||
|
||||
@@ -26,7 +26,7 @@ from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.autoencoders.autoencoder_kl_qwenimage import DistributedAutoencoderKLQwenImage
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import prefetch_subfolders, retry_on_missing_shard
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders
|
||||
from vllm_omni.diffusion.models.dmd2 import DMD2PipelineMixin
|
||||
from vllm_omni.diffusion.models.qwen_image.cfg_parallel import (
|
||||
QwenImageCFGParallelMixin,
|
||||
@@ -279,18 +279,25 @@ class QwenImagePipeline(nn.Module, QwenImageCFGParallelMixin, DiffusionPipelineP
|
||||
|
||||
# See pipeline_qwen_image_edit_plus: guard against transformers v5
|
||||
# multi-worker race on partial subfolder shard sets (Buildkite #1043).
|
||||
qwen_subfolders = ["scheduler", "text_encoder", "vae", "tokenizer"]
|
||||
prefetch_subfolders(
|
||||
model,
|
||||
["scheduler", "text_encoder", "vae", "tokenizer"],
|
||||
qwen_subfolders,
|
||||
)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
self.text_encoder = retry_on_missing_shard(
|
||||
lambda: Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
||||
model, subfolder="text_encoder", local_files_only=local_files_only
|
||||
)
|
||||
# ``from_pretrained_with_prefetch`` re-prefetches and retries on a
|
||||
# half-written cache (missing-shard ``OSError`` *and* the default
|
||||
# -config size-mismatch ``RuntimeError`` that ``retry_on_missing_shard``
|
||||
# could not recover) instead of crashing the worker.
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
# Qwen2.5-VL ships a vision tower that text-to-image does not use.
|
||||
# Drop it while the model is still on CPU, before moving to GPU, so
|
||||
@@ -307,8 +314,12 @@ class QwenImagePipeline(nn.Module, QwenImageCFGParallelMixin, DiffusionPipelineP
|
||||
else:
|
||||
logger.warning("Qwen-Image: vision tower not found on text encoder; skipping drop")
|
||||
self.text_encoder = self.text_encoder.to(self.device)
|
||||
self.vae = DistributedAutoencoderKLQwenImage.from_pretrained(
|
||||
model, subfolder="vae", local_files_only=local_files_only
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
DistributedAutoencoderKLQwenImage.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
transformer_kwargs = get_transformer_config_kwargs(od_config.tf_model_config, QwenImageTransformer2DModel)
|
||||
self.transformer = QwenImageTransformer2DModel(
|
||||
|
||||
@@ -27,7 +27,7 @@ from vllm.model_executor.models.utils import AutoWeightsLoader
|
||||
from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import prefetch_subfolders, retry_on_missing_shard
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders
|
||||
from vllm_omni.diffusion.models.interface import SupportImageInput
|
||||
from vllm_omni.diffusion.models.qwen_image.cfg_parallel import (
|
||||
QwenImageCFGParallelMixin,
|
||||
@@ -247,28 +247,43 @@ class QwenImageEditPipeline(nn.Module, SupportImageInput, QwenImageCFGParallelMi
|
||||
|
||||
# See pipeline_qwen_image_edit_plus: guard against transformers v5
|
||||
# multi-worker race on partial subfolder shard sets (Buildkite #1043).
|
||||
qwen_subfolders = ["scheduler", "text_encoder", "vae", "tokenizer", "processor"]
|
||||
prefetch_subfolders(
|
||||
model,
|
||||
["scheduler", "text_encoder", "vae", "tokenizer", "processor"],
|
||||
qwen_subfolders,
|
||||
)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
self.text_encoder = retry_on_missing_shard(
|
||||
lambda: Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
||||
model, subfolder="text_encoder", local_files_only=local_files_only
|
||||
).to(self.device)
|
||||
)
|
||||
# ``from_pretrained_with_prefetch`` re-prefetches and retries on a
|
||||
# half-written cache (missing-shard ``OSError`` *and* the default
|
||||
# -config size-mismatch ``RuntimeError`` that ``retry_on_missing_shard``
|
||||
# could not recover) instead of crashing the worker.
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
|
||||
self.vae = AutoencoderKLQwenImage.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self.device
|
||||
)
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKLQwenImage.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
transformer_kwargs = get_transformer_config_kwargs(od_config.tf_model_config, QwenImageTransformer2DModel)
|
||||
self.transformer = QwenImageTransformer2DModel(od_config=od_config, **transformer_kwargs)
|
||||
self.tokenizer = Qwen2Tokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.processor = retry_on_missing_shard(
|
||||
lambda: Qwen2VLProcessor.from_pretrained(model, subfolder="processor", local_files_only=local_files_only)
|
||||
self.processor = from_pretrained_with_prefetch(
|
||||
Qwen2VLProcessor.from_pretrained,
|
||||
model,
|
||||
subfolder="processor",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
|
||||
self.stage = None
|
||||
|
||||
@@ -25,7 +25,7 @@ from vllm.model_executor.models.utils import AutoWeightsLoader
|
||||
from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import prefetch_subfolders, retry_on_missing_shard
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders
|
||||
from vllm_omni.diffusion.model_metadata import QWEN_IMAGE_EDIT_PLUS_MAX_INPUT_IMAGES
|
||||
from vllm_omni.diffusion.models.interface import SupportImageInput
|
||||
from vllm_omni.diffusion.models.qwen_image.cfg_parallel import (
|
||||
@@ -216,29 +216,44 @@ class QwenImageEditPlusPipeline(
|
||||
# #1043 for Qwen/Qwen-Image-Edit-2509). snapshot_download takes a
|
||||
# per-repo file lock so the first worker downloads and the rest
|
||||
# wait on a warm cache before loading.
|
||||
qwen_subfolders = ["scheduler", "text_encoder", "vae", "tokenizer", "processor"]
|
||||
prefetch_subfolders(
|
||||
model,
|
||||
["scheduler", "text_encoder", "vae", "tokenizer", "processor"],
|
||||
qwen_subfolders,
|
||||
)
|
||||
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
self.text_encoder = retry_on_missing_shard(
|
||||
lambda: Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
||||
model, subfolder="text_encoder", local_files_only=local_files_only
|
||||
).to(self.device)
|
||||
)
|
||||
# ``from_pretrained_with_prefetch`` re-prefetches and retries on a
|
||||
# half-written cache (missing-shard ``OSError`` *and* the default
|
||||
# -config size-mismatch ``RuntimeError`` that ``retry_on_missing_shard``
|
||||
# could not recover) instead of crashing the worker.
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
|
||||
self.vae = AutoencoderKLQwenImage.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self.device
|
||||
)
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKLQwenImage.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
|
||||
transformer_kwargs = get_transformer_config_kwargs(od_config.tf_model_config, QwenImageTransformer2DModel)
|
||||
self.transformer = QwenImageTransformer2DModel(od_config=od_config, **transformer_kwargs)
|
||||
self.tokenizer = Qwen2Tokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.processor = retry_on_missing_shard(
|
||||
lambda: Qwen2VLProcessor.from_pretrained(model, subfolder="processor", local_files_only=local_files_only)
|
||||
self.processor = from_pretrained_with_prefetch(
|
||||
Qwen2VLProcessor.from_pretrained,
|
||||
model,
|
||||
subfolder="processor",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
|
||||
self.stage = None
|
||||
|
||||
@@ -24,7 +24,7 @@ from vllm.model_executor.models.utils import AutoWeightsLoader
|
||||
from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import prefetch_subfolders, retry_on_missing_shard
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders
|
||||
from vllm_omni.diffusion.models.interface import SupportImageInput
|
||||
from vllm_omni.diffusion.models.qwen_image.autoencoder_kl_qwenimage import (
|
||||
AutoencoderKLQwenImage,
|
||||
@@ -220,26 +220,41 @@ class QwenImageLayeredPipeline(nn.Module, SupportImageInput, QwenImageCFGParalle
|
||||
|
||||
# See pipeline_qwen_image_edit_plus: guard against transformers v5
|
||||
# multi-worker race on partial subfolder shard sets (Buildkite #1043).
|
||||
qwen_subfolders = ["scheduler", "text_encoder", "vae", "tokenizer", "processor"]
|
||||
prefetch_subfolders(
|
||||
model,
|
||||
["scheduler", "text_encoder", "vae", "tokenizer", "processor"],
|
||||
qwen_subfolders,
|
||||
)
|
||||
|
||||
# modules keep same as transformers & diffusers
|
||||
self.scheduler = FlowMatchEulerDiscreteScheduler.from_pretrained(
|
||||
model, subfolder="scheduler", local_files_only=local_files_only
|
||||
)
|
||||
self.text_encoder = retry_on_missing_shard(
|
||||
lambda: Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
||||
model, subfolder="text_encoder", local_files_only=local_files_only
|
||||
).to(self.device)
|
||||
)
|
||||
self.vae = AutoencoderKLQwenImage.from_pretrained(model, subfolder="vae", local_files_only=local_files_only).to(
|
||||
self.device
|
||||
)
|
||||
# ``from_pretrained_with_prefetch`` re-prefetches and retries on a
|
||||
# half-written cache (missing-shard ``OSError`` *and* the default
|
||||
# -config size-mismatch ``RuntimeError`` that ``retry_on_missing_shard``
|
||||
# could not recover) instead of crashing the worker.
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
Qwen2_5_VLForConditionalGeneration.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderKLQwenImage.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
).to(self.device)
|
||||
self.tokenizer = Qwen2Tokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.processor = retry_on_missing_shard(
|
||||
lambda: Qwen2VLProcessor.from_pretrained(model, subfolder="processor", local_files_only=local_files_only)
|
||||
self.processor = from_pretrained_with_prefetch(
|
||||
Qwen2VLProcessor.from_pretrained,
|
||||
model,
|
||||
subfolder="processor",
|
||||
prefetch_list=qwen_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
|
||||
# modules re-implemented for vLLM-Omni
|
||||
|
||||
@@ -19,7 +19,7 @@ from vllm_omni.diffusion.distributed.autoencoders.autoencoder_kl import Distribu
|
||||
from vllm_omni.diffusion.distributed.cfg_parallel import CFGParallelMixin
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import prefetch_subfolders
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders
|
||||
from vllm_omni.diffusion.models.sd3.sd3_transformer import (
|
||||
SD3Transformer2DModel,
|
||||
)
|
||||
@@ -156,18 +156,19 @@ class StableDiffusion3Pipeline(nn.Module, CFGParallelMixin, DiffusionPipelinePro
|
||||
# See ``hub_prefetch.py`` for the transformers v5 subfolder race.
|
||||
# SD3.5 loads six subfolders in a row, each with multi-shard
|
||||
# safetensors - it is the worst-case fan-out for the race window.
|
||||
sd3_subfolders = [
|
||||
"scheduler",
|
||||
"tokenizer",
|
||||
"tokenizer_2",
|
||||
"tokenizer_3",
|
||||
"text_encoder",
|
||||
"text_encoder_2",
|
||||
"text_encoder_3",
|
||||
"vae",
|
||||
]
|
||||
prefetch_subfolders(
|
||||
model,
|
||||
[
|
||||
"scheduler",
|
||||
"tokenizer",
|
||||
"tokenizer_2",
|
||||
"tokenizer_3",
|
||||
"text_encoder",
|
||||
"text_encoder_2",
|
||||
"text_encoder_3",
|
||||
"vae",
|
||||
],
|
||||
sd3_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
|
||||
@@ -198,31 +199,43 @@ class StableDiffusion3Pipeline(nn.Module, CFGParallelMixin, DiffusionPipelinePro
|
||||
self.tokenizer_3 = T5Tokenizer.from_pretrained(
|
||||
model, subfolder="tokenizer_3", local_files_only=local_files_only
|
||||
)
|
||||
self.text_encoder = CLIPTextModelWithProjection.from_pretrained(
|
||||
# ``from_pretrained_with_prefetch`` re-prefetches and retries if a
|
||||
# peer worker left the cache half-written (missing-shard ``OSError`` or
|
||||
# the default-config size-mismatch ``RuntimeError``) instead of
|
||||
# crashing the worker - critical here given the six-subfolder fan-out.
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
CLIPTextModelWithProjection.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=sd3_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
)
|
||||
self.text_encoder_2 = CLIPTextModelWithProjection.from_pretrained(
|
||||
self.text_encoder_2 = from_pretrained_with_prefetch(
|
||||
CLIPTextModelWithProjection.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder_2",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=sd3_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
)
|
||||
self.text_encoder_3 = T5EncoderModel.from_pretrained(
|
||||
self.text_encoder_3 = from_pretrained_with_prefetch(
|
||||
T5EncoderModel.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder_3",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=sd3_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
)
|
||||
self.transformer = SD3Transformer2DModel(od_config=od_config)
|
||||
|
||||
self.vae = DistributedAutoencoderKL.from_pretrained(
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
DistributedAutoencoderKL.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=sd3_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1) if getattr(self, "vae", None) else 8
|
||||
|
||||
@@ -28,6 +28,7 @@ from vllm.model_executor.models.utils import AutoWeightsLoader
|
||||
from vllm_omni.diffusion.data import DiffusionOutput, OmniDiffusionConfig
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
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.models.interface import SupportAudioOutput
|
||||
from vllm_omni.diffusion.models.stable_audio.stable_audio_transformer import (
|
||||
StableAudioDiTModel,
|
||||
@@ -109,6 +110,11 @@ class StableAudioPipeline(nn.Module, SupportAudioOutput, DiffusionPipelineProfil
|
||||
),
|
||||
]
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 multi-worker subfolder
|
||||
# race; prefetch the whole component set before any from_pretrained.
|
||||
sa_subfolders = ["tokenizer", "text_encoder", "vae", "projection_model", "scheduler"]
|
||||
prefetch_subfolders(model, sa_subfolders, local_files_only=local_files_only)
|
||||
|
||||
# Load tokenizer
|
||||
self.tokenizer = T5TokenizerFast.from_pretrained(
|
||||
model,
|
||||
@@ -117,27 +123,33 @@ class StableAudioPipeline(nn.Module, SupportAudioOutput, DiffusionPipelineProfil
|
||||
)
|
||||
|
||||
# Load text encoder
|
||||
self.text_encoder = T5EncoderModel.from_pretrained(
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
T5EncoderModel.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=sa_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
# Load VAE (AutoencoderOobleck for audio)
|
||||
self.vae = AutoencoderOobleck.from_pretrained(
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
AutoencoderOobleck.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
torch_dtype=torch.float32,
|
||||
prefetch_list=sa_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=torch.float32,
|
||||
).to(self.device)
|
||||
|
||||
# Load projection model (using diffusers implementation)
|
||||
self.projection_model = StableAudioProjectionModel.from_pretrained(
|
||||
self.projection_model = from_pretrained_with_prefetch(
|
||||
StableAudioProjectionModel.from_pretrained,
|
||||
model,
|
||||
subfolder="projection_model",
|
||||
torch_dtype=dtype,
|
||||
prefetch_list=sa_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
# Initialize transformer from HF config to keep architecture aligned with checkpoint.
|
||||
|
||||
@@ -26,7 +26,7 @@ from vllm_omni.diffusion.distributed.pipeline_parallel import AsyncLatents, Pipe
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.forward_context import set_forward_context_denoise_step_idx
|
||||
from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import prefetch_subfolders
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders
|
||||
from vllm_omni.diffusion.models.dmd2 import DMD2PipelineMixin
|
||||
from vllm_omni.diffusion.models.progress_bar import ProgressBarMixin, _is_rank_zero
|
||||
from vllm_omni.diffusion.models.schedulers import FlowUniPCMultistepScheduler
|
||||
@@ -336,18 +336,39 @@ class Wan22Pipeline(
|
||||
)
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 subfolder race.
|
||||
component_subfolders = ["tokenizer", "text_encoder", "vae"]
|
||||
prefetch_subfolders(
|
||||
model,
|
||||
["tokenizer", "text_encoder", "vae"],
|
||||
component_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.text_encoder = UMT5EncoderModel.from_pretrained(
|
||||
model, subfolder="text_encoder", torch_dtype=dtype, local_files_only=local_files_only
|
||||
# ``from_pretrained_with_prefetch`` re-prefetches and retries if the
|
||||
# cache is still half-written (the missing-shard ``OSError`` and the
|
||||
# default-``UMT5Config`` size-mismatch ``RuntimeError`` seen on multi
|
||||
# -worker HSDP / ring launches), instead of crashing the worker.
|
||||
self.tokenizer = from_pretrained_with_prefetch(
|
||||
AutoTokenizer.from_pretrained,
|
||||
model,
|
||||
subfolder="tokenizer",
|
||||
prefetch_list=component_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
UMT5EncoderModel.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=component_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
self.vae = DistributedAutoencoderKLWan.from_pretrained(
|
||||
model, subfolder="vae", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
DistributedAutoencoderKLWan.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=component_subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
# Initialize transformers with correct config (weights loaded via load_weights)
|
||||
|
||||
@@ -26,7 +26,7 @@ from vllm_omni.diffusion.distributed.pipeline_parallel import AsyncLatents, Pipe
|
||||
from vllm_omni.diffusion.distributed.utils import get_local_device
|
||||
from vllm_omni.diffusion.forward_context import set_forward_context_denoise_step_idx
|
||||
from vllm_omni.diffusion.model_loader.diffusers_loader import DiffusersPipelineLoader
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import prefetch_subfolders
|
||||
from vllm_omni.diffusion.model_loader.hub_prefetch import from_pretrained_with_prefetch, prefetch_subfolders
|
||||
from vllm_omni.diffusion.models.dmd2 import DMD2PipelineMixin
|
||||
from vllm_omni.diffusion.models.interface import SupportImageInput
|
||||
from vllm_omni.diffusion.models.progress_bar import ProgressBarMixin, _is_rank_zero
|
||||
@@ -197,35 +197,64 @@ class Wan22I2VPipeline(
|
||||
)
|
||||
)
|
||||
|
||||
# Text encoder
|
||||
self.tokenizer = AutoTokenizer.from_pretrained(model, subfolder="tokenizer", local_files_only=local_files_only)
|
||||
self.text_encoder = UMT5EncoderModel.from_pretrained(
|
||||
model, subfolder="text_encoder", torch_dtype=dtype, local_files_only=local_files_only
|
||||
).to(self.device)
|
||||
|
||||
# Image encoder (CLIP) - optional, for Wan2.1-style I2V
|
||||
self.has_image_encoder = "image_encoder" in model_index and model_index["image_encoder"][0] is not None
|
||||
|
||||
# See ``hub_prefetch.py`` for the transformers v5 subfolder race.
|
||||
# See ``hub_prefetch.py`` for the transformers v5 subfolder race. The
|
||||
# prefetch MUST run before any ``from_pretrained`` below - previously
|
||||
# the tokenizer / text_encoder were loaded ahead of this call, so they
|
||||
# never benefited from the prefetch and could hit the half-written
|
||||
# cache directly.
|
||||
subfolders = ["tokenizer", "text_encoder", "vae"]
|
||||
if self.has_image_encoder:
|
||||
subfolders.extend(["image_processor", "image_encoder"])
|
||||
prefetch_subfolders(model, subfolders, local_files_only=local_files_only)
|
||||
|
||||
# Text encoder
|
||||
self.tokenizer = from_pretrained_with_prefetch(
|
||||
AutoTokenizer.from_pretrained,
|
||||
model,
|
||||
subfolder="tokenizer",
|
||||
prefetch_list=subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.text_encoder = from_pretrained_with_prefetch(
|
||||
UMT5EncoderModel.from_pretrained,
|
||||
model,
|
||||
subfolder="text_encoder",
|
||||
prefetch_list=subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
if self.has_image_encoder:
|
||||
self.image_processor = CLIPImageProcessor.from_pretrained(
|
||||
model, subfolder="image_processor", local_files_only=local_files_only
|
||||
self.image_processor = from_pretrained_with_prefetch(
|
||||
CLIPImageProcessor.from_pretrained,
|
||||
model,
|
||||
subfolder="image_processor",
|
||||
prefetch_list=subfolders,
|
||||
local_files_only=local_files_only,
|
||||
)
|
||||
self.image_encoder = CLIPVisionModel.from_pretrained(
|
||||
model, subfolder="image_encoder", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.image_encoder = from_pretrained_with_prefetch(
|
||||
CLIPVisionModel.from_pretrained,
|
||||
model,
|
||||
subfolder="image_encoder",
|
||||
prefetch_list=subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
else:
|
||||
self.image_processor = None
|
||||
self.image_encoder = None
|
||||
|
||||
# VAE
|
||||
self.vae = DistributedAutoencoderKLWan.from_pretrained(
|
||||
model, subfolder="vae", torch_dtype=dtype, local_files_only=local_files_only
|
||||
self.vae = from_pretrained_with_prefetch(
|
||||
DistributedAutoencoderKLWan.from_pretrained,
|
||||
model,
|
||||
subfolder="vae",
|
||||
prefetch_list=subfolders,
|
||||
local_files_only=local_files_only,
|
||||
torch_dtype=dtype,
|
||||
).to(self.device)
|
||||
|
||||
# Transformers (weights loaded via load_weights)
|
||||
|
||||
Reference in new issue
Block a user