hanjian.thu123 commited on
Commit
b088596
·
1 Parent(s): e79fe2d

[update] revise

Browse files
.gitignore CHANGED
@@ -28,3 +28,8 @@ local
28
  tmp
29
  .git_bk
30
  demo
 
 
 
 
 
 
28
  tmp
29
  .git_bk
30
  demo
31
+ .git_hf_space
32
+ .git_github/
33
+ *.pyc
34
+ tmp
35
+ *.png
README.md CHANGED
@@ -20,6 +20,7 @@ short_description: "Generative Refinement Networks"
20
  ---
21
 
22
  ## 🔥 Updates!!
 
23
  * June 3, 2026: 🍉 A toy image-video dataset is provided for GRN-T2I/GRN-T2V training and fine-tuning.
24
  * May 23, 2026: 🌺 We release the training and evaluation code for HBQ tokenizer, enjoy~
25
  * April 14, 2026: 🤗 Paper and code release
@@ -31,22 +32,22 @@ short_description: "Generative Refinement Networks"
31
  - [🚀 Demo](#-demo)
32
  - [📦 Model Zoo](#-model-zoo)
33
  - [🛠️ Installation](#️-installation)
34
- - [🖼️ Class-to-Image](#-class-to-image)
35
- - [Dataset](#dataset)
36
  - [Training](#training)
37
  - [Evaluation](#evaluation)
 
 
 
 
38
  - [🎨 Text-to-Image](#-text-to-image)
39
- - [Data](#data)
40
- - [Train](#train)
41
  - [Inference](#inference)
42
  - [🎬 Text-to-Video](#-text-to-video)
43
- - [Data](#data-1)
44
- - [Train](#train-1)
45
  - [Inference](#inference-1)
46
- - [📦 HBQ Tokenizer](#-hbq-tokenizer)
47
- - [Data](#data-2)
48
- - [Training](#training-1)
49
- - [Evaluation](#evaluation-1)
50
  - [📧 Contact](#-contact)
51
  - [🤗 Acknowledgements](#-acknowledgements)
52
  - [📝 Citation](#-citation)
@@ -70,7 +71,7 @@ GRN achieves state-of-the-art results on ImageNet reconstruction and class-condi
70
 
71
  <figure align="center">
72
  <figcaption><strong><em>Generative Refinement Framework</em></strong></figcaption>
73
- <img src="demo/framework.jpg" width="100%" alt="Framework">
74
  </figure>
75
 
76
  <p align="center">
@@ -130,13 +131,13 @@ Starting from a random token map, GRN randomly selects more predictions at each
130
  ### GRN-2B Class-to-Image Examples
131
  <figure align="center">
132
  <!-- <figcaption><strong><em>GRN-2B Class-to-Image Examples</em></strong></figcaption> -->
133
- <img src="demo/c2i_examples.jpg" width="100%" alt="Class-to-Image Examples">
134
  </figure>
135
 
136
  ### GRN-2B Text-to-Image Examples
137
  <figure align="center">
138
  <!-- <figcaption><strong><em>GRN-2B Text-to-Image Examples</em></strong></figcaption> -->
139
- <img src="demo/t2i_examples.jpg" width="100%" alt="Text-to-Image Examples">
140
  </figure>
141
 
142
  ---
@@ -160,7 +161,7 @@ Try our interactive Text-to-Video demo on Discord:
160
 
161
  <figure align="center">
162
  <figcaption><strong><em>T2V Demo on Discord</em></strong></figcaption>
163
- <img src="demo/t2v_demo.png" width="100%" alt="T2V Demo">
164
  </figure>
165
 
166
  ---
@@ -187,8 +188,9 @@ cd GRN
187
  ### Step 2: Create conda environment
188
  A suitable [conda](https://conda.io/) environment named `GRN` can be created and activated with:
189
  ```bash
190
- conda env create -f environment.yaml
191
  conda activate GRN
 
192
  ```
193
 
194
  ### Troubleshooting
@@ -201,9 +203,44 @@ Check this [issue](https://github.com/conda/conda/issues/13812#issuecomment-2071
201
 
202
  ---
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  ## 🖼️ Class-to-Image
205
 
206
- ### Dataset
207
  Download [ImageNet](http://image-net.org/download) dataset, and place it in your `IMAGENET_PATH`.
208
 
209
  ### Training
@@ -238,35 +275,36 @@ We use [torch-fidelity](https://github.com/LTH14/torch-fidelity) to evaluate FID
238
 
239
  ## 🎨 Text-to-Image
240
  ### Data
241
- Refer to `data/toy_data/jsonls/000001/0001_0008_000000100.jsonl`
242
  ```
243
  {"image_path": "[image_path_1]", "long_caption": "xxx", "long_caption_type": "caption-InternVL2.0", "text": "", "short_caption_type": "blip2_caption", "width": 1080, "height": 1920}
244
  {"image_path": "[image_path_2]", "long_caption": "xxx", "long_caption_type": "caption-InternVL2.0", "text": "", "short_caption_type": "blip2_caption", "width": 1080, "height": 1920}
245
  ...
246
  ```
247
 
248
- ### Train
249
- Run `bash scripts/train_GRN_ind_t2i.sh`
250
 
251
  ### Inference
252
 
253
- You can simply run `python3 t2i_infer.py` or use the following code:
254
 
255
  ```python
256
  from PIL import Image
257
- from grn_pipeline import GRNPipeline
258
 
259
  # Load pipeline
260
  pipeline = GRNPipeline.from_pretrained(
261
  hf_repo_id='bytedance-research/GRN',
262
  task='T2I',
263
  pn='1M',
 
264
  device='cpu',
265
  ).to('cuda')
266
 
267
  # Generate one image
268
  result = pipeline(
269
- prompt="A cute cat playing in the garden",
270
  guidance_scale=3.0,
271
  temperature=1.1,
272
  complexity_aware_Tmin=10,
@@ -287,29 +325,30 @@ image.save('./generated_image.jpg')
287
 
288
  ## 🎬 Text-to-Video
289
  ### Data
290
- Refer to `data/toy_data/jsonls/000001/0001_0008_000000100.jsonl`
291
  ```
292
  {"video_path": "[video_path_1]", "begin_frame_id": xxx, "end_frame_id": xxx, "quality_prompt": "There is text in the video.", "fps": 25.0, "duration": 3.88, "width": 1280, "height": 720, "caption": [{"type": "short", "content": "[short_caption]"}, {"type": "medium", "content": "[medium_caption]"}, {"type": "long", "content": "[long_caption]"}]}
293
  {"video_path": "[video_path_1]", "begin_frame_id": xxx, "end_frame_id": xxx, "quality_prompt": "The quality is very high!", "fps": 25.0, "duration": 3.88, "width": 1280, "height": 720, "caption": [{"type": "short", "content": "[short_caption]"}, {"type": "medium", "content": "[medium_caption]"}, {"type": "long", "content": "[long_caption]"}]}
294
  ...
295
  ```
296
 
297
- ### Train
298
- Run `bash scripts/train_GRN_ind_t2v.sh`
299
 
300
  ### Inference
301
 
302
- You can simply run `python3 t2v_infer.py` or use the following code:
303
 
304
  ```python
305
- from grn_pipeline import GRNPipeline
306
 
307
  # Load pipeline
308
  pipeline = GRNPipeline.from_pretrained(
309
- hf_repo_id='bytedance-research/GRN',
310
- task='T2V',
311
  pn='0.41M',
312
- device='cpu'
 
313
  ).to('cuda')
314
 
315
  # Generate one video
@@ -333,41 +372,6 @@ video_file = result.videos[0]
333
 
334
  ---
335
 
336
- ## 📦 HBQ Tokenizer
337
-
338
- ### Data
339
- Image Dataset, e.g., data_root/username/labels/imagenet/train.txt:
340
- ```
341
- [image_1_full_path]
342
- [image_2_full_path]
343
- [image_3_full_path]
344
- ...
345
- ```
346
-
347
- Video Dataset, e.g., data_root/username/labels_hanjian/high-quality-video/horizontal_videos.txt
348
- ```
349
- [video_1_full_path]
350
- [video_2_full_path]
351
- [video_3_full_path]
352
- ...
353
- ```
354
-
355
- ### Training
356
- For example, set `latent_channels=16/64` and `quant_method=hierarchical_binary_quant_round_4` in `scripts/hbq_tokenizer_train.sh`, then run:
357
- ```bash
358
- cd grn/tokenizer
359
- bash scripts/hbq_tokenizer_train.sh
360
- ```
361
-
362
- ### Evaluation
363
- For example, set `latent_channels=16/64` and `quant_method=hierarchical_binary_quant_round_4` in `scripts/hbq_tokenizer_train.sh`, then run:
364
- ```bash
365
- cd grn/tokenizer
366
- bash scripts/hbq_tokenizer_eval.sh
367
- ```
368
-
369
- ---
370
-
371
  ## 📧 Contact
372
 
373
  If you are interested in scaling GRN for image generation / image editing / video generation / video editing / unified model directions, please feel free to reach out!
 
20
  ---
21
 
22
  ## 🔥 Updates!!
23
+ * June 8, 2026: ✈️ The training & fine-tuning code for GRN-T2I and GRN-T2V is released.
24
  * June 3, 2026: 🍉 A toy image-video dataset is provided for GRN-T2I/GRN-T2V training and fine-tuning.
25
  * May 23, 2026: 🌺 We release the training and evaluation code for HBQ tokenizer, enjoy~
26
  * April 14, 2026: 🤗 Paper and code release
 
32
  - [🚀 Demo](#-demo)
33
  - [📦 Model Zoo](#-model-zoo)
34
  - [🛠️ Installation](#️-installation)
35
+ - [📦 HBQ Tokenizer](#-hbq-tokenizer)
36
+ - [Data](#data)
37
  - [Training](#training)
38
  - [Evaluation](#evaluation)
39
+ - [🖼️ Class-to-Image](#️-class-to-image)
40
+ - [Data](#data-1)
41
+ - [Training](#training-2)
42
+ - [Evaluation](#evaluation-1)
43
  - [🎨 Text-to-Image](#-text-to-image)
44
+ - [Data](#data-2)
45
+ - [Training](#training-2)
46
  - [Inference](#inference)
47
  - [🎬 Text-to-Video](#-text-to-video)
48
+ - [Data](#data-3)
49
+ - [Training](#training-3)
50
  - [Inference](#inference-1)
 
 
 
 
51
  - [📧 Contact](#-contact)
52
  - [🤗 Acknowledgements](#-acknowledgements)
53
  - [📝 Citation](#-citation)
 
71
 
72
  <figure align="center">
73
  <figcaption><strong><em>Generative Refinement Framework</em></strong></figcaption>
74
+ <img src="assets/framework.jpg" width="100%" alt="Framework">
75
  </figure>
76
 
77
  <p align="center">
 
131
  ### GRN-2B Class-to-Image Examples
132
  <figure align="center">
133
  <!-- <figcaption><strong><em>GRN-2B Class-to-Image Examples</em></strong></figcaption> -->
134
+ <img src="assets/c2i_examples.jpg" width="100%" alt="Class-to-Image Examples">
135
  </figure>
136
 
137
  ### GRN-2B Text-to-Image Examples
138
  <figure align="center">
139
  <!-- <figcaption><strong><em>GRN-2B Text-to-Image Examples</em></strong></figcaption> -->
140
+ <img src="assets/t2i_examples.jpg" width="100%" alt="Text-to-Image Examples">
141
  </figure>
142
 
143
  ---
 
161
 
162
  <figure align="center">
163
  <figcaption><strong><em>T2V Demo on Discord</em></strong></figcaption>
164
+ <img src="assets/t2v_demo.png" width="100%" alt="T2V Demo">
165
  </figure>
166
 
167
  ---
 
188
  ### Step 2: Create conda environment
189
  A suitable [conda](https://conda.io/) environment named `GRN` can be created and activated with:
190
  ```bash
191
+ conda create -n GRN python=3.11
192
  conda activate GRN
193
+ pip install -r requirements.txt
194
  ```
195
 
196
  ### Troubleshooting
 
203
 
204
  ---
205
 
206
+ ## 📦 HBQ Tokenizer
207
+
208
+ ### Data
209
+ Image Dataset, e.g., data_root/username/labels/imagenet/train.txt:
210
+ ```
211
+ [image_1_full_path]
212
+ [image_2_full_path]
213
+ [image_3_full_path]
214
+ ...
215
+ ```
216
+
217
+ Video Dataset, e.g., data_root/username/labels_hanjian/high-quality-video/horizontal_videos.txt
218
+ ```
219
+ [video_1_full_path]
220
+ [video_2_full_path]
221
+ [video_3_full_path]
222
+ ...
223
+ ```
224
+
225
+ ### Training
226
+ For example, set `latent_channels=16/64` and `quant_method=hierarchical_binary_quant_round_4` in `scripts/hbq_tokenizer_train.sh`, then run:
227
+ ```bash
228
+ cd grn/tokenizer
229
+ bash scripts/hbq_tokenizer_train.sh
230
+ ```
231
+
232
+ ### Evaluation
233
+ For example, set `latent_channels=16/64` and `quant_method=hierarchical_binary_quant_round_4` in `scripts/hbq_tokenizer_train.sh`, then run:
234
+ ```bash
235
+ cd grn/tokenizer
236
+ bash scripts/hbq_tokenizer_eval.sh
237
+ ```
238
+
239
+ ---
240
+
241
  ## 🖼️ Class-to-Image
242
 
243
+ ### Data
244
  Download [ImageNet](http://image-net.org/download) dataset, and place it in your `IMAGENET_PATH`.
245
 
246
  ### Training
 
275
 
276
  ## 🎨 Text-to-Image
277
  ### Data
278
+ Refer to `data/toy_data/jsonls/000001/0001_0800_000000100.jsonl`
279
  ```
280
  {"image_path": "[image_path_1]", "long_caption": "xxx", "long_caption_type": "caption-InternVL2.0", "text": "", "short_caption_type": "blip2_caption", "width": 1080, "height": 1920}
281
  {"image_path": "[image_path_2]", "long_caption": "xxx", "long_caption_type": "caption-InternVL2.0", "text": "", "short_caption_type": "blip2_caption", "width": 1080, "height": 1920}
282
  ...
283
  ```
284
 
285
+ ### Training
286
+ Run `bash scripts/t2iv/train_GRN_bit_t2iv.sh`
287
 
288
  ### Inference
289
 
290
+ You can simply run `python3 tools/t2i_infer.py` or use the following code:
291
 
292
  ```python
293
  from PIL import Image
294
+ from tools.grn_pipeline import GRNPipeline
295
 
296
  # Load pipeline
297
  pipeline = GRNPipeline.from_pretrained(
298
  hf_repo_id='bytedance-research/GRN',
299
  task='T2I',
300
  pn='1M',
301
+ model='GRN2b',
302
  device='cpu',
303
  ).to('cuda')
304
 
305
  # Generate one image
306
  result = pipeline(
307
+ prompt="<T2I>" + "A cute cat playing in the garden",
308
  guidance_scale=3.0,
309
  temperature=1.1,
310
  complexity_aware_Tmin=10,
 
325
 
326
  ## 🎬 Text-to-Video
327
  ### Data
328
+ Refer to `data/toy_data/jsonls/000001/0001_0800_000000100.jsonl`
329
  ```
330
  {"video_path": "[video_path_1]", "begin_frame_id": xxx, "end_frame_id": xxx, "quality_prompt": "There is text in the video.", "fps": 25.0, "duration": 3.88, "width": 1280, "height": 720, "caption": [{"type": "short", "content": "[short_caption]"}, {"type": "medium", "content": "[medium_caption]"}, {"type": "long", "content": "[long_caption]"}]}
331
  {"video_path": "[video_path_1]", "begin_frame_id": xxx, "end_frame_id": xxx, "quality_prompt": "The quality is very high!", "fps": 25.0, "duration": 3.88, "width": 1280, "height": 720, "caption": [{"type": "short", "content": "[short_caption]"}, {"type": "medium", "content": "[medium_caption]"}, {"type": "long", "content": "[long_caption]"}]}
332
  ...
333
  ```
334
 
335
+ ### Training
336
+ Run `bash scripts/t2iv/train_GRN_bit_t2iv.sh`
337
 
338
  ### Inference
339
 
340
+ You can simply run `python3 tools/t2v_infer.py` or use the following code:
341
 
342
  ```python
343
+ from tools.grn_pipeline import GRNPipeline
344
 
345
  # Load pipeline
346
  pipeline = GRNPipeline.from_pretrained(
347
+ hf_repo_id='bytedance-research/GRN',
348
+ task='T2V',
349
  pn='0.41M',
350
+ model='GRN2b',
351
+ device='cpu',
352
  ).to('cuda')
353
 
354
  # Generate one video
 
372
 
373
  ---
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  ## 📧 Contact
376
 
377
  If you are interested in scaling GRN for image generation / image editing / video generation / video editing / unified model directions, please feel free to reach out!
app.py CHANGED
@@ -7,7 +7,7 @@ import spaces
7
 
8
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
9
 
10
- from grn_pipeline import GRNPipeline
11
 
12
  # Global pipeline
13
  pipe = None
 
7
 
8
  sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
9
 
10
+ from tools.grn_pipeline import GRNPipeline
11
 
12
  # Global pipeline
13
  pipe = None
environment.yaml DELETED
@@ -1,19 +0,0 @@
1
- name: grn
2
- channels:
3
- - pytorch
4
- - defaults
5
- - nvidia
6
- dependencies:
7
- - python=3.10
8
- - pip=22.3
9
- - pytorch-cuda=12.4
10
- - pytorch=2.5.1
11
- - torchvision=0.20.1
12
- - numpy=1.22
13
- - pip:
14
- - opencv-python==4.11.0.86
15
- - timm==0.9.12
16
- - tensorboard==2.10.0
17
- - scipy==1.9.1
18
- - einops==0.8.1
19
- - gdown==5.2.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
{evaluation → grn/evaluation}/gen_eval/_base_/datasets/coco_panoptic.py RENAMED
File without changes
{evaluation → grn/evaluation}/gen_eval/_base_/default_runtime.py RENAMED
File without changes
{evaluation → grn/evaluation}/gen_eval/evaluate_images.py RENAMED
File without changes
{evaluation → grn/evaluation}/gen_eval/mask2former/mask2former_r50_lsj_8x2_50e_coco-panoptic.py RENAMED
File without changes
{evaluation → grn/evaluation}/gen_eval/mask2former/mask2former_r50_lsj_8x2_50e_coco.py RENAMED
File without changes
{evaluation → grn/evaluation}/gen_eval/mask2former/mask2former_swin-s-p4-w7-224_lsj_8x2_50e_coco.py RENAMED
File without changes
{evaluation → grn/evaluation}/gen_eval/mask2former/mask2former_swin-t-p4-w7-224_lsj_8x2_50e_coco.py RENAMED
File without changes
{evaluation → grn/evaluation}/gen_eval/prompts/create_prompts.py RENAMED
File without changes
{evaluation → grn/evaluation}/gen_eval/summary_scores.py RENAMED
File without changes
grn/models/grn.py CHANGED
@@ -606,7 +606,7 @@ class GRN(nn.Module):
606
  pt_unshift = (cur_inner_round_si + 1) / (args.complexity_aware_Tmax - 1)
607
  pt_shift = shift_pt(min(1., pt_unshift), args.snr_shift)
608
  next_pt = 1 - np.cos(np.pi/2*pt_shift)
609
- next_pt = next_pt * 0.999
610
 
611
  pred_cond_labels = torch.argmax(pred_cond_probs, dim=-1) # [B,thw,d]
612
  pred_cond_labels = bld_to_bthwd(pred_cond_labels, pt, ph, pw)
 
606
  pt_unshift = (cur_inner_round_si + 1) / (args.complexity_aware_Tmax - 1)
607
  pt_shift = shift_pt(min(1., pt_unshift), args.snr_shift)
608
  next_pt = 1 - np.cos(np.pi/2*pt_shift)
609
+ next_pt = next_pt * 0.95
610
 
611
  pred_cond_labels = torch.argmax(pred_cond_probs, dim=-1) # [B,thw,d]
612
  pred_cond_labels = bld_to_bthwd(pred_cond_labels, pt, ph, pw)
grn/tokenizer/videovae/models/hbq_tokenizer.py CHANGED
@@ -16,6 +16,13 @@ from videovae.utils.dynamic_resolution_two_pyramid import dynamic_resolution_thw
16
  CACHE_T = 2
17
 
18
 
 
 
 
 
 
 
 
19
  class CausalConv3d(nn.Conv3d):
20
  """
21
  Causal 3d convolusion.
@@ -114,13 +121,22 @@ class Resample(nn.Module):
114
  def forward(self, x, feat_cache=None, feat_idx=[0]):
115
  b, c, t, h, w = x.size()
116
  if self.mode == "upsample3d":
117
- if feat_cache is not None:
 
 
 
 
 
 
 
 
 
118
  idx = feat_idx[0]
119
  if feat_cache[idx] is None:
120
  feat_cache[idx] = "Rep"
121
  feat_idx[0] += 1
122
  else:
123
- cache_x = x[:, :, -CACHE_T:, :, :].clone()
124
  if (cache_x.shape[2] < 2 and feat_cache[idx] is not None and
125
  feat_cache[idx] != "Rep"):
126
  # cache last frame of last two chunk
@@ -157,13 +173,19 @@ class Resample(nn.Module):
157
  x = rearrange(x, "(b t) c h w -> b c t h w", t=t) # this 4 lines do spatial down / up sample
158
 
159
  if self.mode == "downsample3d":
160
- if feat_cache is not None:
 
 
 
 
 
161
  idx = feat_idx[0]
162
  if feat_cache[idx] is None:
163
- feat_cache[idx] = x.clone()
 
164
  feat_idx[0] += 1
165
  else:
166
- cache_x = x[:, :, -1:, :, :].clone()
167
  x = self.time_conv(
168
  torch.cat([feat_cache[idx][:, :, -1:, :, :], x], 2))
169
  feat_cache[idx] = cache_x
@@ -218,7 +240,7 @@ class ResidualBlock(nn.Module):
218
  for layer in self.residual:
219
  if isinstance(layer, CausalConv3d) and feat_cache is not None:
220
  idx = feat_idx[0]
221
- cache_x = x[:, :, -CACHE_T:, :, :].clone()
222
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
223
  # cache last frame of last two chunk
224
  cache_x = torch.cat(
@@ -255,6 +277,7 @@ class AttentionBlock(nn.Module):
255
  nn.init.zeros_(self.proj.weight)
256
 
257
  def forward(self, x):
 
258
  identity = x
259
  b, c, t, h, w = x.size()
260
  x = rearrange(x, "b c t h w -> (b t) c h w")
@@ -447,7 +470,7 @@ class Down_ResidualBlock(nn.Module):
447
  self.downsamples = nn.Sequential(*downsamples)
448
 
449
  def forward(self, x, feat_cache=None, feat_idx=[0]):
450
- x_copy = x.clone()
451
  for module in self.downsamples:
452
  x = module(x, feat_cache, feat_idx)
453
 
@@ -489,7 +512,7 @@ class Up_ResidualBlock(nn.Module):
489
  self.upsamples = nn.Sequential(*upsamples)
490
 
491
  def forward(self, x, feat_cache=None, feat_idx=[0], first_chunk=False):
492
- x_main = x.clone()
493
  for module in self.upsamples:
494
  x_main = module(x_main, feat_cache, feat_idx)
495
  if self.avg_shortcut is not None:
@@ -560,7 +583,7 @@ class Encoder3d(nn.Module):
560
 
561
  if feat_cache is not None:
562
  idx = feat_idx[0]
563
- cache_x = x[:, :, -CACHE_T:, :, :].clone()
564
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
565
  cache_x = torch.cat(
566
  [
@@ -594,7 +617,7 @@ class Encoder3d(nn.Module):
594
  for layer in self.head:
595
  if isinstance(layer, CausalConv3d) and feat_cache is not None:
596
  idx = feat_idx[0]
597
- cache_x = x[:, :, -CACHE_T:, :, :].clone()
598
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
599
  cache_x = torch.cat(
600
  [
@@ -672,7 +695,7 @@ class Decoder3d(nn.Module):
672
  def forward(self, x, feat_cache=None, feat_idx=[0], first_chunk=False):
673
  if feat_cache is not None:
674
  idx = feat_idx[0]
675
- cache_x = x[:, :, -CACHE_T:, :, :].clone()
676
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
677
  cache_x = torch.cat(
678
  [
@@ -699,13 +722,13 @@ class Decoder3d(nn.Module):
699
  if feat_cache is not None:
700
  x = layer(x, feat_cache, feat_idx, first_chunk)
701
  else:
702
- x = layer(x)
703
 
704
  ## head
705
  for layer in self.head:
706
  if isinstance(layer, CausalConv3d) and feat_cache is not None:
707
  idx = feat_idx[0]
708
- cache_x = x[:, :, -CACHE_T:, :, :].clone()
709
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
710
  cache_x = torch.cat(
711
  [
@@ -780,30 +803,33 @@ class WanVAE_(nn.Module):
780
  x_recon = self.decode(mu, scale)
781
  return x_recon, mu
782
 
783
- def encode(self, x, scale=None):
784
  self.clear_cache()
785
  x = patchify(x, patch_size=2)
786
- # import pdb; pdb.set_trace()
787
- # if self.training:
788
- # out = self.encoder(x)
789
- # else:
790
- t = x.shape[2]
791
- iter_ = 1 + (t - 1) // 4
792
- for i in range(iter_):
793
- self._enc_conv_idx = [0]
794
- if i == 0:
795
- out = self.encoder(
796
- x[:, :, :1, :, :],
797
- feat_cache=self._enc_feat_map,
798
- feat_idx=self._enc_conv_idx,
799
- )
800
- else:
801
- out_ = self.encoder(
802
- x[:, :, 1 + 4 * (i - 1):1 + 4 * i, :, :],
803
- feat_cache=self._enc_feat_map,
804
- feat_idx=self._enc_conv_idx,
805
- )
806
- out = torch.cat([out, out_], 2)
 
 
 
807
  mu, log_var = self.conv1(out).chunk(2, dim=1)
808
  if scale is not None:
809
  if isinstance(scale[0], torch.Tensor):
@@ -812,15 +838,15 @@ class WanVAE_(nn.Module):
812
  else:
813
  mu = (mu - scale[0]) * scale[1]
814
  self.clear_cache()
815
- if self.other_args.encoder_out_type == 'feature_tanh':
816
  mu = torch.tanh(mu)
817
- elif self.other_args.encoder_out_type == 'feature':
818
  pass
819
  else:
820
- raise ValueError(f'{self.other_args.encoder_out_type=} is not supported!')
821
  return mu
822
 
823
- def decode(self, z, scale=None):
824
  self.clear_cache()
825
  if scale is not None:
826
  if isinstance(scale[0], torch.Tensor):
@@ -829,18 +855,19 @@ class WanVAE_(nn.Module):
829
  else:
830
  z = z / scale[1] + scale[0]
831
  x = self.conv2(z)
832
- # if self.training:
833
- # out = self.decoder(x)
834
- # else:
835
- iter_ = z.shape[2]
836
- for i in range(iter_):
837
- self._conv_idx = [0]
838
- if i == 0:
839
- out = self.decoder(
840
- x[:, :, i:i + 1, :, :],
841
- feat_cache=self._feat_map,
842
- feat_idx=self._conv_idx,
843
- first_chunk=True,
 
844
  )
845
  else:
846
  out_ = self.decoder(
@@ -848,7 +875,10 @@ class WanVAE_(nn.Module):
848
  feat_cache=self._feat_map,
849
  feat_idx=self._conv_idx,
850
  )
851
- out = torch.cat([out, out_], 2)
 
 
 
852
  out = unpatchify(out, patch_size=2)
853
  self.clear_cache()
854
  return out
 
16
  CACHE_T = 2
17
 
18
 
19
+ def _cache_tensor(x, length=CACHE_T, detach=False):
20
+ cache = x[:, :, -length:, :, :]
21
+ if detach:
22
+ cache = cache.detach()
23
+ return cache.clone()
24
+
25
+
26
  class CausalConv3d(nn.Conv3d):
27
  """
28
  Causal 3d convolusion.
 
121
  def forward(self, x, feat_cache=None, feat_idx=[0]):
122
  b, c, t, h, w = x.size()
123
  if self.mode == "upsample3d":
124
+ if feat_cache is None:
125
+ if t > 1:
126
+ first_frame = x[:, :, :1, :, :]
127
+ x = self.time_conv(x[:, :, 1:, :, :])
128
+ x = x.reshape(b, 2, c, t - 1, h, w)
129
+ x = torch.stack((x[:, 0, :, :, :, :],
130
+ x[:, 1, :, :, :, :]), 3)
131
+ x = x.reshape(b, c, (t - 1) * 2, h, w)
132
+ x = torch.cat([first_frame, x], 2)
133
+ else:
134
  idx = feat_idx[0]
135
  if feat_cache[idx] is None:
136
  feat_cache[idx] = "Rep"
137
  feat_idx[0] += 1
138
  else:
139
+ cache_x = _cache_tensor(x, detach=self.training)
140
  if (cache_x.shape[2] < 2 and feat_cache[idx] is not None and
141
  feat_cache[idx] != "Rep"):
142
  # cache last frame of last two chunk
 
173
  x = rearrange(x, "(b t) c h w -> b c t h w", t=t) # this 4 lines do spatial down / up sample
174
 
175
  if self.mode == "downsample3d":
176
+ if feat_cache is None:
177
+ if t >= 3:
178
+ x = torch.cat([x[:, :, :1, :, :], self.time_conv(x)], 2)
179
+ else:
180
+ x = x[:, :, :1, :, :]
181
+ else:
182
  idx = feat_idx[0]
183
  if feat_cache[idx] is None:
184
+ feat_cache[idx] = _cache_tensor(
185
+ x, length=1, detach=self.training)
186
  feat_idx[0] += 1
187
  else:
188
+ cache_x = _cache_tensor(x, length=1, detach=self.training)
189
  x = self.time_conv(
190
  torch.cat([feat_cache[idx][:, :, -1:, :, :], x], 2))
191
  feat_cache[idx] = cache_x
 
240
  for layer in self.residual:
241
  if isinstance(layer, CausalConv3d) and feat_cache is not None:
242
  idx = feat_idx[0]
243
+ cache_x = _cache_tensor(x, detach=self.training)
244
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
245
  # cache last frame of last two chunk
246
  cache_x = torch.cat(
 
277
  nn.init.zeros_(self.proj.weight)
278
 
279
  def forward(self, x):
280
+ return x
281
  identity = x
282
  b, c, t, h, w = x.size()
283
  x = rearrange(x, "b c t h w -> (b t) c h w")
 
470
  self.downsamples = nn.Sequential(*downsamples)
471
 
472
  def forward(self, x, feat_cache=None, feat_idx=[0]):
473
+ x_copy = x
474
  for module in self.downsamples:
475
  x = module(x, feat_cache, feat_idx)
476
 
 
512
  self.upsamples = nn.Sequential(*upsamples)
513
 
514
  def forward(self, x, feat_cache=None, feat_idx=[0], first_chunk=False):
515
+ x_main = x
516
  for module in self.upsamples:
517
  x_main = module(x_main, feat_cache, feat_idx)
518
  if self.avg_shortcut is not None:
 
583
 
584
  if feat_cache is not None:
585
  idx = feat_idx[0]
586
+ cache_x = _cache_tensor(x, detach=self.training)
587
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
588
  cache_x = torch.cat(
589
  [
 
617
  for layer in self.head:
618
  if isinstance(layer, CausalConv3d) and feat_cache is not None:
619
  idx = feat_idx[0]
620
+ cache_x = _cache_tensor(x, detach=self.training)
621
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
622
  cache_x = torch.cat(
623
  [
 
695
  def forward(self, x, feat_cache=None, feat_idx=[0], first_chunk=False):
696
  if feat_cache is not None:
697
  idx = feat_idx[0]
698
+ cache_x = _cache_tensor(x, detach=self.training)
699
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
700
  cache_x = torch.cat(
701
  [
 
722
  if feat_cache is not None:
723
  x = layer(x, feat_cache, feat_idx, first_chunk)
724
  else:
725
+ x = layer(x, first_chunk=first_chunk)
726
 
727
  ## head
728
  for layer in self.head:
729
  if isinstance(layer, CausalConv3d) and feat_cache is not None:
730
  idx = feat_idx[0]
731
+ cache_x = _cache_tensor(x, detach=self.training)
732
  if cache_x.shape[2] < 2 and feat_cache[idx] is not None:
733
  cache_x = torch.cat(
734
  [
 
803
  x_recon = self.decode(mu, scale)
804
  return x_recon, mu
805
 
806
+ def encode(self, x, scale=None, use_cache=None):
807
  self.clear_cache()
808
  x = patchify(x, patch_size=2)
809
+ if use_cache is None:
810
+ use_cache = not self.training
811
+ if use_cache:
812
+ t = x.shape[2]
813
+ iter_ = 1 + (t - 1) // 4
814
+ outs = []
815
+ for i in range(iter_):
816
+ self._enc_conv_idx = [0]
817
+ if i == 0:
818
+ out_ = self.encoder(
819
+ x[:, :, :1, :, :],
820
+ feat_cache=self._enc_feat_map,
821
+ feat_idx=self._enc_conv_idx,
822
+ )
823
+ else:
824
+ out_ = self.encoder(
825
+ x[:, :, 1 + 4 * (i - 1):1 + 4 * i, :, :],
826
+ feat_cache=self._enc_feat_map,
827
+ feat_idx=self._enc_conv_idx,
828
+ )
829
+ outs.append(out_)
830
+ out = torch.cat(outs, 2) if len(outs) > 1 else outs[0]
831
+ else:
832
+ out = self.encoder(x)
833
  mu, log_var = self.conv1(out).chunk(2, dim=1)
834
  if scale is not None:
835
  if isinstance(scale[0], torch.Tensor):
 
838
  else:
839
  mu = (mu - scale[0]) * scale[1]
840
  self.clear_cache()
841
+ if self.encoder_out_type == 'feature_tanh':
842
  mu = torch.tanh(mu)
843
+ elif self.encoder_out_type == 'feature':
844
  pass
845
  else:
846
+ raise ValueError(f'{self.encoder_out_type=} is not supported!')
847
  return mu
848
 
849
+ def decode(self, z, scale=None, use_cache=None, **kwargs):
850
  self.clear_cache()
851
  if scale is not None:
852
  if isinstance(scale[0], torch.Tensor):
 
855
  else:
856
  z = z / scale[1] + scale[0]
857
  x = self.conv2(z)
858
+ if use_cache is None:
859
+ use_cache = not self.training
860
+ if use_cache:
861
+ iter_ = z.shape[2]
862
+ outs = []
863
+ for i in range(iter_):
864
+ self._conv_idx = [0]
865
+ if i == 0:
866
+ out_ = self.decoder(
867
+ x[:, :, i:i + 1, :, :],
868
+ feat_cache=self._feat_map,
869
+ feat_idx=self._conv_idx,
870
+ first_chunk=True,
871
  )
872
  else:
873
  out_ = self.decoder(
 
875
  feat_cache=self._feat_map,
876
  feat_idx=self._conv_idx,
877
  )
878
+ outs.append(out_)
879
+ out = torch.cat(outs, 2) if len(outs) > 1 else outs[0]
880
+ else:
881
+ out = self.decoder(x, first_chunk=True)
882
  out = unpatchify(out, patch_size=2)
883
  self.clear_cache()
884
  return out
requirements.txt CHANGED
@@ -15,3 +15,4 @@ ftfy>=6.1.1
15
  transformers>=4.35.0
16
  regex>=2023.10.3
17
  pyyaml>=6.0
 
 
15
  transformers>=4.35.0
16
  regex>=2023.10.3
17
  pyyaml>=6.0
18
+ flash-attn-4==4.0.0b14
tools/__init__.py ADDED
File without changes
grn_pipeline.py → tools/grn_pipeline.py RENAMED
@@ -46,12 +46,12 @@ class GRNPipeline:
46
  from huggingface_hub import hf_hub_download, snapshot_download
47
  print(f"download weights from Hugging Face Hub: {hf_repo_id}")
48
  if task == 'T2I':
49
- model_path = hf_hub_download(repo_id=hf_repo_id, filename="GRN_T2I_2B_FSA_94600.pth")
50
  elif task == 'T2V':
51
- model_path = hf_hub_download(repo_id=hf_repo_id, filename="GRN_T2V_2B.pth")
52
  else:
53
  raise ValueError(f"Unknown task: {task}")
54
- vae_path = hf_hub_download(repo_id=hf_repo_id, filename="HBQ_tokenizer_64dim_M4.ckpt")
55
  snapshot_path = snapshot_download(repo_id=hf_repo_id, allow_patterns="umt5-xxl/**")
56
  text_encoder_ckpt = os.path.join(snapshot_path, "umt5-xxl")
57
  print(os.listdir(snapshot_path))
 
46
  from huggingface_hub import hf_hub_download, snapshot_download
47
  print(f"download weights from Hugging Face Hub: {hf_repo_id}")
48
  if task == 'T2I':
49
+ model_path = hf_hub_download(repo_id=hf_repo_id, filename="GRN_T2I_2B_FSA_137200.pth")
50
  elif task == 'T2V':
51
+ model_path = hf_hub_download(repo_id=hf_repo_id, filename="GRN_T2V_2B_FSA_sft3800_non_ema.pth")
52
  else:
53
  raise ValueError(f"Unknown task: {task}")
54
+ vae_path = hf_hub_download(repo_id=hf_repo_id, filename="HBQ_image_video_tokenizer_64dim_M4_20260618.ckpt")
55
  snapshot_path = snapshot_download(repo_id=hf_repo_id, allow_patterns="umt5-xxl/**")
56
  text_encoder_ckpt = os.path.join(snapshot_path, "umt5-xxl")
57
  print(os.listdir(snapshot_path))
t2i_infer.py → tools/t2i_infer.py RENAMED
@@ -1,5 +1,5 @@
1
  from PIL import Image
2
- from grn_pipeline import GRNPipeline
3
 
4
  # Load pipeline
5
  pipeline = GRNPipeline.from_pretrained(
@@ -7,7 +7,7 @@ pipeline = GRNPipeline.from_pretrained(
7
  task='T2I',
8
  pn='1M',
9
  model='GRN2b',
10
- use_slow_attn=True,
11
  device='cpu',
12
  ).to('cuda')
13
 
 
1
  from PIL import Image
2
+ from tools.grn_pipeline import GRNPipeline
3
 
4
  # Load pipeline
5
  pipeline = GRNPipeline.from_pretrained(
 
7
  task='T2I',
8
  pn='1M',
9
  model='GRN2b',
10
+ use_slow_attn=False,
11
  device='cpu',
12
  ).to('cuda')
13
 
t2v_infer.py → tools/t2v_infer.py RENAMED
@@ -1,4 +1,4 @@
1
- from grn_pipeline import GRNPipeline
2
 
3
  negative_prompt = (
4
  # --- quality ---
@@ -25,16 +25,18 @@ pipeline = GRNPipeline.from_pretrained(
25
  hf_repo_id='bytedance-research/GRN',
26
  task='T2V',
27
  pn='0.41M',
 
 
28
  device='cpu'
29
  ).to('cuda')
30
 
31
- prompt="The man, of medium build with short, dark, curly hair, stands centered in the frame, wearing a simple white t-shirt that contrasts with the greenery behind him. He holds a dark smartphone, likely a modern model with a triple-lens camera setup, in his right hand, angled slightly toward his body. His gaze is fixed on the screen, and his facial expression shifts subtly\u2014smiling, nodding, and occasionally pursing his lips\u2014as if reacting to content on the phone. The background features a mix of tall green trees and shrubs, with a light blue metal fence running horizontally across the mid-ground, suggesting a garden or rural boundary. The overcast sky diffuses the light, creating soft shadows and a calm, neutral atmosphere. The man\u2019s slight head movements and micro-expressions indicate engagement, possibly reading or responding to a message or video. The composition places him as the focal point, with the natural, slightly blurred background reinforcing his isolation in the moment. The relative stillness of the scene, apart from his subtle gestures, suggests a private, introspective interaction with technology in a serene outdoor setting"
32
-
33
  # Generate one video
34
  result = pipeline(
35
- prompt=f"{prompt}. masterpiece, high quality.",
36
  negative_prompt=negative_prompt,
37
- guidance_scale=4.0,
38
  temperature=1.0,
39
  complexity_aware_Tmin=10,
40
  complexity_aware_Tmax=50,
 
1
+ from tools.grn_pipeline import GRNPipeline
2
 
3
  negative_prompt = (
4
  # --- quality ---
 
25
  hf_repo_id='bytedance-research/GRN',
26
  task='T2V',
27
  pn='0.41M',
28
+ model='GRN2b',
29
+ use_slow_attn=False,
30
  device='cpu'
31
  ).to('cuda')
32
 
33
+ prompt="The video captures a male performer on stage, wearing a black cap, black t-shirt, and a black beaded bracelet on his left wrist, with a tattoo visible on his left forearm. He holds a microphone close to his mouth with his left hand while raising his right arm in a dynamic gesture, suggesting energetic performance. The stage is illuminated with intense blue and purple lighting, creating a moody atmosphere; a focused spotlight beam is visible in the background, adding depth. The performer’s facial expression is intense, eyes closed or squinting, indicating emotional engagement. The camera maintains a close-up, slightly angled shot of his upper body, with minimal movement, emphasizing his actions and expressions. Across the frames, the lighting subtly shifts, enhancing the visual dynamics of the performance without altering the scene’s core composition"
34
+ prompt='一个头戴耳机的男人正在一个工作室里对着麦克风唱歌,偶尔晃动头部'
35
  # Generate one video
36
  result = pipeline(
37
+ prompt=f"<T2V>{prompt}. The quality is very high!",
38
  negative_prompt=negative_prompt,
39
+ guidance_scale=3.0,
40
  temperature=1.0,
41
  complexity_aware_Tmin=10,
42
  complexity_aware_Tmax=50,