diffusers 0.30.2__py3-none-any.whl → 0.31.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- diffusers/__init__.py +38 -2
- diffusers/configuration_utils.py +12 -0
- diffusers/dependency_versions_table.py +1 -1
- diffusers/image_processor.py +257 -54
- diffusers/loaders/__init__.py +2 -0
- diffusers/loaders/ip_adapter.py +5 -1
- diffusers/loaders/lora_base.py +14 -7
- diffusers/loaders/lora_conversion_utils.py +332 -0
- diffusers/loaders/lora_pipeline.py +707 -41
- diffusers/loaders/peft.py +1 -0
- diffusers/loaders/single_file_utils.py +81 -4
- diffusers/loaders/textual_inversion.py +2 -0
- diffusers/loaders/unet.py +39 -8
- diffusers/models/__init__.py +4 -0
- diffusers/models/adapter.py +53 -53
- diffusers/models/attention.py +86 -10
- diffusers/models/attention_processor.py +169 -133
- diffusers/models/autoencoders/autoencoder_kl.py +71 -11
- diffusers/models/autoencoders/autoencoder_kl_cogvideox.py +287 -85
- diffusers/models/controlnet_flux.py +536 -0
- diffusers/models/controlnet_sd3.py +7 -3
- diffusers/models/controlnet_sparsectrl.py +0 -1
- diffusers/models/embeddings.py +238 -61
- diffusers/models/embeddings_flax.py +23 -9
- diffusers/models/model_loading_utils.py +182 -14
- diffusers/models/modeling_utils.py +283 -46
- diffusers/models/normalization.py +79 -0
- diffusers/models/transformers/__init__.py +1 -0
- diffusers/models/transformers/auraflow_transformer_2d.py +1 -0
- diffusers/models/transformers/cogvideox_transformer_3d.py +58 -36
- diffusers/models/transformers/pixart_transformer_2d.py +9 -1
- diffusers/models/transformers/transformer_cogview3plus.py +386 -0
- diffusers/models/transformers/transformer_flux.py +161 -44
- diffusers/models/transformers/transformer_sd3.py +7 -1
- diffusers/models/unets/unet_2d_condition.py +8 -8
- diffusers/models/unets/unet_motion_model.py +41 -63
- diffusers/models/upsampling.py +6 -6
- diffusers/pipelines/__init__.py +40 -7
- diffusers/pipelines/animatediff/__init__.py +2 -0
- diffusers/pipelines/animatediff/pipeline_animatediff.py +45 -21
- diffusers/pipelines/animatediff/pipeline_animatediff_controlnet.py +44 -20
- diffusers/pipelines/animatediff/pipeline_animatediff_sdxl.py +18 -4
- diffusers/pipelines/animatediff/pipeline_animatediff_sparsectrl.py +2 -0
- diffusers/pipelines/animatediff/pipeline_animatediff_video2video.py +104 -66
- diffusers/pipelines/animatediff/pipeline_animatediff_video2video_controlnet.py +1341 -0
- diffusers/pipelines/aura_flow/pipeline_aura_flow.py +1 -1
- diffusers/pipelines/auto_pipeline.py +39 -8
- diffusers/pipelines/cogvideo/__init__.py +6 -0
- diffusers/pipelines/cogvideo/pipeline_cogvideox.py +32 -34
- diffusers/pipelines/cogvideo/pipeline_cogvideox_fun_control.py +794 -0
- diffusers/pipelines/cogvideo/pipeline_cogvideox_image2video.py +837 -0
- diffusers/pipelines/cogvideo/pipeline_cogvideox_video2video.py +825 -0
- diffusers/pipelines/cogvideo/pipeline_output.py +20 -0
- diffusers/pipelines/cogview3/__init__.py +47 -0
- diffusers/pipelines/cogview3/pipeline_cogview3plus.py +674 -0
- diffusers/pipelines/cogview3/pipeline_output.py +21 -0
- diffusers/pipelines/controlnet/pipeline_controlnet.py +9 -1
- diffusers/pipelines/controlnet/pipeline_controlnet_img2img.py +8 -0
- diffusers/pipelines/controlnet/pipeline_controlnet_inpaint.py +8 -0
- diffusers/pipelines/controlnet/pipeline_controlnet_inpaint_sd_xl.py +36 -13
- diffusers/pipelines/controlnet/pipeline_controlnet_sd_xl.py +9 -1
- diffusers/pipelines/controlnet/pipeline_controlnet_sd_xl_img2img.py +8 -1
- diffusers/pipelines/controlnet_hunyuandit/pipeline_hunyuandit_controlnet.py +17 -3
- diffusers/pipelines/controlnet_sd3/__init__.py +4 -0
- diffusers/pipelines/controlnet_sd3/pipeline_stable_diffusion_3_controlnet.py +3 -1
- diffusers/pipelines/controlnet_sd3/pipeline_stable_diffusion_3_controlnet_inpainting.py +1153 -0
- diffusers/pipelines/ddpm/pipeline_ddpm.py +2 -2
- diffusers/pipelines/deepfloyd_if/pipeline_output.py +6 -5
- diffusers/pipelines/deprecated/alt_diffusion/pipeline_alt_diffusion.py +16 -4
- diffusers/pipelines/deprecated/alt_diffusion/pipeline_alt_diffusion_img2img.py +1 -1
- diffusers/pipelines/deprecated/versatile_diffusion/modeling_text_unet.py +1 -1
- diffusers/pipelines/flux/__init__.py +10 -0
- diffusers/pipelines/flux/pipeline_flux.py +53 -20
- diffusers/pipelines/flux/pipeline_flux_controlnet.py +984 -0
- diffusers/pipelines/flux/pipeline_flux_controlnet_image_to_image.py +988 -0
- diffusers/pipelines/flux/pipeline_flux_controlnet_inpainting.py +1182 -0
- diffusers/pipelines/flux/pipeline_flux_img2img.py +850 -0
- diffusers/pipelines/flux/pipeline_flux_inpaint.py +1015 -0
- diffusers/pipelines/free_noise_utils.py +365 -5
- diffusers/pipelines/hunyuandit/pipeline_hunyuandit.py +15 -3
- diffusers/pipelines/kandinsky2_2/pipeline_kandinsky2_2_combined.py +2 -2
- diffusers/pipelines/kolors/pipeline_kolors.py +1 -1
- diffusers/pipelines/kolors/pipeline_kolors_img2img.py +14 -11
- diffusers/pipelines/kolors/tokenizer.py +4 -0
- diffusers/pipelines/latent_consistency_models/pipeline_latent_consistency_img2img.py +1 -1
- diffusers/pipelines/latent_consistency_models/pipeline_latent_consistency_text2img.py +1 -1
- diffusers/pipelines/latte/pipeline_latte.py +2 -2
- diffusers/pipelines/ledits_pp/pipeline_leditspp_stable_diffusion.py +15 -3
- diffusers/pipelines/ledits_pp/pipeline_leditspp_stable_diffusion_xl.py +15 -3
- diffusers/pipelines/lumina/pipeline_lumina.py +2 -2
- diffusers/pipelines/pag/__init__.py +6 -0
- diffusers/pipelines/pag/pag_utils.py +8 -2
- diffusers/pipelines/pag/pipeline_pag_controlnet_sd.py +1 -1
- diffusers/pipelines/pag/pipeline_pag_controlnet_sd_inpaint.py +1544 -0
- diffusers/pipelines/pag/pipeline_pag_controlnet_sd_xl.py +2 -2
- diffusers/pipelines/pag/pipeline_pag_controlnet_sd_xl_img2img.py +1685 -0
- diffusers/pipelines/pag/pipeline_pag_hunyuandit.py +17 -5
- diffusers/pipelines/pag/pipeline_pag_kolors.py +1 -1
- diffusers/pipelines/pag/pipeline_pag_pixart_sigma.py +1 -1
- diffusers/pipelines/pag/pipeline_pag_sd.py +18 -6
- diffusers/pipelines/pag/pipeline_pag_sd_3.py +12 -3
- diffusers/pipelines/pag/pipeline_pag_sd_animatediff.py +5 -1
- diffusers/pipelines/pag/pipeline_pag_sd_img2img.py +1091 -0
- diffusers/pipelines/pag/pipeline_pag_sd_xl.py +18 -6
- diffusers/pipelines/pag/pipeline_pag_sd_xl_img2img.py +31 -16
- diffusers/pipelines/pag/pipeline_pag_sd_xl_inpaint.py +42 -19
- diffusers/pipelines/pia/pipeline_pia.py +2 -0
- diffusers/pipelines/pipeline_loading_utils.py +225 -27
- diffusers/pipelines/pipeline_utils.py +123 -180
- diffusers/pipelines/pixart_alpha/pipeline_pixart_alpha.py +1 -1
- diffusers/pipelines/pixart_alpha/pipeline_pixart_sigma.py +1 -1
- diffusers/pipelines/stable_cascade/pipeline_stable_cascade.py +35 -3
- diffusers/pipelines/stable_cascade/pipeline_stable_cascade_prior.py +2 -2
- diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion.py +28 -6
- diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_img2img.py +1 -1
- diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_inpaint.py +1 -1
- diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_latent_upscale.py +241 -81
- diffusers/pipelines/stable_diffusion_3/pipeline_stable_diffusion_3.py +12 -3
- diffusers/pipelines/stable_diffusion_3/pipeline_stable_diffusion_3_img2img.py +20 -4
- diffusers/pipelines/stable_diffusion_3/pipeline_stable_diffusion_3_inpaint.py +3 -3
- diffusers/pipelines/stable_diffusion_k_diffusion/pipeline_stable_diffusion_k_diffusion.py +1 -1
- diffusers/pipelines/stable_diffusion_ldm3d/pipeline_stable_diffusion_ldm3d.py +16 -4
- diffusers/pipelines/stable_diffusion_panorama/pipeline_stable_diffusion_panorama.py +16 -4
- diffusers/pipelines/stable_diffusion_xl/pipeline_stable_diffusion_xl.py +16 -4
- diffusers/pipelines/stable_diffusion_xl/pipeline_stable_diffusion_xl_img2img.py +29 -14
- diffusers/pipelines/stable_diffusion_xl/pipeline_stable_diffusion_xl_inpaint.py +29 -14
- diffusers/pipelines/stable_video_diffusion/pipeline_stable_video_diffusion.py +1 -1
- diffusers/pipelines/t2i_adapter/pipeline_stable_diffusion_adapter.py +1 -1
- diffusers/pipelines/t2i_adapter/pipeline_stable_diffusion_xl_adapter.py +16 -4
- diffusers/pipelines/text_to_video_synthesis/pipeline_text_to_video_zero_sdxl.py +15 -3
- diffusers/quantizers/__init__.py +16 -0
- diffusers/quantizers/auto.py +126 -0
- diffusers/quantizers/base.py +233 -0
- diffusers/quantizers/bitsandbytes/__init__.py +2 -0
- diffusers/quantizers/bitsandbytes/bnb_quantizer.py +558 -0
- diffusers/quantizers/bitsandbytes/utils.py +306 -0
- diffusers/quantizers/quantization_config.py +391 -0
- diffusers/schedulers/scheduling_ddim.py +4 -1
- diffusers/schedulers/scheduling_ddim_cogvideox.py +4 -1
- diffusers/schedulers/scheduling_ddim_parallel.py +4 -1
- diffusers/schedulers/scheduling_ddpm.py +4 -1
- diffusers/schedulers/scheduling_ddpm_parallel.py +4 -1
- diffusers/schedulers/scheduling_deis_multistep.py +78 -1
- diffusers/schedulers/scheduling_dpmsolver_multistep.py +82 -1
- diffusers/schedulers/scheduling_dpmsolver_multistep_inverse.py +80 -1
- diffusers/schedulers/scheduling_dpmsolver_sde.py +125 -10
- diffusers/schedulers/scheduling_dpmsolver_singlestep.py +82 -1
- diffusers/schedulers/scheduling_edm_euler.py +8 -6
- diffusers/schedulers/scheduling_euler_ancestral_discrete.py +4 -1
- diffusers/schedulers/scheduling_euler_discrete.py +92 -7
- diffusers/schedulers/scheduling_flow_match_heun_discrete.py +4 -5
- diffusers/schedulers/scheduling_heun_discrete.py +114 -8
- diffusers/schedulers/scheduling_k_dpm_2_ancestral_discrete.py +116 -11
- diffusers/schedulers/scheduling_k_dpm_2_discrete.py +110 -8
- diffusers/schedulers/scheduling_lms_discrete.py +76 -1
- diffusers/schedulers/scheduling_sasolver.py +78 -1
- diffusers/schedulers/scheduling_unclip.py +4 -1
- diffusers/schedulers/scheduling_unipc_multistep.py +78 -1
- diffusers/training_utils.py +48 -18
- diffusers/utils/__init__.py +2 -1
- diffusers/utils/dummy_pt_objects.py +60 -0
- diffusers/utils/dummy_torch_and_transformers_objects.py +195 -0
- diffusers/utils/hub_utils.py +16 -4
- diffusers/utils/import_utils.py +31 -8
- diffusers/utils/loading_utils.py +28 -4
- diffusers/utils/peft_utils.py +3 -3
- diffusers/utils/testing_utils.py +59 -0
- {diffusers-0.30.2.dist-info → diffusers-0.31.0.dist-info}/METADATA +7 -6
- {diffusers-0.30.2.dist-info → diffusers-0.31.0.dist-info}/RECORD +173 -147
- {diffusers-0.30.2.dist-info → diffusers-0.31.0.dist-info}/WHEEL +1 -1
- {diffusers-0.30.2.dist-info → diffusers-0.31.0.dist-info}/LICENSE +0 -0
- {diffusers-0.30.2.dist-info → diffusers-0.31.0.dist-info}/entry_points.txt +0 -0
- {diffusers-0.30.2.dist-info → diffusers-0.31.0.dist-info}/top_level.txt +0 -0
@@ -88,9 +88,21 @@ EXAMPLE_DOC_STRING = """
|
|
88
88
|
|
89
89
|
# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.rescale_noise_cfg
|
90
90
|
def rescale_noise_cfg(noise_cfg, noise_pred_text, guidance_rescale=0.0):
|
91
|
-
"""
|
92
|
-
|
93
|
-
|
91
|
+
r"""
|
92
|
+
Rescales `noise_cfg` tensor based on `guidance_rescale` to improve image quality and fix overexposure. Based on
|
93
|
+
Section 3.4 from [Common Diffusion Noise Schedules and Sample Steps are
|
94
|
+
Flawed](https://arxiv.org/pdf/2305.08891.pdf).
|
95
|
+
|
96
|
+
Args:
|
97
|
+
noise_cfg (`torch.Tensor`):
|
98
|
+
The predicted noise tensor for the guided diffusion process.
|
99
|
+
noise_pred_text (`torch.Tensor`):
|
100
|
+
The predicted noise tensor for the text-guided diffusion process.
|
101
|
+
guidance_rescale (`float`, *optional*, defaults to 0.0):
|
102
|
+
A rescale factor applied to the noise predictions.
|
103
|
+
|
104
|
+
Returns:
|
105
|
+
noise_cfg (`torch.Tensor`): The rescaled noise prediction tensor.
|
94
106
|
"""
|
95
107
|
std_text = noise_pred_text.std(dim=list(range(1, noise_pred_text.ndim)), keepdim=True)
|
96
108
|
std_cfg = noise_cfg.std(dim=list(range(1, noise_cfg.ndim)), keepdim=True)
|
@@ -110,7 +122,7 @@ def retrieve_timesteps(
|
|
110
122
|
sigmas: Optional[List[float]] = None,
|
111
123
|
**kwargs,
|
112
124
|
):
|
113
|
-
"""
|
125
|
+
r"""
|
114
126
|
Calls the scheduler's `set_timesteps` method and retrieves timesteps from the scheduler after the call. Handles
|
115
127
|
custom timesteps. Any kwargs will be supplied to `scheduler.set_timesteps`.
|
116
128
|
|
@@ -1237,8 +1249,8 @@ class StableDiffusionXLPAGPipeline(
|
|
1237
1249
|
|
1238
1250
|
# perform guidance
|
1239
1251
|
if self.do_perturbed_attention_guidance:
|
1240
|
-
noise_pred = self._apply_perturbed_attention_guidance(
|
1241
|
-
noise_pred, self.do_classifier_free_guidance, self.guidance_scale, t
|
1252
|
+
noise_pred, noise_pred_text = self._apply_perturbed_attention_guidance(
|
1253
|
+
noise_pred, self.do_classifier_free_guidance, self.guidance_scale, t, True
|
1242
1254
|
)
|
1243
1255
|
|
1244
1256
|
elif self.do_classifier_free_guidance:
|
@@ -92,9 +92,21 @@ EXAMPLE_DOC_STRING = """
|
|
92
92
|
|
93
93
|
# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.rescale_noise_cfg
|
94
94
|
def rescale_noise_cfg(noise_cfg, noise_pred_text, guidance_rescale=0.0):
|
95
|
-
"""
|
96
|
-
|
97
|
-
|
95
|
+
r"""
|
96
|
+
Rescales `noise_cfg` tensor based on `guidance_rescale` to improve image quality and fix overexposure. Based on
|
97
|
+
Section 3.4 from [Common Diffusion Noise Schedules and Sample Steps are
|
98
|
+
Flawed](https://arxiv.org/pdf/2305.08891.pdf).
|
99
|
+
|
100
|
+
Args:
|
101
|
+
noise_cfg (`torch.Tensor`):
|
102
|
+
The predicted noise tensor for the guided diffusion process.
|
103
|
+
noise_pred_text (`torch.Tensor`):
|
104
|
+
The predicted noise tensor for the text-guided diffusion process.
|
105
|
+
guidance_rescale (`float`, *optional*, defaults to 0.0):
|
106
|
+
A rescale factor applied to the noise predictions.
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
noise_cfg (`torch.Tensor`): The rescaled noise prediction tensor.
|
98
110
|
"""
|
99
111
|
std_text = noise_pred_text.std(dim=list(range(1, noise_pred_text.ndim)), keepdim=True)
|
100
112
|
std_cfg = noise_cfg.std(dim=list(range(1, noise_cfg.ndim)), keepdim=True)
|
@@ -128,7 +140,7 @@ def retrieve_timesteps(
|
|
128
140
|
sigmas: Optional[List[float]] = None,
|
129
141
|
**kwargs,
|
130
142
|
):
|
131
|
-
"""
|
143
|
+
r"""
|
132
144
|
Calls the scheduler's `set_timesteps` method and retrieves timesteps from the scheduler after the call. Handles
|
133
145
|
custom timesteps. Any kwargs will be supplied to `scheduler.set_timesteps`.
|
134
146
|
|
@@ -648,14 +660,16 @@ class StableDiffusionXLPAGImg2ImgPipeline(
|
|
648
660
|
if denoising_start is None:
|
649
661
|
init_timestep = min(int(num_inference_steps * strength), num_inference_steps)
|
650
662
|
t_start = max(num_inference_steps - init_timestep, 0)
|
651
|
-
else:
|
652
|
-
t_start = 0
|
653
663
|
|
654
|
-
|
664
|
+
timesteps = self.scheduler.timesteps[t_start * self.scheduler.order :]
|
665
|
+
if hasattr(self.scheduler, "set_begin_index"):
|
666
|
+
self.scheduler.set_begin_index(t_start * self.scheduler.order)
|
655
667
|
|
656
|
-
|
657
|
-
|
658
|
-
|
668
|
+
return timesteps, num_inference_steps - t_start
|
669
|
+
|
670
|
+
else:
|
671
|
+
# Strength is irrelevant if we directly request a timestep to start at;
|
672
|
+
# that is, strength is determined by the denoising_start instead.
|
659
673
|
discrete_timestep_cutoff = int(
|
660
674
|
round(
|
661
675
|
self.scheduler.config.num_train_timesteps
|
@@ -663,7 +677,7 @@ class StableDiffusionXLPAGImg2ImgPipeline(
|
|
663
677
|
)
|
664
678
|
)
|
665
679
|
|
666
|
-
num_inference_steps = (timesteps < discrete_timestep_cutoff).sum().item()
|
680
|
+
num_inference_steps = (self.scheduler.timesteps < discrete_timestep_cutoff).sum().item()
|
667
681
|
if self.scheduler.order == 2 and num_inference_steps % 2 == 0:
|
668
682
|
# if the scheduler is a 2nd order scheduler we might have to do +1
|
669
683
|
# because `num_inference_steps` might be even given that every timestep
|
@@ -674,11 +688,12 @@ class StableDiffusionXLPAGImg2ImgPipeline(
|
|
674
688
|
num_inference_steps = num_inference_steps + 1
|
675
689
|
|
676
690
|
# because t_n+1 >= t_n, we slice the timesteps starting from the end
|
677
|
-
|
691
|
+
t_start = len(self.scheduler.timesteps) - num_inference_steps
|
692
|
+
timesteps = self.scheduler.timesteps[t_start:]
|
693
|
+
if hasattr(self.scheduler, "set_begin_index"):
|
694
|
+
self.scheduler.set_begin_index(t_start)
|
678
695
|
return timesteps, num_inference_steps
|
679
696
|
|
680
|
-
return timesteps, num_inference_steps - t_start
|
681
|
-
|
682
697
|
# Copied from diffusers.pipelines.stable_diffusion_xl.pipeline_stable_diffusion_xl_img2img.StableDiffusionXLImg2ImgPipeline.prepare_latents
|
683
698
|
def prepare_latents(
|
684
699
|
self, image, timestep, batch_size, num_images_per_prompt, dtype, device, generator=None, add_noise=True
|
@@ -1434,8 +1449,8 @@ class StableDiffusionXLPAGImg2ImgPipeline(
|
|
1434
1449
|
|
1435
1450
|
# perform guidance
|
1436
1451
|
if self.do_perturbed_attention_guidance:
|
1437
|
-
noise_pred = self._apply_perturbed_attention_guidance(
|
1438
|
-
noise_pred, self.do_classifier_free_guidance, self.guidance_scale, t
|
1452
|
+
noise_pred, noise_pred_text = self._apply_perturbed_attention_guidance(
|
1453
|
+
noise_pred, self.do_classifier_free_guidance, self.guidance_scale, t, True
|
1439
1454
|
)
|
1440
1455
|
elif self.do_classifier_free_guidance:
|
1441
1456
|
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
|
@@ -105,9 +105,21 @@ EXAMPLE_DOC_STRING = """
|
|
105
105
|
|
106
106
|
# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.rescale_noise_cfg
|
107
107
|
def rescale_noise_cfg(noise_cfg, noise_pred_text, guidance_rescale=0.0):
|
108
|
-
"""
|
109
|
-
|
110
|
-
|
108
|
+
r"""
|
109
|
+
Rescales `noise_cfg` tensor based on `guidance_rescale` to improve image quality and fix overexposure. Based on
|
110
|
+
Section 3.4 from [Common Diffusion Noise Schedules and Sample Steps are
|
111
|
+
Flawed](https://arxiv.org/pdf/2305.08891.pdf).
|
112
|
+
|
113
|
+
Args:
|
114
|
+
noise_cfg (`torch.Tensor`):
|
115
|
+
The predicted noise tensor for the guided diffusion process.
|
116
|
+
noise_pred_text (`torch.Tensor`):
|
117
|
+
The predicted noise tensor for the text-guided diffusion process.
|
118
|
+
guidance_rescale (`float`, *optional*, defaults to 0.0):
|
119
|
+
A rescale factor applied to the noise predictions.
|
120
|
+
|
121
|
+
Returns:
|
122
|
+
noise_cfg (`torch.Tensor`): The rescaled noise prediction tensor.
|
111
123
|
"""
|
112
124
|
std_text = noise_pred_text.std(dim=list(range(1, noise_pred_text.ndim)), keepdim=True)
|
113
125
|
std_cfg = noise_cfg.std(dim=list(range(1, noise_cfg.ndim)), keepdim=True)
|
@@ -141,7 +153,7 @@ def retrieve_timesteps(
|
|
141
153
|
sigmas: Optional[List[float]] = None,
|
142
154
|
**kwargs,
|
143
155
|
):
|
144
|
-
"""
|
156
|
+
r"""
|
145
157
|
Calls the scheduler's `set_timesteps` method and retrieves timesteps from the scheduler after the call. Handles
|
146
158
|
custom timesteps. Any kwargs will be supplied to `scheduler.set_timesteps`.
|
147
159
|
|
@@ -897,14 +909,16 @@ class StableDiffusionXLPAGInpaintPipeline(
|
|
897
909
|
if denoising_start is None:
|
898
910
|
init_timestep = min(int(num_inference_steps * strength), num_inference_steps)
|
899
911
|
t_start = max(num_inference_steps - init_timestep, 0)
|
900
|
-
else:
|
901
|
-
t_start = 0
|
902
912
|
|
903
|
-
|
913
|
+
timesteps = self.scheduler.timesteps[t_start * self.scheduler.order :]
|
914
|
+
if hasattr(self.scheduler, "set_begin_index"):
|
915
|
+
self.scheduler.set_begin_index(t_start * self.scheduler.order)
|
904
916
|
|
905
|
-
|
906
|
-
|
907
|
-
|
917
|
+
return timesteps, num_inference_steps - t_start
|
918
|
+
|
919
|
+
else:
|
920
|
+
# Strength is irrelevant if we directly request a timestep to start at;
|
921
|
+
# that is, strength is determined by the denoising_start instead.
|
908
922
|
discrete_timestep_cutoff = int(
|
909
923
|
round(
|
910
924
|
self.scheduler.config.num_train_timesteps
|
@@ -912,7 +926,7 @@ class StableDiffusionXLPAGInpaintPipeline(
|
|
912
926
|
)
|
913
927
|
)
|
914
928
|
|
915
|
-
num_inference_steps = (timesteps < discrete_timestep_cutoff).sum().item()
|
929
|
+
num_inference_steps = (self.scheduler.timesteps < discrete_timestep_cutoff).sum().item()
|
916
930
|
if self.scheduler.order == 2 and num_inference_steps % 2 == 0:
|
917
931
|
# if the scheduler is a 2nd order scheduler we might have to do +1
|
918
932
|
# because `num_inference_steps` might be even given that every timestep
|
@@ -923,11 +937,12 @@ class StableDiffusionXLPAGInpaintPipeline(
|
|
923
937
|
num_inference_steps = num_inference_steps + 1
|
924
938
|
|
925
939
|
# because t_n+1 >= t_n, we slice the timesteps starting from the end
|
926
|
-
|
940
|
+
t_start = len(self.scheduler.timesteps) - num_inference_steps
|
941
|
+
timesteps = self.scheduler.timesteps[t_start:]
|
942
|
+
if hasattr(self.scheduler, "set_begin_index"):
|
943
|
+
self.scheduler.set_begin_index(t_start)
|
927
944
|
return timesteps, num_inference_steps
|
928
945
|
|
929
|
-
return timesteps, num_inference_steps - t_start
|
930
|
-
|
931
946
|
# Copied from diffusers.pipelines.stable_diffusion_xl.pipeline_stable_diffusion_xl_img2img.StableDiffusionXLImg2ImgPipeline._get_add_time_ids
|
932
947
|
def _get_add_time_ids(
|
933
948
|
self,
|
@@ -1471,6 +1486,14 @@ class StableDiffusionXLPAGInpaintPipeline(
|
|
1471
1486
|
generator,
|
1472
1487
|
self.do_classifier_free_guidance,
|
1473
1488
|
)
|
1489
|
+
if self.do_perturbed_attention_guidance:
|
1490
|
+
if self.do_classifier_free_guidance:
|
1491
|
+
mask, _ = mask.chunk(2)
|
1492
|
+
masked_image_latents, _ = masked_image_latents.chunk(2)
|
1493
|
+
mask = self._prepare_perturbed_attention_guidance(mask, mask, self.do_classifier_free_guidance)
|
1494
|
+
masked_image_latents = self._prepare_perturbed_attention_guidance(
|
1495
|
+
masked_image_latents, masked_image_latents, self.do_classifier_free_guidance
|
1496
|
+
)
|
1474
1497
|
|
1475
1498
|
# 8. Check that sizes of mask, masked image and latents match
|
1476
1499
|
if num_channels_unet == 9:
|
@@ -1638,8 +1661,8 @@ class StableDiffusionXLPAGInpaintPipeline(
|
|
1638
1661
|
|
1639
1662
|
# perform guidance
|
1640
1663
|
if self.do_perturbed_attention_guidance:
|
1641
|
-
noise_pred = self._apply_perturbed_attention_guidance(
|
1642
|
-
noise_pred, self.do_classifier_free_guidance, self.guidance_scale, t
|
1664
|
+
noise_pred, noise_pred_text = self._apply_perturbed_attention_guidance(
|
1665
|
+
noise_pred, self.do_classifier_free_guidance, self.guidance_scale, t, True
|
1643
1666
|
)
|
1644
1667
|
elif self.do_classifier_free_guidance:
|
1645
1668
|
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
|
@@ -1659,10 +1682,10 @@ class StableDiffusionXLPAGInpaintPipeline(
|
|
1659
1682
|
|
1660
1683
|
if num_channels_unet == 4:
|
1661
1684
|
init_latents_proper = image_latents
|
1662
|
-
if self.
|
1663
|
-
init_mask, _ = mask.chunk(2)
|
1685
|
+
if self.do_perturbed_attention_guidance:
|
1686
|
+
init_mask, *_ = mask.chunk(3) if self.do_classifier_free_guidance else mask.chunk(2)
|
1664
1687
|
else:
|
1665
|
-
init_mask = mask
|
1688
|
+
init_mask, *_ = mask.chunk(2) if self.do_classifier_free_guidance else mask
|
1666
1689
|
|
1667
1690
|
if i < len(timesteps) - 1:
|
1668
1691
|
noise_timestep = timesteps[i + 1]
|
@@ -824,6 +824,8 @@ class PIAPipeline(
|
|
824
824
|
if self.do_classifier_free_guidance:
|
825
825
|
prompt_embeds = torch.cat([negative_prompt_embeds, prompt_embeds])
|
826
826
|
|
827
|
+
prompt_embeds = prompt_embeds.repeat_interleave(repeats=num_frames, dim=0)
|
828
|
+
|
827
829
|
if ip_adapter_image is not None or ip_adapter_image_embeds is not None:
|
828
830
|
image_embeds = self.prepare_ip_adapter_image_embeds(
|
829
831
|
ip_adapter_image,
|
@@ -22,7 +22,7 @@ from pathlib import Path
|
|
22
22
|
from typing import Any, Dict, List, Optional, Union
|
23
23
|
|
24
24
|
import torch
|
25
|
-
from huggingface_hub import model_info
|
25
|
+
from huggingface_hub import ModelCard, model_info
|
26
26
|
from huggingface_hub.utils import validate_hf_hub_args
|
27
27
|
from packaging import version
|
28
28
|
|
@@ -33,6 +33,7 @@ from ..utils import (
|
|
33
33
|
ONNX_WEIGHTS_NAME,
|
34
34
|
SAFETENSORS_WEIGHTS_NAME,
|
35
35
|
WEIGHTS_NAME,
|
36
|
+
deprecate,
|
36
37
|
get_class_from_dynamic_module,
|
37
38
|
is_accelerate_available,
|
38
39
|
is_peft_available,
|
@@ -89,49 +90,50 @@ for library in LOADABLE_CLASSES:
|
|
89
90
|
ALL_IMPORTABLE_CLASSES.update(LOADABLE_CLASSES[library])
|
90
91
|
|
91
92
|
|
92
|
-
def is_safetensors_compatible(filenames,
|
93
|
+
def is_safetensors_compatible(filenames, passed_components=None, folder_names=None) -> bool:
|
93
94
|
"""
|
94
95
|
Checking for safetensors compatibility:
|
95
|
-
-
|
96
|
-
|
97
|
-
- The model is safetensors compatible only if there is a matching safetensors file for every default pytorch file.
|
96
|
+
- The model is safetensors compatible only if there is a safetensors file for each model component present in
|
97
|
+
filenames.
|
98
98
|
|
99
99
|
Converting default pytorch serialized filenames to safetensors serialized filenames:
|
100
100
|
- For models from the diffusers library, just replace the ".bin" extension with ".safetensors"
|
101
101
|
- For models from the transformers library, the filename changes from "pytorch_model" to "model", and the ".bin"
|
102
102
|
extension is replaced with ".safetensors"
|
103
103
|
"""
|
104
|
-
pt_filenames = []
|
105
|
-
|
106
|
-
sf_filenames = set()
|
107
|
-
|
108
104
|
passed_components = passed_components or []
|
105
|
+
if folder_names is not None:
|
106
|
+
filenames = {f for f in filenames if os.path.split(f)[0] in folder_names}
|
109
107
|
|
108
|
+
# extract all components of the pipeline and their associated files
|
109
|
+
components = {}
|
110
110
|
for filename in filenames:
|
111
|
-
|
111
|
+
if not len(filename.split("/")) == 2:
|
112
|
+
continue
|
112
113
|
|
113
|
-
|
114
|
+
component, component_filename = filename.split("/")
|
115
|
+
if component in passed_components:
|
114
116
|
continue
|
115
117
|
|
116
|
-
|
117
|
-
|
118
|
-
elif extension == ".safetensors":
|
119
|
-
sf_filenames.add(os.path.normpath(filename))
|
118
|
+
components.setdefault(component, [])
|
119
|
+
components[component].append(component_filename)
|
120
120
|
|
121
|
-
for
|
122
|
-
|
123
|
-
|
124
|
-
filename, extension = os.path.splitext(filename)
|
121
|
+
# If there are no component folders check the main directory for safetensors files
|
122
|
+
if not components:
|
123
|
+
return any(".safetensors" in filename for filename in filenames)
|
125
124
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
125
|
+
# iterate over all files of a component
|
126
|
+
# check if safetensor files exist for that component
|
127
|
+
# if variant is provided check if the variant of the safetensors exists
|
128
|
+
for component, component_filenames in components.items():
|
129
|
+
matches = []
|
130
|
+
for component_filename in component_filenames:
|
131
|
+
filename, extension = os.path.splitext(component_filename)
|
132
|
+
|
133
|
+
match_exists = extension == ".safetensors"
|
134
|
+
matches.append(match_exists)
|
130
135
|
|
131
|
-
|
132
|
-
expected_sf_filename = f"{expected_sf_filename}.safetensors"
|
133
|
-
if expected_sf_filename not in sf_filenames:
|
134
|
-
logger.warning(f"{expected_sf_filename} not found")
|
136
|
+
if not any(matches):
|
135
137
|
return False
|
136
138
|
|
137
139
|
return True
|
@@ -603,6 +605,7 @@ def load_sub_model(
|
|
603
605
|
variant: str,
|
604
606
|
low_cpu_mem_usage: bool,
|
605
607
|
cached_folder: Union[str, os.PathLike],
|
608
|
+
use_safetensors: bool,
|
606
609
|
):
|
607
610
|
"""Helper method to load the module `name` from `library_name` and `class_name`"""
|
608
611
|
|
@@ -672,6 +675,7 @@ def load_sub_model(
|
|
672
675
|
loading_kwargs["offload_folder"] = offload_folder
|
673
676
|
loading_kwargs["offload_state_dict"] = offload_state_dict
|
674
677
|
loading_kwargs["variant"] = model_variants.pop(name, None)
|
678
|
+
loading_kwargs["use_safetensors"] = use_safetensors
|
675
679
|
|
676
680
|
if from_flax:
|
677
681
|
loading_kwargs["from_flax"] = True
|
@@ -749,3 +753,197 @@ def _fetch_class_library_tuple(module):
|
|
749
753
|
class_name = not_compiled_module.__class__.__name__
|
750
754
|
|
751
755
|
return (library, class_name)
|
756
|
+
|
757
|
+
|
758
|
+
def _identify_model_variants(folder: str, variant: str, config: dict) -> dict:
|
759
|
+
model_variants = {}
|
760
|
+
if variant is not None:
|
761
|
+
for sub_folder in os.listdir(folder):
|
762
|
+
folder_path = os.path.join(folder, sub_folder)
|
763
|
+
is_folder = os.path.isdir(folder_path) and sub_folder in config
|
764
|
+
variant_exists = is_folder and any(p.split(".")[1].startswith(variant) for p in os.listdir(folder_path))
|
765
|
+
if variant_exists:
|
766
|
+
model_variants[sub_folder] = variant
|
767
|
+
return model_variants
|
768
|
+
|
769
|
+
|
770
|
+
def _resolve_custom_pipeline_and_cls(folder, config, custom_pipeline):
|
771
|
+
custom_class_name = None
|
772
|
+
if os.path.isfile(os.path.join(folder, f"{custom_pipeline}.py")):
|
773
|
+
custom_pipeline = os.path.join(folder, f"{custom_pipeline}.py")
|
774
|
+
elif isinstance(config["_class_name"], (list, tuple)) and os.path.isfile(
|
775
|
+
os.path.join(folder, f"{config['_class_name'][0]}.py")
|
776
|
+
):
|
777
|
+
custom_pipeline = os.path.join(folder, f"{config['_class_name'][0]}.py")
|
778
|
+
custom_class_name = config["_class_name"][1]
|
779
|
+
|
780
|
+
return custom_pipeline, custom_class_name
|
781
|
+
|
782
|
+
|
783
|
+
def _maybe_raise_warning_for_inpainting(pipeline_class, pretrained_model_name_or_path: str, config: dict):
|
784
|
+
if pipeline_class.__name__ == "StableDiffusionInpaintPipeline" and version.parse(
|
785
|
+
version.parse(config["_diffusers_version"]).base_version
|
786
|
+
) <= version.parse("0.5.1"):
|
787
|
+
from diffusers import StableDiffusionInpaintPipeline, StableDiffusionInpaintPipelineLegacy
|
788
|
+
|
789
|
+
pipeline_class = StableDiffusionInpaintPipelineLegacy
|
790
|
+
|
791
|
+
deprecation_message = (
|
792
|
+
"You are using a legacy checkpoint for inpainting with Stable Diffusion, therefore we are loading the"
|
793
|
+
f" {StableDiffusionInpaintPipelineLegacy} class instead of {StableDiffusionInpaintPipeline}. For"
|
794
|
+
" better inpainting results, we strongly suggest using Stable Diffusion's official inpainting"
|
795
|
+
" checkpoint: https://huggingface.co/runwayml/stable-diffusion-inpainting instead or adapting your"
|
796
|
+
f" checkpoint {pretrained_model_name_or_path} to the format of"
|
797
|
+
" https://huggingface.co/runwayml/stable-diffusion-inpainting. Note that we do not actively maintain"
|
798
|
+
" the {StableDiffusionInpaintPipelineLegacy} class and will likely remove it in version 1.0.0."
|
799
|
+
)
|
800
|
+
deprecate("StableDiffusionInpaintPipelineLegacy", "1.0.0", deprecation_message, standard_warn=False)
|
801
|
+
|
802
|
+
|
803
|
+
def _update_init_kwargs_with_connected_pipeline(
|
804
|
+
init_kwargs: dict, passed_pipe_kwargs: dict, passed_class_objs: dict, folder: str, **pipeline_loading_kwargs
|
805
|
+
) -> dict:
|
806
|
+
from .pipeline_utils import DiffusionPipeline
|
807
|
+
|
808
|
+
modelcard = ModelCard.load(os.path.join(folder, "README.md"))
|
809
|
+
connected_pipes = {prefix: getattr(modelcard.data, prefix, [None])[0] for prefix in CONNECTED_PIPES_KEYS}
|
810
|
+
|
811
|
+
# We don't scheduler argument to match the existing logic:
|
812
|
+
# https://github.com/huggingface/diffusers/blob/867e0c919e1aa7ef8b03c8eb1460f4f875a683ae/src/diffusers/pipelines/pipeline_utils.py#L906C13-L925C14
|
813
|
+
pipeline_loading_kwargs_cp = pipeline_loading_kwargs.copy()
|
814
|
+
if pipeline_loading_kwargs_cp is not None and len(pipeline_loading_kwargs_cp) >= 1:
|
815
|
+
for k in pipeline_loading_kwargs:
|
816
|
+
if "scheduler" in k:
|
817
|
+
_ = pipeline_loading_kwargs_cp.pop(k)
|
818
|
+
|
819
|
+
def get_connected_passed_kwargs(prefix):
|
820
|
+
connected_passed_class_obj = {
|
821
|
+
k.replace(f"{prefix}_", ""): w for k, w in passed_class_objs.items() if k.split("_")[0] == prefix
|
822
|
+
}
|
823
|
+
connected_passed_pipe_kwargs = {
|
824
|
+
k.replace(f"{prefix}_", ""): w for k, w in passed_pipe_kwargs.items() if k.split("_")[0] == prefix
|
825
|
+
}
|
826
|
+
|
827
|
+
connected_passed_kwargs = {**connected_passed_class_obj, **connected_passed_pipe_kwargs}
|
828
|
+
return connected_passed_kwargs
|
829
|
+
|
830
|
+
connected_pipes = {
|
831
|
+
prefix: DiffusionPipeline.from_pretrained(
|
832
|
+
repo_id, **pipeline_loading_kwargs_cp, **get_connected_passed_kwargs(prefix)
|
833
|
+
)
|
834
|
+
for prefix, repo_id in connected_pipes.items()
|
835
|
+
if repo_id is not None
|
836
|
+
}
|
837
|
+
|
838
|
+
for prefix, connected_pipe in connected_pipes.items():
|
839
|
+
# add connected pipes to `init_kwargs` with <prefix>_<component_name>, e.g. "prior_text_encoder"
|
840
|
+
init_kwargs.update(
|
841
|
+
{"_".join([prefix, name]): component for name, component in connected_pipe.components.items()}
|
842
|
+
)
|
843
|
+
|
844
|
+
return init_kwargs
|
845
|
+
|
846
|
+
|
847
|
+
def _get_custom_components_and_folders(
|
848
|
+
pretrained_model_name: str,
|
849
|
+
config_dict: Dict[str, Any],
|
850
|
+
filenames: Optional[List[str]] = None,
|
851
|
+
variant_filenames: Optional[List[str]] = None,
|
852
|
+
variant: Optional[str] = None,
|
853
|
+
):
|
854
|
+
config_dict = config_dict.copy()
|
855
|
+
|
856
|
+
# retrieve all folder_names that contain relevant files
|
857
|
+
folder_names = [k for k, v in config_dict.items() if isinstance(v, list) and k != "_class_name"]
|
858
|
+
|
859
|
+
diffusers_module = importlib.import_module(__name__.split(".")[0])
|
860
|
+
pipelines = getattr(diffusers_module, "pipelines")
|
861
|
+
|
862
|
+
# optionally create a custom component <> custom file mapping
|
863
|
+
custom_components = {}
|
864
|
+
for component in folder_names:
|
865
|
+
module_candidate = config_dict[component][0]
|
866
|
+
|
867
|
+
if module_candidate is None or not isinstance(module_candidate, str):
|
868
|
+
continue
|
869
|
+
|
870
|
+
# We compute candidate file path on the Hub. Do not use `os.path.join`.
|
871
|
+
candidate_file = f"{component}/{module_candidate}.py"
|
872
|
+
|
873
|
+
if candidate_file in filenames:
|
874
|
+
custom_components[component] = module_candidate
|
875
|
+
elif module_candidate not in LOADABLE_CLASSES and not hasattr(pipelines, module_candidate):
|
876
|
+
raise ValueError(
|
877
|
+
f"{candidate_file} as defined in `model_index.json` does not exist in {pretrained_model_name} and is not a module in 'diffusers/pipelines'."
|
878
|
+
)
|
879
|
+
|
880
|
+
if len(variant_filenames) == 0 and variant is not None:
|
881
|
+
error_message = f"You are trying to load the model files of the `variant={variant}`, but no such modeling files are available."
|
882
|
+
raise ValueError(error_message)
|
883
|
+
|
884
|
+
return custom_components, folder_names
|
885
|
+
|
886
|
+
|
887
|
+
def _get_ignore_patterns(
|
888
|
+
passed_components,
|
889
|
+
model_folder_names: List[str],
|
890
|
+
model_filenames: List[str],
|
891
|
+
variant_filenames: List[str],
|
892
|
+
use_safetensors: bool,
|
893
|
+
from_flax: bool,
|
894
|
+
allow_pickle: bool,
|
895
|
+
use_onnx: bool,
|
896
|
+
is_onnx: bool,
|
897
|
+
variant: Optional[str] = None,
|
898
|
+
) -> List[str]:
|
899
|
+
if (
|
900
|
+
use_safetensors
|
901
|
+
and not allow_pickle
|
902
|
+
and not is_safetensors_compatible(
|
903
|
+
model_filenames, passed_components=passed_components, folder_names=model_folder_names
|
904
|
+
)
|
905
|
+
):
|
906
|
+
raise EnvironmentError(
|
907
|
+
f"Could not find the necessary `safetensors` weights in {model_filenames} (variant={variant})"
|
908
|
+
)
|
909
|
+
|
910
|
+
if from_flax:
|
911
|
+
ignore_patterns = ["*.bin", "*.safetensors", "*.onnx", "*.pb"]
|
912
|
+
|
913
|
+
elif use_safetensors and is_safetensors_compatible(
|
914
|
+
model_filenames, passed_components=passed_components, folder_names=model_folder_names
|
915
|
+
):
|
916
|
+
ignore_patterns = ["*.bin", "*.msgpack"]
|
917
|
+
|
918
|
+
use_onnx = use_onnx if use_onnx is not None else is_onnx
|
919
|
+
if not use_onnx:
|
920
|
+
ignore_patterns += ["*.onnx", "*.pb"]
|
921
|
+
|
922
|
+
safetensors_variant_filenames = {f for f in variant_filenames if f.endswith(".safetensors")}
|
923
|
+
safetensors_model_filenames = {f for f in model_filenames if f.endswith(".safetensors")}
|
924
|
+
if len(safetensors_variant_filenames) > 0 and safetensors_model_filenames != safetensors_variant_filenames:
|
925
|
+
logger.warning(
|
926
|
+
f"\nA mixture of {variant} and non-{variant} filenames will be loaded.\nLoaded {variant} filenames:\n"
|
927
|
+
f"[{', '.join(safetensors_variant_filenames)}]\nLoaded non-{variant} filenames:\n"
|
928
|
+
f"[{', '.join(safetensors_model_filenames - safetensors_variant_filenames)}\nIf this behavior is not "
|
929
|
+
f"expected, please check your folder structure."
|
930
|
+
)
|
931
|
+
|
932
|
+
else:
|
933
|
+
ignore_patterns = ["*.safetensors", "*.msgpack"]
|
934
|
+
|
935
|
+
use_onnx = use_onnx if use_onnx is not None else is_onnx
|
936
|
+
if not use_onnx:
|
937
|
+
ignore_patterns += ["*.onnx", "*.pb"]
|
938
|
+
|
939
|
+
bin_variant_filenames = {f for f in variant_filenames if f.endswith(".bin")}
|
940
|
+
bin_model_filenames = {f for f in model_filenames if f.endswith(".bin")}
|
941
|
+
if len(bin_variant_filenames) > 0 and bin_model_filenames != bin_variant_filenames:
|
942
|
+
logger.warning(
|
943
|
+
f"\nA mixture of {variant} and non-{variant} filenames will be loaded.\nLoaded {variant} filenames:\n"
|
944
|
+
f"[{', '.join(bin_variant_filenames)}]\nLoaded non-{variant} filenames:\n"
|
945
|
+
f"[{', '.join(bin_model_filenames - bin_variant_filenames)}\nIf this behavior is not expected, please check "
|
946
|
+
f"your folder structure."
|
947
|
+
)
|
948
|
+
|
949
|
+
return ignore_patterns
|