From 5c7a6a3f9b2f490163aefff0b0223e1518a22373 Mon Sep 17 00:00:00 2001 From: MrForExample <62230687+MrForExample@users.noreply.github.com> Date: Sun, 21 Jan 2024 17:56:58 +0100 Subject: [PATCH] Update After RCFG experiment - Update readme to log the RCFG experiment - Refactor code - Add delta parameter on Animate_Anyone_Sampler node - Add ComfyUI Sampler progress bar --- README.md | 15 +- .../MooreAnimateAnyone_DDIM.json | 541 +++++++++--------- _test.py | 20 +- nodes.py | 10 +- src/models/main_diffuser.py | 162 +++--- src/models/main_model_patcher.py | 13 - 6 files changed, 363 insertions(+), 398 deletions(-) delete mode 100644 src/models/main_model_patcher.py diff --git a/README.md b/README.md index 0d0fc21..eae3023 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,15 @@ - I tried to break it down into as many modules as possible, so the workflow in ComfyUI would closely resemble the original pipeline from AnimateAnyone paper:
![_Example_Workflow\_Other_Imgs\AA_pipeline.png](_Example_Workflow/_Other_Imgs/AA_pipeline.png) -## Will Do Next -- Train a LCM Lora for denoise unet (**Estimated speed up: 5X**) -- Convert Model using [stable-fast](https://github.com/chengzeyi/stable-fast) (**Estimated speed up: 2X**) -- Implement the compoents (Residual CFG) proposed in [StreamDiffusion](https://github.com/cumulo-autumn/StreamDiffusion?tab=readme-ov-file) (**Estimated speed up: 2X**) -- Incorporate the implementation & Pre-trained Models from [Open-AnimateAnyone](https://github.com/guoqincode/Open-AnimateAnyone) & [AnimateAnyone](https://github.com/HumanAIGC/AnimateAnyone) once they released -- Training a new Model using better dataset to improve results quality (Optional, we'll see if there is any need for me to do it ;) +## Roadmap +- [x] Implement the compoents (Residual CFG) proposed in [StreamDiffusion](https://github.com/cumulo-autumn/StreamDiffusion?tab=readme-ov-file) (**Estimated speed up: 2X**) + - **Result:** + Generated result is not good enough when using DDIM Scheduler togather with RCFG, even though it speed up the generating process by about 4X.
+ In StreamDiffusion, RCFG works with LCM, could also be the case here, so keep it in another branch for now. +- [ ] Convert Model using [stable-fast](https://github.com/chengzeyi/stable-fast) (**Estimated speed up: 2X**) +- [ ] Train a LCM Lora for denoise unet (**Estimated speed up: 5X**) +- [ ] Incorporate the implementation & Pre-trained Models from [Open-AnimateAnyone](https://github.com/guoqincode/Open-AnimateAnyone) & [AnimateAnyone](https://github.com/HumanAIGC/AnimateAnyone) once they released +- [ ] Training a new Model using better dataset to improve results quality (Optional, we'll see if there is any need for me to do it ;) - Continuous research, always moving towards something better & faster🚀 ## Install (Will add it to ComfyUI Manager Soon!) diff --git a/_Example_Workflow/MooreAnimateAnyone_DDIM.json b/_Example_Workflow/MooreAnimateAnyone_DDIM.json index ef5c353..b52a618 100644 --- a/_Example_Workflow/MooreAnimateAnyone_DDIM.json +++ b/_Example_Workflow/MooreAnimateAnyone_DDIM.json @@ -1,6 +1,6 @@ { - "last_node_id": 26, - "last_link_id": 32, + "last_node_id": 31, + "last_link_id": 56, "nodes": [ { "id": 15, @@ -56,7 +56,7 @@ { "name": "samples", "type": "LATENT", - "link": 23 + "link": 56 }, { "name": "vae", @@ -79,121 +79,6 @@ "Node name for S&R": "VAEDecode" } }, - { - "id": 11, - "type": "[ComfyUI-3D] Load UNet2D ConditionModel", - "pos": [ - 1435, - 195 - ], - "size": { - "0": 407.1247863769531, - "1": 86.651123046875 - }, - "flags": {}, - "order": 0, - "mode": 0, - "outputs": [ - { - "name": "unet2d", - "type": "UNET2D", - "links": [ - 18 - ], - "shape": 3, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "[ComfyUI-3D] Load UNet2D ConditionModel" - }, - "widgets_values": [ - "./pretrained_weights/stable-diffusion-v1-5/unet/", - "./pretrained_weights/reference_unet.pth" - ] - }, - { - "id": 12, - "type": "[ComfyUI-3D] Load UNet3D ConditionModel", - "pos": [ - 1471, - 358 - ], - "size": { - "0": 409.384033203125, - "1": 106 - }, - "flags": {}, - "order": 1, - "mode": 0, - "outputs": [ - { - "name": "unet3d", - "type": "UNET3D", - "links": [ - 19 - ], - "shape": 3, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "[ComfyUI-3D] Load UNet3D ConditionModel" - }, - "widgets_values": [ - "./pretrained_weights/stable-diffusion-v1-5/unet/", - "./pretrained_weights/denoising_unet.pth", - "./pretrained_weights/motion_module.pth" - ] - }, - { - "id": 2, - "type": "VAEEncode", - "pos": [ - 1542, - 88 - ], - "size": { - "0": 210, - "1": 46 - }, - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [ - { - "name": "pixels", - "type": "IMAGE", - "link": 24 - }, - { - "name": "vae", - "type": "VAE", - "link": 1 - } - ], - "outputs": [ - { - "name": "LATENT", - "type": "LATENT", - "links": [ - 20 - ], - "shape": 3, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "VAEEncode", - "ttNbgOverride": { - "color": "#223", - "bgcolor": "#335", - "groupcolor": "#88A" - } - }, - "color": "#223", - "bgcolor": "#335" - }, { "id": 7, "type": "[ComfyUI-3D] Load Pose Guider", @@ -206,7 +91,7 @@ "1": 58 }, "flags": {}, - "order": 2, + "order": 0, "mode": 0, "outputs": [ { @@ -226,47 +111,6 @@ "./pretrained_weights/pose_guider.pth" ] }, - { - "id": 8, - "type": "[ComfyUI-3D] Pose Guider Encode", - "pos": [ - 1668, - 704 - ], - "size": { - "0": 292.20001220703125, - "1": 46 - }, - "flags": {}, - "order": 14, - "mode": 0, - "inputs": [ - { - "name": "pose_guider", - "type": "POSE_GUIDER", - "link": 5 - }, - { - "name": "pose_images", - "type": "IMAGE", - "link": 27 - } - ], - "outputs": [ - { - "name": "pose_latent", - "type": "POSE_LATENT", - "links": [ - 22 - ], - "shape": 3, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "[ComfyUI-3D] Pose Guider Encode" - } - }, { "id": 6, "type": "CLIPVisionLoader", @@ -279,7 +123,7 @@ "1": 58 }, "flags": {}, - "order": 3, + "order": 1, "mode": 0, "outputs": [ { @@ -299,47 +143,6 @@ "pytorch_model.bin" ] }, - { - "id": 5, - "type": "CLIPVisionEncode", - "pos": [ - 1544, - 592 - ], - "size": { - "0": 380.4000244140625, - "1": 46 - }, - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [ - { - "name": "clip_vision", - "type": "CLIP_VISION", - "link": 3 - }, - { - "name": "image", - "type": "IMAGE", - "link": 25 - } - ], - "outputs": [ - { - "name": "CLIP_VISION_OUTPUT", - "type": "CLIP_VISION_OUTPUT", - "links": [ - 21 - ], - "shape": 3, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "CLIPVisionEncode" - } - }, { "id": 4, "type": "LoadImage", @@ -352,7 +155,7 @@ "1": 314 }, "flags": {}, - "order": 4, + "order": 2, "mode": 0, "outputs": [ { @@ -391,7 +194,7 @@ "1": 58 }, "flags": {}, - "order": 5, + "order": 3, "mode": 0, "outputs": [ { @@ -426,7 +229,7 @@ "1": 58 }, "flags": {}, - "order": 6, + "order": 4, "mode": 0, "outputs": [ { @@ -461,7 +264,7 @@ "1": 60.091087341308594 }, "flags": {}, - "order": 7, + "order": 5, "mode": 0, "outputs": [ { @@ -655,7 +458,7 @@ "hidden": false, "paused": false, "params": { - "filename": "video_00019.mp4", + "filename": "video_00087.mp4", "subfolder": "AnimateAnyone", "type": "output", "format": "video/h265-mp4" @@ -664,15 +467,212 @@ } }, { - "id": 21, - "type": "[ComfyUI-3D] Animate Anyone Sampler", + "id": 11, + "type": "[ComfyUI-3D] Load UNet2D ConditionModel", "pos": [ - 2159, - 48 + 1435, + 195 ], "size": { - "0": 328.86407470703125, - "1": 594 + "0": 407.1247863769531, + "1": 86.651123046875 + }, + "flags": {}, + "order": 6, + "mode": 0, + "outputs": [ + { + "name": "unet2d", + "type": "UNET2D", + "links": [ + 51 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "[ComfyUI-3D] Load UNet2D ConditionModel" + }, + "widgets_values": [ + "./pretrained_weights/stable-diffusion-v1-5/unet/", + "./pretrained_weights/reference_unet.pth" + ] + }, + { + "id": 12, + "type": "[ComfyUI-3D] Load UNet3D ConditionModel", + "pos": [ + 1471, + 358 + ], + "size": { + "0": 409.384033203125, + "1": 106 + }, + "flags": {}, + "order": 7, + "mode": 0, + "outputs": [ + { + "name": "unet3d", + "type": "UNET3D", + "links": [ + 52 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "[ComfyUI-3D] Load UNet3D ConditionModel" + }, + "widgets_values": [ + "./pretrained_weights/stable-diffusion-v1-5/unet/", + "./pretrained_weights/denoising_unet.pth", + "./pretrained_weights/motion_module.pth" + ] + }, + { + "id": 2, + "type": "VAEEncode", + "pos": [ + 1542, + 88 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "pixels", + "type": "IMAGE", + "link": 24 + }, + { + "name": "vae", + "type": "VAE", + "link": 1 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 53 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEEncode", + "ttNbgOverride": { + "color": "#223", + "bgcolor": "#335", + "groupcolor": "#88A" + } + }, + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 5, + "type": "CLIPVisionEncode", + "pos": [ + 1544, + 592 + ], + "size": { + "0": 380.4000244140625, + "1": 46 + }, + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "clip_vision", + "type": "CLIP_VISION", + "link": 3 + }, + { + "name": "image", + "type": "IMAGE", + "link": 25 + } + ], + "outputs": [ + { + "name": "CLIP_VISION_OUTPUT", + "type": "CLIP_VISION_OUTPUT", + "links": [ + 54 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPVisionEncode" + } + }, + { + "id": 8, + "type": "[ComfyUI-3D] Pose Guider Encode", + "pos": [ + 1668, + 704 + ], + "size": { + "0": 292.20001220703125, + "1": 46 + }, + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "pose_guider", + "type": "POSE_GUIDER", + "link": 5 + }, + { + "name": "pose_images", + "type": "IMAGE", + "link": 27 + } + ], + "outputs": [ + { + "name": "pose_latent", + "type": "POSE_LATENT", + "links": [ + 55 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "[ComfyUI-3D] Pose Guider Encode" + } + }, + { + "id": 31, + "type": "[ComfyUI-3D] Animate Anyone Sampler", + "pos": [ + 2091, + 47 + ], + "size": { + "0": 315, + "1": 618 }, "flags": {}, "order": 15, @@ -681,27 +681,27 @@ { "name": "reference_unet", "type": "UNET2D", - "link": 18 + "link": 51 }, { "name": "denoising_unet", "type": "UNET3D", - "link": 19 + "link": 52 }, { "name": "ref_image_latent", "type": "LATENT", - "link": 20 + "link": 53 }, { "name": "clip_image_embeds", "type": "CLIP_VISION_OUTPUT", - "link": 21 + "link": 54 }, { "name": "pose_latent", "type": "POSE_LATENT", - "link": 22 + "link": 55 } ], "outputs": [ @@ -709,7 +709,7 @@ "name": "latent", "type": "LATENT", "links": [ - 23 + 56 ], "shape": 3, "slot_index": 0 @@ -723,22 +723,23 @@ "fixed", 20, 3.5, + 1, 24, 1, 4, 1, 1, "DDIM", - 0.0008500000000000001, + 0.00085, 0.012, "linear", "v_prediction", "trailing", 1, false, - "cammy_white_v1.safetensors", + true, false, - "lcm-lora-sdv1-5.safetensors" + "cammy_white_v1.safetensors" ] }, { @@ -856,54 +857,6 @@ 0, "IMAGE" ], - [ - 18, - 11, - 0, - 21, - 0, - "UNET2D" - ], - [ - 19, - 12, - 0, - 21, - 1, - "UNET3D" - ], - [ - 20, - 2, - 0, - 21, - 2, - "LATENT" - ], - [ - 21, - 5, - 0, - 21, - 3, - "CLIP_VISION_OUTPUT" - ], - [ - 22, - 8, - 0, - 21, - 4, - "POSE_LATENT" - ], - [ - 23, - 21, - 0, - 14, - 0, - "LATENT" - ], [ 24, 22, @@ -975,6 +928,54 @@ 23, 2, "INT" + ], + [ + 51, + 11, + 0, + 31, + 0, + "UNET2D" + ], + [ + 52, + 12, + 0, + 31, + 1, + "UNET3D" + ], + [ + 53, + 2, + 0, + 31, + 2, + "LATENT" + ], + [ + 54, + 5, + 0, + 31, + 3, + "CLIP_VISION_OUTPUT" + ], + [ + 55, + 8, + 0, + 31, + 4, + "POSE_LATENT" + ], + [ + 56, + 31, + 0, + 14, + 0, + "LATENT" ] ], "groups": [], diff --git a/_test.py b/_test.py index 9b8e6f0..be444e6 100644 --- a/_test.py +++ b/_test.py @@ -1,9 +1,13 @@ -class MyClass: - def my_function(self): - self.x = 123 - pass +import inspect +from diffusers.schedulers import ( + DDIMScheduler, + DPMSolverMultistepScheduler, + LCMScheduler, + EulerDiscreteScheduler, + EulerAncestralDiscreteScheduler, + LMSDiscreteScheduler, + PNDMScheduler, +) -mc = MyClass() -mc.my_function() -if hasattr(mc, 'z'): - print('MyClass has x') \ No newline at end of file +print("clip_samples" in inspect.signature(DDIMScheduler.__init__).parameters) + \ No newline at end of file diff --git a/nodes.py b/nodes.py index b0fe065..28f5a40 100644 --- a/nodes.py +++ b/nodes.py @@ -18,12 +18,10 @@ from diffusers.schedulers import ( PNDMScheduler, ) -from .src.models.mutual_self_attention import ReferenceAttentionControl from .src.models.pose_guider import PoseGuider from .src.models.unet_2d_condition import UNet2DConditionModel from .src.models.unet_3d import UNet3DConditionModel -from .src.models.main_model_patcher import AnimateAnyoneModelPatcher -from .src.models.main_diffuser import AADiffusion, CFGType +from .src.models.main_diffuser import AADiffusion ROOT_PATH = os.path.join(comfy_paths.get_folder_paths("custom_nodes")[0], "./ComfyUI-AnimateAnyone-Evolved") DEFAULT_CONFIG_PATH = os.path.join(ROOT_PATH, "./configs/default.yaml") @@ -57,8 +55,6 @@ class Animate_Anyone_Sampler: "steps": ("INT", {"default": 20, "min": 1, "max": 10000}), "cfg": ("FLOAT", {"default": 3.5, "min": 0.0, "max": 100.0, "step":0.1, "round": 0.01}), "delta": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 100.0, "step":0.1, "round": 0.01}), - "cfg_type": (["rcfg_self_negative", "rcfg_one_time_negative", "full_double_pass"],), - "steps_rcfg": ("INT", {"default": 3, "min": 1, "max": 10000}), "context_frames": ("INT", {"default": 24, "min": 1}), "context_stride": ("INT", {"default": 1, "min": 1}), "context_overlap": ("INT", {"default": 4, "min": 0}), @@ -100,9 +96,7 @@ class Animate_Anyone_Sampler: seed, steps, cfg, - steps_rcfg, delta, - cfg_type, context_frames, context_stride, context_overlap, @@ -159,8 +153,6 @@ class Animate_Anyone_Sampler: steps, cfg, delta, - CFGType[cfg_type], - steps_rcfg, ref_image_latent, pose_latent, encoder_hidden_states, diff --git a/src/models/main_diffuser.py b/src/models/main_diffuser.py index 7d4222d..038e9c8 100644 --- a/src/models/main_diffuser.py +++ b/src/models/main_diffuser.py @@ -4,8 +4,10 @@ import math from enum import Enum from typing import Callable, List, Optional, Union +import comfy.utils + import torch -from diffusers import DiffusionPipeline +from diffusers import DiffusionPipeline, StableDiffusionPipeline from diffusers.loaders import LoraLoaderMixin from diffusers.schedulers import ( DDIMScheduler, @@ -20,17 +22,12 @@ from diffusers.utils.torch_utils import randn_tensor from .mutual_self_attention import ReferenceAttentionControl from ..utils.util import get_tensor_interpolation_method, get_context_scheduler - -class CFGType(Enum): - rcfg_self_negative = 1 - rcfg_one_time_negative = 2 - full_double_pass = 3 class AADiffusion(DiffusionPipeline, LoraLoaderMixin): def __init__( self, reference_unet, - denoising_unet, + unet, scheduler: Union[ DDIMScheduler, LCMScheduler, @@ -44,11 +41,11 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): super().__init__() self.register_modules( reference_unet=reference_unet, - denoising_unet=denoising_unet, + unet=unet, scheduler=scheduler, ) self.reference_unet = reference_unet - self.denoising_unet = denoising_unet + self.unet = unet self.scheduler = scheduler self.noise_pred_uncond_prev = None @@ -172,44 +169,38 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): return new_latents - def calculate_residual_noise(self, t, latents, pred_original_sample): - # compute the residual empty/negative condition noise sample - alpha_prod_t = self.scheduler.alphas_cumprod[t].to(latents.device) - beta_prod_t = 1 - alpha_prod_t + def perform_guidance( + self, + noise_pred, + counter, + cfg, + delta, + do_double_pass, + ): - if self.scheduler.config.prediction_type == "epsilon": - # "predicted x_0" of formula (12) from https://arxiv.org/pdf/2010.02502.pdf - # rearranged from formular: pred_original_sample = (latents - beta_prod_t ** (0.5) * noise_pred) / alpha_prod_t ** (0.5) - noise_pred_uncond_prev = (latents - alpha_prod_t ** (0.5) * pred_original_sample) / beta_prod_t ** (0.5) - - elif self.scheduler.config.prediction_type == "v_prediction": - # v_prediction: (see section 2.4 of [Imagen Video](https://imagen.research.google/video/paper.pdf) - # rearranged from formular: pred_original_sample = (alpha_prod_t ** (0.5) * latents - (beta_prod_t ** (0.5) * noise_pred - noise_pred_uncond_prev = (alpha_prod_t ** (0.5) * latents - pred_original_sample) / beta_prod_t ** (0.5) - - return noise_pred_uncond_prev + # perform CFG + if do_double_pass: + noise_pred_uncond, noise_pred_cond = (noise_pred / counter).chunk(2) + else: + noise_pred_cond = noise_pred_uncond = noise_pred / counter + cfg = 0.0 + noise_pred = delta * noise_pred_uncond + cfg * (noise_pred_cond - delta * noise_pred_uncond) + + return noise_pred def denoise_all_one_step( self, t, latents, encoder_hidden_states, - uncond_encoder_hidden_states, pose_latent, global_context, + do_double_pass, device, ): noise_pred = torch.zeros( ( - latents.shape[0], - *latents.shape[1:], - ), - device=device, - dtype=latents.dtype, - ) - noise_pred_uncond = torch.zeros( - ( - latents.shape[0], + latents.shape[0] * (2 if do_double_pass else 1), *latents.shape[1:], ), device=device, @@ -226,6 +217,7 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): latent_model_input = ( torch.cat([latents[:, :, c] for c in context]) # Concatenates the context in the same batch .to(device) + .repeat(2 if do_double_pass else 1, 1, 1, 1, 1) ) latent_model_input = self.scheduler.scale_model_input( latent_model_input, t @@ -233,66 +225,56 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): b, c, f, h, w = latent_model_input.shape latent_pose_input = torch.cat( [pose_latent[:, :, c] for c in context] - ) - pred = self.denoising_unet( + ).repeat(2 if do_double_pass else 1, 1, 1, 1, 1) + pred = self.unet( latent_model_input, # torch.Size([2, 4, 24, 96, 64]) t, encoder_hidden_states=encoder_hidden_states[:b], pose_cond_fea=latent_pose_input, # torch.Size([2, 320, 24, 96, 64]) return_dict=False, )[0] - pred_uncond = self.denoising_unet( - latent_model_input, # torch.Size([2, 4, 24, 96, 64]) - t, - encoder_hidden_states=uncond_encoder_hidden_states[:b], - pose_cond_fea=latent_pose_input, # torch.Size([2, 320, 24, 96, 64]) - return_dict=False, - )[0] for j, c in enumerate(context): noise_pred[:, :, c] = noise_pred[:, :, c] + pred - noise_pred_uncond[:, :, c] = noise_pred_uncond[:, :, c] + pred_uncond counter[:, :, c] = counter[:, :, c] + 1 - return noise_pred, noise_pred_uncond, counter + return noise_pred, counter def solve_one_step( self, t, latents, encoder_hidden_states, - uncond_encoder_hidden_states, pose_latent, global_context, cfg, delta, - do_rcfg, - noise_pred_uncond_prev, + do_double_pass, device, extra_step_kwargs, ): - noise_pred, noise_pred_uncond, counter = self.denoise_all_one_step( - t, - latents, - encoder_hidden_states, - uncond_encoder_hidden_states, - pose_latent, - global_context, - device, + noise_pred, counter = self.denoise_all_one_step( + t=t, + latents=latents, + encoder_hidden_states=encoder_hidden_states, + pose_latent=pose_latent, + global_context=global_context, + do_double_pass=do_double_pass, + device=device, ) - # CFG - noise_pred_cond = noise_pred / counter - noise_pred_uncond = noise_pred_uncond / counter - noise_pred = delta * noise_pred_uncond + cfg * (noise_pred_cond - delta * noise_pred_uncond) + noise_pred = self.perform_guidance( + noise_pred=noise_pred, + counter=counter, + cfg=cfg, + delta=delta, + do_double_pass=do_double_pass, + ) scheduler_output = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs) - - if do_rcfg: - noise_pred_uncond_prev = self.calculate_residual_noise(t, latents, scheduler_output.pred_original_sample) - return scheduler_output.prev_sample, noise_pred_uncond_prev + return scheduler_output.prev_sample def denoise_loop( self, @@ -305,13 +287,16 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): cfg, delta, do_double_pass, - do_rcfg, interpolation_factor, device, extra_step_kwargs, ): # Prepare confitional embeds - uncond_encoder_hidden_states = torch.zeros_like(encoder_hidden_states) + if do_double_pass: + uncond_encoder_hidden_states = torch.zeros_like(encoder_hidden_states) + encoder_hidden_states=torch.cat( + [uncond_encoder_hidden_states, encoder_hidden_states], dim=0 + ) # Prepare reference attention control reference_control_writer = ReferenceAttentionControl( @@ -321,7 +306,7 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): fusion_blocks="full", ) reference_control_reader = ReferenceAttentionControl( - self.denoising_unet, + self.unet, do_classifier_free_guidance=do_double_pass, mode="read", fusion_blocks="full", @@ -330,10 +315,7 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): self.reference_unet( ref_image_latent.repeat(2 if do_double_pass else 1, 1, 1, 1), torch.zeros(size=(1,), dtype=int, device=device), - #encoder_hidden_states=encoder_hidden_states, - encoder_hidden_states=torch.cat( - [uncond_encoder_hidden_states, encoder_hidden_states], dim=0 - ) if do_double_pass else encoder_hidden_states, + encoder_hidden_states=encoder_hidden_states, return_dict=False, ) reference_control_reader.update(reference_control_writer) @@ -342,25 +324,26 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): self.scheduler.set_timesteps(loop_steps, device=device) timesteps = self.scheduler.timesteps + comfy_pbar = comfy.utils.ProgressBar(loop_steps) + with self.progress_bar(total=loop_steps) as progress_bar: for i, t in enumerate(timesteps): - latents, self.noise_pred_uncond_prev = self.solve_one_step( - t, - latents, - encoder_hidden_states, - uncond_encoder_hidden_states, - pose_latent, - global_context, - cfg, - delta, - do_rcfg, - self.noise_pred_uncond_prev, - device, - extra_step_kwargs, + latents = self.solve_one_step( + t=t, + latents=latents, + encoder_hidden_states=encoder_hidden_states, + pose_latent=pose_latent, + global_context=global_context, + cfg=cfg, + delta=delta, + do_double_pass=do_double_pass, + device=device, + extra_step_kwargs=extra_step_kwargs, ) progress_bar.update() + comfy_pbar.update_absolute(i + 1) if interpolation_factor > 0: latents = self.interpolate_latents(latents, interpolation_factor, device) @@ -376,8 +359,6 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): steps, cfg, delta, - cfg_type, - steps_rcfg, ref_image_latent, pose_latent, encoder_hidden_states, @@ -391,9 +372,7 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): interpolation_factor=1, ): - do_classifier_free_guidance = cfg > 0 - do_double_pass = do_classifier_free_guidance and cfg_type == CFGType.full_double_pass - do_rcfg = do_classifier_free_guidance and (cfg_type == CFGType.rcfg_self_negative or cfg_type == CFGType.rcfg_one_time_negative) + do_double_pass = cfg > 0 device = pose_latent.device generator=torch.manual_seed(seed) @@ -448,7 +427,7 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): # Prepare initial latents latents = self.prepare_latents( batch_size=pose_latent.shape[0], - num_channels_latents=self.denoising_unet.config.in_channels, + num_channels_latents=self.unet.config.in_channels, video_length=video_length, height=pose_latent.shape[-2], width=pose_latent.shape[-1], @@ -467,8 +446,7 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin): global_context=global_context, cfg=cfg, delta=delta, - do_double_pass=False, - do_rcfg=False, + do_double_pass=do_double_pass, interpolation_factor=interpolation_factor, device=device, extra_step_kwargs=extra_step_kwargs, diff --git a/src/models/main_model_patcher.py b/src/models/main_model_patcher.py deleted file mode 100644 index 4ba4731..0000000 --- a/src/models/main_model_patcher.py +++ /dev/null @@ -1,13 +0,0 @@ -import torch - -from comfy.model_patcher import ModelPatcher - -from .unet_3d import UNet3DConditionModel - -class AnimateAnyoneModelPatcher(ModelPatcher): - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.model: UNet3DConditionModel = self.model - - \ No newline at end of file