24 Commits
Author SHA1 Message Date
bubbliiiing 2dda7b2943 Update Training Readme 2025-01-22 07:26:08 +00:00
bubbliiiing 3f1a1cbd66 Merge branch 'main' into v5.1 2025-01-22 07:17:10 +00:00
hkunzhe 4839daa1ff support vae gradient checkpointing in reward training 2025-01-22 14:35:25 +08:00
bubbliiiing 1509f1c383 Update ui 2025-01-22 06:04:26 +00:00
bubbliiiing 81583f10f5 Update Readme 2025-01-22 05:50:23 +00:00
bubbliiiing a676e1cf7d Update Demo 2025-01-22 05:48:02 +00:00
bubbliiiing 0cdc88b1a0 Update Readme && Remove to in prediction 2025-01-22 04:30:24 +00:00
hkunzhe 2a97f7632b fix extract frames in compute_semantic_consistency 2025-01-21 20:10:28 +08:00
bubbliiiing d5f8ecdf1c Merge branch 'v5.1' of github.com:aigc-apps/EasyAnimate into v5.1 2025-01-21 10:02:01 +00:00
bubbliiiing eab152ac4b Update Readme 2025-01-21 10:01:44 +00:00
hkunzhe 68b01135cf update reward training 2025-01-21 14:37:28 +08:00
bubbliiiing 286b9617eb Delete files 2025-01-17 02:40:06 +00:00
bubbliiiing 4d8e8a1320 Update Comment 2025-01-17 02:27:05 +00:00
bubbliiiing 96430fcdf2 Update ComfyUI 2025-01-17 02:24:46 +00:00
bubbliiiing 57a963e065 Update V5.1 training Code 2025-01-17 02:23:33 +00:00
bubbliiiing 83c2da3f58 Update V5.1 and mix multi text_encoders to one pipeline 2025-01-17 02:18:48 +00:00
hkunzhe 3f9a13ff63 update reward training 2025-01-10 16:47:57 +08:00
hkunzhe dd01a9bfee update train_reward_lora.py 2024-12-27 10:24:21 +08:00
bubbliiiing 1ca8119b1f Merge branch 'main' into v5.1 2024-12-26 07:16:54 +00:00
bubbliiiing fece877980 Fix bug in t2v 2024-12-26 07:15:55 +00:00
hkunzhe a4443d40ef add image recaptioning 2024-12-25 11:15:51 +08:00
bubbliiiing da09cc4983 Update Flow 2024-12-24 09:10:25 +00:00
bubbliiiing 938aac0c5f Update Flow 2024-12-24 09:09:49 +00:00
bubbliiiing 2ac1956384 Update Flow 2024-12-24 07:25:59 +00:00
16 changed files with 344 additions and 605 deletions
+2 -7
View File
@@ -24,11 +24,6 @@ if __name__ == "__main__":
# EasyAnimateV4, V5 support "model_cpu_offload" "model_cpu_offload_and_qfloat8" "sequential_cpu_offload"
# EasyAnimateV5.1 support "model_cpu_offload" "model_cpu_offload_and_qfloat8"
GPU_memory_mode = "model_cpu_offload_and_qfloat8"
# EasyAnimateV5.1 support TeaCache.
enable_teacache = True
# Recommended to be set between 0.05 and 0.1. A larger threshold can cache more steps, speeding up the inference process,
# but it may cause slight differences between the generated content and the original content.
teacache_threshold = 0.1
# Use torch.float16 if GPU does not support torch.bfloat16
# ome graphics cards, such as v100, 2080ti, do not support torch.bfloat16
weight_dtype = torch.bfloat16
@@ -49,11 +44,11 @@ if __name__ == "__main__":
savedir_sample = "samples"
if ui_mode == "modelscope":
demo, controller = ui_modelscope(model_type, edition, config_path, model_name, savedir_sample, GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype)
demo, controller = ui_modelscope(model_type, edition, config_path, model_name, savedir_sample, GPU_memory_mode, weight_dtype)
elif ui_mode == "eas":
demo, controller = ui_eas(edition, config_path, model_name, savedir_sample)
else:
demo, controller = ui(GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype)
demo, controller = ui(GPU_memory_mode, weight_dtype)
# launch gradio
app, _, _ = demo.queue(status_update_rate=1).launch(
+4 -19
View File
@@ -442,7 +442,7 @@ class EasyAnimateT2VSampler:
FUNCTION = "process"
CATEGORY = "EasyAnimateWrapper"
def process(self, easyanimate_model, prompt, negative_prompt, video_length, width, height, is_image, seed, steps, cfg, scheduler, teacache_threshold=0.10, enable_teacache=False):
def process(self, easyanimate_model, prompt, negative_prompt, video_length, width, height, is_image, seed, steps, cfg, scheduler):
global transformer_cpu_cache
global lora_path_before
device = mm.get_torch_device()
@@ -459,9 +459,6 @@ class EasyAnimateT2VSampler:
# Load Sampler
pipeline.scheduler = all_cheduler_dict[scheduler].from_pretrained(model_name, subfolder='scheduler')
if enable_teacache:
pipeline.transformer.enable_teacache(steps, teacache_threshold)
generator= torch.Generator(device).manual_seed(seed)
video_length = 1 if is_image else video_length
@@ -591,8 +588,6 @@ class EasyAnimateV5_T2VSampler(EasyAnimateT2VSampler):
"default": 'Flow'
}
),
"teacache_threshold": ("FLOAT", {"default": 0.10, "min": 0.00, "max": 1.00, "step": 0.005}),
"enable_teacache":([False, True], {"default": True,}),
},
}
@@ -654,7 +649,7 @@ class EasyAnimateI2VSampler:
FUNCTION = "process"
CATEGORY = "EasyAnimateWrapper"
def process(self, easyanimate_model, prompt, negative_prompt, video_length, base_resolution, seed, steps, cfg, scheduler, start_img=None, end_img=None, teacache_threshold=0.10, enable_teacache=False):
def process(self, easyanimate_model, prompt, negative_prompt, video_length, base_resolution, seed, steps, cfg, scheduler, start_img=None, end_img=None):
global transformer_cpu_cache
global lora_path_before
device = mm.get_torch_device()
@@ -679,9 +674,6 @@ class EasyAnimateI2VSampler:
# Load Sampler
pipeline.scheduler = all_cheduler_dict[scheduler].from_pretrained(model_name, subfolder='scheduler')
if enable_teacache:
pipeline.transformer.enable_teacache(steps, teacache_threshold)
generator= torch.Generator(device).manual_seed(seed)
with torch.no_grad():
@@ -788,9 +780,7 @@ class EasyAnimateV5_I2VSampler(EasyAnimateI2VSampler):
{
"default": 'Flow'
}
),
"teacache_threshold": ("FLOAT", {"default": 0.10, "min": 0.00, "max": 1.00, "step": 0.005}),
"enable_teacache":([False, True], {"default": True,}),
)
},
"optional":{
"start_img": ("IMAGE",),
@@ -859,7 +849,7 @@ class EasyAnimateV2VSampler:
FUNCTION = "process"
CATEGORY = "EasyAnimateWrapper"
def process(self, easyanimate_model, prompt, negative_prompt, video_length, base_resolution, seed, steps, cfg, denoise_strength, scheduler, validation_video=None, control_video=None, ref_image=None, camera_conditions=None, teacache_threshold=0.10, enable_teacache=False):
def process(self, easyanimate_model, prompt, negative_prompt, video_length, base_resolution, seed, steps, cfg, denoise_strength, scheduler, validation_video=None, control_video=None, ref_image=None, camera_conditions=None):
global transformer_cpu_cache
global lora_path_before
@@ -902,9 +892,6 @@ class EasyAnimateV2VSampler:
# Load Sampler
pipeline.scheduler = all_cheduler_dict[scheduler].from_pretrained(model_name, subfolder='scheduler')
if enable_teacache:
pipeline.transformer.enable_teacache(steps, teacache_threshold)
generator= torch.Generator(device).manual_seed(seed)
with torch.no_grad():
@@ -1046,8 +1033,6 @@ class EasyAnimateV5_V2VSampler(EasyAnimateV2VSampler):
"default": 'Flow'
}
),
"teacache_threshold": ("FLOAT", {"default": 0.10, "min": 0.00, "max": 1.00, "step": 0.005}),
"enable_teacache":([False, True], {"default": True,}),
},
"optional":{
"validation_video": ("IMAGE",),
@@ -214,6 +214,89 @@
"bf16"
]
},
{
"id": 131,
"type": "EasyAnimateV5_V2VSampler",
"pos": {
"0": 821,
"1": 242
},
"size": {
"0": 504,
"1": 350
},
"flags": {},
"order": 12,
"mode": 0,
"inputs": [
{
"name": "easyanimate_model",
"type": "EASYANIMATESMODEL",
"link": 271
},
{
"name": "prompt",
"type": "STRING_PROMPT",
"link": 272
},
{
"name": "negative_prompt",
"type": "STRING_PROMPT",
"link": 273
},
{
"name": "validation_video",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "control_video",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "ref_image",
"type": "IMAGE",
"link": 274,
"shape": 7
},
{
"name": "camera_conditions",
"type": "STRING",
"link": 275,
"widget": {
"name": "camera_conditions"
},
"shape": 7
}
],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
276
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EasyAnimateV5_V2VSampler"
},
"widgets_values": [
49,
512,
43,
"fixed",
43,
6,
1,
"Flow",
""
]
},
{
"id": 129,
"type": "CameraTrajectoryFromChaoJie",
@@ -371,7 +454,7 @@
},
"size": [
390,
546
535.4285714285714
],
"flags": {},
"order": 13,
@@ -449,10 +532,10 @@
"0": 819,
"1": 658
},
"size": {
"0": 517.6458129882812,
"1": 93.61251831054688
},
"size": [
517.6458089787227,
93.61251593411134
],
"flags": {},
"order": 10,
"mode": 0,
@@ -466,91 +549,6 @@
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 131,
"type": "EasyAnimateV5_V2VSampler",
"pos": {
"0": 822,
"1": 211
},
"size": {
"0": 504,
"1": 394
},
"flags": {},
"order": 12,
"mode": 0,
"inputs": [
{
"name": "easyanimate_model",
"type": "EASYANIMATESMODEL",
"link": 271
},
{
"name": "prompt",
"type": "STRING_PROMPT",
"link": 272
},
{
"name": "negative_prompt",
"type": "STRING_PROMPT",
"link": 273
},
{
"name": "validation_video",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "control_video",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "ref_image",
"type": "IMAGE",
"link": 274,
"shape": 7
},
{
"name": "camera_conditions",
"type": "STRING",
"link": 275,
"widget": {
"name": "camera_conditions"
},
"shape": 7
}
],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
276
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EasyAnimateV5_V2VSampler"
},
"widgets_values": [
49,
512,
43,
"fixed",
43,
6,
1,
"Flow",
0.10,
true,
""
]
}
],
"links": [
@@ -664,16 +662,11 @@
"config": {},
"extra": {
"ds": {
"scale": 1.1,
"scale": 0.6209213230591558,
"offset": [
-465.8996857769304,
51.92597569190605
417.7460035994012,
-70.36580413723722
]
},
"node_versions": {
"EasyAnimate": "de24d49f07f6d9b12b4e98de98ec959a8b44b989",
"comfy-core": "v0.2.7-3-g8afb97c",
"ComfyUI-VideoHelperSuite": "70faa9bcef65932ab72e7404d6373fb300013a2e"
}
},
"version": 0.4
@@ -211,6 +211,86 @@
"color": "#432",
"bgcolor": "#653"
},
{
"id": 106,
"type": "VHS_VideoCombine",
"pos": {
"0": 1497,
"1": 204
},
"size": [
390,
546
],
"flags": {},
"order": 14,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 261,
"slot_index": 0,
"label": "图像",
"shape": 7
},
{
"name": "audio",
"type": "AUDIO",
"link": null,
"label": "音频",
"shape": 7
},
{
"name": "meta_batch",
"type": "VHS_BatchManager",
"link": null,
"label": "批次管理",
"shape": 7
},
{
"name": "vae",
"type": "VAE",
"link": null,
"shape": 7
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null,
"slot_index": 0,
"shape": 3,
"label": "文件名"
}
],
"properties": {
"Node name for S&R": "VHS_VideoCombine"
},
"widgets_values": {
"frame_rate": 8,
"loop_count": 0,
"filename_prefix": "EasyAnimate",
"format": "video/h264-mp4",
"pix_fmt": "yuv420p",
"crf": 22,
"save_metadata": true,
"pingpong": false,
"save_output": true,
"videopreview": {
"hidden": false,
"paused": false,
"params": {
"filename": "EasyAnimate_00105.mp4",
"subfolder": "",
"type": "output",
"format": "video/h264-mp4",
"frame_rate": 8
}
}
}
},
{
"id": 99,
"type": "LoadEasyAnimateModel",
@@ -241,12 +321,96 @@
},
"widgets_values": [
"EasyAnimateV5.1-12b-zh-Control",
"model_cpu_offload_and_qfloat8",
"model_cpu_offload",
"Control",
"easyanimate_video_v5.1_magvit_qwen.yaml",
"bf16"
]
},
{
"id": 111,
"type": "EasyAnimateV5_V2VSampler",
"pos": {
"0": 905,
"1": 201
},
"size": {
"0": 504,
"1": 350
},
"flags": {},
"order": 13,
"mode": 0,
"inputs": [
{
"name": "easyanimate_model",
"type": "EASYANIMATESMODEL",
"link": 256
},
{
"name": "prompt",
"type": "STRING_PROMPT",
"link": 257
},
{
"name": "negative_prompt",
"type": "STRING_PROMPT",
"link": 258
},
{
"name": "validation_video",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "control_video",
"type": "IMAGE",
"link": 259,
"shape": 7
},
{
"name": "ref_image",
"type": "IMAGE",
"link": 260,
"shape": 7
},
{
"name": "camera_conditions",
"type": "STRING",
"link": null,
"widget": {
"name": "camera_conditions"
},
"shape": 7
}
],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
261,
263
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EasyAnimateV5_V2VSampler"
},
"widgets_values": [
49,
512,
43,
"fixed",
50,
6,
1,
"Flow",
""
]
},
{
"id": 97,
"type": "SplineEditor",
@@ -334,7 +498,7 @@
},
"size": [
530,
310
650.4
],
"flags": {},
"order": 12,
@@ -457,10 +621,10 @@
"0": 1140.1396484375,
"1": 909.9193115234375
},
"size": {
"0": 315,
"1": 82
},
"size": [
315,
82
],
"flags": {
"collapsed": false
},
@@ -551,7 +715,7 @@
},
"size": [
530,
310
630
],
"flags": {},
"order": 16,
@@ -626,10 +790,10 @@
"0": 1544.139404296875,
"1": 1047.919189453125
},
"size": {
"0": 645,
"1": 812
},
"size": [
645,
812
],
"flags": {},
"order": 9,
"mode": 0,
@@ -694,172 +858,6 @@
null,
null
]
},
{
"id": 111,
"type": "EasyAnimateV5_V2VSampler",
"pos": {
"0": 876,
"1": 147
},
"size": {
"0": 504,
"1": 394
},
"flags": {},
"order": 13,
"mode": 0,
"inputs": [
{
"name": "easyanimate_model",
"type": "EASYANIMATESMODEL",
"link": 256
},
{
"name": "prompt",
"type": "STRING_PROMPT",
"link": 257
},
{
"name": "negative_prompt",
"type": "STRING_PROMPT",
"link": 258
},
{
"name": "validation_video",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "control_video",
"type": "IMAGE",
"link": 259,
"shape": 7
},
{
"name": "ref_image",
"type": "IMAGE",
"link": 260,
"shape": 7
},
{
"name": "camera_conditions",
"type": "STRING",
"link": null,
"widget": {
"name": "camera_conditions"
},
"shape": 7
}
],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [
261,
263
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EasyAnimateV5_V2VSampler"
},
"widgets_values": [
49,
512,
43,
"fixed",
50,
6,
1,
"Flow",
0.10,
true,
""
]
},
{
"id": 106,
"type": "VHS_VideoCombine",
"pos": {
"0": 1496,
"1": 153
},
"size": [
390,
310
],
"flags": {},
"order": 14,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 261,
"slot_index": 0,
"label": "图像",
"shape": 7
},
{
"name": "audio",
"type": "AUDIO",
"link": null,
"label": "音频",
"shape": 7
},
{
"name": "meta_batch",
"type": "VHS_BatchManager",
"link": null,
"label": "批次管理",
"shape": 7
},
{
"name": "vae",
"type": "VAE",
"link": null,
"shape": 7
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null,
"slot_index": 0,
"shape": 3,
"label": "文件名"
}
],
"properties": {
"Node name for S&R": "VHS_VideoCombine"
},
"widgets_values": {
"frame_rate": 8,
"loop_count": 0,
"filename_prefix": "EasyAnimate",
"format": "video/h264-mp4",
"pix_fmt": "yuv420p",
"crf": 22,
"save_metadata": true,
"pingpong": false,
"save_output": true,
"videopreview": {
"hidden": false,
"paused": false,
"params": {
"filename": "EasyAnimate_00105.mp4",
"subfolder": "",
"type": "output",
"format": "video/h264-mp4",
"frame_rate": 8
}
}
}
}
],
"links": [
@@ -1029,17 +1027,11 @@
"config": {},
"extra": {
"ds": {
"scale": 1.1,
"scale": 0.5054470284993016,
"offset": [
-465.8996857769304,
51.92597569190605
-239.62344289721364,
114.98345539297088
]
},
"node_versions": {
"EasyAnimate": "de24d49f07f6d9b12b4e98de98ec959a8b44b989",
"comfy-core": "v0.2.7-3-g8afb97c",
"ComfyUI-KJNodes": "4c5c26a2c91de356212419ac8bc7fcf9869527e9",
"ComfyUI-VideoHelperSuite": "70faa9bcef65932ab72e7404d6373fb300013a2e"
}
},
"version": 0.4
@@ -289,9 +289,7 @@
"fixed",
50,
6,
"Flow",
0.10,
true
"Flow"
]
},
{
@@ -84,9 +84,7 @@
"fixed",
50,
6,
"Flow",
0.10,
true
"Flow"
]
},
{
@@ -305,8 +305,6 @@
6,
0.7000000000000001,
"Flow",
0.10,
true,
""
]
},
@@ -154,7 +154,7 @@
},
"size": [
390.9534912109375,
546.5720947265625
973.1686096191406
],
"flags": {},
"order": 9,
@@ -234,7 +234,7 @@
},
"size": {
"0": 336,
"1": 394
"1": 350
},
"flags": {},
"order": 8,
@@ -275,15 +275,6 @@
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "camera_conditions",
"type": "STRING",
"link": null,
"widget": {
"name": "camera_conditions"
},
"shape": 7
}
],
"outputs": [
@@ -309,8 +300,6 @@
6,
1,
"Flow",
0.10,
true,
""
]
},
@@ -360,7 +349,7 @@
},
"size": [
252.056640625,
262
685.7
],
"flags": {},
"order": 6,
@@ -443,10 +432,10 @@
"0": -192,
"1": -293
},
"size": {
"0": 427.074951171875,
"1": 143.9142608642578
},
"size": [
427.074951171875,
143.9142608642578
],
"flags": {},
"order": 7,
"mode": 0,
@@ -506,14 +495,14 @@
],
"groups": [
{
"title": "Upload Your Video",
"title": "Prompts",
"bounding": [
218,
385,
487,
789
-127,
450,
483
],
"color": "#a1309b",
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
@@ -530,14 +519,14 @@
"flags": {}
},
{
"title": "Prompts",
"title": "Upload Your Video",
"bounding": [
218,
-127,
450,
483
385,
487,
789
],
"color": "#3f789e",
"color": "#a1309b",
"font_size": 24,
"flags": {}
}
@@ -545,18 +534,14 @@
"config": {},
"extra": {
"ds": {
"scale": 0.8264462809917354,
"scale": 0.5644739300537782,
"offset": [
-156.13347668602108,
275.2525393282698
634.4708817322136,
478.05663679245043
]
},
"workspace_info": {
"id": "776b62b4-bd17-4ed3-9923-b7aad000b1ea"
},
"node_versions": {
"EasyAnimate": "de24d49f07f6d9b12b4e98de98ec959a8b44b989",
"ComfyUI-VideoHelperSuite": "70faa9bcef65932ab72e7404d6373fb300013a2e"
}
},
"version": 0.4
+1 -19
View File
@@ -226,21 +226,6 @@
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "ref_image",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "camera_conditions",
"type": "STRING",
"link": null,
"widget": {
"name": "camera_conditions"
},
"shape": 7
}
],
"outputs": [
@@ -265,10 +250,7 @@
35,
7,
0.7,
"DDIM",
0.10,
true,
""
"DDIM"
]
},
{
@@ -391,21 +391,6 @@
"type": "IMAGE",
"link": 53,
"shape": 7
},
{
"name": "ref_image",
"type": "IMAGE",
"link": null,
"shape": 7
},
{
"name": "camera_conditions",
"type": "STRING",
"link": null,
"widget": {
"name": "camera_conditions"
},
"shape": 7
}
],
"outputs": [
@@ -430,10 +415,7 @@
35,
6,
1,
"DDIM",
0.10,
true,
""
"DDIM"
]
},
{
+39 -161
View File
@@ -87,40 +87,6 @@ class Transformer3DModelOutput(BaseOutput):
sample: torch.FloatTensor
class TeaCache():
"""
Timestep Embedding Aware Cache, a training-free caching approach that estimates and leverages
the fluctuating differences among model outputs across timesteps, thereby accelerating the inference.
Please refer to:
1. https://github.com/ali-vilab/TeaCache.
2. Liu, Feng, et al. "Timestep Embedding Tells: It's Time to Cache for Video Diffusion Model." arXiv preprint arXiv:2411.19108 (2024).
"""
def __init__(self, coefficients: list[float], num_steps: int, rel_l1_thresh: float = 0.0):
if num_steps < 1:
raise ValueError("`num_steps` must be greater than 0 but is {num_steps}.")
if rel_l1_thresh < 0:
raise ValueError("`rel_l1_thresh` must be greater than or equal to 0 but is {rel_l1_thresh}.")
self.coefficients = coefficients
self.cnt = 0
self.num_steps = num_steps
self.rel_l1_thresh = rel_l1_thresh
self.accumulated_rel_l1_distance = 0
self.previous_modulated_input = None
self.previous_residual = None
self.rescale_func = np.poly1d(self.coefficients)
@staticmethod
def compute_rel_l1_distance(prev, cur):
rel_l1_distance = (torch.abs(cur - prev).mean()) / torch.abs(prev).mean()
return rel_l1_distance.cpu().item()
def reset(self):
self.cnt = 0
self.previous_modulated_input = None
self.previous_residual = None
class Transformer3DModel(ModelMixin, ConfigMixin):
"""
A 3D Transformer model for image-like data.
@@ -1462,21 +1428,7 @@ class EasyAnimateTransformer3DModel(ModelMixin, ConfigMixin):
)
self.proj_out = nn.Linear(self.inner_dim, patch_size * patch_size * out_channels)
self.teacache = None
self.gradient_checkpointing = False
def enable_teacache(
self,
num_steps: int,
rel_l1_thresh: float,
coefficients: list[float] = [-10.47857366, 8.33844143, -0.78477557, 0.68798618, 0.0136149]
):
# The coefficient was obtained by sampling videos from T2V CompBench using EasyAnimateV5.1-12b-zh-InP.
# This coefficient can be applied to both the EasyAnimateV5.1-12b-zh and EasyAnimateV5.1-12b-Control.
# The coefficients for EasyAnimateV5.1-7b-zh-InP should be:
# [-3.64204720e+03, 1.43764725e+03, -1.93045263e+02, 1.09596499e+01, -1.70663507e-01]
self.teacache = TeaCache(coefficients, num_steps, rel_l1_thresh=rel_l1_thresh)
def _set_gradient_checkpointing(self, module, value=False):
self.gradient_checkpointing = value
@@ -1547,122 +1499,48 @@ class EasyAnimateTransformer3DModel(ModelMixin, ConfigMixin):
clip_encoder_hidden_states = self.clip_proj(clip_encoder_hidden_states)
encoder_hidden_states = torch.concat([clip_encoder_hidden_states, ref_latents], dim=1)
# TeaCache
if self.teacache is not None:
inp = hidden_states.clone()
temb_ = temb.clone()
encoder_hidden_states_ = encoder_hidden_states.clone()
modulated_inp, _, _, _ = self.transformer_blocks[0].norm1(inp, encoder_hidden_states_, temb_)
if self.teacache.cnt == 0 or self.teacache.cnt == self.teacache.num_steps - 1:
should_calc = True
self.teacache.accumulated_rel_l1_distance = 0
# 4. Transformer blocks
for i, block in enumerate(self.transformer_blocks):
if torch.is_grad_enabled() and self.gradient_checkpointing:
def create_custom_forward(module, return_dict=None):
def custom_forward(*inputs):
if return_dict is not None:
return module(*inputs, return_dict=return_dict)
else:
return module(*inputs)
return custom_forward
ckpt_kwargs: Dict[str, Any] = {"use_reentrant": False} if is_torch_version(">=", "1.11.0") else {}
hidden_states, encoder_hidden_states = torch.utils.checkpoint.checkpoint(
create_custom_forward(block),
hidden_states,
encoder_hidden_states,
temb,
image_rotary_emb,
video_length,
height // self.patch_size,
width // self.patch_size,
**ckpt_kwargs,
)
else:
rel_l1_distance = self.teacache.compute_rel_l1_distance(self.teacache.previous_modulated_input, modulated_inp)
self.teacache.accumulated_rel_l1_distance += self.teacache.rescale_func(rel_l1_distance)
if self.teacache.accumulated_rel_l1_distance < self.teacache.rel_l1_thresh:
should_calc = False
else:
should_calc = True
self.teacache.accumulated_rel_l1_distance = 0
self.teacache.previous_modulated_input = modulated_inp
self.teacache.cnt += 1
if self.teacache.cnt == self.teacache.num_steps:
# self.cnt = 0
self.teacache.reset()
hidden_states, encoder_hidden_states = block(
hidden_states=hidden_states,
encoder_hidden_states=encoder_hidden_states,
temb=temb,
image_rotary_emb=image_rotary_emb,
num_frames=video_length,
height=height // self.patch_size,
width=width // self.patch_size
)
# TeaCache
if self.teacache is not None:
if not should_calc:
hidden_states += self.teacache.previous_residual
else:
ori_hidden_states = hidden_states.clone()
# 4. Transformer blocks
for i, block in enumerate(self.transformer_blocks):
if torch.is_grad_enabled() and self.gradient_checkpointing:
def create_custom_forward(module, return_dict=None):
def custom_forward(*inputs):
if return_dict is not None:
return module(*inputs, return_dict=return_dict)
else:
return module(*inputs)
return custom_forward
ckpt_kwargs: Dict[str, Any] = {"use_reentrant": False} if is_torch_version(">=", "1.11.0") else {}
hidden_states, encoder_hidden_states = torch.utils.checkpoint.checkpoint(
create_custom_forward(block),
hidden_states,
encoder_hidden_states,
temb,
image_rotary_emb,
video_length,
height // self.patch_size,
width // self.patch_size,
**ckpt_kwargs,
)
else:
hidden_states, encoder_hidden_states = block(
hidden_states=hidden_states,
encoder_hidden_states=encoder_hidden_states,
temb=temb,
image_rotary_emb=image_rotary_emb,
num_frames=video_length,
height=height // self.patch_size,
width=width // self.patch_size
)
hidden_states = torch.cat([encoder_hidden_states, hidden_states], dim=1)
hidden_states = self.norm_final(hidden_states)
hidden_states = hidden_states[:, encoder_hidden_states.size()[1]:]
# 5. Final block
hidden_states = self.norm_out(hidden_states, temb=temb)
self.teacache.previous_residual = hidden_states - ori_hidden_states
else:
# 4. Transformer blocks
for i, block in enumerate(self.transformer_blocks):
if torch.is_grad_enabled() and self.gradient_checkpointing:
def create_custom_forward(module, return_dict=None):
def custom_forward(*inputs):
if return_dict is not None:
return module(*inputs, return_dict=return_dict)
else:
return module(*inputs)
return custom_forward
ckpt_kwargs: Dict[str, Any] = {"use_reentrant": False} if is_torch_version(">=", "1.11.0") else {}
hidden_states, encoder_hidden_states = torch.utils.checkpoint.checkpoint(
create_custom_forward(block),
hidden_states,
encoder_hidden_states,
temb,
image_rotary_emb,
video_length,
height // self.patch_size,
width // self.patch_size,
**ckpt_kwargs,
)
else:
hidden_states, encoder_hidden_states = block(
hidden_states=hidden_states,
encoder_hidden_states=encoder_hidden_states,
temb=temb,
image_rotary_emb=image_rotary_emb,
num_frames=video_length,
height=height // self.patch_size,
width=width // self.patch_size
)
hidden_states = torch.cat([encoder_hidden_states, hidden_states], dim=1)
hidden_states = self.norm_final(hidden_states)
hidden_states = hidden_states[:, encoder_hidden_states.size()[1]:]
# 5. Final block
hidden_states = self.norm_out(hidden_states, temb=temb)
hidden_states = torch.cat([encoder_hidden_states, hidden_states], dim=1)
hidden_states = self.norm_final(hidden_states)
hidden_states = hidden_states[:, encoder_hidden_states.size()[1]:]
# 5. Final block
hidden_states = self.norm_out(hidden_states, temb=temb)
hidden_states = self.proj_out(hidden_states)
# 6. Unpatchify
+6 -17
View File
@@ -67,7 +67,7 @@ css = """
"""
class EasyAnimateController:
def __init__(self, GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype):
def __init__(self, GPU_memory_mode, weight_dtype):
# config dirs
self.basedir = os.getcwd()
self.config_dir = os.path.join(self.basedir, "config")
@@ -97,8 +97,6 @@ class EasyAnimateController:
self.base_model_path = "none"
self.lora_model_path = "none"
self.GPU_memory_mode = GPU_memory_mode
self.enable_teacache = enable_teacache
self.teacache_threshold = teacache_threshold
self.weight_dtype = weight_dtype
self.edition = "v5.1"
@@ -464,9 +462,6 @@ class EasyAnimateController:
# lora part
self.pipeline = merge_lora(self.pipeline, self.lora_model_path, multiplier=lora_alpha_slider)
if self.edition == "v5.1" and self.enable_teacache:
self.pipeline.transformer.enable_teacache(sample_step_slider, self.teacache_threshold)
try:
if self.model_type == "Inpaint":
if self.transformer.config.in_channels != self.vae.config.latent_channels:
@@ -666,8 +661,8 @@ class EasyAnimateController:
return gr.Image.update(visible=False, value=None), gr.Video.update(value=save_sample_path, visible=True), "Success"
def ui(GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype):
controller = EasyAnimateController(GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype)
def ui(GPU_memory_mode, weight_dtype):
controller = EasyAnimateController(GPU_memory_mode, weight_dtype)
with gr.Blocks(css=css) as demo:
gr.Markdown(
@@ -1005,7 +1000,7 @@ def ui(GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype):
class EasyAnimateController_Modelscope:
def __init__(self, model_type, edition, config_path, model_name, savedir_sample, GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype):
def __init__(self, model_type, edition, config_path, model_name, savedir_sample, GPU_memory_mode, weight_dtype):
# Basic dir
self.basedir = os.getcwd()
self.personalized_model_dir = os.path.join(self.basedir, "models", "Personalized_Model")
@@ -1017,8 +1012,6 @@ class EasyAnimateController_Modelscope:
# Config and model path
self.model_type = model_type
self.edition = edition
self.enable_teacache = enable_teacache
self.teacache_threshold = teacache_threshold
self.weight_dtype = weight_dtype
self.inference_config = OmegaConf.load(config_path)
Choosen_AutoencoderKL = name_to_autoencoder_magvit[
@@ -1266,10 +1259,6 @@ class EasyAnimateController_Modelscope:
# lora part
self.pipeline = merge_lora(self.pipeline, self.lora_model_path, multiplier=lora_alpha_slider)
if self.edition == "v5.1" and self.enable_teacache:
print(f"Enable TeaCache with threshold: {self.teacache_threshold}.")
self.pipeline.transformer.enable_teacache(sample_step_slider, self.teacache_threshold)
try:
if self.model_type == "Inpaint":
if self.vae.cache_mag_vae:
@@ -1384,8 +1373,8 @@ class EasyAnimateController_Modelscope:
return gr.Image.update(visible=False, value=None), gr.Video.update(value=save_sample_path, visible=True), "Success"
def ui_modelscope(model_type, edition, config_path, model_name, savedir_sample, GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype):
controller = EasyAnimateController_Modelscope(model_type, edition, config_path, model_name, savedir_sample, GPU_memory_mode, enable_teacache, teacache_threshold, weight_dtype)
def ui_modelscope(model_type, edition, config_path, model_name, savedir_sample, GPU_memory_mode, weight_dtype):
controller = EasyAnimateController_Modelscope(model_type, edition, config_path, model_name, savedir_sample, GPU_memory_mode, weight_dtype)
with gr.Blocks(css=css) as demo:
gr.Markdown(
-9
View File
@@ -33,11 +33,6 @@ from easyanimate.utils.utils import get_image_to_video_latent, save_videos_grid
# EasyAnimateV4, V5 support "model_cpu_offload" "model_cpu_offload_and_qfloat8" "sequential_cpu_offload"
# EasyAnimateV5.1 support "model_cpu_offload" "model_cpu_offload_and_qfloat8"
GPU_memory_mode = "model_cpu_offload_and_qfloat8"
# EasyAnimateV5.1 support TeaCache.
enable_teacache = True
# Recommended to be set between 0.05 and 0.1. A larger threshold can cache more steps, speeding up the inference process,
# but it may cause slight differences between the generated content and the original content.
teacache_threshold = 0.1
# Config and model path
config_path = "config/easyanimate_video_v5.1_magvit_qwen.yaml"
@@ -253,10 +248,6 @@ elif GPU_memory_mode == "model_cpu_offload_and_qfloat8":
else:
pipeline.enable_model_cpu_offload()
if "v5.1" in config_path and enable_teacache:
print(f"Enable TeaCache with threshold: {teacache_threshold}.")
pipeline.transformer.enable_teacache(num_inference_steps, teacache_threshold)
generator = torch.Generator(device="cuda").manual_seed(seed)
if lora_path is not None:
-9
View File
@@ -35,11 +35,6 @@ from easyanimate.utils.utils import get_image_to_video_latent, save_videos_grid
# EasyAnimateV4, V5 support "model_cpu_offload" "model_cpu_offload_and_qfloat8" "sequential_cpu_offload"
# EasyAnimateV5.1 support "model_cpu_offload" "model_cpu_offload_and_qfloat8"
GPU_memory_mode = "model_cpu_offload_and_qfloat8"
# EasyAnimateV5.1 support TeaCache.
enable_teacache = True
# Recommended to be set between 0.05 and 0.1. A larger threshold can cache more steps, speeding up the inference process,
# but it may cause slight differences between the generated content and the original content.
teacache_threshold = 0.1
# Config and model path
config_path = "config/easyanimate_video_v5.1_magvit_qwen.yaml"
@@ -261,10 +256,6 @@ elif GPU_memory_mode == "model_cpu_offload_and_qfloat8":
else:
pipeline.enable_model_cpu_offload()
if "v5.1" in config_path and enable_teacache:
print(f"Enable TeaCache with threshold: {teacache_threshold}.")
pipeline.transformer.enable_teacache(num_inference_steps, teacache_threshold)
generator = torch.Generator(device="cuda").manual_seed(seed)
if lora_path is not None:
-9
View File
@@ -34,11 +34,6 @@ from easyanimate.utils.utils import (get_video_to_video_latent,
# EasyAnimateV4, V5 support "model_cpu_offload" "model_cpu_offload_and_qfloat8" "sequential_cpu_offload"
# EasyAnimateV5.1 support "model_cpu_offload" "model_cpu_offload_and_qfloat8"
GPU_memory_mode = "model_cpu_offload_and_qfloat8"
# EasyAnimateV5.1 support TeaCache.
enable_teacache = True
# Recommended to be set between 0.05 and 0.1. A larger threshold can cache more steps, speeding up the inference process,
# but it may cause slight differences between the generated content and the original content.
teacache_threshold = 0.1
# Config and model path
config_path = "config/easyanimate_video_v5.1_magvit_qwen.yaml"
@@ -248,10 +243,6 @@ elif GPU_memory_mode == "model_cpu_offload_and_qfloat8":
else:
pipeline.enable_model_cpu_offload()
if "v5.1" in config_path and enable_teacache:
print(f"Enable TeaCache with threshold: {teacache_threshold}.")
pipeline.transformer.enable_teacache(num_inference_steps, teacache_threshold)
generator = torch.Generator(device="cuda").manual_seed(seed)
if lora_path is not None:
-9
View File
@@ -34,11 +34,6 @@ from diffusers import FlowMatchEulerDiscreteScheduler
# EasyAnimateV5 support "model_cpu_offload" "model_cpu_offload_and_qfloat8" "sequential_cpu_offload"
# EasyAnimateV5.1 support "model_cpu_offload" "model_cpu_offload_and_qfloat8"
GPU_memory_mode = "model_cpu_offload_and_qfloat8"
# EasyAnimateV5.1 support TeaCache.
enable_teacache = True
# Recommended to be set between 0.05 and 0.1. A larger threshold can cache more steps, speeding up the inference process,
# but it may cause slight differences between the generated content and the original content.
teacache_threshold = 0.1
# Config and model path
config_path = "config/easyanimate_video_v5.1_magvit_qwen.yaml"
@@ -233,10 +228,6 @@ elif GPU_memory_mode == "model_cpu_offload_and_qfloat8":
else:
pipeline.enable_model_cpu_offload()
if "v5.1" in config_path and enable_teacache:
print(f"Enable TeaCache with threshold: {teacache_threshold}.")
pipeline.transformer.enable_teacache(num_inference_steps, teacache_threshold)
generator = torch.Generator(device="cuda").manual_seed(seed)
if lora_path is not None: