From 44129d7d678d1492e2179786d20688b4bad0f6ea Mon Sep 17 00:00:00 2001 From: Zhimin Li <46835311+zml-ai@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:16:36 +0800 Subject: [PATCH 1/2] Update LICENSE.txt --- LICENSE.txt | 63 ++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 61ea65d..c848c55 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,9 +1,10 @@ TENCENT HUNYUAN COMMUNITY LICENSE AGREEMENT -Tencent Hunyuan Release Date: 2024/5/14 +Tencent Hunyuan DiT Release Date: 14 May 2024 +THIS LICENSE AGREEMENT DOES NOT APPLY IN THE EUROPEAN UNION AND IS EXPRESSLY LIMITED TO THE TERRITORY, AS DEFINED BELOW. By clicking to agree or by using, reproducing, modifying, distributing, performing or displaying any portion or element of the Tencent Hunyuan Works, including via any Hosted Service, You will be deemed to have recognized and accepted the content of this Agreement, which is effective immediately. 1. DEFINITIONS. a. “Acceptable Use Policy” shall mean the policy made available by Tencent as set forth in the Exhibit A. -b. “Agreement” shall mean the terms and conditions for use, reproduction, distribution, modification, performance and displaying of the Hunyuan Works or any portion or element thereof set forth herein. +b. “Agreement” shall mean the terms and conditions for use, reproduction, distribution, modification, performance and displaying of Tencent Hunyuan Works or any portion or element thereof set forth herein. c. “Documentation” shall mean the specifications, manuals and documentation for Tencent Hunyuan made publicly available by Tencent. d. “Hosted Service” shall mean a hosted service offered via an application programming interface (API), web access, or any other electronic or remote means. e. “Licensee,” “You” or “Your” shall mean a natural person or legal entity exercising the rights granted by this Agreement and/or using the Tencent Hunyuan Works for any purpose and in any field of use. @@ -11,27 +12,29 @@ f. “Materials” shall mean, collectively, Tencent’s proprietary Tencent Hun g. “Model Derivatives” shall mean all: (i) modifications to Tencent Hunyuan or any Model Derivative of Tencent Hunyuan; (ii) works based on Tencent Hunyuan or any Model Derivative of Tencent Hunyuan; or (iii) any other machine learning model which is created by transfer of patterns of the weights, parameters, operations, or Output of Tencent Hunyuan or any Model Derivative of Tencent Hunyuan, to that model in order to cause that model to perform similarly to Tencent Hunyuan or a Model Derivative of Tencent Hunyuan, including distillation methods, methods that use intermediate data representations, or methods based on the generation of synthetic data Outputs by Tencent Hunyuan or a Model Derivative of Tencent Hunyuan for training that model. For clarity, Outputs by themselves are not deemed Model Derivatives. h. “Output” shall mean the information and/or content output of Tencent Hunyuan or a Model Derivative that results from operating or otherwise using Tencent Hunyuan or a Model Derivative, including via a Hosted Service. i. “Tencent,” “We” or “Us” shall mean THL A29 Limited. -j. “Tencent Hunyuan” shall mean the large language models, image/video/audio/3D generation models, and multimodal large language models and their software and algorithms, including trained model weights, parameters (including optimizer states), machine-learning model code, inference-enabling code, training-enabling code, fine-tuning enabling code and other elements of the foregoing made publicly available by Us at https://huggingface.co/Tencent-Hunyuan/HunyuanDiT and https://github.com/Tencent/HunyuanDiT . +j. “Tencent Hunyuan” shall mean the large language models, text/image/video/audio/3D generation models, and multimodal large language models and their software and algorithms, including trained model weights, parameters (including optimizer states), machine-learning model code, inference-enabling code, training-enabling code, fine-tuning enabling code and other elements of the foregoing made publicly available by Us, including, without limitation to, Tencent Hunyuan DiT released at https://huggingface.co/Tencent-Hunyuan/HunyuanDiT. k. “Tencent Hunyuan Works” shall mean: (i) the Materials; (ii) Model Derivatives; and (iii) all derivative works thereof. -l. “Third Party” or “Third Parties” shall mean individuals or legal entities that are not under common control with Us or You. -m. “including” shall mean including but not limited to. +l. “Territory” shall mean the worldwide territory, excluding the territory of the European Union. +m. “Third Party” or “Third Parties” shall mean individuals or legal entities that are not under common control with Us or You. +n. “including” shall mean including but not limited to. 2. GRANT OF RIGHTS. -We grant You a non-exclusive, worldwide, non-transferable and royalty-free limited license under Tencent’s intellectual property or other rights owned by Us embodied in or utilized by the Materials to use, reproduce, distribute, create derivative works of (including Model Derivatives), and make modifications to the Materials, only in accordance with the terms of this Agreement and the Acceptable Use Policy, and You must not violate (or encourage or permit anyone else to violate) any term of this Agreement or the Acceptable Use Policy. +We grant You, for the Territory only, a non-exclusive, non-transferable and royalty-free limited license under Tencent’s intellectual property or other rights owned by Us embodied in or utilized by the Materials to use, reproduce, distribute, create derivative works of (including Model Derivatives), and make modifications to the Materials, only in accordance with the terms of this Agreement and the Acceptable Use Policy, and You must not violate (or encourage or permit anyone else to violate) any term of this Agreement or the Acceptable Use Policy. 3. DISTRIBUTION. -You may, subject to Your compliance with this Agreement, distribute or make available to Third Parties the Tencent Hunyuan Works, provided that You meet all of the following conditions: +You may, subject to Your compliance with this Agreement, distribute or make available to Third Parties the Tencent Hunyuan Works, exclusively in the Territory, provided that You meet all of the following conditions: a. You must provide all such Third Party recipients of the Tencent Hunyuan Works or products or services using them a copy of this Agreement; b. You must cause any modified files to carry prominent notices stating that You changed the files; c. You are encouraged to: (i) publish at least one technology introduction blogpost or one public statement expressing Your experience of using the Tencent Hunyuan Works; and (ii) mark the products or services developed by using the Tencent Hunyuan Works to indicate that the product/service is “Powered by Tencent Hunyuan”; and d. All distributions to Third Parties (other than through a Hosted Service) must be accompanied by a “Notice” text file that contains the following notice: “Tencent Hunyuan is licensed under the Tencent Hunyuan Community License Agreement, Copyright © 2024 Tencent. All Rights Reserved. The trademark rights of “Tencent Hunyuan” are owned by Tencent or its affiliate.” -You may add Your own copyright statement to Your modifications and, except as set forth in this Section and in Section 5, may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Model Derivatives as a whole, provided Your use, reproduction, modification, distribution, performance and display of the work otherwise complies with the terms and conditions of this Agreement. If You receive Tencent Hunyuan Works from a Licensee as part of an integrated end user product, then this Section 3 of this Agreement will not apply to You. +You may add Your own copyright statement to Your modifications and, except as set forth in this Section and in Section 5, may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Model Derivatives as a whole, provided Your use, reproduction, modification, distribution, performance and display of the work otherwise complies with the terms and conditions of this Agreement (including as regards the Territory). If You receive Tencent Hunyuan Works from a Licensee as part of an integrated end user product, then this Section 3 of this Agreement will not apply to You. 4. ADDITIONAL COMMERCIAL TERMS. If, on the Tencent Hunyuan version release date, the monthly active users of all products or services made available by or for Licensee is greater than 100 million monthly active users in the preceding calendar month, You must request a license from Tencent, which Tencent may grant to You in its sole discretion, and You are not authorized to exercise any of the rights under this Agreement unless or until Tencent otherwise expressly grants You such rights. 5. RULES OF USE. a. Your use of the Tencent Hunyuan Works must comply with applicable laws and regulations (including trade compliance laws and regulations) and adhere to the Acceptable Use Policy for the Tencent Hunyuan Works, which is hereby incorporated by reference into this Agreement. You must include the use restrictions referenced in these Sections 5(a) and 5(b) as an enforceable provision in any agreement (e.g., license agreement, terms of use, etc.) governing the use and/or distribution of Tencent Hunyuan Works and You must provide notice to subsequent users to whom You distribute that Tencent Hunyuan Works are subject to the use restrictions in these Sections 5(a) and 5(b). b. You must not use the Tencent Hunyuan Works or any Output or results of the Tencent Hunyuan Works to improve any other large language model (other than Tencent Hunyuan or Model Derivatives thereof). +c. You must not use, reproduce, modify, distribute, or display the Tencent Hunyuan Works, Output or results of the Tencent Hunyuan Works outside the Territory. Any such use outside the Territory is unlicensed and unauthorized under this Agreement. 6. INTELLECTUAL PROPERTY. a. Subject to Tencent’s ownership of Tencent Hunyuan Works made by or for Tencent and intellectual property rights therein, conditioned upon Your compliance with the terms and conditions of this Agreement, as between You and Tencent, You will be the owner of any derivative works and modifications of the Materials and any Model Derivatives that are made by or for You. -b. No trademark licenses are granted under this Agreement, and in connection with the Tencent Hunyuan Works, Licensee may not use any name or mark owned by or associated with Tencent or any of its affiliates, except as required for reasonable and customary use in describing and distributing the Tencent Hunyuan Works. Tencent hereby grants You a license to use “Tencent Hunyuan” (the “Mark”) solely as required to comply with the provisions of Section 3(c), provided that You comply with any applicable laws related to trademark protection. All goodwill arising out of Your use of the Mark will inure to the benefit of Tencent. +b. No trademark licenses are granted under this Agreement, and in connection with the Tencent Hunyuan Works, Licensee may not use any name or mark owned by or associated with Tencent or any of its affiliates, except as required for reasonable and customary use in describing and distributing the Tencent Hunyuan Works. Tencent hereby grants You a license to use “Tencent Hunyuan” (the “Mark”) in the Territory solely as required to comply with the provisions of Section 3(c), provided that You comply with any applicable laws related to trademark protection. All goodwill arising out of Your use of the Mark will inure to the benefit of Tencent. c. If You commence a lawsuit or other proceedings (including a cross-claim or counterclaim in a lawsuit) against Us or any person or entity alleging that the Materials or any Output, or any portion of any of the foregoing, infringe any intellectual property or other right owned or licensable by You, then all licenses granted to You under this Agreement shall terminate as of the date such lawsuit or other proceeding is filed. You will defend, indemnify and hold harmless Us from and against any claim by any Third Party arising out of or related to Your or the Third Party’s use or distribution of the Tencent Hunyuan Works. d. Tencent claims no rights in Outputs You generate. You and Your users are solely responsible for Outputs and their subsequent uses. 7. DISCLAIMERS OF WARRANTY AND LIMITATIONS OF LIABILITY. @@ -45,30 +48,30 @@ b. We may terminate this Agreement if You breach any of the terms or conditions a. This Agreement and any dispute arising out of or relating to it will be governed by the laws of the Hong Kong Special Administrative Region of the People’s Republic of China, without regard to conflict of law principles, and the UN Convention on Contracts for the International Sale of Goods does not apply to this Agreement. b. Exclusive jurisdiction and venue for any dispute arising out of or relating to this Agreement will be a court of competent jurisdiction in the Hong Kong Special Administrative Region of the People’s Republic of China, and Tencent and Licensee consent to the exclusive jurisdiction of such court with respect to any such dispute.   - EXHIBIT A ACCEPTABLE USE POLICY Tencent reserves the right to update this Acceptable Use Policy from time to time. -Last modified: 2024/5/14 +Last modified: [insert date] Tencent endeavors to promote safe and fair use of its tools and features, including Tencent Hunyuan. You agree not to use Tencent Hunyuan or Model Derivatives: -1. In any way that violates any applicable national, federal, state, local, international or any other law or regulation; -2. To harm Yourself or others; -3. To repurpose or distribute output from Tencent Hunyuan or any Model Derivatives to harm Yourself or others; -4. To override or circumvent the safety guardrails and safeguards We have put in place; -5. For the purpose of exploiting, harming or attempting to exploit or harm minors in any way; -6. To generate or disseminate verifiably false information and/or content with the purpose of harming others or influencing elections; -7. To generate or facilitate false online engagement, including fake reviews and other means of fake online engagement; -8. To intentionally defame, disparage or otherwise harass others; -9. To generate and/or disseminate malware (including ransomware) or any other content to be used for the purpose of harming electronic systems; -10. To generate or disseminate personal identifiable information with the purpose of harming others; -11. To generate or disseminate information (including images, code, posts, articles), and place the information in any public context (including –through the use of bot generated tweets), without expressly and conspicuously identifying that the information and/or content is machine generated; -12. To impersonate another individual without consent, authorization, or legal right; -13. To make high-stakes automated decisions in domains that affect an individual’s safety, rights or wellbeing (e.g., law enforcement, migration, medicine/health, management of critical infrastructure, safety components of products, essential services, credit, employment, housing, education, social scoring, or insurance); -14. In a manner that violates or disrespects the social ethics and moral standards of other countries or regions; -15. To perform, facilitate, threaten, incite, plan, promote or encourage violent extremism or terrorism; -16. For any use intended to discriminate against or harm individuals or groups based on protected characteristics or categories, online or offline social behavior or known or predicted personal or personality characteristics; -17. To intentionally exploit any of the vulnerabilities of a specific group of persons based on their age, social, physical or mental characteristics, in order to materially distort the behavior of a person pertaining to that group in a manner that causes or is likely to cause that person or another person physical or psychological harm; -18. For military purposes; -19. To engage in the unauthorized or unlicensed practice of any profession including, but not limited to, financial, legal, medical/health, or other professional practices. +1. Outside the Territory; +2. In any way that violates any applicable national, federal, state, local, international or any other law or regulation; +3. To harm Yourself or others; +4. To repurpose or distribute output from Tencent Hunyuan or any Model Derivatives to harm Yourself or others; +5. To override or circumvent the safety guardrails and safeguards We have put in place; +6. For the purpose of exploiting, harming or attempting to exploit or harm minors in any way; +7. To generate or disseminate verifiably false information and/or content with the purpose of harming others or influencing elections; +8. To generate or facilitate false online engagement, including fake reviews and other means of fake online engagement; +9. To intentionally defame, disparage or otherwise harass others; +10. To generate and/or disseminate malware (including ransomware) or any other content to be used for the purpose of harming electronic systems; +11. To generate or disseminate personal identifiable information with the purpose of harming others; +12. To generate or disseminate information (including images, code, posts, articles), and place the information in any public context (including –through the use of bot generated tweets), without expressly and conspicuously identifying that the information and/or content is machine generated; +13. To impersonate another individual without consent, authorization, or legal right; +14. To make high-stakes automated decisions in domains that affect an individual’s safety, rights or wellbeing (e.g., law enforcement, migration, medicine/health, management of critical infrastructure, safety components of products, essential services, credit, employment, housing, education, social scoring, or insurance); +15. In a manner that violates or disrespects the social ethics and moral standards of other countries or regions; +16. To perform, facilitate, threaten, incite, plan, promote or encourage violent extremism or terrorism; +17. For any use intended to discriminate against or harm individuals or groups based on protected characteristics or categories, online or offline social behavior or known or predicted personal or personality characteristics; +18. To intentionally exploit any of the vulnerabilities of a specific group of persons based on their age, social, physical or mental characteristics, in order to materially distort the behavior of a person pertaining to that group in a manner that causes or is likely to cause that person or another person physical or psychological harm; +19. For military purposes; +20. To engage in the unauthorized or unlicensed practice of any profession including, but not limited to, financial, legal, medical/health, or other professional practices. From d0416973fcae272b59f079429766ebcbe7dfac6d Mon Sep 17 00:00:00 2001 From: "chenguanjie@pjlab.org.cn" Date: Mon, 2 Dec 2024 18:56:50 +0800 Subject: [PATCH 2/2] add skip-cache --- hydit/config.py | 2 + hydit/inference.py | 19 +- hydit/modules/skip_cache.py | 446 ++++++++++++++++++++++++++++++++++++ 3 files changed, 462 insertions(+), 5 deletions(-) create mode 100644 hydit/modules/skip_cache.py diff --git a/hydit/config.py b/hydit/config.py index e9164b0..b99513b 100644 --- a/hydit/config.py +++ b/hydit/config.py @@ -207,6 +207,8 @@ def get_args(default_args=None): parser.add_argument("--gradient-checkpointing", action="store_true", help="Use gradient checkpointing.") parser.add_argument("--cpu-offloading", action="store_true", help="Use cpu offloading for parameters and optimizer states.") parser.add_argument("--save-optimizer-state", action="store_true", help="Save optimizer state in the checkpoint.") + parser.add_argument("--use-cache", action="store_true", help="Accelerate with skip-cahce. This is a training-free caching method which can accelerate Hunyuan-DiT at most 2x for free.") + parser.add_argument("--cache-step", type=int, default=2, choices=[2, 3, 4, 5, 6], help="Specify steps to cache using skip-cache for a 1.5x~2.1x speedup.") # ======================================================================================================== # Deepspeed config diff --git a/hydit/inference.py b/hydit/inference.py index f058003..ada5f48 100644 --- a/hydit/inference.py +++ b/hydit/inference.py @@ -18,6 +18,7 @@ from .constants import SAMPLER_FACTORY, NEGATIVE_PROMPT, TRT_MAX_WIDTH, TRT_MAX_HEIGHT, TRT_MAX_BATCH_SIZE from .diffusion.pipeline import StableDiffusionPipeline from .modules.models import HunYuanDiT, HUNYUAN_DIT_CONFIG +from .modules.skip_cache import HunYuanDiT_skip_cache from .modules.posemb_layers import get_2d_rotary_pos_embed, get_fill_resize_and_crop from .modules.text_encoder import MT5Embedder from .utils.tools import set_seeds @@ -205,11 +206,19 @@ def __init__(self, args, models_root_path): self.infer_mode = self.args.infer_mode if self.infer_mode in ['fa', 'torch']: # Build model structure - self.model = HunYuanDiT(self.args, - input_size=latent_size, - **model_config, - log_fn=logger.info, - ).half().to(self.device) # Force to use fp16 + if not self.args.use_cache: + self.model = HunYuanDiT(self.args, + input_size=latent_size, + **model_config, + log_fn=logger.info, + ).half().to(self.device) # Force to use fp16 + else: + logger.info(f"Accelerating HunYuan-DiT model with skip-cache...") + self.model = HunYuanDiT_skip_cache(self.args, + input_size=latent_size, + **model_config, + log_fn=logger.info, + ).half().to(self.device) # Force to use fp16 # Load model checkpoint self.load_torch_weights() diff --git a/hydit/modules/skip_cache.py b/hydit/modules/skip_cache.py new file mode 100644 index 0000000..0ca6254 --- /dev/null +++ b/hydit/modules/skip_cache.py @@ -0,0 +1,446 @@ +from typing import Any + +import torch +import torch.nn as nn +import torch.nn.functional as F +from diffusers.configuration_utils import ConfigMixin, register_to_config +from diffusers.models import ModelMixin +from peft.utils import ( + ModulesToSaveWrapper, + _get_submodules, +) +from timm.models.vision_transformer import Mlp +from torch.utils import checkpoint +from tqdm import tqdm +from transformers.integrations import PeftAdapterMixin + +from .attn_layers import Attention, FlashCrossMHAModified, FlashSelfMHAModified, CrossAttention +from .embedders import TimestepEmbedder, PatchEmbed, timestep_embedding +from .norm_layers import RMSNorm +from .poolers import AttentionPool +from .models import modulate, FP32_Layernorm, FP32_SiLU, HunYuanDiTBlock, FinalLayer + + + +class HunYuanDiT_skip_cache(ModelMixin, ConfigMixin, PeftAdapterMixin): + """ + HunYuanDiT: Diffusion model with a Transformer backbone. + + Inherit ModelMixin and ConfigMixin to be compatible with the sampler StableDiffusionPipeline of diffusers. + + Inherit PeftAdapterMixin to be compatible with the PEFT training pipeline. + + Parameters + ---------- + args: argparse.Namespace + The arguments parsed by argparse. + input_size: tuple + The size of the input image. + patch_size: int + The size of the patch. + in_channels: int + The number of input channels. + hidden_size: int + The hidden size of the transformer backbone. + depth: int + The number of transformer blocks. + num_heads: int + The number of attention heads. + mlp_ratio: float + The ratio of the hidden size of the MLP in the transformer block. + log_fn: callable + The logging function. + """ + @register_to_config + def __init__(self, + args: Any, + input_size: tuple = (32, 32), + patch_size: int = 2, + in_channels: int = 4, + hidden_size: int = 1152, + depth: int = 28, + num_heads: int = 16, + mlp_ratio: float = 4.0, + log_fn: callable = print, + ): + super().__init__() + self.args = args + self.log_fn = log_fn + self.depth = depth + self.learn_sigma = args.learn_sigma + self.in_channels = in_channels + self.out_channels = in_channels * 2 if args.learn_sigma else in_channels + self.patch_size = patch_size + self.num_heads = num_heads + self.hidden_size = hidden_size + self.text_states_dim = args.text_states_dim + self.text_states_dim_t5 = args.text_states_dim_t5 + self.text_len = args.text_len + self.text_len_t5 = args.text_len_t5 + self.norm = args.norm + + use_flash_attn = args.infer_mode == 'fa' or args.use_flash_attn + if use_flash_attn: + log_fn(f" Enable Flash Attention.") + qk_norm = args.qk_norm # See http://arxiv.org/abs/2302.05442 for details. + + self.mlp_t5 = nn.Sequential( + nn.Linear(self.text_states_dim_t5, self.text_states_dim_t5 * 4, bias=True), + FP32_SiLU(), + nn.Linear(self.text_states_dim_t5 * 4, self.text_states_dim, bias=True), + ) + # learnable replace + self.text_embedding_padding = nn.Parameter( + torch.randn(self.text_len + self.text_len_t5, self.text_states_dim, dtype=torch.float32)) + + # Attention pooling + pooler_out_dim = 1024 + self.pooler = AttentionPool(self.text_len_t5, self.text_states_dim_t5, num_heads=8, output_dim=pooler_out_dim) + + # Dimension of the extra input vectors + self.extra_in_dim = pooler_out_dim + + if args.size_cond: + # Image size and crop size conditions + self.extra_in_dim += 6 * 256 + + if args.use_style_cond: + # Here we use a default learned embedder layer for future extension. + self.style_embedder = nn.Embedding(1, hidden_size) + self.extra_in_dim += hidden_size + + # Text embedding for `add` + self.x_embedder = PatchEmbed(input_size, patch_size, in_channels, hidden_size) + self.t_embedder = TimestepEmbedder(hidden_size) + self.extra_embedder = nn.Sequential( + nn.Linear(self.extra_in_dim, hidden_size * 4), + FP32_SiLU(), + nn.Linear(hidden_size * 4, hidden_size, bias=True), + ) + + # Image embedding + num_patches = self.x_embedder.num_patches + log_fn(f" Number of tokens: {num_patches}") + + # HUnYuanDiT Blocks + self.blocks = nn.ModuleList([ + HunYuanDiTBlock(hidden_size=hidden_size, + c_emb_size=hidden_size, + num_heads=num_heads, + mlp_ratio=mlp_ratio, + text_states_dim=self.text_states_dim, + use_flash_attn=use_flash_attn, + qk_norm=qk_norm, + norm_type=self.norm, + skip=layer > depth // 2, + ) + for layer in range(depth) + ]) + + self.final_layer = FinalLayer(hidden_size, hidden_size, patch_size, self.out_channels) + self.unpatchify_channels = self.out_channels + + # Set up skip-cache + " This caching method is proposed in [Accelerating Vision Diffusion Transformers with Skip Branches]." + " Caching is performed at timestep [700-50], we calculate the high-level feature every ${args.cache_step}, and reuse it in the following ${args.cache_step-1} steps" + self.cache_conf = {'cont': 0, 'cache_val': None, 'cache_step': args.cache_step, 'start_cache_timestep': 700, 'end_cache_timestep': 50, 'cache_at_branch': 1} + + self.initialize_weights() + + def check_condition_validation(self, image_meta_size, style): + if self.args.size_cond is None and image_meta_size is not None: + raise ValueError(f"When `size_cond` is None, `image_meta_size` should be None, but got " + f"{type(image_meta_size)}. ") + if self.args.size_cond is not None and image_meta_size is None: + raise ValueError(f"When `size_cond` is not None, `image_meta_size` should not be None. ") + if not self.args.use_style_cond and style is not None: + raise ValueError(f"When `use_style_cond` is False, `style` should be None, but got {type(style)}. ") + if self.args.use_style_cond and style is None: + raise ValueError(f"When `use_style_cond` is True, `style` should be not None.") + + def enable_gradient_checkpointing(self): + for block in self.blocks: + block.gradient_checkpointing = True + + def disable_gradient_checkpointing(self): + for block in self.blocks: + block.gradient_checkpointing = False + + def forward(self, + x, + t, + encoder_hidden_states=None, + text_embedding_mask=None, + encoder_hidden_states_t5=None, + text_embedding_mask_t5=None, + image_meta_size=None, + style=None, + cos_cis_img=None, + sin_cis_img=None, + return_dict=True, + controls=None, + ): + """ + Forward pass of the encoder. + + Parameters + ---------- + x: torch.Tensor + (B, D, H, W) + t: torch.Tensor + (B) + encoder_hidden_states: torch.Tensor + CLIP text embedding, (B, L_clip, D) + text_embedding_mask: torch.Tensor + CLIP text embedding mask, (B, L_clip) + encoder_hidden_states_t5: torch.Tensor + T5 text embedding, (B, L_t5, D) + text_embedding_mask_t5: torch.Tensor + T5 text embedding mask, (B, L_t5) + image_meta_size: torch.Tensor + (B, 6) + style: torch.Tensor + (B) + cos_cis_img: torch.Tensor + sin_cis_img: torch.Tensor + return_dict: bool + Whether to return a dictionary. + """ + if self.args.use_cache: + cur_timestep = t[0].item() + + text_states = encoder_hidden_states # 2,77,1024 + text_states_t5 = encoder_hidden_states_t5 # 2,256,2048 + text_states_mask = text_embedding_mask.bool() # 2,77 + text_states_t5_mask = text_embedding_mask_t5.bool() # 2,256 + b_t5, l_t5, c_t5 = text_states_t5.shape + text_states_t5 = self.mlp_t5(text_states_t5.view(-1, c_t5)) + text_states = torch.cat([text_states, text_states_t5.view(b_t5, l_t5, -1)], dim=1) # 2,205,1024 + clip_t5_mask = torch.cat([text_states_mask, text_states_t5_mask], dim=-1) + + clip_t5_mask = clip_t5_mask + text_states = torch.where(clip_t5_mask.unsqueeze(2), text_states, self.text_embedding_padding.to(text_states)) + + _, _, oh, ow = x.shape + th, tw = oh // self.patch_size, ow // self.patch_size + + # ========================= Build time and image embedding ========================= + t = self.t_embedder(t) + x = self.x_embedder(x) + + # Get image RoPE embedding according to `reso`lution. + freqs_cis_img = (cos_cis_img, sin_cis_img) + + # ========================= Concatenate all extra vectors ========================= + # Build text tokens with pooling + extra_vec = self.pooler(encoder_hidden_states_t5) + + if self.args.size_cond == None: + image_meta_size = None + self.check_condition_validation(image_meta_size, style) + # Build image meta size tokens if applicable + if image_meta_size is not None: + image_meta_size = timestep_embedding(image_meta_size.view(-1), 256) # [B * 6, 256] + if self.args.use_fp16: + image_meta_size = image_meta_size.half() + image_meta_size = image_meta_size.view(-1, 6 * 256) + extra_vec = torch.cat([extra_vec, image_meta_size], dim=1) # [B, D + 6 * 256] + + # Build style tokens + if style is not None: + style_embedding = self.style_embedder(style) + extra_vec = torch.cat([extra_vec, style_embedding], dim=1) + + # Concatenate all extra vectors + c = t + self.extra_embedder(extra_vec) # [B, D] + + # ========================= Forward pass through HunYuanDiT blocks ========================= + if self.training: + skips = [] + for layer, block in enumerate(self.blocks): + if layer > self.depth // 2: + if controls is not None: + skip = skips.pop() + controls.pop() + else: + skip = skips.pop() + x = block(x, c, text_states, freqs_cis_img, skip) # (N, L, D) + else: + x = block(x, c, text_states, freqs_cis_img) # (N, L, D) + + if layer < (self.depth // 2 - 1): + skips.append(x) + if controls is not None and len(controls) != 0: + raise ValueError("The number of controls is not equal to the number of skip connections.") + + # ========================= Faster forward pass through HunYuanDiT blocks with skip-cache ========================= + else: + # 1. Setup caching + cache_conf = self.cache_conf + do_cache = True + if cache_conf['cont'] % cache_conf['cache_step'] == 0 or cur_timestep >= cache_conf['start_cache_timestep'] or cur_timestep <= cache_conf['end_cache_timestep']: + do_cache = False + + # 2. Start to forward with caching + skips = [] + for layer, block in enumerate(self.blocks): + if do_cache and (not (layer < cache_conf['cache_at_branch'] or layer >= len(self.blocks) - cache_conf['cache_at_branch'])): + # skip middle layers + continue + if layer == len(self.blocks) - cache_conf['cache_at_branch']: + # reuse high-level features + if do_cache: + x = cache_conf['cache_val'] + else: + cache_conf['cache_val'] = x + if layer > self.depth // 2: + if controls is not None: + skip = skips.pop() + controls.pop() + else: + skip = skips.pop() + x = block(x, c, text_states, freqs_cis_img, skip) # (N, L, D) + else: + x = block(x, c, text_states, freqs_cis_img) # (N, L, D) + + if layer < (self.depth // 2 - 1): + skips.append(x) + if controls is not None and len(controls) != 0: + raise ValueError("The number of controls is not equal to the number of skip connections.") + + # 3. Update cache config + if cur_timestep <= cache_conf['end_cache_timestep']: + cache_conf['cache_val'] = None + cache_conf['cont'] = 0 + else: + cache_conf['cont'] += 1 + + # ========================= Final layer ========================= + x = self.final_layer(x, c) # (N, L, patch_size ** 2 * out_channels) + x = self.unpatchify(x, th, tw) # (N, out_channels, H, W) + + if return_dict: + return {'x': x} + return x + + def initialize_weights(self): + # Initialize transformer layers: + def _basic_init(module): + if isinstance(module, nn.Linear): + torch.nn.init.xavier_uniform_(module.weight) + if module.bias is not None: + nn.init.constant_(module.bias, 0) + self.apply(_basic_init) + + # Initialize patch_embed like nn.Linear (instead of nn.Conv2d): + w = self.x_embedder.proj.weight.data + nn.init.xavier_uniform_(w.view([w.shape[0], -1])) + nn.init.constant_(self.x_embedder.proj.bias, 0) + + # Initialize label embedding table: + nn.init.normal_(self.extra_embedder[0].weight, std=0.02) + nn.init.normal_(self.extra_embedder[2].weight, std=0.02) + + # Initialize timestep embedding MLP: + nn.init.normal_(self.t_embedder.mlp[0].weight, std=0.02) + nn.init.normal_(self.t_embedder.mlp[2].weight, std=0.02) + + # Zero-out adaLN modulation layers in HunYuanDiT blocks: + for block in self.blocks: + nn.init.constant_(block.default_modulation[-1].weight, 0) + nn.init.constant_(block.default_modulation[-1].bias, 0) + + # Zero-out output layers: + nn.init.constant_(self.final_layer.adaLN_modulation[-1].weight, 0) + nn.init.constant_(self.final_layer.adaLN_modulation[-1].bias, 0) + nn.init.constant_(self.final_layer.linear.weight, 0) + nn.init.constant_(self.final_layer.linear.bias, 0) + + def unpatchify(self, x, h, w): + """ + x: (N, T, patch_size**2 * C) + imgs: (N, H, W, C) + """ + c = self.unpatchify_channels + p = self.x_embedder.patch_size[0] + # h = w = int(x.shape[1] ** 0.5) + assert h * w == x.shape[1] + + x = x.reshape(shape=(x.shape[0], h, w, p, p, c)) + x = torch.einsum('nhwpqc->nchpwq', x) + imgs = x.reshape(shape=(x.shape[0], c, h * p, w * p)) + return imgs + + def _replace_module(self, parent, child_name, new_module, child) -> None: + setattr(parent, child_name, new_module) + # It's not necessary to set requires_grad here, as that is handled by + # _mark_only_adapters_as_trainable + + # child layer wraps the original module, unpack it + if hasattr(child, "base_layer"): + child = child.get_base_layer() + elif hasattr(child, "quant_linear_module"): + # TODO maybe not necessary to have special treatment? + child = child.quant_linear_module + + if not hasattr(new_module, "base_layer"): + new_module.weight = child.weight + if hasattr(child, "bias"): + new_module.bias = child.bias + + if getattr(child, "state", None) is not None: + if hasattr(new_module, "base_layer"): + new_module.base_layer.state = child.state + else: + new_module.state = child.state + new_module.to(child.weight.device) + + # dispatch to correct device + for name, module in new_module.named_modules(): + # if any(prefix in name for prefix in PREFIXES): + # module.to(child.weight.device) + if "ranknum" in name: + module.to(child.weight.device) + + def merge_and_unload(self, + merge=True, + progressbar: bool = False, + safe_merge: bool = False, + adapter_names = None,): + if merge: + if getattr(self, "quantization_method", None) == "gptq": + raise ValueError("Cannot merge layers when the model is gptq quantized") + + def merge_recursively(module): + # helper function to recursively merge the base_layer of the target + path = [] + layer = module + while hasattr(layer, "base_layer"): + path.append(layer) + layer = layer.base_layer + for layer_before, layer_after in zip(path[:-1], path[1:]): + layer_after.merge(safe_merge=safe_merge, adapter_names=adapter_names) + layer_before.base_layer = layer_after.base_layer + module.merge(safe_merge=safe_merge, adapter_names=adapter_names) + + key_list = [key for key, _ in self.named_modules()] + desc = "Unloading " + ("and merging " if merge else "") + "model" + + for key in tqdm(key_list, disable=not progressbar, desc=desc): + try: + parent, target, target_name = _get_submodules(self, key) + except AttributeError: + continue + + if hasattr(target, "base_layer"): + if merge: + merge_recursively(target) + self._replace_module(parent, target_name, target.get_base_layer(), target) + elif isinstance(target, ModulesToSaveWrapper): + # save any additional trainable modules part of `modules_to_save` + new_module = target.modules_to_save[target.active_adapter] + if hasattr(new_module, "base_layer"): + # check if the module is itself a tuner layer + if merge: + new_module.merge(safe_merge=safe_merge, adapter_names=adapter_names) + new_module = new_module.get_base_layer() + setattr(parent, target_name, new_module) +