diffusers/community-pipelines-mirror
Community Pipeline Examples For more information about community pipelines, please have a look at this issue. Community pipeline examples consist pipelines that have been added by the community. Please have a look at the following tables to get an overview of all community examples. Click on the Code Example to get a copy-and-paste ready code example that you can try out. If a community pipeline doesn't work as expected, please open an issue and ping the author on it. Please… See the full description on the dataset page: https://huggingface.co/datasets/diffusers/community-pipelines-mirror.
922k
1# Copyright 2025 The HuggingFace Team. All rights reserved.2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7# http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14 15import inspect16from typing import Any, Callable, Dict, List, Optional, Union17 18import intel_extension_for_pytorch as ipex19import torch20from packaging import version21from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer22 23from diffusers.configuration_utils import FrozenDict24from diffusers.loaders import StableDiffusionLoraLoaderMixin, TextualInversionLoaderMixin25from diffusers.models import AutoencoderKL, UNet2DConditionModel26from diffusers.pipelines.pipeline_utils import DiffusionPipeline, StableDiffusionMixin27from diffusers.pipelines.stable_diffusion import StableDiffusionPipelineOutput28from diffusers.pipelines.stable_diffusion.safety_checker import StableDiffusionSafetyChecker29from diffusers.schedulers import KarrasDiffusionSchedulers30from diffusers.utils import (31 deprecate,32 logging,33 replace_example_docstring,34)35from diffusers.utils.torch_utils import randn_tensor36 37 38logger = logging.get_logger(__name__) # pylint: disable=invalid-name39 40EXAMPLE_DOC_STRING = """41 Examples:42 ```py43 >>> import torch44 >>> from diffusers import StableDiffusionPipeline45 46 >>> pipe = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", custom_pipeline="stable_diffusion_ipex")47 48 >>> # For Float3249 >>> pipe.prepare_for_ipex(prompt, dtype=torch.float32, height=512, width=512) #value of image height/width should be consistent with the pipeline inference50 >>> # For BFloat1651 >>> pipe.prepare_for_ipex(prompt, dtype=torch.bfloat16, height=512, width=512) #value of image height/width should be consistent with the pipeline inference52 53 >>> prompt = "a photo of an astronaut riding a horse on mars"54 >>> # For Float3255 >>> image = pipe(prompt, num_inference_steps=num_inference_steps, height=512, width=512).images[0] #value of image height/width should be consistent with 'prepare_for_ipex()'56 >>> # For BFloat1657 >>> with torch.cpu.amp.autocast(enabled=True, dtype=torch.bfloat16):58 >>> image = pipe(prompt, num_inference_steps=num_inference_steps, height=512, width=512).images[0] #value of image height/width should be consistent with 'prepare_for_ipex()'59 ```60"""61 62 63class StableDiffusionIPEXPipeline(64 DiffusionPipeline, StableDiffusionMixin, TextualInversionLoaderMixin, StableDiffusionLoraLoaderMixin65):66 r"""67 Pipeline for text-to-image generation using Stable Diffusion on IPEX.68 69 This model inherits from [`DiffusionPipeline`]. Check the superclass documentation for the generic methods the70 library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)71 72 Args:73 vae ([`AutoencoderKL`]):74 Variational Auto-Encoder (VAE) Model to encode and decode images to and from latent representations.75 text_encoder ([`CLIPTextModel`]):76 Frozen text-encoder. Stable Diffusion uses the text portion of77 [CLIP](https://huggingface.co/docs/transformers/model_doc/clip#transformers.CLIPTextModel), specifically78 the [clip-vit-large-patch14](https://huggingface.co/openai/clip-vit-large-patch14) variant.79 tokenizer (`CLIPTokenizer`):80 Tokenizer of class81 [CLIPTokenizer](https://huggingface.co/docs/transformers/v4.21.0/en/model_doc/clip#transformers.CLIPTokenizer).82 unet ([`UNet2DConditionModel`]): Conditional U-Net architecture to denoise the encoded image latents.83 scheduler ([`SchedulerMixin`]):84 A scheduler to be used in combination with `unet` to denoise the encoded image latents. Can be one of85 [`DDIMScheduler`], [`LMSDiscreteScheduler`], or [`PNDMScheduler`].86 safety_checker ([`StableDiffusionSafetyChecker`]):87 Classification module that estimates whether generated images could be considered offensive or harmful.88 Please, refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for details.89 feature_extractor ([`CLIPImageProcessor`]):90 Model that extracts features from generated images to be used as inputs for the `safety_checker`.91 """92 93 _optional_components = ["safety_checker", "feature_extractor"]94 95 def __init__(96 self,97 vae: AutoencoderKL,98 text_encoder: CLIPTextModel,99 tokenizer: CLIPTokenizer,100 unet: UNet2DConditionModel,101 scheduler: KarrasDiffusionSchedulers,102 safety_checker: StableDiffusionSafetyChecker,103 feature_extractor: CLIPImageProcessor,104 requires_safety_checker: bool = True,105 ):106 super().__init__()107 108 if scheduler is not None and getattr(scheduler.config, "steps_offset", 1) != 1:109 deprecation_message = (110 f"The configuration file of this scheduler: {scheduler} is outdated. `steps_offset`"111 f" should be set to 1 instead of {scheduler.config.steps_offset}. Please make sure "112 "to update the config accordingly as leaving `steps_offset` might led to incorrect results"113 " in future versions. If you have downloaded this checkpoint from the Hugging Face Hub,"114 " it would be very nice if you could open a Pull request for the `scheduler/scheduler_config.json`"115 " file"116 )117 deprecate("steps_offset!=1", "1.0.0", deprecation_message, standard_warn=False)118 new_config = dict(scheduler.config)119 new_config["steps_offset"] = 1120 scheduler._internal_dict = FrozenDict(new_config)121 122 if scheduler is not None and getattr(scheduler.config, "clip_sample", False) is True:123 deprecation_message = (124 f"The configuration file of this scheduler: {scheduler} has not set the configuration `clip_sample`."125 " `clip_sample` should be set to False in the configuration file. Please make sure to update the"126 " config accordingly as not setting `clip_sample` in the config might lead to incorrect results in"127 " future versions. If you have downloaded this checkpoint from the Hugging Face Hub, it would be very"128 " nice if you could open a Pull request for the `scheduler/scheduler_config.json` file"129 )130 deprecate("clip_sample not set", "1.0.0", deprecation_message, standard_warn=False)131 new_config = dict(scheduler.config)132 new_config["clip_sample"] = False133 scheduler._internal_dict = FrozenDict(new_config)134 135 if safety_checker is None and requires_safety_checker:136 logger.warning(137 f"You have disabled the safety checker for {self.__class__} by passing `safety_checker=None`. Ensure"138 " that you abide to the conditions of the Stable Diffusion license and do not expose unfiltered"139 " results in services or applications open to the public. Both the diffusers team and Hugging Face"140 " strongly recommend to keep the safety filter enabled in all public facing circumstances, disabling"141 " it only for use-cases that involve analyzing network behavior or auditing its results. For more"142 " information, please have a look at https://github.com/huggingface/diffusers/pull/254 ."143 )144 145 if safety_checker is not None and feature_extractor is None:146 raise ValueError(147 "Make sure to define a feature extractor when loading {self.__class__} if you want to use the safety"148 " checker. If you do not want to use the safety checker, you can pass `'safety_checker=None'` instead."149 )150 151 is_unet_version_less_0_9_0 = (152 unet is not None153 and hasattr(unet.config, "_diffusers_version")154 and version.parse(version.parse(unet.config._diffusers_version).base_version) < version.parse("0.9.0.dev0")155 )156 is_unet_sample_size_less_64 = (157 unet is not None and hasattr(unet.config, "sample_size") and unet.config.sample_size < 64158 )159 if is_unet_version_less_0_9_0 and is_unet_sample_size_less_64:160 deprecation_message = (161 "The configuration file of the unet has set the default `sample_size` to smaller than"162 " 64 which seems highly unlikely. If your checkpoint is a fine-tuned version of any of the"163 " following: \n- CompVis/stable-diffusion-v1-4 \n- CompVis/stable-diffusion-v1-3 \n-"164 " CompVis/stable-diffusion-v1-2 \n- CompVis/stable-diffusion-v1-1 \n- runwayml/stable-diffusion-v1-5"165 " \n- runwayml/stable-diffusion-inpainting \n you should change 'sample_size' to 64 in the"166 " configuration file. Please make sure to update the config accordingly as leaving `sample_size=32`"167 " in the config might lead to incorrect results in future versions. If you have downloaded this"168 " checkpoint from the Hugging Face Hub, it would be very nice if you could open a Pull request for"169 " the `unet/config.json` file"170 )171 deprecate("sample_size<64", "1.0.0", deprecation_message, standard_warn=False)172 new_config = dict(unet.config)173 new_config["sample_size"] = 64174 unet._internal_dict = FrozenDict(new_config)175 176 self.register_modules(177 vae=vae,178 text_encoder=text_encoder,179 tokenizer=tokenizer,180 unet=unet,181 scheduler=scheduler,182 safety_checker=safety_checker,183 feature_extractor=feature_extractor,184 )185 self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1) if getattr(self, "vae", None) else 8186 self.register_to_config(requires_safety_checker=requires_safety_checker)187 188 def get_input_example(self, prompt, height=None, width=None, guidance_scale=7.5, num_images_per_prompt=1):189 prompt_embeds = None190 negative_prompt_embeds = None191 negative_prompt = None192 callback_steps = 1193 generator = None194 latents = None195 196 # 0. Default height and width to unet197 height = height or self.unet.config.sample_size * self.vae_scale_factor198 width = width or self.unet.config.sample_size * self.vae_scale_factor199 200 # 1. Check inputs. Raise error if not correct201 self.check_inputs(202 prompt, height, width, callback_steps, negative_prompt, prompt_embeds, negative_prompt_embeds203 )204 205 # 2. Define call parameters206 if prompt is not None and isinstance(prompt, str):207 batch_size = 1208 elif prompt is not None and isinstance(prompt, list):209 batch_size = len(prompt)210 211 device = "cpu"212 # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)213 # of the Imagen paper: https://huggingface.co/papers/2205.11487 . `guidance_scale = 1`214 # corresponds to doing no classifier free guidance.215 do_classifier_free_guidance = guidance_scale > 1.0216 217 # 3. Encode input prompt218 prompt_embeds = self._encode_prompt(219 prompt,220 device,221 num_images_per_prompt,222 do_classifier_free_guidance,223 negative_prompt,224 prompt_embeds=prompt_embeds,225 negative_prompt_embeds=negative_prompt_embeds,226 )227 228 # 5. Prepare latent variables229 latents = self.prepare_latents(230 batch_size * num_images_per_prompt,231 self.unet.config.in_channels,232 height,233 width,234 prompt_embeds.dtype,235 device,236 generator,237 latents,238 )239 dummy = torch.ones(1, dtype=torch.int32)240 latent_model_input = torch.cat([latents] * 2) if do_classifier_free_guidance else latents241 latent_model_input = self.scheduler.scale_model_input(latent_model_input, dummy)242 243 unet_input_example = (latent_model_input, dummy, prompt_embeds)244 vae_decoder_input_example = latents245 246 return unet_input_example, vae_decoder_input_example247 248 def prepare_for_ipex(self, promt, dtype=torch.float32, height=None, width=None, guidance_scale=7.5):249 self.unet = self.unet.to(memory_format=torch.channels_last)250 self.vae.decoder = self.vae.decoder.to(memory_format=torch.channels_last)251 self.text_encoder = self.text_encoder.to(memory_format=torch.channels_last)252 if self.safety_checker is not None:253 self.safety_checker = self.safety_checker.to(memory_format=torch.channels_last)254 255 unet_input_example, vae_decoder_input_example = self.get_input_example(promt, height, width, guidance_scale)256 257 # optimize with ipex258 if dtype == torch.bfloat16:259 self.unet = ipex.optimize(self.unet.eval(), dtype=torch.bfloat16, inplace=True)260 self.vae.decoder = ipex.optimize(self.vae.decoder.eval(), dtype=torch.bfloat16, inplace=True)261 self.text_encoder = ipex.optimize(self.text_encoder.eval(), dtype=torch.bfloat16, inplace=True)262 if self.safety_checker is not None:263 self.safety_checker = ipex.optimize(self.safety_checker.eval(), dtype=torch.bfloat16, inplace=True)264 elif dtype == torch.float32:265 self.unet = ipex.optimize(266 self.unet.eval(),267 dtype=torch.float32,268 inplace=True,269 weights_prepack=True,270 auto_kernel_selection=False,271 )272 self.vae.decoder = ipex.optimize(273 self.vae.decoder.eval(),274 dtype=torch.float32,275 inplace=True,276 weights_prepack=True,277 auto_kernel_selection=False,278 )279 self.text_encoder = ipex.optimize(280 self.text_encoder.eval(),281 dtype=torch.float32,282 inplace=True,283 weights_prepack=True,284 auto_kernel_selection=False,285 )286 if self.safety_checker is not None:287 self.safety_checker = ipex.optimize(288 self.safety_checker.eval(),289 dtype=torch.float32,290 inplace=True,291 weights_prepack=True,292 auto_kernel_selection=False,293 )294 else:295 raise ValueError(" The value of 'dtype' should be 'torch.bfloat16' or 'torch.float32' !")296 297 # trace unet model to get better performance on IPEX298 with torch.cpu.amp.autocast(enabled=dtype == torch.bfloat16), torch.no_grad():299 unet_trace_model = torch.jit.trace(self.unet, unet_input_example, check_trace=False, strict=False)300 unet_trace_model = torch.jit.freeze(unet_trace_model)301 self.unet.forward = unet_trace_model.forward302 303 # trace vae.decoder model to get better performance on IPEX304 with torch.cpu.amp.autocast(enabled=dtype == torch.bfloat16), torch.no_grad():305 ave_decoder_trace_model = torch.jit.trace(306 self.vae.decoder, vae_decoder_input_example, check_trace=False, strict=False307 )308 ave_decoder_trace_model = torch.jit.freeze(ave_decoder_trace_model)309 self.vae.decoder.forward = ave_decoder_trace_model.forward310 311 def _encode_prompt(312 self,313 prompt,314 device,315 num_images_per_prompt,316 do_classifier_free_guidance,317 negative_prompt=None,318 prompt_embeds: Optional[torch.Tensor] = None,319 negative_prompt_embeds: Optional[torch.Tensor] = None,320 ):321 r"""322 Encodes the prompt into text encoder hidden states.323 324 Args:325 prompt (`str` or `List[str]`, *optional*):326 prompt to be encoded327 device: (`torch.device`):328 torch device329 num_images_per_prompt (`int`):330 number of images that should be generated per prompt331 do_classifier_free_guidance (`bool`):332 whether to use classifier free guidance or not333 negative_prompt (`str` or `List[str]`, *optional*):334 The prompt or prompts not to guide the image generation. If not defined, one has to pass335 `negative_prompt_embeds`. instead. If not defined, one has to pass `negative_prompt_embeds`. instead.336 Ignored when not using guidance (i.e., ignored if `guidance_scale` is less than `1`).337 prompt_embeds (`torch.Tensor`, *optional*):338 Pre-generated text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt weighting. If not339 provided, text embeddings will be generated from `prompt` input argument.340 negative_prompt_embeds (`torch.Tensor`, *optional*):341 Pre-generated negative text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt342 weighting. If not provided, negative_prompt_embeds will be generated from `negative_prompt` input343 argument.344 """345 if prompt is not None and isinstance(prompt, str):346 batch_size = 1347 elif prompt is not None and isinstance(prompt, list):348 batch_size = len(prompt)349 else:350 batch_size = prompt_embeds.shape[0]351 352 if prompt_embeds is None:353 # textual inversion: process multi-vector tokens if necessary354 if isinstance(self, TextualInversionLoaderMixin):355 prompt = self.maybe_convert_prompt(prompt, self.tokenizer)356 357 text_inputs = self.tokenizer(358 prompt,359 padding="max_length",360 max_length=self.tokenizer.model_max_length,361 truncation=True,362 return_tensors="pt",363 )364 text_input_ids = text_inputs.input_ids365 untruncated_ids = self.tokenizer(prompt, padding="longest", return_tensors="pt").input_ids366 367 if untruncated_ids.shape[-1] >= text_input_ids.shape[-1] and not torch.equal(368 text_input_ids, untruncated_ids369 ):370 removed_text = self.tokenizer.batch_decode(371 untruncated_ids[:, self.tokenizer.model_max_length - 1 : -1]372 )373 logger.warning(374 "The following part of your input was truncated because CLIP can only handle sequences up to"375 f" {self.tokenizer.model_max_length} tokens: {removed_text}"376 )377 378 if hasattr(self.text_encoder.config, "use_attention_mask") and self.text_encoder.config.use_attention_mask:379 attention_mask = text_inputs.attention_mask.to(device)380 else:381 attention_mask = None382 383 prompt_embeds = self.text_encoder(384 text_input_ids.to(device),385 attention_mask=attention_mask,386 )387 prompt_embeds = prompt_embeds[0]388 389 prompt_embeds = prompt_embeds.to(dtype=self.text_encoder.dtype, device=device)390 391 bs_embed, seq_len, _ = prompt_embeds.shape392 # duplicate text embeddings for each generation per prompt, using mps friendly method393 prompt_embeds = prompt_embeds.repeat(1, num_images_per_prompt, 1)394 prompt_embeds = prompt_embeds.view(bs_embed * num_images_per_prompt, seq_len, -1)395 396 # get unconditional embeddings for classifier free guidance397 if do_classifier_free_guidance and negative_prompt_embeds is None:398 uncond_tokens: List[str]399 if negative_prompt is None:400 uncond_tokens = [""] * batch_size401 elif type(prompt) is not type(negative_prompt):402 raise TypeError(403 f"`negative_prompt` should be the same type to `prompt`, but got {type(negative_prompt)} !="404 f" {type(prompt)}."405 )406 elif isinstance(negative_prompt, str):407 uncond_tokens = [negative_prompt]408 elif batch_size != len(negative_prompt):409 raise ValueError(410 f"`negative_prompt`: {negative_prompt} has batch size {len(negative_prompt)}, but `prompt`:"411 f" {prompt} has batch size {batch_size}. Please make sure that passed `negative_prompt` matches"412 " the batch size of `prompt`."413 )414 else:415 uncond_tokens = negative_prompt416 417 # textual inversion: process multi-vector tokens if necessary418 if isinstance(self, TextualInversionLoaderMixin):419 uncond_tokens = self.maybe_convert_prompt(uncond_tokens, self.tokenizer)420 421 max_length = prompt_embeds.shape[1]422 uncond_input = self.tokenizer(423 uncond_tokens,424 padding="max_length",425 max_length=max_length,426 truncation=True,427 return_tensors="pt",428 )429 430 if hasattr(self.text_encoder.config, "use_attention_mask") and self.text_encoder.config.use_attention_mask:431 attention_mask = uncond_input.attention_mask.to(device)432 else:433 attention_mask = None434 435 negative_prompt_embeds = self.text_encoder(436 uncond_input.input_ids.to(device),437 attention_mask=attention_mask,438 )439 negative_prompt_embeds = negative_prompt_embeds[0]440 441 if do_classifier_free_guidance:442 # duplicate unconditional embeddings for each generation per prompt, using mps friendly method443 seq_len = negative_prompt_embeds.shape[1]444 445 negative_prompt_embeds = negative_prompt_embeds.to(dtype=self.text_encoder.dtype, device=device)446 447 negative_prompt_embeds = negative_prompt_embeds.repeat(1, num_images_per_prompt, 1)448 negative_prompt_embeds = negative_prompt_embeds.view(batch_size * num_images_per_prompt, seq_len, -1)449 450 # For classifier free guidance, we need to do two forward passes.451 # Here we concatenate the unconditional and text embeddings into a single batch452 # to avoid doing two forward passes453 prompt_embeds = torch.cat([negative_prompt_embeds, prompt_embeds])454 455 return prompt_embeds456 457 def run_safety_checker(self, image, device, dtype):458 if self.safety_checker is not None:459 safety_checker_input = self.feature_extractor(self.numpy_to_pil(image), return_tensors="pt").to(device)460 image, has_nsfw_concept = self.safety_checker(461 images=image, clip_input=safety_checker_input.pixel_values.to(dtype)462 )463 else:464 has_nsfw_concept = None465 return image, has_nsfw_concept466 467 def decode_latents(self, latents):468 latents = 1 / self.vae.config.scaling_factor * latents469 image = self.vae.decode(latents).sample470 image = (image / 2 + 0.5).clamp(0, 1)471 # we always cast to float32 as this does not cause significant overhead and is compatible with bfloat16472 image = image.cpu().permute(0, 2, 3, 1).float().numpy()473 return image474 475 def prepare_extra_step_kwargs(self, generator, eta):476 # prepare extra kwargs for the scheduler step, since not all schedulers have the same signature477 # eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers.478 # eta corresponds to η in DDIM paper: https://huggingface.co/papers/2010.02502479 # and should be between [0, 1]480 481 accepts_eta = "eta" in set(inspect.signature(self.scheduler.step).parameters.keys())482 extra_step_kwargs = {}483 if accepts_eta:484 extra_step_kwargs["eta"] = eta485 486 # check if the scheduler accepts generator487 accepts_generator = "generator" in set(inspect.signature(self.scheduler.step).parameters.keys())488 if accepts_generator:489 extra_step_kwargs["generator"] = generator490 return extra_step_kwargs491 492 def check_inputs(493 self,494 prompt,495 height,496 width,497 callback_steps,498 negative_prompt=None,499 prompt_embeds=None,500 negative_prompt_embeds=None,501 ):502 if height % 8 != 0 or width % 8 != 0:503 raise ValueError(f"`height` and `width` have to be divisible by 8 but are {height} and {width}.")504 505 if (callback_steps is None) or (506 callback_steps is not None and (not isinstance(callback_steps, int) or callback_steps <= 0)507 ):508 raise ValueError(509 f"`callback_steps` has to be a positive integer but is {callback_steps} of type"510 f" {type(callback_steps)}."511 )512 513 if prompt is not None and prompt_embeds is not None:514 raise ValueError(515 f"Cannot forward both `prompt`: {prompt} and `prompt_embeds`: {prompt_embeds}. Please make sure to"516 " only forward one of the two."517 )518 elif prompt is None and prompt_embeds is None:519 raise ValueError(520 "Provide either `prompt` or `prompt_embeds`. Cannot leave both `prompt` and `prompt_embeds` undefined."521 )522 elif prompt is not None and (not isinstance(prompt, str) and not isinstance(prompt, list)):523 raise ValueError(f"`prompt` has to be of type `str` or `list` but is {type(prompt)}")524 525 if negative_prompt is not None and negative_prompt_embeds is not None:526 raise ValueError(527 f"Cannot forward both `negative_prompt`: {negative_prompt} and `negative_prompt_embeds`:"528 f" {negative_prompt_embeds}. Please make sure to only forward one of the two."529 )530 531 if prompt_embeds is not None and negative_prompt_embeds is not None:532 if prompt_embeds.shape != negative_prompt_embeds.shape:533 raise ValueError(534 "`prompt_embeds` and `negative_prompt_embeds` must have the same shape when passed directly, but"535 f" got: `prompt_embeds` {prompt_embeds.shape} != `negative_prompt_embeds`"536 f" {negative_prompt_embeds.shape}."537 )538 539 def prepare_latents(self, batch_size, num_channels_latents, height, width, dtype, device, generator, latents=None):540 shape = (541 batch_size,542 num_channels_latents,543 int(height) // self.vae_scale_factor,544 int(width) // self.vae_scale_factor,545 )546 if isinstance(generator, list) and len(generator) != batch_size:547 raise ValueError(548 f"You have passed a list of generators of length {len(generator)}, but requested an effective batch"549 f" size of {batch_size}. Make sure the batch size matches the length of the generators."550 )551 552 if latents is None:553 latents = randn_tensor(shape, generator=generator, device=device, dtype=dtype)554 else:555 latents = latents.to(device)556 557 # scale the initial noise by the standard deviation required by the scheduler558 latents = latents * self.scheduler.init_noise_sigma559 return latents560 561 @torch.no_grad()562 @replace_example_docstring(EXAMPLE_DOC_STRING)563 def __call__(564 self,565 prompt: Union[str, List[str]] = None,566 height: Optional[int] = None,567 width: Optional[int] = None,568 num_inference_steps: int = 50,569 guidance_scale: float = 7.5,570 negative_prompt: Optional[Union[str, List[str]]] = None,571 num_images_per_prompt: Optional[int] = 1,572 eta: float = 0.0,573 generator: Optional[Union[torch.Generator, List[torch.Generator]]] = None,574 latents: Optional[torch.Tensor] = None,575 prompt_embeds: Optional[torch.Tensor] = None,576 negative_prompt_embeds: Optional[torch.Tensor] = None,577 output_type: Optional[str] = "pil",578 return_dict: bool = True,579 callback: Optional[Callable[[int, int, torch.Tensor], None]] = None,580 callback_steps: int = 1,581 cross_attention_kwargs: Optional[Dict[str, Any]] = None,582 ):583 r"""584 Function invoked when calling the pipeline for generation.585 586 Args:587 prompt (`str` or `List[str]`, *optional*):588 The prompt or prompts to guide the image generation. If not defined, one has to pass `prompt_embeds`.589 instead.590 height (`int`, *optional*, defaults to self.unet.config.sample_size * self.vae_scale_factor):591 The height in pixels of the generated image.592 width (`int`, *optional*, defaults to self.unet.config.sample_size * self.vae_scale_factor):593 The width in pixels of the generated image.594 num_inference_steps (`int`, *optional*, defaults to 50):595 The number of denoising steps. More denoising steps usually lead to a higher quality image at the596 expense of slower inference.597 guidance_scale (`float`, *optional*, defaults to 7.5):598 Guidance scale as defined in [Classifier-Free Diffusion Guidance](https://huggingface.co/papers/2207.12598).599 `guidance_scale` is defined as `w` of equation 2. of [Imagen600 Paper](https://huggingface.co/papers/2205.11487). Guidance scale is enabled by setting `guidance_scale >601 1`. Higher guidance scale encourages to generate images that are closely linked to the text `prompt`,602 usually at the expense of lower image quality.603 negative_prompt (`str` or `List[str]`, *optional*):604 The prompt or prompts not to guide the image generation. If not defined, one has to pass605 `negative_prompt_embeds`. instead. If not defined, one has to pass `negative_prompt_embeds`. instead.606 Ignored when not using guidance (i.e., ignored if `guidance_scale` is less than `1`).607 num_images_per_prompt (`int`, *optional*, defaults to 1):608 The number of images to generate per prompt.609 eta (`float`, *optional*, defaults to 0.0):610 Corresponds to parameter eta (η) in the DDIM paper: https://huggingface.co/papers/2010.02502. Only applies to611 [`schedulers.DDIMScheduler`], will be ignored for others.612 generator (`torch.Generator` or `List[torch.Generator]`, *optional*):613 One or a list of [torch generator(s)](https://pytorch.org/docs/stable/generated/torch.Generator.html)614 to make generation deterministic.615 latents (`torch.Tensor`, *optional*):616 Pre-generated noisy latents, sampled from a Gaussian distribution, to be used as inputs for image617 generation. Can be used to tweak the same generation with different prompts. If not provided, a latents618 tensor will ge generated by sampling using the supplied random `generator`.619 prompt_embeds (`torch.Tensor`, *optional*):620 Pre-generated text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt weighting. If not621 provided, text embeddings will be generated from `prompt` input argument.622 negative_prompt_embeds (`torch.Tensor`, *optional*):623 Pre-generated negative text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt624 weighting. If not provided, negative_prompt_embeds will be generated from `negative_prompt` input625 argument.626 output_type (`str`, *optional*, defaults to `"pil"`):627 The output format of the generate image. Choose between628 [PIL](https://pillow.readthedocs.io/en/stable/): `PIL.Image.Image` or `np.array`.629 return_dict (`bool`, *optional*, defaults to `True`):630 Whether or not to return a [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] instead of a631 plain tuple.632 callback (`Callable`, *optional*):633 A function that will be called every `callback_steps` steps during inference. The function will be634 called with the following arguments: `callback(step: int, timestep: int, latents: torch.Tensor)`.635 callback_steps (`int`, *optional*, defaults to 1):636 The frequency at which the `callback` function will be called. If not specified, the callback will be637 called at every step.638 cross_attention_kwargs (`dict`, *optional*):639 A kwargs dictionary that if specified is passed along to the `AttnProcessor` as defined under640 `self.processor` in641 [diffusers.models.attention_processor](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention_processor.py).642 643 Examples:644 645 Returns:646 [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] or `tuple`:647 [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] if `return_dict` is True, otherwise a `tuple.648 When returning a tuple, the first element is a list with the generated images, and the second element is a649 list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work"650 (nsfw) content, according to the `safety_checker`.651 """652 # 0. Default height and width to unet653 height = height or self.unet.config.sample_size * self.vae_scale_factor654 width = width or self.unet.config.sample_size * self.vae_scale_factor655 656 # 1. Check inputs. Raise error if not correct657 self.check_inputs(658 prompt, height, width, callback_steps, negative_prompt, prompt_embeds, negative_prompt_embeds659 )660 661 # 2. Define call parameters662 if prompt is not None and isinstance(prompt, str):663 batch_size = 1664 elif prompt is not None and isinstance(prompt, list):665 batch_size = len(prompt)666 else:667 batch_size = prompt_embeds.shape[0]668 669 device = self._execution_device670 # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)671 # of the Imagen paper: https://huggingface.co/papers/2205.11487 . `guidance_scale = 1`672 # corresponds to doing no classifier free guidance.673 do_classifier_free_guidance = guidance_scale > 1.0674 675 # 3. Encode input prompt676 prompt_embeds = self._encode_prompt(677 prompt,678 device,679 num_images_per_prompt,680 do_classifier_free_guidance,681 negative_prompt,682 prompt_embeds=prompt_embeds,683 negative_prompt_embeds=negative_prompt_embeds,684 )685 686 # 4. Prepare timesteps687 self.scheduler.set_timesteps(num_inference_steps, device=device)688 timesteps = self.scheduler.timesteps689 690 # 5. Prepare latent variables691 num_channels_latents = self.unet.config.in_channels692 latents = self.prepare_latents(693 batch_size * num_images_per_prompt,694 num_channels_latents,695 height,696 width,697 prompt_embeds.dtype,698 device,699 generator,700 latents,701 )702 703 # 6. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline704 extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)705 706 # 7. Denoising loop707 num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order708 with self.progress_bar(total=num_inference_steps) as progress_bar:709 for i, t in enumerate(timesteps):710 # expand the latents if we are doing classifier free guidance711 latent_model_input = torch.cat([latents] * 2) if do_classifier_free_guidance else latents712 latent_model_input = self.scheduler.scale_model_input(latent_model_input, t)713 714 # predict the noise residual715 noise_pred = self.unet(latent_model_input, t, encoder_hidden_states=prompt_embeds)["sample"]716 717 # perform guidance718 if do_classifier_free_guidance:719 noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)720 noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)721 722 # compute the previous noisy sample x_t -> x_t-1723 latents = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs).prev_sample724 725 # call the callback, if provided726 if i == len(timesteps) - 1 or ((i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0):727 progress_bar.update()728 if callback is not None and i % callback_steps == 0:729 step_idx = i // getattr(self.scheduler, "order", 1)730 callback(step_idx, t, latents)731 732 if output_type == "latent":733 image = latents734 has_nsfw_concept = None735 elif output_type == "pil":736 # 8. Post-processing737 image = self.decode_latents(latents)738 739 # 9. Run safety checker740 image, has_nsfw_concept = self.run_safety_checker(image, device, prompt_embeds.dtype)741 742 # 10. Convert to PIL743 image = self.numpy_to_pil(image)744 else:745 # 8. Post-processing746 image = self.decode_latents(latents)747 748 # 9. Run safety checker749 image, has_nsfw_concept = self.run_safety_checker(image, device, prompt_embeds.dtype)750 751 # Offload last model to CPU752 if hasattr(self, "final_offload_hook") and self.final_offload_hook is not None:753 self.final_offload_hook.offload()754 755 if not return_dict:756 return (image, has_nsfw_concept)757 758 return StableDiffusionPipelineOutput(images=image, nsfw_content_detected=has_nsfw_concept)759 