cbensimon HF Staff commited on
Commit
b156879
·
1 Parent(s): 06f5eae

Almost the right structure

Browse files
Files changed (1) hide show
  1. job.py +75 -51
job.py CHANGED
@@ -9,13 +9,19 @@
9
  # "setuptools",
10
  # ]
11
  # ///
 
12
 
 
13
  import spaces
14
  import torch
15
  from diffusers.pipelines.flux2.pipeline_flux2_klein import Flux2KleinPipeline
16
- from PIL import Image
17
- from spaces.zero.torch.aoti import LazyAOTIModel
18
- from torch.utils._pytree import tree_map
 
 
 
 
19
 
20
 
21
  TRANSFORMER_IMAGE_DIM = torch.export.Dim('image_seq_length', min=4096, max=16384) # min: 0 images, max: 3 (1024x1024) images
@@ -51,64 +57,82 @@ INDUCTOR_CONFIGS = {
51
  }
52
 
53
 
54
- pipeline = Flux2KleinPipeline.from_pretrained(
55
- 'black-forest-labs/FLUX.2-klein-4B',
56
- torch_dtype=torch.bfloat16
57
- ).to('cuda')
58
 
 
 
 
 
59
 
60
- def generate_sample(filename: str):
61
- pipeline(
62
- prompt="Remove the sunglasses",
63
- image=[Image.open('cat-sunglasses.jpg')],
64
- guidance_scale=2.5,
65
- generator=torch.Generator(device='cuda').manual_seed(42),
66
- ).images[0].save(filename) # pyright: ignore[reportAttributeAccessIssue]
67
-
68
-
69
- generate_sample('before.png')
70
-
71
-
72
- blocks = {
73
- 'double': pipeline.transformer.transformer_blocks,
74
- 'single': pipeline.transformer.single_transformer_blocks,
75
- }
76
 
77
- def compile_block(blocks_kind: str):
78
- block = blocks[blocks_kind][0]
79
- with spaces.aoti_capture(block) as call:
80
- pipeline(
81
- prompt="prompt",
82
- image=[Image.new("RGB", (1024, 1024))],
83
- )
84
 
85
- dynamic_shapes = tree_map(lambda t: None, call.kwargs)
86
- dynamic_shapes |= TRANSFORMER_DYNAMIC_SHAPES[blocks_kind]
 
 
 
 
 
87
 
88
- with torch.no_grad():
89
- exported = torch.export.export(
90
- mod=block,
91
- args=call.args,
92
- kwargs=call.kwargs,
93
- dynamic_shapes=dynamic_shapes,
94
- )
95
 
96
- return spaces.aoti_compile(exported, INDUCTOR_CONFIGS).archive_file
 
 
 
97
 
98
- for blocks_kind in ('double', 'single'):
99
- archive_file = compile_block(blocks_kind)
100
- with open(f'{blocks_kind}.pt2', 'wb') as f:
101
- f.write(archive_file.getbuffer()) # pyright: ignore[reportAttributeAccessIssue]
102
 
 
 
 
 
 
 
 
103
 
104
- # TODO: Do it with some spaces.aoti_ helper (lower-level aoti_blocks_load)
105
- for blocks_kind in ('double', 'single'):
106
- archive_file_path = f'{blocks_kind}.pt2'
107
- for block in blocks[blocks_kind]:
108
- block.forward = LazyAOTIModel(archive_file_path).with_weights(block.state_dict())
109
 
110
-
111
- generate_sample('after.png')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
  # Push structure to hub
114
  # Push script to hub
 
9
  # "setuptools",
10
  # ]
11
  # ///
12
+ # fmt: off
13
 
14
+ #region how-to
15
  import spaces
16
  import torch
17
  from diffusers.pipelines.flux2.pipeline_flux2_klein import Flux2KleinPipeline
18
+ from huggingface_hub import hf_hub_download
19
+
20
+ pipeline = Flux2KleinPipeline.from_pretrained(
21
+ 'black-forest-labs/FLUX.2-klein-4B',
22
+ torch_dtype=torch.bfloat16
23
+ ).to('cuda')
24
+ #endregion
25
 
26
 
27
  TRANSFORMER_IMAGE_DIM = torch.export.Dim('image_seq_length', min=4096, max=16384) # min: 0 images, max: 3 (1024x1024) images
 
57
  }
58
 
59
 
60
+ def compile_module(module: torch.nn.Module, output_dir: str):
61
+ from PIL import Image
62
+ from torch.utils._pytree import tree_map
 
63
 
64
+ blocks = {
65
+ 'double': module.transformer_blocks,
66
+ 'single': module.single_transformer_blocks,
67
+ }
68
 
69
+ def compile_block(blocks_kind: str):
70
+ block = blocks[blocks_kind][0]
71
+ with spaces.aoti_capture(block) as call:
72
+ pipeline(
73
+ prompt="prompt",
74
+ image=[Image.new("RGB", (1024, 1024))],
75
+ )
 
 
 
 
 
 
 
 
 
76
 
77
+ dynamic_shapes = tree_map(lambda t: None, call.kwargs)
78
+ dynamic_shapes |= TRANSFORMER_DYNAMIC_SHAPES[blocks_kind]
 
 
 
 
 
79
 
80
+ with torch.no_grad():
81
+ exported = torch.export.export(
82
+ mod=block,
83
+ args=call.args,
84
+ kwargs=call.kwargs,
85
+ dynamic_shapes=dynamic_shapes,
86
+ )
87
 
88
+ return spaces.aoti_compile(exported, INDUCTOR_CONFIGS).archive_file
 
 
 
 
 
 
89
 
90
+ for blocks_kind in ('double', 'single'):
91
+ with open(f'{output_dir}/{blocks_kind}.pt2', 'wb') as f:
92
+ archive = compile_block(blocks_kind)
93
+ f.write(archive.getbuffer())
94
 
 
 
 
 
95
 
96
+ def load_compiled(module: torch.nn.Module, repo_id: str, revision: str | None = None):
97
+ single = hf_hub_download(repo_id, 'single.pt2', revision=revision)
98
+ double = hf_hub_download(repo_id, 'double.pt2', revision=revision)
99
+ for block in module.single_transformer_blocks:
100
+ spaces.aoti_apply_graph(single, block)
101
+ for block in module.transformer_blocks:
102
+ spaces.aoti_apply_graph(double, block)
103
 
 
 
 
 
 
104
 
105
+ def generate_samples(output_dir: str):
106
+ output = pipeline(
107
+ prompt="Remove the sunglasses",
108
+ image=[Image.open('cat-sunglasses.jpg')],
109
+ guidance_scale=2.5,
110
+ generator=torch.Generator(device='cuda').manual_seed(42),
111
+ )
112
+ output.images[0].save(f'{output_dir}/edited.png') # pyright: ignore[reportAttributeAccessIssue]
113
+
114
+
115
+ aot_init(
116
+ module=pipeline.transformer,
117
+ compile_module=compile_module,
118
+ load_compiled=load_compiled, # Optional (uses spaces.aoti_load as default)
119
+ generate_samples=generate_samples,
120
+ readme_template="""
121
+ ## How to use
122
+ ``` python
123
+ {HOW_TO}
124
+ {LOAD_COMPILED}
125
+ ```
126
+
127
+ # How to customize
128
+ ``` bash
129
+ ``` bash
130
+ pip install huggingface_hub
131
+ hf download {REPO_ID} job.py
132
+ hf jobs uv run --hardware h200 job.py
133
+ ```
134
+ """
135
+ )
136
 
137
  # Push structure to hub
138
  # Push script to hub