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 Long Lian, the GLIGEN Authors, and 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 15# This is a single file implementation of LMD+. See README.md for examples.16 17import ast18import gc19import inspect20import math21import warnings22from collections.abc import Iterable23from typing import Any, Callable, Dict, List, Optional, Union24 25import torch26import torch.nn.functional as F27from packaging import version28from transformers import CLIPImageProcessor, CLIPTextModel, CLIPTokenizer, CLIPVisionModelWithProjection29 30from diffusers.configuration_utils import FrozenDict31from diffusers.image_processor import PipelineImageInput, VaeImageProcessor32from diffusers.loaders import (33 FromSingleFileMixin,34 IPAdapterMixin,35 StableDiffusionLoraLoaderMixin,36 TextualInversionLoaderMixin,37)38from diffusers.models import AutoencoderKL, UNet2DConditionModel39from diffusers.models.attention import Attention, GatedSelfAttentionDense40from diffusers.models.attention_processor import AttnProcessor2_041from diffusers.models.lora import adjust_lora_scale_text_encoder42from diffusers.pipelines import DiffusionPipeline43from diffusers.pipelines.pipeline_utils import StableDiffusionMixin44from diffusers.pipelines.stable_diffusion.pipeline_output import StableDiffusionPipelineOutput45from diffusers.pipelines.stable_diffusion.safety_checker import StableDiffusionSafetyChecker46from diffusers.schedulers import KarrasDiffusionSchedulers47from diffusers.utils import (48 USE_PEFT_BACKEND,49 deprecate,50 logging,51 replace_example_docstring,52 scale_lora_layers,53 unscale_lora_layers,54)55from diffusers.utils.torch_utils import randn_tensor56 57 58EXAMPLE_DOC_STRING = """59 Examples:60 ```py61 >>> import torch62 >>> from diffusers import DiffusionPipeline63 64 >>> pipe = DiffusionPipeline.from_pretrained(65 ... "longlian/lmd_plus",66 ... custom_pipeline="llm_grounded_diffusion",67 ... custom_revision="main",68 ... variant="fp16", torch_dtype=torch.float1669 ... )70 >>> pipe.enable_model_cpu_offload()71 72 >>> # Generate an image described by the prompt and73 >>> # insert objects described by text at the region defined by bounding boxes74 >>> prompt = "a waterfall and a modern high speed train in a beautiful forest with fall foliage"75 >>> boxes = [[0.1387, 0.2051, 0.4277, 0.7090], [0.4980, 0.4355, 0.8516, 0.7266]]76 >>> phrases = ["a waterfall", "a modern high speed train"]77 78 >>> images = pipe(79 ... prompt=prompt,80 ... phrases=phrases,81 ... boxes=boxes,82 ... gligen_scheduled_sampling_beta=0.4,83 ... output_type="pil",84 ... num_inference_steps=50,85 ... lmd_guidance_kwargs={}86 ... ).images87 88 >>> images[0].save("./lmd_plus_generation.jpg")89 90 >>> # Generate directly from a text prompt and an LLM response91 >>> prompt = "a waterfall and a modern high speed train in a beautiful forest with fall foliage"92 >>> phrases, boxes, bg_prompt, neg_prompt = pipe.parse_llm_response(\"""93 [('a waterfall', [71, 105, 148, 258]), ('a modern high speed train', [255, 223, 181, 149])]94 Background prompt: A beautiful forest with fall foliage95 Negative prompt:96 \""")97 98 >> images = pipe(99 ... prompt=prompt,100 ... negative_prompt=neg_prompt,101 ... phrases=phrases,102 ... boxes=boxes,103 ... gligen_scheduled_sampling_beta=0.4,104 ... output_type="pil",105 ... num_inference_steps=50,106 ... lmd_guidance_kwargs={}107 ... ).images108 109 >>> images[0].save("./lmd_plus_generation.jpg")110 111images[0]112 113 ```114"""115 116logger = logging.get_logger(__name__) # pylint: disable=invalid-name117 118# All keys in Stable Diffusion models: [('down', 0, 0, 0), ('down', 0, 1, 0), ('down', 1, 0, 0), ('down', 1, 1, 0), ('down', 2, 0, 0), ('down', 2, 1, 0), ('mid', 0, 0, 0), ('up', 1, 0, 0), ('up', 1, 1, 0), ('up', 1, 2, 0), ('up', 2, 0, 0), ('up', 2, 1, 0), ('up', 2, 2, 0), ('up', 3, 0, 0), ('up', 3, 1, 0), ('up', 3, 2, 0)]119# Note that the first up block is `UpBlock2D` rather than `CrossAttnUpBlock2D` and does not have attention. The last index is always 0 in our case since we have one `BasicTransformerBlock` in each `Transformer2DModel`.120DEFAULT_GUIDANCE_ATTN_KEYS = [121 ("mid", 0, 0, 0),122 ("up", 1, 0, 0),123 ("up", 1, 1, 0),124 ("up", 1, 2, 0),125]126 127 128def convert_attn_keys(key):129 """Convert the attention key from tuple format to the torch state format"""130 131 if key[0] == "mid":132 assert key[1] == 0, f"mid block only has one block but the index is {key[1]}"133 return f"{key[0]}_block.attentions.{key[2]}.transformer_blocks.{key[3]}.attn2.processor"134 135 return f"{key[0]}_blocks.{key[1]}.attentions.{key[2]}.transformer_blocks.{key[3]}.attn2.processor"136 137 138DEFAULT_GUIDANCE_ATTN_KEYS = [convert_attn_keys(key) for key in DEFAULT_GUIDANCE_ATTN_KEYS]139 140 141def scale_proportion(obj_box, H, W):142 # Separately rounding box_w and box_h to allow shift invariant box sizes. Otherwise box sizes may change when both coordinates being rounded end with ".5".143 x_min, y_min = round(obj_box[0] * W), round(obj_box[1] * H)144 box_w, box_h = round((obj_box[2] - obj_box[0]) * W), round((obj_box[3] - obj_box[1]) * H)145 x_max, y_max = x_min + box_w, y_min + box_h146 147 x_min, y_min = max(x_min, 0), max(y_min, 0)148 x_max, y_max = min(x_max, W), min(y_max, H)149 150 return x_min, y_min, x_max, y_max151 152 153# Adapted from the parent class `AttnProcessor2_0`154class AttnProcessorWithHook(AttnProcessor2_0):155 def __init__(156 self,157 attn_processor_key,158 hidden_size,159 cross_attention_dim,160 hook=None,161 fast_attn=True,162 enabled=True,163 ):164 super().__init__()165 self.attn_processor_key = attn_processor_key166 self.hidden_size = hidden_size167 self.cross_attention_dim = cross_attention_dim168 self.hook = hook169 self.fast_attn = fast_attn170 self.enabled = enabled171 172 def __call__(173 self,174 attn: Attention,175 hidden_states,176 encoder_hidden_states=None,177 attention_mask=None,178 temb=None,179 scale: float = 1.0,180 ):181 residual = hidden_states182 183 if attn.spatial_norm is not None:184 hidden_states = attn.spatial_norm(hidden_states, temb)185 186 input_ndim = hidden_states.ndim187 188 if input_ndim == 4:189 batch_size, channel, height, width = hidden_states.shape190 hidden_states = hidden_states.view(batch_size, channel, height * width).transpose(1, 2)191 192 batch_size, sequence_length, _ = (193 hidden_states.shape if encoder_hidden_states is None else encoder_hidden_states.shape194 )195 196 if attention_mask is not None:197 attention_mask = attn.prepare_attention_mask(attention_mask, sequence_length, batch_size)198 199 if attn.group_norm is not None:200 hidden_states = attn.group_norm(hidden_states.transpose(1, 2)).transpose(1, 2)201 202 args = () if USE_PEFT_BACKEND else (scale,)203 query = attn.to_q(hidden_states, *args)204 205 if encoder_hidden_states is None:206 encoder_hidden_states = hidden_states207 elif attn.norm_cross:208 encoder_hidden_states = attn.norm_encoder_hidden_states(encoder_hidden_states)209 210 key = attn.to_k(encoder_hidden_states, *args)211 value = attn.to_v(encoder_hidden_states, *args)212 213 inner_dim = key.shape[-1]214 head_dim = inner_dim // attn.heads215 216 if (self.hook is not None and self.enabled) or not self.fast_attn:217 query_batch_dim = attn.head_to_batch_dim(query)218 key_batch_dim = attn.head_to_batch_dim(key)219 value_batch_dim = attn.head_to_batch_dim(value)220 attention_probs = attn.get_attention_scores(query_batch_dim, key_batch_dim, attention_mask)221 222 if self.hook is not None and self.enabled:223 # Call the hook with query, key, value, and attention maps224 self.hook(225 self.attn_processor_key,226 query_batch_dim,227 key_batch_dim,228 value_batch_dim,229 attention_probs,230 )231 232 if self.fast_attn:233 query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)234 235 key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)236 value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)237 238 if attention_mask is not None:239 # scaled_dot_product_attention expects attention_mask shape to be240 # (batch, heads, source_length, target_length)241 attention_mask = attention_mask.view(batch_size, attn.heads, -1, attention_mask.shape[-1])242 243 # the output of sdp = (batch, num_heads, seq_len, head_dim)244 # TODO: add support for attn.scale when we move to Torch 2.1245 hidden_states = F.scaled_dot_product_attention(246 query,247 key,248 value,249 attn_mask=attention_mask,250 dropout_p=0.0,251 is_causal=False,252 )253 hidden_states = hidden_states.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim)254 hidden_states = hidden_states.to(query.dtype)255 else:256 hidden_states = torch.bmm(attention_probs, value)257 hidden_states = attn.batch_to_head_dim(hidden_states)258 259 # linear proj260 hidden_states = attn.to_out[0](hidden_states, *args)261 # dropout262 hidden_states = attn.to_out[1](hidden_states)263 264 if input_ndim == 4:265 hidden_states = hidden_states.transpose(-1, -2).reshape(batch_size, channel, height, width)266 267 if attn.residual_connection:268 hidden_states = hidden_states + residual269 270 hidden_states = hidden_states / attn.rescale_output_factor271 272 return hidden_states273 274 275class LLMGroundedDiffusionPipeline(276 DiffusionPipeline,277 StableDiffusionMixin,278 TextualInversionLoaderMixin,279 StableDiffusionLoraLoaderMixin,280 IPAdapterMixin,281 FromSingleFileMixin,282):283 r"""284 Pipeline for layout-grounded text-to-image generation using LLM-grounded Diffusion (LMD+): https://huggingface.co/papers/2305.13655.285 286 This model inherits from [`StableDiffusionPipeline`] and aims at implementing the pipeline with minimal modifications. Check the superclass documentation for the generic methods287 implemented for all pipelines (downloading, saving, running on a particular device, etc.).288 289 This is a simplified implementation that does not perform latent or attention transfer from single object generation to overall generation. The final image is generated directly with attention and adapters control.290 291 Args:292 vae ([`AutoencoderKL`]):293 Variational Auto-Encoder (VAE) model to encode and decode images to and from latent representations.294 text_encoder ([`~transformers.CLIPTextModel`]):295 Frozen text-encoder ([clip-vit-large-patch14](https://huggingface.co/openai/clip-vit-large-patch14)).296 tokenizer ([`~transformers.CLIPTokenizer`]):297 A `CLIPTokenizer` to tokenize text.298 unet ([`UNet2DConditionModel`]):299 A `UNet2DConditionModel` to denoise the encoded image latents.300 scheduler ([`SchedulerMixin`]):301 A scheduler to be used in combination with `unet` to denoise the encoded image latents. Can be one of302 [`DDIMScheduler`], [`LMSDiscreteScheduler`], or [`PNDMScheduler`].303 safety_checker ([`StableDiffusionSafetyChecker`]):304 Classification module that estimates whether generated images could be considered offensive or harmful.305 Please refer to the [model card](https://huggingface.co/runwayml/stable-diffusion-v1-5) for more details306 about a model's potential harms.307 feature_extractor ([`~transformers.CLIPImageProcessor`]):308 A `CLIPImageProcessor` to extract features from generated images; used as inputs to the `safety_checker`.309 requires_safety_checker (bool):310 Whether a safety checker is needed for this pipeline.311 """312 313 model_cpu_offload_seq = "text_encoder->unet->vae"314 _optional_components = ["safety_checker", "feature_extractor", "image_encoder"]315 _exclude_from_cpu_offload = ["safety_checker"]316 _callback_tensor_inputs = ["latents", "prompt_embeds", "negative_prompt_embeds"]317 318 objects_text = "Objects: "319 bg_prompt_text = "Background prompt: "320 bg_prompt_text_no_trailing_space = bg_prompt_text.rstrip()321 neg_prompt_text = "Negative prompt: "322 neg_prompt_text_no_trailing_space = neg_prompt_text.rstrip()323 324 def __init__(325 self,326 vae: AutoencoderKL,327 text_encoder: CLIPTextModel,328 tokenizer: CLIPTokenizer,329 unet: UNet2DConditionModel,330 scheduler: KarrasDiffusionSchedulers,331 safety_checker: StableDiffusionSafetyChecker,332 feature_extractor: CLIPImageProcessor,333 image_encoder: CLIPVisionModelWithProjection = None,334 requires_safety_checker: bool = True,335 ):336 # This is copied from StableDiffusionPipeline, with hook initizations for LMD+.337 super().__init__()338 339 if scheduler is not None and getattr(scheduler.config, "steps_offset", 1) != 1:340 deprecation_message = (341 f"The configuration file of this scheduler: {scheduler} is outdated. `steps_offset`"342 f" should be set to 1 instead of {scheduler.config.steps_offset}. Please make sure "343 "to update the config accordingly as leaving `steps_offset` might led to incorrect results"344 " in future versions. If you have downloaded this checkpoint from the Hugging Face Hub,"345 " it would be very nice if you could open a Pull request for the `scheduler/scheduler_config.json`"346 " file"347 )348 deprecate("steps_offset!=1", "1.0.0", deprecation_message, standard_warn=False)349 new_config = dict(scheduler.config)350 new_config["steps_offset"] = 1351 scheduler._internal_dict = FrozenDict(new_config)352 353 if scheduler is not None and getattr(scheduler.config, "clip_sample", False) is True:354 deprecation_message = (355 f"The configuration file of this scheduler: {scheduler} has not set the configuration `clip_sample`."356 " `clip_sample` should be set to False in the configuration file. Please make sure to update the"357 " config accordingly as not setting `clip_sample` in the config might lead to incorrect results in"358 " future versions. If you have downloaded this checkpoint from the Hugging Face Hub, it would be very"359 " nice if you could open a Pull request for the `scheduler/scheduler_config.json` file"360 )361 deprecate("clip_sample not set", "1.0.0", deprecation_message, standard_warn=False)362 new_config = dict(scheduler.config)363 new_config["clip_sample"] = False364 scheduler._internal_dict = FrozenDict(new_config)365 366 if safety_checker is None and requires_safety_checker:367 logger.warning(368 f"You have disabled the safety checker for {self.__class__} by passing `safety_checker=None`. Ensure"369 " that you abide to the conditions of the Stable Diffusion license and do not expose unfiltered"370 " results in services or applications open to the public. Both the diffusers team and Hugging Face"371 " strongly recommend to keep the safety filter enabled in all public facing circumstances, disabling"372 " it only for use-cases that involve analyzing network behavior or auditing its results. For more"373 " information, please have a look at https://github.com/huggingface/diffusers/pull/254 ."374 )375 376 if safety_checker is not None and feature_extractor is None:377 raise ValueError(378 "Make sure to define a feature extractor when loading {self.__class__} if you want to use the safety"379 " checker. If you do not want to use the safety checker, you can pass `'safety_checker=None'` instead."380 )381 382 is_unet_version_less_0_9_0 = (383 unet is not None384 and hasattr(unet.config, "_diffusers_version")385 and version.parse(version.parse(unet.config._diffusers_version).base_version) < version.parse("0.9.0.dev0")386 )387 is_unet_sample_size_less_64 = (388 unet is not None and hasattr(unet.config, "sample_size") and unet.config.sample_size < 64389 )390 if is_unet_version_less_0_9_0 and is_unet_sample_size_less_64:391 deprecation_message = (392 "The configuration file of the unet has set the default `sample_size` to smaller than"393 " 64 which seems highly unlikely. If your checkpoint is a fine-tuned version of any of the"394 " following: \n- CompVis/stable-diffusion-v1-4 \n- CompVis/stable-diffusion-v1-3 \n-"395 " CompVis/stable-diffusion-v1-2 \n- CompVis/stable-diffusion-v1-1 \n- runwayml/stable-diffusion-v1-5"396 " \n- runwayml/stable-diffusion-inpainting \n you should change 'sample_size' to 64 in the"397 " configuration file. Please make sure to update the config accordingly as leaving `sample_size=32`"398 " in the config might lead to incorrect results in future versions. If you have downloaded this"399 " checkpoint from the Hugging Face Hub, it would be very nice if you could open a Pull request for"400 " the `unet/config.json` file"401 )402 deprecate("sample_size<64", "1.0.0", deprecation_message, standard_warn=False)403 new_config = dict(unet.config)404 new_config["sample_size"] = 64405 unet._internal_dict = FrozenDict(new_config)406 407 self.register_modules(408 vae=vae,409 text_encoder=text_encoder,410 tokenizer=tokenizer,411 unet=unet,412 scheduler=scheduler,413 safety_checker=safety_checker,414 feature_extractor=feature_extractor,415 image_encoder=image_encoder,416 )417 self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1) if getattr(self, "vae", None) else 8418 self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor)419 self.register_to_config(requires_safety_checker=requires_safety_checker)420 421 # Initialize the attention hooks for LLM-grounded Diffusion422 self.register_attn_hooks(unet)423 self._saved_attn = None424 425 def attn_hook(self, name, query, key, value, attention_probs):426 if name in DEFAULT_GUIDANCE_ATTN_KEYS:427 self._saved_attn[name] = attention_probs428 429 @classmethod430 def convert_box(cls, box, height, width):431 # box: x, y, w, h (in 512 format) -> x_min, y_min, x_max, y_max432 x_min, y_min = box[0] / width, box[1] / height433 w_box, h_box = box[2] / width, box[3] / height434 435 x_max, y_max = x_min + w_box, y_min + h_box436 437 return x_min, y_min, x_max, y_max438 439 @classmethod440 def _parse_response_with_negative(cls, text):441 if not text:442 raise ValueError("LLM response is empty")443 444 if cls.objects_text in text:445 text = text.split(cls.objects_text)[1]446 447 text_split = text.split(cls.bg_prompt_text_no_trailing_space)448 if len(text_split) == 2:449 gen_boxes, text_rem = text_split450 else:451 raise ValueError(f"LLM response is incomplete: {text}")452 453 text_split = text_rem.split(cls.neg_prompt_text_no_trailing_space)454 455 if len(text_split) == 2:456 bg_prompt, neg_prompt = text_split457 else:458 raise ValueError(f"LLM response is incomplete: {text}")459 460 try:461 gen_boxes = ast.literal_eval(gen_boxes)462 except SyntaxError as e:463 # Sometimes the response is in plain text464 if "No objects" in gen_boxes or gen_boxes.strip() == "":465 gen_boxes = []466 else:467 raise e468 bg_prompt = bg_prompt.strip()469 neg_prompt = neg_prompt.strip()470 471 # LLM may return "None" to mean no negative prompt provided.472 if neg_prompt == "None":473 neg_prompt = ""474 475 return gen_boxes, bg_prompt, neg_prompt476 477 @classmethod478 def parse_llm_response(cls, response, canvas_height=512, canvas_width=512):479 # Infer from spec480 gen_boxes, bg_prompt, neg_prompt = cls._parse_response_with_negative(text=response)481 482 gen_boxes = sorted(gen_boxes, key=lambda gen_box: gen_box[0])483 484 phrases = [name for name, _ in gen_boxes]485 boxes = [cls.convert_box(box, height=canvas_height, width=canvas_width) for _, box in gen_boxes]486 487 return phrases, boxes, bg_prompt, neg_prompt488 489 def check_inputs(490 self,491 prompt,492 height,493 width,494 callback_steps,495 phrases,496 boxes,497 negative_prompt=None,498 prompt_embeds=None,499 negative_prompt_embeds=None,500 phrase_indices=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 elif prompt is None and phrase_indices is None:525 raise ValueError("If the prompt is None, the phrase_indices cannot be None")526 527 if negative_prompt is not None and negative_prompt_embeds is not None:528 raise ValueError(529 f"Cannot forward both `negative_prompt`: {negative_prompt} and `negative_prompt_embeds`:"530 f" {negative_prompt_embeds}. Please make sure to only forward one of the two."531 )532 533 if prompt_embeds is not None and negative_prompt_embeds is not None:534 if prompt_embeds.shape != negative_prompt_embeds.shape:535 raise ValueError(536 "`prompt_embeds` and `negative_prompt_embeds` must have the same shape when passed directly, but"537 f" got: `prompt_embeds` {prompt_embeds.shape} != `negative_prompt_embeds`"538 f" {negative_prompt_embeds.shape}."539 )540 541 if len(phrases) != len(boxes):542 raise ValueError(543 "length of `phrases` and `boxes` has to be same, but"544 f" got: `phrases` {len(phrases)} != `boxes` {len(boxes)}"545 )546 547 def register_attn_hooks(self, unet):548 """Registering hooks to obtain the attention maps for guidance"""549 550 attn_procs = {}551 552 for name in unet.attn_processors.keys():553 # Only obtain the queries and keys from cross-attention554 if name.endswith("attn1.processor") or name.endswith("fuser.attn.processor"):555 # Keep the same attn_processors for self-attention (no hooks for self-attention)556 attn_procs[name] = unet.attn_processors[name]557 continue558 559 cross_attention_dim = None if name.endswith("attn1.processor") else unet.config.cross_attention_dim560 561 if name.startswith("mid_block"):562 hidden_size = unet.config.block_out_channels[-1]563 elif name.startswith("up_blocks"):564 block_id = int(name[len("up_blocks.")])565 hidden_size = list(reversed(unet.config.block_out_channels))[block_id]566 elif name.startswith("down_blocks"):567 block_id = int(name[len("down_blocks.")])568 hidden_size = unet.config.block_out_channels[block_id]569 570 attn_procs[name] = AttnProcessorWithHook(571 attn_processor_key=name,572 hidden_size=hidden_size,573 cross_attention_dim=cross_attention_dim,574 hook=self.attn_hook,575 fast_attn=True,576 # Not enabled by default577 enabled=False,578 )579 580 unet.set_attn_processor(attn_procs)581 582 def enable_fuser(self, enabled=True):583 for module in self.unet.modules():584 if isinstance(module, GatedSelfAttentionDense):585 module.enabled = enabled586 587 def enable_attn_hook(self, enabled=True):588 for module in self.unet.attn_processors.values():589 if isinstance(module, AttnProcessorWithHook):590 module.enabled = enabled591 592 def get_token_map(self, prompt, padding="do_not_pad", verbose=False):593 """Get a list of mapping: prompt index to str (prompt in a list of token str)"""594 fg_prompt_tokens = self.tokenizer([prompt], padding=padding, max_length=77, return_tensors="np")595 input_ids = fg_prompt_tokens["input_ids"][0]596 597 token_map = []598 for ind, item in enumerate(input_ids.tolist()):599 token = self.tokenizer._convert_id_to_token(item)600 601 if verbose:602 logger.info(f"{ind}, {token} ({item})")603 604 token_map.append(token)605 606 return token_map607 608 def get_phrase_indices(609 self,610 prompt,611 phrases,612 token_map=None,613 add_suffix_if_not_found=False,614 verbose=False,615 ):616 for obj in phrases:617 # Suffix the prompt with object name for attention guidance if object is not in the prompt, using "|" to separate the prompt and the suffix618 if obj not in prompt:619 prompt += "| " + obj620 621 if token_map is None:622 # We allow using a pre-computed token map.623 token_map = self.get_token_map(prompt=prompt, padding="do_not_pad", verbose=verbose)624 token_map_str = " ".join(token_map)625 626 phrase_indices = []627 628 for obj in phrases:629 phrase_token_map = self.get_token_map(prompt=obj, padding="do_not_pad", verbose=verbose)630 # Remove <bos> and <eos> in substr631 phrase_token_map = phrase_token_map[1:-1]632 phrase_token_map_len = len(phrase_token_map)633 phrase_token_map_str = " ".join(phrase_token_map)634 635 if verbose:636 logger.info(637 "Full str:",638 token_map_str,639 "Substr:",640 phrase_token_map_str,641 "Phrase:",642 phrases,643 )644 645 # Count the number of token before substr646 # The substring comes with a trailing space that needs to be removed by minus one in the index.647 obj_first_index = len(token_map_str[: token_map_str.index(phrase_token_map_str) - 1].split(" "))648 649 obj_position = list(range(obj_first_index, obj_first_index + phrase_token_map_len))650 phrase_indices.append(obj_position)651 652 if add_suffix_if_not_found:653 return phrase_indices, prompt654 655 return phrase_indices656 657 def add_ca_loss_per_attn_map_to_loss(658 self,659 loss,660 attn_map,661 object_number,662 bboxes,663 phrase_indices,664 fg_top_p=0.2,665 bg_top_p=0.2,666 fg_weight=1.0,667 bg_weight=1.0,668 ):669 # b is the number of heads, not batch670 b, i, j = attn_map.shape671 H = W = int(math.sqrt(i))672 for obj_idx in range(object_number):673 obj_loss = 0674 mask = torch.zeros(size=(H, W), device="cuda")675 obj_boxes = bboxes[obj_idx]676 677 # We support two level (one box per phrase) and three level (multiple boxes per phrase)678 if not isinstance(obj_boxes[0], Iterable):679 obj_boxes = [obj_boxes]680 681 for obj_box in obj_boxes:682 # x_min, y_min, x_max, y_max = int(obj_box[0] * W), int(obj_box[1] * H), int(obj_box[2] * W), int(obj_box[3] * H)683 x_min, y_min, x_max, y_max = scale_proportion(obj_box, H=H, W=W)684 mask[y_min:y_max, x_min:x_max] = 1685 686 for obj_position in phrase_indices[obj_idx]:687 # Could potentially optimize to compute this for loop in batch.688 # Could crop the ref cross attention before saving to save memory.689 690 ca_map_obj = attn_map[:, :, obj_position].reshape(b, H, W)691 692 # shape: (b, H * W)693 ca_map_obj = attn_map[:, :, obj_position] # .reshape(b, H, W)694 k_fg = (mask.sum() * fg_top_p).long().clamp_(min=1)695 k_bg = ((1 - mask).sum() * bg_top_p).long().clamp_(min=1)696 697 mask_1d = mask.view(1, -1)698 699 # Max-based loss function700 701 # Take the topk over spatial dimension, and then take the sum over heads dim702 # The mean is over k_fg and k_bg dimension, so we don't need to sum and divide on our own.703 obj_loss += (1 - (ca_map_obj * mask_1d).topk(k=k_fg).values.mean(dim=1)).sum(dim=0) * fg_weight704 obj_loss += ((ca_map_obj * (1 - mask_1d)).topk(k=k_bg).values.mean(dim=1)).sum(dim=0) * bg_weight705 706 loss += obj_loss / len(phrase_indices[obj_idx])707 708 return loss709 710 def compute_ca_loss(711 self,712 saved_attn,713 bboxes,714 phrase_indices,715 guidance_attn_keys,716 verbose=False,717 **kwargs,718 ):719 """720 The `saved_attn` is supposed to be passed to `save_attn_to_dict` in `cross_attention_kwargs` prior to computing ths loss.721 `AttnProcessor` will put attention maps into the `save_attn_to_dict`.722 723 `index` is the timestep.724 `ref_ca_word_token_only`: This has precedence over `ref_ca_last_token_only` (i.e., if both are enabled, we take the token from word rather than the last token).725 `ref_ca_last_token_only`: `ref_ca_saved_attn` comes from the attention map of the last token of the phrase in single object generation, so we apply it only to the last token of the phrase in overall generation if this is set to True. If set to False, `ref_ca_saved_attn` will be applied to all the text tokens.726 """727 loss = torch.tensor(0).float().cuda()728 object_number = len(bboxes)729 if object_number == 0:730 return loss731 732 for attn_key in guidance_attn_keys:733 # We only have 1 cross attention for mid.734 735 attn_map_integrated = saved_attn[attn_key]736 if not attn_map_integrated.is_cuda:737 attn_map_integrated = attn_map_integrated.cuda()738 # Example dimension: [20, 64, 77]739 attn_map = attn_map_integrated.squeeze(dim=0)740 741 loss = self.add_ca_loss_per_attn_map_to_loss(742 loss, attn_map, object_number, bboxes, phrase_indices, **kwargs743 )744 745 num_attn = len(guidance_attn_keys)746 747 if num_attn > 0:748 loss = loss / (object_number * num_attn)749 750 return loss751 752 @torch.no_grad()753 @replace_example_docstring(EXAMPLE_DOC_STRING)754 def __call__(755 self,756 prompt: Union[str, List[str]] = None,757 height: Optional[int] = None,758 width: Optional[int] = None,759 num_inference_steps: int = 50,760 guidance_scale: float = 7.5,761 gligen_scheduled_sampling_beta: float = 0.3,762 phrases: List[str] = None,763 boxes: List[List[float]] = None,764 negative_prompt: Optional[Union[str, List[str]]] = None,765 num_images_per_prompt: Optional[int] = 1,766 eta: float = 0.0,767 generator: Optional[Union[torch.Generator, List[torch.Generator]]] = None,768 latents: Optional[torch.Tensor] = None,769 prompt_embeds: Optional[torch.Tensor] = None,770 negative_prompt_embeds: Optional[torch.Tensor] = None,771 ip_adapter_image: Optional[PipelineImageInput] = None,772 output_type: Optional[str] = "pil",773 return_dict: bool = True,774 callback: Optional[Callable[[int, int, torch.Tensor], None]] = None,775 callback_steps: int = 1,776 cross_attention_kwargs: Optional[Dict[str, Any]] = None,777 clip_skip: Optional[int] = None,778 lmd_guidance_kwargs: Optional[Dict[str, Any]] = {},779 phrase_indices: Optional[List[int]] = None,780 ):781 r"""782 The call function to the pipeline for generation.783 784 Args:785 prompt (`str` or `List[str]`, *optional*):786 The prompt or prompts to guide image generation. If not defined, you need to pass `prompt_embeds`.787 height (`int`, *optional*, defaults to `self.unet.config.sample_size * self.vae_scale_factor`):788 The height in pixels of the generated image.789 width (`int`, *optional*, defaults to `self.unet.config.sample_size * self.vae_scale_factor`):790 The width in pixels of the generated image.791 num_inference_steps (`int`, *optional*, defaults to 50):792 The number of denoising steps. More denoising steps usually lead to a higher quality image at the793 expense of slower inference.794 guidance_scale (`float`, *optional*, defaults to 7.5):795 A higher guidance scale value encourages the model to generate images closely linked to the text796 `prompt` at the expense of lower image quality. Guidance scale is enabled when `guidance_scale > 1`.797 phrases (`List[str]`):798 The phrases to guide what to include in each of the regions defined by the corresponding799 `boxes`. There should only be one phrase per bounding box.800 boxes (`List[List[float]]`):801 The bounding boxes that identify rectangular regions of the image that are going to be filled with the802 content described by the corresponding `phrases`. Each rectangular box is defined as a803 `List[float]` of 4 elements `[xmin, ymin, xmax, ymax]` where each value is between [0,1].804 gligen_scheduled_sampling_beta (`float`, defaults to 0.3):805 Scheduled Sampling factor from [GLIGEN: Open-Set Grounded Text-to-Image806 Generation](https://huggingface.co/papers/2301.07093). Scheduled Sampling factor is only varied for807 scheduled sampling during inference for improved quality and controllability.808 negative_prompt (`str` or `List[str]`, *optional*):809 The prompt or prompts to guide what to not include in image generation. If not defined, you need to810 pass `negative_prompt_embeds` instead. Ignored when not using guidance (`guidance_scale < 1`).811 num_images_per_prompt (`int`, *optional*, defaults to 1):812 The number of images to generate per prompt.813 eta (`float`, *optional*, defaults to 0.0):814 Corresponds to parameter eta (η) from the [DDIM](https://huggingface.co/papers/2010.02502) paper. Only applies815 to the [`~schedulers.DDIMScheduler`], and is ignored in other schedulers.816 generator (`torch.Generator` or `List[torch.Generator]`, *optional*):817 A [`torch.Generator`](https://pytorch.org/docs/stable/generated/torch.Generator.html) to make818 generation deterministic.819 latents (`torch.Tensor`, *optional*):820 Pre-generated noisy latents sampled from a Gaussian distribution, to be used as inputs for image821 generation. Can be used to tweak the same generation with different prompts. If not provided, a latents822 tensor is generated by sampling using the supplied random `generator`.823 prompt_embeds (`torch.Tensor`, *optional*):824 Pre-generated text embeddings. Can be used to easily tweak text inputs (prompt weighting). If not825 provided, text embeddings are generated from the `prompt` input argument.826 negative_prompt_embeds (`torch.Tensor`, *optional*):827 Pre-generated negative text embeddings. Can be used to easily tweak text inputs (prompt weighting). If828 not provided, `negative_prompt_embeds` are generated from the `negative_prompt` input argument.829 ip_adapter_image: (`PipelineImageInput`, *optional*): Optional image input to work with IP Adapters.830 output_type (`str`, *optional*, defaults to `"pil"`):831 The output format of the generated image. Choose between `PIL.Image` or `np.array`.832 return_dict (`bool`, *optional*, defaults to `True`):833 Whether or not to return a [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] instead of a834 plain tuple.835 callback (`Callable`, *optional*):836 A function that calls every `callback_steps` steps during inference. The function is called with the837 following arguments: `callback(step: int, timestep: int, latents: torch.Tensor)`.838 callback_steps (`int`, *optional*, defaults to 1):839 The frequency at which the `callback` function is called. If not specified, the callback is called at840 every step.841 cross_attention_kwargs (`dict`, *optional*):842 A kwargs dictionary that if specified is passed along to the [`AttentionProcessor`] as defined in843 [`self.processor`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention_processor.py).844 guidance_rescale (`float`, *optional*, defaults to 0.0):845 Guidance rescale factor from [Common Diffusion Noise Schedules and Sample Steps are846 Flawed](https://huggingface.co/papers/2305.08891). Guidance rescale factor should fix overexposure when847 using zero terminal SNR.848 clip_skip (`int`, *optional*):849 Number of layers to be skipped from CLIP while computing the prompt embeddings. A value of 1 means that850 the output of the pre-final layer will be used for computing the prompt embeddings.851 lmd_guidance_kwargs (`dict`, *optional*):852 A kwargs dictionary that if specified is passed along to `latent_lmd_guidance` function. Useful keys include `loss_scale` (the guidance strength), `loss_threshold` (when loss is lower than this value, the guidance is not applied anymore), `max_iter` (the number of iterations of guidance for each step), and `guidance_timesteps` (the number of diffusion timesteps to apply guidance on). See `latent_lmd_guidance` for implementation details.853 phrase_indices (`list` of `list`, *optional*): The indices of the tokens of each phrase in the overall prompt. If omitted, the pipeline will match the first token subsequence. The pipeline will append the missing phrases to the end of the prompt by default.854 Examples:855 856 Returns:857 [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] or `tuple`:858 If `return_dict` is `True`, [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] is returned,859 otherwise a `tuple` is returned where the first element is a list with the generated images and the860 second element is a list of `bool`s indicating whether the corresponding generated image contains861 "not-safe-for-work" (nsfw) content.862 """863 # 0. Default height and width to unet864 height = height or self.unet.config.sample_size * self.vae_scale_factor865 width = width or self.unet.config.sample_size * self.vae_scale_factor866 867 # 1. Check inputs. Raise error if not correct868 self.check_inputs(869 prompt,870 height,871 width,872 callback_steps,873 phrases,874 boxes,875 negative_prompt,876 prompt_embeds,877 negative_prompt_embeds,878 phrase_indices,879 )880 881 # 2. Define call parameters882 if prompt is not None and isinstance(prompt, str):883 batch_size = 1884 if phrase_indices is None:885 phrase_indices, prompt = self.get_phrase_indices(prompt, phrases, add_suffix_if_not_found=True)886 elif prompt is not None and isinstance(prompt, list):887 batch_size = len(prompt)888 if phrase_indices is None:889 phrase_indices = []890 prompt_parsed = []891 for prompt_item in prompt:892 (893 phrase_indices_parsed_item,894 prompt_parsed_item,895 ) = self.get_phrase_indices(prompt_item, add_suffix_if_not_found=True)896 phrase_indices.append(phrase_indices_parsed_item)897 prompt_parsed.append(prompt_parsed_item)898 prompt = prompt_parsed899 else:900 batch_size = prompt_embeds.shape[0]901 902 device = self._execution_device903 # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)904 # of the Imagen paper: https://huggingface.co/papers/2205.11487 . `guidance_scale = 1`905 # corresponds to doing no classifier free guidance.906 do_classifier_free_guidance = guidance_scale > 1.0907 908 # 3. Encode input prompt909 prompt_embeds, negative_prompt_embeds = self.encode_prompt(910 prompt,911 device,912 num_images_per_prompt,913 do_classifier_free_guidance,914 negative_prompt,915 prompt_embeds=prompt_embeds,916 negative_prompt_embeds=negative_prompt_embeds,917 clip_skip=clip_skip,918 )919 920 cond_prompt_embeds = prompt_embeds921 922 # For classifier free guidance, we need to do two forward passes.923 # Here we concatenate the unconditional and text embeddings into a single batch924 # to avoid doing two forward passes925 if do_classifier_free_guidance:926 prompt_embeds = torch.cat([negative_prompt_embeds, prompt_embeds])927 928 if ip_adapter_image is not None:929 image_embeds, negative_image_embeds = self.encode_image(ip_adapter_image, device, num_images_per_prompt)930 if self.do_classifier_free_guidance:931 image_embeds = torch.cat([negative_image_embeds, image_embeds])932 933 # 4. Prepare timesteps934 self.scheduler.set_timesteps(num_inference_steps, device=device)935 timesteps = self.scheduler.timesteps936 937 # 5. Prepare latent variables938 num_channels_latents = self.unet.config.in_channels939 latents = self.prepare_latents(940 batch_size * num_images_per_prompt,941 num_channels_latents,942 height,943 width,944 prompt_embeds.dtype,945 device,946 generator,947 latents,948 )949 950 # 5.1 Prepare GLIGEN variables951 max_objs = 30952 if len(boxes) > max_objs:953 warnings.warn(954 f"More that {max_objs} objects found. Only first {max_objs} objects will be processed.",955 FutureWarning,956 )957 phrases = phrases[:max_objs]958 boxes = boxes[:max_objs]959 960 n_objs = len(boxes)961 if n_objs:962 # prepare batched input to the PositionNet (boxes, phrases, mask)963 # Get tokens for phrases from pre-trained CLIPTokenizer964 tokenizer_inputs = self.tokenizer(phrases, padding=True, return_tensors="pt").to(device)965 # For the token, we use the same pre-trained text encoder966 # to obtain its text feature967 _text_embeddings = self.text_encoder(**tokenizer_inputs).pooler_output968 969 # For each entity, described in phrases, is denoted with a bounding box,970 # we represent the location information as (xmin,ymin,xmax,ymax)971 cond_boxes = torch.zeros(max_objs, 4, device=device, dtype=self.text_encoder.dtype)972 if n_objs:973 cond_boxes[:n_objs] = torch.tensor(boxes)974 text_embeddings = torch.zeros(975 max_objs,976 self.unet.config.cross_attention_dim,977 device=device,978 dtype=self.text_encoder.dtype,979 )980 if n_objs:981 text_embeddings[:n_objs] = _text_embeddings982 # Generate a mask for each object that is entity described by phrases983 masks = torch.zeros(max_objs, device=device, dtype=self.text_encoder.dtype)984 masks[:n_objs] = 1985 986 repeat_batch = batch_size * num_images_per_prompt987 cond_boxes = cond_boxes.unsqueeze(0).expand(repeat_batch, -1, -1).clone()988 text_embeddings = text_embeddings.unsqueeze(0).expand(repeat_batch, -1, -1).clone()989 masks = masks.unsqueeze(0).expand(repeat_batch, -1).clone()990 if do_classifier_free_guidance:991 repeat_batch = repeat_batch * 2992 cond_boxes = torch.cat([cond_boxes] * 2)993 text_embeddings = torch.cat([text_embeddings] * 2)994 masks = torch.cat([masks] * 2)995 masks[: repeat_batch // 2] = 0996 if cross_attention_kwargs is None:997 cross_attention_kwargs = {}998 cross_attention_kwargs["gligen"] = {999 "boxes": cond_boxes,1000 "positive_embeddings": text_embeddings,1001 "masks": masks,1002 }1003 1004 num_grounding_steps = int(gligen_scheduled_sampling_beta * len(timesteps))1005 self.enable_fuser(True)1006 1007 # 6. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline1008 extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)1009 1010 # 6.1 Add image embeds for IP-Adapter1011 added_cond_kwargs = {"image_embeds": image_embeds} if ip_adapter_image is not None else None1012 1013 loss_attn = torch.tensor(10000.0)1014 1015 # 7. Denoising loop1016 num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order1017 with self.progress_bar(total=num_inference_steps) as progress_bar:1018 for i, t in enumerate(timesteps):1019 # Scheduled sampling1020 if i == num_grounding_steps:1021 self.enable_fuser(False)1022 1023 if latents.shape[1] != 4:1024 latents = torch.randn_like(latents[:, :4])1025 1026 # 7.1 Perform LMD guidance1027 if boxes:1028 latents, loss_attn = self.latent_lmd_guidance(1029 cond_prompt_embeds,1030 index=i,1031 boxes=boxes,1032 phrase_indices=phrase_indices,1033 t=t,1034 latents=latents,1035 loss=loss_attn,1036 **lmd_guidance_kwargs,1037 )1038 1039 # expand the latents if we are doing classifier free guidance1040 latent_model_input = torch.cat([latents] * 2) if do_classifier_free_guidance else latents1041 latent_model_input = self.scheduler.scale_model_input(latent_model_input, t)1042 1043 # predict the noise residual1044 noise_pred = self.unet(1045 latent_model_input,1046 t,1047 encoder_hidden_states=prompt_embeds,1048 cross_attention_kwargs=cross_attention_kwargs,1049 added_cond_kwargs=added_cond_kwargs,1050 ).sample1051 1052 # perform guidance1053 if do_classifier_free_guidance:1054 noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)1055 noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)1056 1057 # compute the previous noisy sample x_t -> x_t-11058 latents = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs).prev_sample1059 1060 # call the callback, if provided1061 if i == len(timesteps) - 1 or ((i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0):1062 progress_bar.update()1063 if callback is not None and i % callback_steps == 0:1064 step_idx = i // getattr(self.scheduler, "order", 1)1065 callback(step_idx, t, latents)1066 1067 if not output_type == "latent":1068 image = self.vae.decode(latents / self.vae.config.scaling_factor, return_dict=False)[0]1069 image, has_nsfw_concept = self.run_safety_checker(image, device, prompt_embeds.dtype)1070 else:1071 image = latents1072 has_nsfw_concept = None1073 1074 if has_nsfw_concept is None:1075 do_denormalize = [True] * image.shape[0]1076 else:1077 do_denormalize = [not has_nsfw for has_nsfw in has_nsfw_concept]1078 1079 image = self.image_processor.postprocess(image, output_type=output_type, do_denormalize=do_denormalize)1080 1081 # Offload last model to CPU1082 if hasattr(self, "final_offload_hook") and self.final_offload_hook is not None:1083 self.final_offload_hook.offload()1084 1085 if not return_dict:1086 return (image, has_nsfw_concept)1087 1088 return StableDiffusionPipelineOutput(images=image, nsfw_content_detected=has_nsfw_concept)1089 1090 @torch.set_grad_enabled(True)1091 def latent_lmd_guidance(1092 self,1093 cond_embeddings,1094 index,1095 boxes,1096 phrase_indices,1097 t,1098 latents,1099 loss,1100 *,1101 loss_scale=20,1102 loss_threshold=5.0,1103 max_iter=[3] * 5 + [2] * 5 + [1] * 5,1104 guidance_timesteps=15,1105 cross_attention_kwargs=None,1106 guidance_attn_keys=DEFAULT_GUIDANCE_ATTN_KEYS,1107 verbose=False,1108 clear_cache=False,1109 unet_additional_kwargs={},1110 guidance_callback=None,1111 **kwargs,1112 ):1113 scheduler, unet = self.scheduler, self.unet1114 1115 iteration = 01116 1117 if index < guidance_timesteps:1118 if isinstance(max_iter, list):1119 max_iter = max_iter[index]1120 1121 if verbose:1122 logger.info(1123 f"time index {index}, loss: {loss.item() / loss_scale:.3f} (de-scaled with scale {loss_scale:.1f}), loss threshold: {loss_threshold:.3f}"1124 )1125 1126 try:1127 self.enable_attn_hook(enabled=True)1128 1129 while (1130 loss.item() / loss_scale > loss_threshold and iteration < max_iter and index < guidance_timesteps1131 ):1132 self._saved_attn = {}1133 1134 latents.requires_grad_(True)1135 latent_model_input = latents1136 latent_model_input = scheduler.scale_model_input(latent_model_input, t)1137 1138 unet(1139 latent_model_input,1140 t,1141 encoder_hidden_states=cond_embeddings,1142 cross_attention_kwargs=cross_attention_kwargs,1143 **unet_additional_kwargs,1144 )1145 1146 # update latents with guidance1147 loss = (1148 self.compute_ca_loss(1149 saved_attn=self._saved_attn,1150 bboxes=boxes,1151 phrase_indices=phrase_indices,1152 guidance_attn_keys=guidance_attn_keys,1153 verbose=verbose,1154 **kwargs,1155 )1156 * loss_scale1157 )1158 1159 if torch.isnan(loss):1160 raise RuntimeError("**Loss is NaN**")1161 1162 # This callback allows visualizations.1163 if guidance_callback is not None:1164 guidance_callback(self, latents, loss, iteration, index)1165 1166 self._saved_attn = None1167 1168 grad_cond = torch.autograd.grad(loss.requires_grad_(True), [latents])[0]1169 1170 latents.requires_grad_(False)1171 1172 # Scaling with classifier guidance1173 alpha_prod_t = scheduler.alphas_cumprod[t]1174 # Classifier guidance: https://huggingface.co/papers/2105.052331175 # DDIM: https://huggingface.co/papers/2010.025021176 scale = (1 - alpha_prod_t) ** (0.5)1177 latents = latents - scale * grad_cond1178 1179 iteration += 11180 1181 if clear_cache:1182 gc.collect()1183 torch.cuda.empty_cache()1184 1185 if verbose:1186 logger.info(1187 f"time index {index}, loss: {loss.item() / loss_scale:.3f}, loss threshold: {loss_threshold:.3f}, iteration: {iteration}"1188 )1189 1190 finally:1191 self.enable_attn_hook(enabled=False)1192 1193 return latents, loss1194 1195 # Below are methods copied from StableDiffusionPipeline1196 # The design choice of not inheriting from StableDiffusionPipeline is discussed here: https://github.com/huggingface/diffusers/pull/5993#issuecomment-18342585171197 1198 # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline._encode_prompt1199 def _encode_prompt(1200 self,