Upload 7 files

#5
by wop - opened
Files changed (7) hide show
  1. .gitattributes +43 -43
  2. README.md +14 -14
  3. app.py +219 -158
  4. mmdit.py +141 -0
  5. pixel_dit.py +133 -133
  6. requirements.txt +13 -11
  7. voxel_dit.py +134 -134
.gitattributes CHANGED
@@ -1,43 +1,43 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
36
- examples/demo19.jpg filter=lfs diff=lfs merge=lfs -text
37
- assets/DA-2K.png filter=lfs diff=lfs merge=lfs -text
38
- assets/examples_video/basketball.mp4 filter=lfs diff=lfs merge=lfs -text
39
- assets/examples_video/ferris_wheel.mp4 filter=lfs diff=lfs merge=lfs -text
40
- assets/examples/demo19.jpg filter=lfs diff=lfs merge=lfs -text
41
- assets/teaser.png filter=lfs diff=lfs merge=lfs -text
42
- metric_depth/assets/compare_zoedepth.png filter=lfs diff=lfs merge=lfs -text
43
- metric_depth/dataset/splits/hypersim/train.txt filter=lfs diff=lfs merge=lfs -text
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ examples/demo19.jpg filter=lfs diff=lfs merge=lfs -text
37
+ assets/DA-2K.png filter=lfs diff=lfs merge=lfs -text
38
+ assets/examples_video/basketball.mp4 filter=lfs diff=lfs merge=lfs -text
39
+ assets/examples_video/ferris_wheel.mp4 filter=lfs diff=lfs merge=lfs -text
40
+ assets/examples/demo19.jpg filter=lfs diff=lfs merge=lfs -text
41
+ assets/teaser.png filter=lfs diff=lfs merge=lfs -text
42
+ metric_depth/assets/compare_zoedepth.png filter=lfs diff=lfs merge=lfs -text
43
+ metric_depth/dataset/splits/hypersim/train.txt filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,14 +1,14 @@
1
- ---
2
- title: BenchLabs Models
3
- emoji: 🏛️
4
- colorFrom: red
5
- colorTo: blue
6
- sdk: gradio
7
- sdk_version: 5.50.0
8
- app_file: app.py
9
- pinned: false
10
- license: apache-2.0
11
- ---
12
-
13
- # BenchLabs Inference Space
14
- This space runs **PixelModel-v5** (Text-to-Image) and **VoxelModel-v1** (Text-to-3D) dynamically on CPU.
 
1
+ ---
2
+ title: BenchLabs Models
3
+ emoji: 🏛️
4
+ colorFrom: red
5
+ colorTo: blue
6
+ sdk: gradio
7
+ sdk_version: 5.50.0
8
+ app_file: app.py
9
+ pinned: false
10
+ license: apache-2.0
11
+ ---
12
+
13
+ # BenchLabs Inference Space
14
+ This space runs **PixelModel-v5** (Text-to-Image) and **VoxelModel-v1** (Text-to-3D) dynamically on CPU.
app.py CHANGED
@@ -1,158 +1,219 @@
1
- from __future__ import annotations
2
-
3
- import tempfile
4
-
5
- import gradio as gr
6
- import numpy as np
7
- import torch
8
- import trimesh
9
- from diffusers import AutoencoderKL
10
- from huggingface_hub import hf_hub_download
11
- from safetensors.torch import load_file
12
- from transformers import CLIPTextModel, CLIPTokenizer
13
-
14
- from pixel_dit import DiT
15
- from voxel_dit import VoxelDiT
16
-
17
- DEV = "cpu"
18
- SCALE = 0.18215
19
- CLIP_ID = "openai/clip-vit-base-patch32"
20
- MAX_TOKENS = 40
21
-
22
- print("[boot] loading shared CLIP text encoder...")
23
- tokenizer = CLIPTokenizer.from_pretrained(CLIP_ID)
24
- text_encoder = CLIPTextModel.from_pretrained(CLIP_ID).to(DEV).eval()
25
-
26
-
27
- @torch.no_grad()
28
- def encode(strings: list[str]):
29
- t = tokenizer(strings, padding="max_length", max_length=MAX_TOKENS, truncation=True, return_tensors="pt").to(DEV)
30
- o = text_encoder(**t)
31
- return o.last_hidden_state.float(), o.pooler_output.float()
32
-
33
-
34
- null_seq, null_pool = encode([""])
35
-
36
- print("[boot] loading PixelModel v5...")
37
- pm5_weights = hf_hub_download("bench-labs/PixelModel-v5", "model.safetensors")
38
- pm5_state = load_file(pm5_weights)
39
- pixel_model = DiT(dim=384, depth=12, heads=6).to(DEV).eval()
40
- pixel_model.load_state_dict({k[len("dit."):]: v for k, v in pm5_state.items() if k.startswith("dit.")})
41
- vae = AutoencoderKL.from_pretrained("stabilityai/sd-vae-ft-mse").to(DEV).eval()
42
-
43
- print("[boot] loading VoxelModel v1...")
44
- vm1_weights = hf_hub_download("bench-labs/VoxelModel-v1", "model.safetensors")
45
- voxel_model = VoxelDiT().to(DEV).eval()
46
- voxel_model.load_state_dict(load_file(vm1_weights))
47
-
48
- print("[boot] ready.")
49
-
50
-
51
- @torch.no_grad()
52
- def sample_image(prompt: str, steps: int, cfg: float, seed: int, progress=gr.Progress()):
53
- if not prompt.strip():
54
- raise gr.Error("Type a prompt first.")
55
- steps = int(steps)
56
- g = torch.Generator(device=DEV).manual_seed(int(seed))
57
- seq, pool = encode([prompt])
58
- x = torch.randn(1, 4, 32, 32, device=DEV, generator=g)
59
- dt = 1.0 / steps
60
- for i in progress.tqdm(range(steps), desc="sampling"):
61
- t = torch.full((1,), i * dt, device=DEV)
62
- vc = pixel_model(x, t, seq, pool)
63
- vu = pixel_model(x, t, null_seq, null_pool)
64
- x = x + (vu + cfg * (vc - vu)) * dt
65
- img = vae.decode((x / SCALE)).sample
66
- img = ((img.clamp(-1, 1) + 1) / 2).permute(0, 2, 3, 1).numpy()[0]
67
- return (img * 255).round().astype(np.uint8)
68
-
69
-
70
- @torch.no_grad()
71
- def sample_voxel(prompt: str, steps: int, cfg: float, threshold: float, seed: int, progress=gr.Progress()):
72
- if not prompt.strip():
73
- raise gr.Error("Type a prompt first.")
74
- steps = int(steps)
75
- g = torch.Generator(device=DEV).manual_seed(int(seed))
76
- seq, pool = encode([prompt])
77
- x = torch.randn(1, 1, 32, 32, 32, device=DEV, generator=g)
78
- dt = 1.0 / steps
79
- for i in progress.tqdm(range(steps), desc="sampling"):
80
- t = torch.full((1,), i * dt, device=DEV)
81
- vc = voxel_model(x, t, seq, pool)
82
- vu = voxel_model(x, t, null_seq, null_pool)
83
- x = x + (vu + cfg * (vc - vu)) * dt
84
- grid = (x[0, 0] > threshold).numpy()
85
- if not grid.any():
86
- raise gr.Error("Nothing came back above the occupancy threshold — try lowering it or re-rolling the seed.")
87
- return grid_to_glb(grid)
88
-
89
-
90
- def grid_to_glb(grid: np.ndarray) -> str:
91
- voxel = trimesh.voxel.VoxelGrid(encoding=grid)
92
- mesh = voxel.as_boxes()
93
- mesh.visual.face_colors = [180, 180, 190, 255]
94
- path = tempfile.NamedTemporaryFile(suffix=".glb", delete=False).name
95
- mesh.export(path)
96
- return path
97
-
98
-
99
- with gr.Blocks(title="BenchLabs Models") as demo:
100
- gr.Markdown(
101
- "# BenchLabs Models\n"
102
- "Two tiny diffusion models, running live on CPU, no GPU behind this Space. "
103
- "Both are under 45M trained parameters, so generation is slower than a hosted API "
104
- "but the whole model fits in a PNG image if you're curious — see the model pages linked below."
105
- )
106
- with gr.Tab("Text Image (PixelModel v5)"):
107
- gr.Markdown(
108
- "Good at material and light: food, landscapes, skies, interiors. "
109
- "Weak on faces, hands, and anything needing precise structure or text."
110
- )
111
- with gr.Row():
112
- with gr.Column():
113
- img_prompt = gr.Textbox(label="Prompt", placeholder="a bowl of ramen with a soft boiled egg")
114
- img_steps = gr.Slider(10, 50, value=25, step=1, label="Detail (sampling steps)")
115
- img_cfg = gr.Slider(1.0, 10.0, value=5.0, step=0.5, label="Prompt strength (CFG)")
116
- img_seed = gr.Number(value=0, precision=0, label="Seed")
117
- img_btn = gr.Button("Generate image", variant="primary")
118
- with gr.Column():
119
- img_out = gr.Image(label="Result", type="numpy")
120
- img_btn.click(sample_image, [img_prompt, img_steps, img_cfg, img_seed], img_out)
121
- gr.Examples(
122
- [["a bowl of ramen with a soft boiled egg", 25, 5.0, 0],
123
- ["a wet cobblestone street at night", 25, 5.0, 0],
124
- ["a library of wooden shelves", 25, 5.0, 0]],
125
- [img_prompt, img_steps, img_cfg, img_seed],
126
- )
127
-
128
- with gr.Tab("Text 3D (VoxelModel v1)"):
129
- gr.Markdown(
130
- "Good at bulky objects: chairs, tables, cars, mushrooms. "
131
- "Thin objects (swords, keys) don't survive 32³ voxelization, in the training "
132
- "data or the model, so expect a blob rather than a blade."
133
- )
134
- with gr.Row():
135
- with gr.Column():
136
- vox_prompt = gr.Textbox(label="Prompt", placeholder="a wooden chair")
137
- vox_steps = gr.Slider(10, 50, value=25, step=1, label="Detail (sampling steps)")
138
- vox_cfg = gr.Slider(1.0, 10.0, value=5.0, step=0.5, label="Prompt strength (CFG)")
139
- vox_thresh = gr.Slider(-1.0, 1.0, value=0.0, step=0.05, label="Occupancy threshold")
140
- vox_seed = gr.Number(value=0, precision=0, label="Seed")
141
- vox_btn = gr.Button("Generate 3D model", variant="primary")
142
- with gr.Column():
143
- vox_out = gr.Model3D(label="Result")
144
- vox_btn.click(sample_voxel, [vox_prompt, vox_steps, vox_cfg, vox_thresh, vox_seed], vox_out)
145
- gr.Examples(
146
- [["a wooden chair", 25, 5.0, 0.0, 0],
147
- ["a purple mushroom", 25, 5.0, 0.0, 0],
148
- ["a small boat", 25, 5.0, 0.0, 0]],
149
- [vox_prompt, vox_steps, vox_cfg, vox_thresh, vox_seed],
150
- )
151
-
152
- gr.Markdown(
153
- "Models: [PixelModel v5](https://huggingface.co/bench-labs/PixelModel-v5) · "
154
- "[VoxelModel v1](https://huggingface.co/bench-labs/VoxelModel-v1)"
155
- )
156
-
157
- if __name__ == "__main__":
158
- demo.queue(max_size=20).launch(server_name="0.0.0.0")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import tempfile
4
+ import os
5
+
6
+ os.environ.setdefault("HF_HOME", r"D:\hf-cache")
7
+ os.environ.setdefault("HUGGINGFACE_HUB_CACHE", r"D:\hf-cache\hub")
8
+
9
+ import gradio as gr
10
+ import numpy as np
11
+ import torch
12
+ import trimesh
13
+ from diffusers import AutoencoderKL
14
+ from huggingface_hub import hf_hub_download
15
+ from safetensors.torch import load_file
16
+ from transformers import CLIPTextModel, CLIPTokenizer, T5EncoderModel, T5TokenizerFast
17
+
18
+ from pixel_dit import DiT
19
+ from voxel_dit import VoxelDiT
20
+ from mmdit import MMDiT
21
+
22
+ DEV = "cpu"
23
+ SCALE = 0.18215
24
+ CLIP_ID = "openai/clip-vit-base-patch32"
25
+ MAX_TOKENS = 40
26
+
27
+ print("[boot] loading shared CLIP text encoder...")
28
+ tokenizer = CLIPTokenizer.from_pretrained(CLIP_ID)
29
+ text_encoder = CLIPTextModel.from_pretrained(CLIP_ID).to(DEV).eval()
30
+
31
+
32
+ @torch.no_grad()
33
+ def encode(strings: list[str]):
34
+ t = tokenizer(strings, padding="max_length", max_length=MAX_TOKENS, truncation=True, return_tensors="pt").to(DEV)
35
+ o = text_encoder(**t)
36
+ return o.last_hidden_state.float(), o.pooler_output.float()
37
+
38
+
39
+ null_seq, null_pool = encode([""])
40
+
41
+ print("[boot] loading PixelModel v5...")
42
+ pm5_weights = hf_hub_download("bench-labs/PixelModel-v5", "model.safetensors")
43
+ pm5_state = load_file(pm5_weights)
44
+ pixel_model = DiT(dim=384, depth=12, heads=6).to(DEV).eval()
45
+ pixel_model.load_state_dict({k[len("dit."):]: v for k, v in pm5_state.items() if k.startswith("dit.")})
46
+ vae = AutoencoderKL.from_pretrained("stabilityai/sd-vae-ft-mse").to(DEV).eval()
47
+
48
+ print("[boot] loading VoxelModel v1...")
49
+ vm1_weights = hf_hub_download("bench-labs/VoxelModel-v1", "model.safetensors")
50
+ voxel_model = VoxelDiT().to(DEV).eval()
51
+ voxel_model.load_state_dict(load_file(vm1_weights))
52
+
53
+ print("[boot] loading PixelModel v6...")
54
+ v6_weights = hf_hub_download("bench-labs/PixelModel-v6", "model.safetensors")
55
+ pixel_model_v6 = MMDiT().to(DEV).eval()
56
+ pixel_model_v6.load_state_dict(load_file(v6_weights), strict=False)
57
+ t5_tokenizer = T5TokenizerFast.from_pretrained("google/flan-t5-base")
58
+ t5_encoder = T5EncoderModel.from_pretrained("google/flan-t5-base").to(DEV).eval()
59
+ vae_v6 = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix").to(DEV).float().eval()
60
+ null_v6_seq, null_v6_mask, null_v6_pool = None, None, None
61
+
62
+ print("[boot] ready.")
63
+
64
+
65
+ @torch.no_grad()
66
+ def sample_image(prompt: str, steps: int, cfg: float, seed: int, progress=gr.Progress()):
67
+ if not prompt.strip():
68
+ raise gr.Error("Type a prompt first.")
69
+ steps = int(steps)
70
+ g = torch.Generator(device=DEV).manual_seed(int(seed))
71
+ seq, pool = encode([prompt])
72
+ x = torch.randn(1, 4, 32, 32, device=DEV, generator=g)
73
+ dt = 1.0 / steps
74
+ for i in progress.tqdm(range(steps), desc="sampling"):
75
+ t = torch.full((1,), i * dt, device=DEV)
76
+ vc = pixel_model(x, t, seq, pool)
77
+ vu = pixel_model(x, t, null_seq, null_pool)
78
+ x = x + (vu + cfg * (vc - vu)) * dt
79
+ img = vae.decode((x / SCALE)).sample
80
+ img = ((img.clamp(-1, 1) + 1) / 2).permute(0, 2, 3, 1).numpy()[0]
81
+ return (img * 255).round().astype(np.uint8)
82
+
83
+
84
+ @torch.no_grad()
85
+ def sample_voxel(prompt: str, steps: int, cfg: float, threshold: float, seed: int, progress=gr.Progress()):
86
+ if not prompt.strip():
87
+ raise gr.Error("Type a prompt first.")
88
+ steps = int(steps)
89
+ g = torch.Generator(device=DEV).manual_seed(int(seed))
90
+ seq, pool = encode([prompt])
91
+ x = torch.randn(1, 1, 32, 32, 32, device=DEV, generator=g)
92
+ dt = 1.0 / steps
93
+ for i in progress.tqdm(range(steps), desc="sampling"):
94
+ t = torch.full((1,), i * dt, device=DEV)
95
+ vc = voxel_model(x, t, seq, pool)
96
+ vu = voxel_model(x, t, null_seq, null_pool)
97
+ x = x + (vu + cfg * (vc - vu)) * dt
98
+ grid = (x[0, 0] > threshold).numpy()
99
+ if not grid.any():
100
+ raise gr.Error("Nothing came back above the occupancy threshold — try lowering it or re-rolling the seed.")
101
+ return grid_to_glb(grid)
102
+
103
+
104
+ @torch.no_grad()
105
+ def sample_image_v6(prompt: str, steps: int, cfg: float, seed: int, progress=gr.Progress()):
106
+ global null_v6_seq, null_v6_mask, null_v6_pool
107
+ if not prompt.strip():
108
+ raise gr.Error("Type a prompt first.")
109
+ steps = int(steps)
110
+
111
+ def encode_v6(strings):
112
+ t = t5_tokenizer(strings, padding="max_length", max_length=32, truncation=True, return_tensors="pt").to(DEV)
113
+ seq = t5_encoder(**t).last_hidden_state.float()
114
+ _, pool = encode(strings)
115
+ return seq, t["attention_mask"].float(), pool
116
+
117
+ seq, mask, pool = encode_v6([prompt])
118
+ if null_v6_seq is None:
119
+ null_v6_seq, null_v6_mask, null_v6_pool = encode_v6([""])
120
+ g = torch.Generator(device=DEV).manual_seed(int(seed))
121
+ x = torch.randn(1, 4, 32, 32, device=DEV, generator=g)
122
+ dt = 1.0 / steps
123
+ for i in progress.tqdm(range(steps), desc="sampling"):
124
+ t = torch.full((1,), i * dt, device=DEV)
125
+ vc = pixel_model_v6(x, t, seq, mask, pool)
126
+ vu = pixel_model_v6(x, t, null_v6_seq, null_v6_mask, null_v6_pool)
127
+ x = x + (vu + cfg * (vc - vu)) * dt
128
+ img = vae_v6.decode(x / vae_v6.config.scaling_factor).sample
129
+ return (((img.clamp(-1, 1) + 1) / 2).permute(0, 2, 3, 1).numpy()[0] * 255).round().astype(np.uint8)
130
+
131
+
132
+ def grid_to_glb(grid: np.ndarray) -> str:
133
+ voxel = trimesh.voxel.VoxelGrid(encoding=grid)
134
+ mesh = voxel.as_boxes()
135
+ mesh.visual.face_colors = [180, 180, 190, 255]
136
+ path = tempfile.NamedTemporaryFile(suffix=".glb", delete=False).name
137
+ mesh.export(path)
138
+ return path
139
+
140
+
141
+ with gr.Blocks(title="BenchLabs Models") as demo:
142
+ gr.Markdown(
143
+ "# BenchLabs Models\n"
144
+ "Two tiny diffusion models, running live on CPU, no GPU behind this Space. "
145
+ "Both are under 45M trained parameters, so generation is slower than a hosted API "
146
+ "but the whole model fits in a PNG image if you're curious — see the model pages linked below."
147
+ )
148
+ with gr.Tab("Text Image (PixelModel v6)"):
149
+ gr.Markdown("A larger MMDiT model conditioned by T5 and CLIP. CPU generation is slower; 256x256 output.")
150
+ with gr.Row():
151
+ with gr.Column():
152
+ v6_prompt = gr.Textbox(label="Prompt", placeholder="a red fox sitting in a snowy forest")
153
+ v6_steps = gr.Slider(10, 100, value=50, step=5, label="Detail (sampling steps)")
154
+ v6_cfg = gr.Slider(1.0, 10.0, value=3.0, step=0.5, label="Prompt strength (CFG)")
155
+ v6_seed = gr.Number(value=0, precision=0, label="Seed")
156
+ v6_btn = gr.Button("Generate image", variant="primary")
157
+ with gr.Column():
158
+ v6_out = gr.Image(label="Result", type="numpy")
159
+ v6_btn.click(sample_image_v6, [v6_prompt, v6_steps, v6_cfg, v6_seed], v6_out)
160
+ gr.Examples(
161
+ [["a red fox sitting in a snowy forest", 50, 3.0, 0],
162
+ ["a lighthouse on a cliff at sunset", 50, 3.0, 0],
163
+ ["a city street at night with neon signs", 50, 3.0, 0]],
164
+ [v6_prompt, v6_steps, v6_cfg, v6_seed],
165
+ )
166
+
167
+ with gr.Tab("Text → 3D (VoxelModel v1)"):
168
+ gr.Markdown(
169
+ "Good at bulky objects: chairs, tables, cars, mushrooms. "
170
+ "Thin objects (swords, keys) don't survive 32³ voxelization, in the training "
171
+ "data or the model, so expect a blob rather than a blade."
172
+ )
173
+ with gr.Row():
174
+ with gr.Column():
175
+ vox_prompt = gr.Textbox(label="Prompt", placeholder="a wooden chair")
176
+ vox_steps = gr.Slider(10, 50, value=25, step=1, label="Detail (sampling steps)")
177
+ vox_cfg = gr.Slider(1.0, 10.0, value=5.0, step=0.5, label="Prompt strength (CFG)")
178
+ vox_thresh = gr.Slider(-1.0, 1.0, value=0.0, step=0.05, label="Occupancy threshold")
179
+ vox_seed = gr.Number(value=0, precision=0, label="Seed")
180
+ vox_btn = gr.Button("Generate 3D model", variant="primary")
181
+ with gr.Column():
182
+ vox_out = gr.Model3D(label="Result")
183
+ vox_btn.click(sample_voxel, [vox_prompt, vox_steps, vox_cfg, vox_thresh, vox_seed], vox_out)
184
+ gr.Examples(
185
+ [["a wooden chair", 25, 5.0, 0.0, 0],
186
+ ["a purple mushroom", 25, 5.0, 0.0, 0],
187
+ ["a small boat", 25, 5.0, 0.0, 0]],
188
+ [vox_prompt, vox_steps, vox_cfg, vox_thresh, vox_seed],
189
+ )
190
+
191
+ with gr.Tab("Text → Image (PixelModel v5)"):
192
+ gr.Markdown(
193
+ "Good at material and light: food, landscapes, skies, interiors. "
194
+ "Weak on faces, hands, and anything needing precise structure or text."
195
+ )
196
+ with gr.Row():
197
+ with gr.Column():
198
+ img_prompt = gr.Textbox(label="Prompt", placeholder="a bowl of ramen with a soft boiled egg")
199
+ img_steps = gr.Slider(10, 50, value=25, step=1, label="Detail (sampling steps)")
200
+ img_cfg = gr.Slider(1.0, 10.0, value=5.0, step=0.5, label="Prompt strength (CFG)")
201
+ img_seed = gr.Number(value=0, precision=0, label="Seed")
202
+ img_btn = gr.Button("Generate image", variant="primary")
203
+ with gr.Column():
204
+ img_out = gr.Image(label="Result", type="numpy")
205
+ img_btn.click(sample_image, [img_prompt, img_steps, img_cfg, img_seed], img_out)
206
+ gr.Examples(
207
+ [["a bowl of ramen with a soft boiled egg", 25, 5.0, 0],
208
+ ["a wet cobblestone street at night", 25, 5.0, 0],
209
+ ["a library of wooden shelves", 25, 5.0, 0]],
210
+ [img_prompt, img_steps, img_cfg, img_seed],
211
+ )
212
+
213
+ gr.Markdown(
214
+ "Models: [PixelModel v5](https://huggingface.co/bench-labs/PixelModel-v5) · "
215
+ "[VoxelModel v1](https://huggingface.co/bench-labs/VoxelModel-v1)"
216
+ )
217
+
218
+ if __name__ == "__main__":
219
+ demo.queue(max_size=20).launch(server_name="0.0.0.0")
mmdit.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+
8
+
9
+ def modulate(x, shift, scale):
10
+ return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
11
+
12
+
13
+ def timestep_embedding(t, dim, max_period=10000):
14
+ half = dim // 2
15
+ freqs = torch.exp(-math.log(max_period) * torch.arange(half, device=t.device) / half)
16
+ args = t[:, None].float() * freqs[None]
17
+ emb = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
18
+ return torch.cat([emb, torch.zeros_like(emb[:, :1])], dim=-1) if dim % 2 else emb
19
+
20
+
21
+ def rope_freqs(positions, dim, base=10000.0):
22
+ inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
23
+ return torch.outer(positions.float(), inv_freq)
24
+
25
+
26
+ def rope_cos_sin(freqs):
27
+ emb = torch.cat([freqs, freqs], dim=-1)
28
+ return emb.cos(), emb.sin()
29
+
30
+
31
+ def rotate_half(x):
32
+ x1, x2 = x.chunk(2, dim=-1)
33
+ return torch.cat([-x2, x1], dim=-1)
34
+
35
+
36
+ def apply_rope(x, cos, sin):
37
+ return x * cos + rotate_half(x) * sin
38
+
39
+
40
+ def apply_rope_2d(x, row_cos, row_sin, col_cos, col_sin):
41
+ x1, x2 = x.chunk(2, dim=-1)
42
+ return torch.cat([apply_rope(x1, row_cos, row_sin), apply_rope(x2, col_cos, col_sin)], dim=-1)
43
+
44
+
45
+ class RMSNormHead(nn.Module):
46
+ def __init__(self, head_dim, eps=1e-6):
47
+ super().__init__()
48
+ self.weight = nn.Parameter(torch.ones(head_dim))
49
+ self.eps = eps
50
+
51
+ def forward(self, x):
52
+ return x * x.pow(2).mean(-1, keepdim=True).add(self.eps).rsqrt() * self.weight
53
+
54
+
55
+ class SwiGLU(nn.Module):
56
+ def __init__(self, dim, hidden):
57
+ super().__init__()
58
+ self.gate = nn.Linear(dim, hidden)
59
+ self.up = nn.Linear(dim, hidden)
60
+ self.down = nn.Linear(hidden, dim)
61
+
62
+ def forward(self, x):
63
+ return self.down(F.silu(self.gate(x)) * self.up(x))
64
+
65
+
66
+ class JointBlock(nn.Module):
67
+ def __init__(self, dim, heads, mlp_hidden):
68
+ super().__init__()
69
+ self.heads, self.head_dim = heads, dim // heads
70
+ self.norm1_img = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
71
+ self.norm1_txt = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
72
+ self.qkv_img = nn.Linear(dim, 3 * dim)
73
+ self.qkv_txt = nn.Linear(dim, 3 * dim)
74
+ self.qn_img, self.kn_img = RMSNormHead(self.head_dim), RMSNormHead(self.head_dim)
75
+ self.qn_txt, self.kn_txt = RMSNormHead(self.head_dim), RMSNormHead(self.head_dim)
76
+ self.proj_img, self.proj_txt = nn.Linear(dim, dim), nn.Linear(dim, dim)
77
+ self.norm2_img = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
78
+ self.norm2_txt = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
79
+ self.mlp_img, self.mlp_txt = SwiGLU(dim, mlp_hidden), SwiGLU(dim, mlp_hidden)
80
+ self.ada_img = nn.Sequential(nn.SiLU(), nn.Linear(dim, 6 * dim))
81
+ self.ada_txt = nn.Sequential(nn.SiLU(), nn.Linear(dim, 6 * dim))
82
+
83
+ def forward(self, img, txt, c, rope_img, rope_txt, key_valid):
84
+ s1i, sc1i, g1i, s2i, sc2i, g2i = self.ada_img(c).chunk(6, dim=-1)
85
+ s1t, sc1t, g1t, s2t, sc2t, g2t = self.ada_txt(c).chunk(6, dim=-1)
86
+ xi, xt = modulate(self.norm1_img(img), s1i, sc1i), modulate(self.norm1_txt(txt), s1t, sc1t)
87
+ b, ni, cdim = xi.shape; nt = xt.shape[1]; h, d = self.heads, self.head_dim
88
+ qi, ki, vi = self.qkv_img(xi).reshape(b, ni, 3, h, d).permute(2, 0, 3, 1, 4)
89
+ qt, kt, vt = self.qkv_txt(xt).reshape(b, nt, 3, h, d).permute(2, 0, 3, 1, 4)
90
+ qi, ki, qt, kt = self.qn_img(qi), self.kn_img(ki), self.qn_txt(qt), self.kn_txt(kt)
91
+ rc, rs, cc, cs = rope_img; tc, ts = rope_txt
92
+ qi, ki = apply_rope_2d(qi, rc, rs, cc, cs), apply_rope_2d(ki, rc, rs, cc, cs)
93
+ qt, kt = apply_rope(qt, tc, ts), apply_rope(kt, tc, ts)
94
+ q, k, v = torch.cat([qi, qt], 2), torch.cat([ki, kt], 2), torch.cat([vi, vt], 2)
95
+ o = F.scaled_dot_product_attention(q, k, v, attn_mask=key_valid[:, None, None, :])
96
+ o = o.transpose(1, 2).reshape(b, ni + nt, cdim)
97
+ oi, ot = o[:, :ni], o[:, ni:]
98
+ img = img + g1i[:, None] * self.proj_img(oi)
99
+ txt = txt + g1t[:, None] * self.proj_txt(ot)
100
+ img = img + g2i[:, None] * self.mlp_img(modulate(self.norm2_img(img), s2i, sc2i))
101
+ txt = txt + g2t[:, None] * self.mlp_txt(modulate(self.norm2_txt(txt), s2t, sc2t))
102
+ return img, txt
103
+
104
+
105
+ class MMDiT(nn.Module):
106
+ def __init__(self, latent_ch=4, latent_size=32, patch=2, dim=512, depth=16, heads=8,
107
+ t5_dim=768, clip_dim=512, t5_len=32, mlp_hidden=1408, repa_dim=384, repa_layer=8):
108
+ super().__init__()
109
+ self.latent_ch, self.latent_size, self.patch = latent_ch, latent_size, patch
110
+ self.grid, self.patch_dim, self.dim = latent_size // patch, latent_ch * patch * patch, dim
111
+ self.t5_len, self.repa_layer = t5_len, repa_layer
112
+ self.x_embed = nn.Linear(self.patch_dim, dim)
113
+ self.t_mlp = nn.Sequential(nn.Linear(dim, dim), nn.SiLU(), nn.Linear(dim, dim))
114
+ self.clip_proj, self.t5_proj = nn.Linear(clip_dim, dim), nn.Linear(t5_dim, dim)
115
+ self.blocks = nn.ModuleList([JointBlock(dim, heads, mlp_hidden) for _ in range(depth)])
116
+ self.norm_out = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
117
+ self.ada_out, self.head = nn.Sequential(nn.SiLU(), nn.Linear(dim, 2 * dim)), nn.Linear(dim, self.patch_dim)
118
+ self.repa_head = nn.Sequential(nn.Linear(dim, dim), nn.GELU(approximate="tanh"), nn.Linear(dim, repa_dim))
119
+ hd2 = (dim // heads) // 2
120
+ rows = torch.arange(self.grid).repeat_interleave(self.grid); cols = torch.arange(self.grid).repeat(self.grid)
121
+ for name, value in zip(("row_cos", "row_sin", "col_cos", "col_sin"), (*rope_cos_sin(rope_freqs(rows, hd2)), *rope_cos_sin(rope_freqs(cols, hd2)))):
122
+ self.register_buffer(name, value, persistent=False)
123
+ self.register_buffer("t_cos", rope_cos_sin(rope_freqs(torch.arange(t5_len), dim // heads))[0], persistent=False)
124
+ self.register_buffer("t_sin", rope_cos_sin(rope_freqs(torch.arange(t5_len), dim // heads))[1], persistent=False)
125
+
126
+ def patchify(self, x):
127
+ b, c, h, w = x.shape; p = self.patch
128
+ return x.reshape(b, c, h // p, p, w // p, p).permute(0, 2, 4, 1, 3, 5).reshape(b, (h // p) * (w // p), c * p * p)
129
+
130
+ def unpatchify(self, x):
131
+ b, _, _ = x.shape; p, g, c = self.patch, self.grid, self.latent_ch
132
+ return x.reshape(b, g, g, c, p, p).permute(0, 3, 1, 4, 2, 5).reshape(b, c, g * p, g * p)
133
+
134
+ def forward(self, x, t, t5_seq, t5_mask, clip_pool):
135
+ b = x.shape[0]; img = self.x_embed(self.patchify(x)); txt = self.t5_proj(t5_seq)
136
+ c = self.t_mlp(timestep_embedding(t, self.dim)) + self.clip_proj(clip_pool)
137
+ valid = torch.cat([torch.ones(b, img.shape[1], dtype=torch.bool, device=x.device), t5_mask.bool()], dim=1)
138
+ ri = (self.row_cos, self.row_sin, self.col_cos, self.col_sin); rt = (self.t_cos, self.t_sin)
139
+ for block in self.blocks: img, txt = block(img, txt, c, ri, rt, valid)
140
+ shift, scale = self.ada_out(c).chunk(2, dim=-1)
141
+ return self.unpatchify(self.head(modulate(self.norm_out(img), shift, scale)))
pixel_dit.py CHANGED
@@ -1,133 +1,133 @@
1
- from __future__ import annotations
2
-
3
- import math
4
- import numpy as np
5
- import torch
6
- import torch.nn as nn
7
- import torch.nn.functional as F
8
-
9
- def modulate(x, shift, scale):
10
- return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
11
-
12
- def timestep_embedding(t, dim, max_period=10000):
13
- half = dim // 2
14
- freqs = torch.exp(-math.log(max_period) * torch.arange(half, device=t.device) / half)
15
- args = t[:, None].float() * freqs[None]
16
- emb = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
17
- if dim % 2:
18
- emb = torch.cat([emb, torch.zeros_like(emb[:, :1])], dim=-1)
19
- return emb
20
-
21
- def sincos_2d(dim, grid_size):
22
- g = np.arange(grid_size, dtype=np.float32)
23
- gx, gy = np.meshgrid(g, g, indexing="xy")
24
- assert dim % 4 == 0
25
- d4 = dim // 4
26
- omega = 1.0 / (10000 ** (np.arange(d4, dtype=np.float32) / d4))
27
- def emb1(p):
28
- out = p.reshape(-1)[:, None] * omega[None]
29
- return np.concatenate([np.sin(out), np.cos(out)], axis=1)
30
- pe = np.concatenate([emb1(gx), emb1(gy)], axis=1)
31
- return torch.from_numpy(pe).float()
32
-
33
- class Attention(nn.Module):
34
- def __init__(self, dim, heads):
35
- super().__init__()
36
- self.heads = heads
37
- self.q = nn.Linear(dim, dim)
38
- self.kv = nn.Linear(dim, dim * 2)
39
- self.proj = nn.Linear(dim, dim)
40
-
41
- def forward(self, x, ctx=None):
42
- ctx = x if ctx is None else ctx
43
- B, N, C = x.shape
44
- M = ctx.shape[1]
45
- h = self.heads
46
- q = self.q(x).reshape(B, N, h, C // h).transpose(1, 2)
47
- kv = self.kv(ctx).reshape(B, M, 2, h, C // h).permute(2, 0, 3, 1, 4)
48
- k, v = kv[0], kv[1]
49
- o = F.scaled_dot_product_attention(q, k, v)
50
- o = o.transpose(1, 2).reshape(B, N, C)
51
- return self.proj(o)
52
-
53
- class Block(nn.Module):
54
- def __init__(self, dim, heads, mlp_ratio=4.0):
55
- super().__init__()
56
- self.norm1 = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
57
- self.attn = Attention(dim, heads)
58
- self.norm_ca = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
59
- self.cross = Attention(dim, heads)
60
- self.norm2 = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
61
- hidden = int(dim * mlp_ratio)
62
- self.mlp = nn.Sequential(nn.Linear(dim, hidden), nn.GELU(approximate="tanh"),
63
- nn.Linear(hidden, dim))
64
- self.ada = nn.Sequential(nn.SiLU(), nn.Linear(dim, 6 * dim))
65
- self.cross_gate = nn.Parameter(torch.zeros(1))
66
-
67
- def forward(self, x, c, text):
68
- shift1, scale1, gate1, shift2, scale2, gate2 = self.ada(c).chunk(6, dim=1)
69
- x = x + gate1.unsqueeze(1) * self.attn(modulate(self.norm1(x), shift1, scale1))
70
- x = x + self.cross_gate * self.cross(self.norm_ca(x), text)
71
- x = x + gate2.unsqueeze(1) * self.mlp(modulate(self.norm2(x), shift2, scale2))
72
- return x
73
-
74
- class DiT(nn.Module):
75
- def __init__(self, latent_ch=4, latent_size=32, patch=2, dim=384, depth=12,
76
- heads=6, text_dim=512, mlp_ratio=4.0):
77
- super().__init__()
78
- self.latent_ch = latent_ch
79
- self.latent_size = latent_size
80
- self.patch = patch
81
- self.grid = latent_size // patch
82
- self.patch_dim = latent_ch * patch * patch
83
- self.x_embed = nn.Linear(self.patch_dim, dim)
84
- self.register_buffer("pos", sincos_2d(dim, self.grid).unsqueeze(0))
85
- self.t_mlp = nn.Sequential(nn.Linear(dim, dim), nn.SiLU(), nn.Linear(dim, dim))
86
- self.text_proj = nn.Linear(text_dim, dim)
87
- self.text_pool = nn.Linear(text_dim, dim)
88
- self.blocks = nn.ModuleList([Block(dim, heads, mlp_ratio) for _ in range(depth)])
89
- self.norm_out = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
90
- self.ada_out = nn.Sequential(nn.SiLU(), nn.Linear(dim, 2 * dim))
91
- self.head = nn.Linear(dim, self.patch_dim)
92
- self.dim = dim
93
- self._init()
94
-
95
- def _init(self):
96
- for m in self.modules():
97
- if isinstance(m, nn.Linear):
98
- nn.init.xavier_uniform_(m.weight)
99
- if m.bias is not None:
100
- nn.init.zeros_(m.bias)
101
- for b in self.blocks:
102
- nn.init.zeros_(b.ada[-1].weight); nn.init.zeros_(b.ada[-1].bias)
103
- nn.init.zeros_(self.ada_out[-1].weight); nn.init.zeros_(self.ada_out[-1].bias)
104
- nn.init.zeros_(self.head.weight); nn.init.zeros_(self.head.bias)
105
-
106
- def patchify(self, x):
107
- B, C, H, W = x.shape
108
- p = self.patch
109
- x = x.reshape(B, C, H // p, p, W // p, p)
110
- x = x.permute(0, 2, 4, 1, 3, 5).reshape(B, (H // p) * (W // p), C * p * p)
111
- return x
112
-
113
- def unpatchify(self, x):
114
- B, N, _ = x.shape
115
- p = self.patch
116
- g = self.grid
117
- C = self.latent_ch
118
- x = x.reshape(B, g, g, C, p, p).permute(0, 3, 1, 4, 2, 5)
119
- return x.reshape(B, C, g * p, g * p)
120
-
121
- def forward(self, x, t, text_seq, text_pool):
122
- x = self.x_embed(self.patchify(x)) + self.pos
123
- c = self.t_mlp(timestep_embedding(t, self.dim)) + self.text_pool(text_pool)
124
- text = self.text_proj(text_seq)
125
- for blk in self.blocks:
126
- x = blk(x, c, text)
127
- shift, scale = self.ada_out(c).chunk(2, dim=1)
128
- x = modulate(self.norm_out(x), shift, scale)
129
- x = self.head(x)
130
- return self.unpatchify(x)
131
-
132
- def num_params(self):
133
- return sum(p.numel() for p in self.parameters())
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import numpy as np
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+
9
+ def modulate(x, shift, scale):
10
+ return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
11
+
12
+ def timestep_embedding(t, dim, max_period=10000):
13
+ half = dim // 2
14
+ freqs = torch.exp(-math.log(max_period) * torch.arange(half, device=t.device) / half)
15
+ args = t[:, None].float() * freqs[None]
16
+ emb = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
17
+ if dim % 2:
18
+ emb = torch.cat([emb, torch.zeros_like(emb[:, :1])], dim=-1)
19
+ return emb
20
+
21
+ def sincos_2d(dim, grid_size):
22
+ g = np.arange(grid_size, dtype=np.float32)
23
+ gx, gy = np.meshgrid(g, g, indexing="xy")
24
+ assert dim % 4 == 0
25
+ d4 = dim // 4
26
+ omega = 1.0 / (10000 ** (np.arange(d4, dtype=np.float32) / d4))
27
+ def emb1(p):
28
+ out = p.reshape(-1)[:, None] * omega[None]
29
+ return np.concatenate([np.sin(out), np.cos(out)], axis=1)
30
+ pe = np.concatenate([emb1(gx), emb1(gy)], axis=1)
31
+ return torch.from_numpy(pe).float()
32
+
33
+ class Attention(nn.Module):
34
+ def __init__(self, dim, heads):
35
+ super().__init__()
36
+ self.heads = heads
37
+ self.q = nn.Linear(dim, dim)
38
+ self.kv = nn.Linear(dim, dim * 2)
39
+ self.proj = nn.Linear(dim, dim)
40
+
41
+ def forward(self, x, ctx=None):
42
+ ctx = x if ctx is None else ctx
43
+ B, N, C = x.shape
44
+ M = ctx.shape[1]
45
+ h = self.heads
46
+ q = self.q(x).reshape(B, N, h, C // h).transpose(1, 2)
47
+ kv = self.kv(ctx).reshape(B, M, 2, h, C // h).permute(2, 0, 3, 1, 4)
48
+ k, v = kv[0], kv[1]
49
+ o = F.scaled_dot_product_attention(q, k, v)
50
+ o = o.transpose(1, 2).reshape(B, N, C)
51
+ return self.proj(o)
52
+
53
+ class Block(nn.Module):
54
+ def __init__(self, dim, heads, mlp_ratio=4.0):
55
+ super().__init__()
56
+ self.norm1 = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
57
+ self.attn = Attention(dim, heads)
58
+ self.norm_ca = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
59
+ self.cross = Attention(dim, heads)
60
+ self.norm2 = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
61
+ hidden = int(dim * mlp_ratio)
62
+ self.mlp = nn.Sequential(nn.Linear(dim, hidden), nn.GELU(approximate="tanh"),
63
+ nn.Linear(hidden, dim))
64
+ self.ada = nn.Sequential(nn.SiLU(), nn.Linear(dim, 6 * dim))
65
+ self.cross_gate = nn.Parameter(torch.zeros(1))
66
+
67
+ def forward(self, x, c, text):
68
+ shift1, scale1, gate1, shift2, scale2, gate2 = self.ada(c).chunk(6, dim=1)
69
+ x = x + gate1.unsqueeze(1) * self.attn(modulate(self.norm1(x), shift1, scale1))
70
+ x = x + self.cross_gate * self.cross(self.norm_ca(x), text)
71
+ x = x + gate2.unsqueeze(1) * self.mlp(modulate(self.norm2(x), shift2, scale2))
72
+ return x
73
+
74
+ class DiT(nn.Module):
75
+ def __init__(self, latent_ch=4, latent_size=32, patch=2, dim=384, depth=12,
76
+ heads=6, text_dim=512, mlp_ratio=4.0):
77
+ super().__init__()
78
+ self.latent_ch = latent_ch
79
+ self.latent_size = latent_size
80
+ self.patch = patch
81
+ self.grid = latent_size // patch
82
+ self.patch_dim = latent_ch * patch * patch
83
+ self.x_embed = nn.Linear(self.patch_dim, dim)
84
+ self.register_buffer("pos", sincos_2d(dim, self.grid).unsqueeze(0))
85
+ self.t_mlp = nn.Sequential(nn.Linear(dim, dim), nn.SiLU(), nn.Linear(dim, dim))
86
+ self.text_proj = nn.Linear(text_dim, dim)
87
+ self.text_pool = nn.Linear(text_dim, dim)
88
+ self.blocks = nn.ModuleList([Block(dim, heads, mlp_ratio) for _ in range(depth)])
89
+ self.norm_out = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
90
+ self.ada_out = nn.Sequential(nn.SiLU(), nn.Linear(dim, 2 * dim))
91
+ self.head = nn.Linear(dim, self.patch_dim)
92
+ self.dim = dim
93
+ self._init()
94
+
95
+ def _init(self):
96
+ for m in self.modules():
97
+ if isinstance(m, nn.Linear):
98
+ nn.init.xavier_uniform_(m.weight)
99
+ if m.bias is not None:
100
+ nn.init.zeros_(m.bias)
101
+ for b in self.blocks:
102
+ nn.init.zeros_(b.ada[-1].weight); nn.init.zeros_(b.ada[-1].bias)
103
+ nn.init.zeros_(self.ada_out[-1].weight); nn.init.zeros_(self.ada_out[-1].bias)
104
+ nn.init.zeros_(self.head.weight); nn.init.zeros_(self.head.bias)
105
+
106
+ def patchify(self, x):
107
+ B, C, H, W = x.shape
108
+ p = self.patch
109
+ x = x.reshape(B, C, H // p, p, W // p, p)
110
+ x = x.permute(0, 2, 4, 1, 3, 5).reshape(B, (H // p) * (W // p), C * p * p)
111
+ return x
112
+
113
+ def unpatchify(self, x):
114
+ B, N, _ = x.shape
115
+ p = self.patch
116
+ g = self.grid
117
+ C = self.latent_ch
118
+ x = x.reshape(B, g, g, C, p, p).permute(0, 3, 1, 4, 2, 5)
119
+ return x.reshape(B, C, g * p, g * p)
120
+
121
+ def forward(self, x, t, text_seq, text_pool):
122
+ x = self.x_embed(self.patchify(x)) + self.pos
123
+ c = self.t_mlp(timestep_embedding(t, self.dim)) + self.text_pool(text_pool)
124
+ text = self.text_proj(text_seq)
125
+ for blk in self.blocks:
126
+ x = blk(x, c, text)
127
+ shift, scale = self.ada_out(c).chunk(2, dim=1)
128
+ x = modulate(self.norm_out(x), shift, scale)
129
+ x = self.head(x)
130
+ return self.unpatchify(x)
131
+
132
+ def num_params(self):
133
+ return sum(p.numel() for p in self.parameters())
requirements.txt CHANGED
@@ -1,11 +1,13 @@
1
- gradio
2
- torch
3
- diffusers==0.31.0
4
- transformers==4.49.0
5
- safetensors
6
- numpy
7
- Pillow
8
- huggingface_hub
9
- trimesh
10
- scipy
11
- audioop-lts
 
 
 
1
+ gradio
2
+ torch
3
+ diffusers==0.31.0
4
+ transformers==4.49.0
5
+ safetensors
6
+ numpy
7
+ Pillow
8
+ huggingface_hub
9
+ trimesh
10
+ scipy
11
+ audioop-lts
12
+ sentencepiece
13
+ accelerate
voxel_dit.py CHANGED
@@ -1,134 +1,134 @@
1
- from __future__ import annotations
2
-
3
- import math
4
- import numpy as np
5
- import torch
6
- import torch.nn as nn
7
- import torch.nn.functional as F
8
-
9
- def modulate(x, shift, scale):
10
- return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
11
-
12
- def timestep_embedding(t, dim, max_period=10000):
13
- half = dim // 2
14
- freqs = torch.exp(-math.log(max_period) * torch.arange(half, device=t.device) / half)
15
- args = t[:, None].float() * freqs[None]
16
- emb = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
17
- if dim % 2:
18
- emb = torch.cat([emb, torch.zeros_like(emb[:, :1])], dim=-1)
19
- return emb
20
-
21
- def sincos_3d(dim, grid_size):
22
- assert dim % 6 == 0
23
- g = np.arange(grid_size, dtype=np.float32)
24
- gz, gy, gx = np.meshgrid(g, g, g, indexing="ij")
25
- d6 = dim // 6
26
- omega = 1.0 / (10000 ** (np.arange(d6, dtype=np.float32) / d6))
27
- def emb1(p):
28
- out = p.reshape(-1)[:, None] * omega[None]
29
- return np.concatenate([np.sin(out), np.cos(out)], axis=1)
30
- pe = np.concatenate([emb1(gz), emb1(gy), emb1(gx)], axis=1)
31
- return torch.from_numpy(pe).float()
32
-
33
- class Attention(nn.Module):
34
- def __init__(self, dim, heads):
35
- super().__init__()
36
- self.heads = heads
37
- self.q = nn.Linear(dim, dim)
38
- self.kv = nn.Linear(dim, dim * 2)
39
- self.proj = nn.Linear(dim, dim)
40
-
41
- def forward(self, x, ctx=None):
42
- ctx = x if ctx is None else ctx
43
- B, N, C = x.shape
44
- M = ctx.shape[1]
45
- h = self.heads
46
- q = self.q(x).reshape(B, N, h, C // h).transpose(1, 2)
47
- kv = self.kv(ctx).reshape(B, M, 2, h, C // h).permute(2, 0, 3, 1, 4)
48
- k, v = kv[0], kv[1]
49
- o = F.scaled_dot_product_attention(q, k, v)
50
- o = o.transpose(1, 2).reshape(B, N, C)
51
- return self.proj(o)
52
-
53
- class Block(nn.Module):
54
- def __init__(self, dim, heads, mlp_ratio=4.0):
55
- super().__init__()
56
- self.norm1 = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
57
- self.attn = Attention(dim, heads)
58
- self.norm_ca = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
59
- self.cross = Attention(dim, heads)
60
- self.norm2 = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
61
- hidden = int(dim * mlp_ratio)
62
- self.mlp = nn.Sequential(nn.Linear(dim, hidden), nn.GELU(approximate="tanh"),
63
- nn.Linear(hidden, dim))
64
- self.ada = nn.Sequential(nn.SiLU(), nn.Linear(dim, 6 * dim))
65
- self.cross_gate = nn.Parameter(torch.zeros(1))
66
-
67
- def forward(self, x, c, text):
68
- shift1, scale1, gate1, shift2, scale2, gate2 = self.ada(c).chunk(6, dim=1)
69
- x = x + gate1.unsqueeze(1) * self.attn(modulate(self.norm1(x), shift1, scale1))
70
- x = x + self.cross_gate * self.cross(self.norm_ca(x), text)
71
- x = x + gate2.unsqueeze(1) * self.mlp(modulate(self.norm2(x), shift2, scale2))
72
- return x
73
-
74
- class VoxelDiT(nn.Module):
75
- def __init__(self, vox_ch=1, vox_size=32, patch=4, dim=384, depth=12,
76
- heads=6, text_dim=512, mlp_ratio=4.0):
77
- super().__init__()
78
- self.vox_ch = vox_ch
79
- self.vox_size = vox_size
80
- self.patch = patch
81
- self.grid = vox_size // patch
82
- self.patch_dim = vox_ch * patch * patch * patch
83
- self.x_embed = nn.Linear(self.patch_dim, dim)
84
- self.register_buffer("pos", sincos_3d(dim, self.grid).unsqueeze(0))
85
- self.t_mlp = nn.Sequential(nn.Linear(dim, dim), nn.SiLU(), nn.Linear(dim, dim))
86
- self.text_proj = nn.Linear(text_dim, dim)
87
- self.text_pool = nn.Linear(text_dim, dim)
88
- self.blocks = nn.ModuleList([Block(dim, heads, mlp_ratio) for _ in range(depth)])
89
- self.norm_out = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
90
- self.ada_out = nn.Sequential(nn.SiLU(), nn.Linear(dim, 2 * dim))
91
- self.head = nn.Linear(dim, self.patch_dim)
92
- self.dim = dim
93
- self._init()
94
-
95
- def _init(self):
96
- for m in self.modules():
97
- if isinstance(m, nn.Linear):
98
- nn.init.xavier_uniform_(m.weight)
99
- if m.bias is not None:
100
- nn.init.zeros_(m.bias)
101
- for b in self.blocks:
102
- nn.init.zeros_(b.ada[-1].weight); nn.init.zeros_(b.ada[-1].bias)
103
- nn.init.zeros_(self.ada_out[-1].weight); nn.init.zeros_(self.ada_out[-1].bias)
104
- nn.init.zeros_(self.head.weight); nn.init.zeros_(self.head.bias)
105
-
106
- def patchify(self, x):
107
- B, C, D, H, W = x.shape
108
- p = self.patch
109
- x = x.reshape(B, C, D // p, p, H // p, p, W // p, p)
110
- x = x.permute(0, 2, 4, 6, 1, 3, 5, 7)
111
- return x.reshape(B, (D // p) * (H // p) * (W // p), C * p * p * p)
112
-
113
- def unpatchify(self, x):
114
- B, N, _ = x.shape
115
- p = self.patch
116
- g = self.grid
117
- C = self.vox_ch
118
- x = x.reshape(B, g, g, g, C, p, p, p)
119
- x = x.permute(0, 4, 1, 5, 2, 6, 3, 7)
120
- return x.reshape(B, C, g * p, g * p, g * p)
121
-
122
- def forward(self, x, t, text_seq, text_pool):
123
- x = self.x_embed(self.patchify(x)) + self.pos
124
- c = self.t_mlp(timestep_embedding(t, self.dim)) + self.text_pool(text_pool)
125
- text = self.text_proj(text_seq)
126
- for blk in self.blocks:
127
- x = blk(x, c, text)
128
- shift, scale = self.ada_out(c).chunk(2, dim=1)
129
- x = modulate(self.norm_out(x), shift, scale)
130
- x = self.head(x)
131
- return self.unpatchify(x)
132
-
133
- def num_params(self):
134
- return sum(p.numel() for p in self.parameters())
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import numpy as np
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+
9
+ def modulate(x, shift, scale):
10
+ return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
11
+
12
+ def timestep_embedding(t, dim, max_period=10000):
13
+ half = dim // 2
14
+ freqs = torch.exp(-math.log(max_period) * torch.arange(half, device=t.device) / half)
15
+ args = t[:, None].float() * freqs[None]
16
+ emb = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
17
+ if dim % 2:
18
+ emb = torch.cat([emb, torch.zeros_like(emb[:, :1])], dim=-1)
19
+ return emb
20
+
21
+ def sincos_3d(dim, grid_size):
22
+ assert dim % 6 == 0
23
+ g = np.arange(grid_size, dtype=np.float32)
24
+ gz, gy, gx = np.meshgrid(g, g, g, indexing="ij")
25
+ d6 = dim // 6
26
+ omega = 1.0 / (10000 ** (np.arange(d6, dtype=np.float32) / d6))
27
+ def emb1(p):
28
+ out = p.reshape(-1)[:, None] * omega[None]
29
+ return np.concatenate([np.sin(out), np.cos(out)], axis=1)
30
+ pe = np.concatenate([emb1(gz), emb1(gy), emb1(gx)], axis=1)
31
+ return torch.from_numpy(pe).float()
32
+
33
+ class Attention(nn.Module):
34
+ def __init__(self, dim, heads):
35
+ super().__init__()
36
+ self.heads = heads
37
+ self.q = nn.Linear(dim, dim)
38
+ self.kv = nn.Linear(dim, dim * 2)
39
+ self.proj = nn.Linear(dim, dim)
40
+
41
+ def forward(self, x, ctx=None):
42
+ ctx = x if ctx is None else ctx
43
+ B, N, C = x.shape
44
+ M = ctx.shape[1]
45
+ h = self.heads
46
+ q = self.q(x).reshape(B, N, h, C // h).transpose(1, 2)
47
+ kv = self.kv(ctx).reshape(B, M, 2, h, C // h).permute(2, 0, 3, 1, 4)
48
+ k, v = kv[0], kv[1]
49
+ o = F.scaled_dot_product_attention(q, k, v)
50
+ o = o.transpose(1, 2).reshape(B, N, C)
51
+ return self.proj(o)
52
+
53
+ class Block(nn.Module):
54
+ def __init__(self, dim, heads, mlp_ratio=4.0):
55
+ super().__init__()
56
+ self.norm1 = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
57
+ self.attn = Attention(dim, heads)
58
+ self.norm_ca = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
59
+ self.cross = Attention(dim, heads)
60
+ self.norm2 = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
61
+ hidden = int(dim * mlp_ratio)
62
+ self.mlp = nn.Sequential(nn.Linear(dim, hidden), nn.GELU(approximate="tanh"),
63
+ nn.Linear(hidden, dim))
64
+ self.ada = nn.Sequential(nn.SiLU(), nn.Linear(dim, 6 * dim))
65
+ self.cross_gate = nn.Parameter(torch.zeros(1))
66
+
67
+ def forward(self, x, c, text):
68
+ shift1, scale1, gate1, shift2, scale2, gate2 = self.ada(c).chunk(6, dim=1)
69
+ x = x + gate1.unsqueeze(1) * self.attn(modulate(self.norm1(x), shift1, scale1))
70
+ x = x + self.cross_gate * self.cross(self.norm_ca(x), text)
71
+ x = x + gate2.unsqueeze(1) * self.mlp(modulate(self.norm2(x), shift2, scale2))
72
+ return x
73
+
74
+ class VoxelDiT(nn.Module):
75
+ def __init__(self, vox_ch=1, vox_size=32, patch=4, dim=384, depth=12,
76
+ heads=6, text_dim=512, mlp_ratio=4.0):
77
+ super().__init__()
78
+ self.vox_ch = vox_ch
79
+ self.vox_size = vox_size
80
+ self.patch = patch
81
+ self.grid = vox_size // patch
82
+ self.patch_dim = vox_ch * patch * patch * patch
83
+ self.x_embed = nn.Linear(self.patch_dim, dim)
84
+ self.register_buffer("pos", sincos_3d(dim, self.grid).unsqueeze(0))
85
+ self.t_mlp = nn.Sequential(nn.Linear(dim, dim), nn.SiLU(), nn.Linear(dim, dim))
86
+ self.text_proj = nn.Linear(text_dim, dim)
87
+ self.text_pool = nn.Linear(text_dim, dim)
88
+ self.blocks = nn.ModuleList([Block(dim, heads, mlp_ratio) for _ in range(depth)])
89
+ self.norm_out = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
90
+ self.ada_out = nn.Sequential(nn.SiLU(), nn.Linear(dim, 2 * dim))
91
+ self.head = nn.Linear(dim, self.patch_dim)
92
+ self.dim = dim
93
+ self._init()
94
+
95
+ def _init(self):
96
+ for m in self.modules():
97
+ if isinstance(m, nn.Linear):
98
+ nn.init.xavier_uniform_(m.weight)
99
+ if m.bias is not None:
100
+ nn.init.zeros_(m.bias)
101
+ for b in self.blocks:
102
+ nn.init.zeros_(b.ada[-1].weight); nn.init.zeros_(b.ada[-1].bias)
103
+ nn.init.zeros_(self.ada_out[-1].weight); nn.init.zeros_(self.ada_out[-1].bias)
104
+ nn.init.zeros_(self.head.weight); nn.init.zeros_(self.head.bias)
105
+
106
+ def patchify(self, x):
107
+ B, C, D, H, W = x.shape
108
+ p = self.patch
109
+ x = x.reshape(B, C, D // p, p, H // p, p, W // p, p)
110
+ x = x.permute(0, 2, 4, 6, 1, 3, 5, 7)
111
+ return x.reshape(B, (D // p) * (H // p) * (W // p), C * p * p * p)
112
+
113
+ def unpatchify(self, x):
114
+ B, N, _ = x.shape
115
+ p = self.patch
116
+ g = self.grid
117
+ C = self.vox_ch
118
+ x = x.reshape(B, g, g, g, C, p, p, p)
119
+ x = x.permute(0, 4, 1, 5, 2, 6, 3, 7)
120
+ return x.reshape(B, C, g * p, g * p, g * p)
121
+
122
+ def forward(self, x, t, text_seq, text_pool):
123
+ x = self.x_embed(self.patchify(x)) + self.pos
124
+ c = self.t_mlp(timestep_embedding(t, self.dim)) + self.text_pool(text_pool)
125
+ text = self.text_proj(text_seq)
126
+ for blk in self.blocks:
127
+ x = blk(x, c, text)
128
+ shift, scale = self.ada_out(c).chunk(2, dim=1)
129
+ x = modulate(self.norm_out(x), shift, scale)
130
+ x = self.head(x)
131
+ return self.unpatchify(x)
132
+
133
+ def num_params(self):
134
+ return sum(p.numel() for p in self.parameters())