Gorluxor commited on
Commit
16eb15e
·
1 Parent(s): 97187f3

initial demo

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* 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
 
 
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
+ *.jpg filter=lfs diff=lfs merge=lfs -text
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Gorluxor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -4,11 +4,33 @@ emoji: 🌖
4
  colorFrom: yellow
5
  colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 5.44.1
 
 
8
  app_file: app.py
9
- pinned: false
10
  license: mit
11
  short_description: Fine-Grained Image Editing using Pre-Trained Diffusion Model
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
4
  colorFrom: yellow
5
  colorTo: indigo
6
  sdk: gradio
7
+ sdk_version: 4.44.1 # newest at the time 5.44.1
8
+ suggested_hardware: "a10g-large"
9
+ python_version: 3.10
10
  app_file: app.py
11
+ pinned: true
12
  license: mit
13
  short_description: Fine-Grained Image Editing using Pre-Trained Diffusion Model
14
+ tags:
15
+ - text-to-image
16
+ - part-editing
17
+ - stable-diffusion
18
+ - diffusion-models
19
+ - transformers
20
+ - pytorch
21
+ - computer-vision
22
+ - generative-ai
23
+ - image-generation
24
+ - image-editing
25
+ - gradio
26
+ - machine-learning
27
+ - deep-learning
28
+ - ai
29
+ - artificial-intelligence
30
+ - demo
31
+ - research
32
+ preload_from_hub:
33
+ - stabilityai/stable-diffusion-xl-base-1.0
34
  ---
35
 
36
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py CHANGED
@@ -1,7 +1,291 @@
 
 
 
 
 
 
 
 
1
  import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
1
+ #!/usr/bin/env python
2
+
3
+ import os
4
+ import random
5
+ from typing import Optional, Tuple, Union, List
6
+
7
+ import numpy as np
8
+ import PIL.Image
9
  import gradio as gr
10
+ import torch
11
+ import spaces # 👈 ZeroGPU support
12
+
13
+ from model import PartEditSDXLModel, PART_TOKENS
14
+ from datasets import load_dataset
15
+
16
+ import base64
17
+ from io import BytesIO
18
+ import tempfile
19
+ import uuid
20
+
21
+ MAX_SEED = np.iinfo(np.int32).max
22
+ CACHE_EXAMPLES = os.environ.get("CACHE_EXAMPLES") == "1"
23
+ AVAILABLE_TOKENS = list(PART_TOKENS.keys())
24
+
25
+ # Download examples directly from the huggingface PartEdit-Bench
26
+ # Login using e.g. `huggingface-cli login` or `hf login` if needed.
27
+ bench = load_dataset("Aleksandar/PartEdit-Bench", revision="v1.1", split="synth")
28
+
29
+ use_examples = None # all with None
30
+ logo = "assets/partedit.png"
31
+ loaded_logo = PIL.Image.open(logo).convert("RGB")
32
+ # base encoded logo
33
+
34
+ logo_encoded = None
35
+ with open(logo, "rb") as f:
36
+ logo_encoded = base64.b64encode(f.read()).decode()
37
+
38
+
39
+ def _save_image_for_download(edited: Union[PIL.Image.Image, np.ndarray, str, List]) -> str:
40
+ """Save the first edited image to a temp file and return its filepath."""
41
+ # clone to be sure we don't modify the input
42
+ edited = edited.copy()
43
+ img = edited[0] if isinstance(edited, list) else edited
44
+ if isinstance(img, str):
45
+ # path on disk already
46
+ return img
47
+ if isinstance(img, np.ndarray):
48
+ img = PIL.Image.fromarray(img)
49
+ assert isinstance(img, PIL.Image.Image), "Edited output must be PIL, ndarray, str path, or list of these."
50
+ out_path = os.path.join(tempfile.gettempdir(), f"partedit_{uuid.uuid4().hex}.png")
51
+ img.save(out_path)
52
+ return out_path
53
+
54
+
55
+
56
+ def get_example(idx, bench):
57
+ # [prompt_original, subject, token_cls, edit, "", 50, 7.5, seed, 50]
58
+ example = bench[idx]
59
+ return [
60
+ example["prompt_original"],
61
+ example["subject"],
62
+ example["token_cls"],
63
+ example["edit"],
64
+ "",
65
+ 50,
66
+ 7.5,
67
+ example["seed"],
68
+ 50,
69
+ ]
70
+
71
+ examples = [get_example(idx, bench) for idx in (use_examples if use_examples is not None else range(len(bench)))]
72
+ first_ex = examples[0] if len(examples) else ["", "", AVAILABLE_TOKENS[0], "", "", 50, 7.5, 0, 50]
73
+
74
+ title = f"""
75
+ <div style="display: flex; align-items: center;">
76
+ <img src="data:image/png;base64,{logo_encoded}" alt="PartEdit Logo">
77
+ <div style="margin-left: 10px;">
78
+ <h1 style="margin: 0;">PartEdit with SDXL</h1>
79
+ <p style="margin: 2px 0 0 0;">Official demo for the PartEdit paper.</p>
80
+ <h2 style="margin: 6px 0 0 0;">PartEdit: Fine-Grained Image Editing using Pre-Trained Diffusion Models</h2>
81
+ <p style="margin: 6px 0 0 0; font-size: 14px;">
82
+ It <b>simultaneously predicts the part-localization mask and edits the original trajectory</b>.
83
+ Supports <b>Hugging Face ZeroGPU</b> and one-click <b>Duplicate</b> for private use.
84
+ </p>
85
+ </div>
86
+ </div>
87
+ """
88
+
89
+
90
+ def _as_gallery(edited: Union[PIL.Image.Image, np.ndarray, str, List]) -> List:
91
+ """Ensure the output fits a Gallery component."""
92
+ if isinstance(edited, list):
93
+ return edited
94
+ return [edited]
95
+
96
+
97
+ def edit_demo(model: PartEditSDXLModel) -> gr.Blocks:
98
+ @spaces.GPU(duration=120) # 👈 request a ZeroGPU allocation during this call
99
+ def run(
100
+ prompt: str,
101
+ subject: str,
102
+ part: str,
103
+ edit: str,
104
+ negative_prompt: str,
105
+ num_inference_steps: int = 50,
106
+ guidance_scale: float = 7.5,
107
+ seed: int = 0,
108
+ t_e: int = 50,
109
+ progress=gr.Progress(track_tqdm=True),
110
+ ) -> Tuple[List, Optional[PIL.Image.Image]]:
111
+ if seed == -1:
112
+ seed = random.randint(0, MAX_SEED)
113
+
114
+ out = model.edit(
115
+ prompt=prompt,
116
+ subject=subject,
117
+ part=part,
118
+ edit=edit,
119
+ negative_prompt=negative_prompt,
120
+ num_inference_steps=num_inference_steps,
121
+ guidance_scale=guidance_scale,
122
+ seed=seed,
123
+ t_e=t_e,
124
+ )
125
+
126
+ # Accept either (image, mask) or just image from model.edit
127
+ if isinstance(out, tuple) and len(out) == 2:
128
+ edited, mask_img = out
129
+ else:
130
+ edited, mask_img = out, None
131
+
132
+ download_path = _save_image_for_download(edited)
133
+ return _as_gallery(edited), mask_img, gr.update(value=download_path, visible=True)
134
+
135
+
136
+
137
+ with gr.Blocks() as demo:
138
+ with gr.Row():
139
+ with gr.Column(scale=2):
140
+ with gr.Group():
141
+ prompt = gr.Textbox(
142
+ first_ex[0], # <- was "a closeup of a man full-body"
143
+ placeholder="Prompt",
144
+ label="Original Prompt",
145
+ show_label=True,
146
+ max_lines=1,
147
+ )
148
+ with gr.Row():
149
+ subject = gr.Textbox(value=first_ex[1], label="Subject", show_label=True, max_lines=1)
150
+ edit = gr.Textbox(value=first_ex[3], label="Edit", show_label=True, max_lines=1)
151
+ part = gr.Dropdown(label="Part Name", choices=AVAILABLE_TOKENS, value=first_ex[2])
152
+
153
+ seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=int(first_ex[7]))
154
+ run_button = gr.Button("Apply Edit")
155
+
156
+ with gr.Accordion("Advanced options", open=False):
157
+ negative_prompt = gr.Textbox(label="Negative prompt", value=first_ex[4])
158
+ num_inference_steps = gr.Slider(
159
+ label="Number of steps",
160
+ minimum=1,
161
+ maximum=PartEditSDXLModel.MAX_NUM_INFERENCE_STEPS,
162
+ step=1,
163
+ value=int(first_ex[5]),
164
+ )
165
+ guidance_scale = gr.Slider(
166
+ label="Guidance scale",
167
+ minimum=0.1,
168
+ maximum=30.0,
169
+ step=0.1,
170
+ value=float(first_ex[6]),
171
+ )
172
+ t_e = gr.Slider(
173
+ label="Editing steps",
174
+ minimum=1,
175
+ maximum=PartEditSDXLModel.MAX_NUM_INFERENCE_STEPS,
176
+ step=1,
177
+ value=int(first_ex[8]),
178
+ )
179
+ with gr.Accordion('Citation', open=True):
180
+ gr.Markdown(citation)
181
+
182
+
183
+ with gr.Column(scale=3):
184
+ with gr.Row(equal_height=False):
185
+ with gr.Column(scale=1, min_width=120):
186
+ mask = gr.Image(label="Editing Mask", width=100, height=100, show_label=True)
187
+ with gr.Column(scale=7):
188
+ result = gr.Gallery(
189
+ label="Edited Image",
190
+ height=700,
191
+ object_fit="fill",
192
+ preview=True,
193
+ selected_index=0,
194
+ show_label=True,
195
+ )
196
+ download_btn = gr.File(
197
+ label="Download full-resolution",
198
+ type="filepath",
199
+ file_count="single", # <-- keeps it to one file
200
+ interactive=False,
201
+ height=48, # <-- compact
202
+ visible=False # <-- hide until we have a file
203
+ )
204
+
205
+ inputs = [prompt, subject, part, edit, negative_prompt, num_inference_steps, guidance_scale, seed, t_e]
206
+
207
+ gr.Examples(
208
+ examples=examples,
209
+ inputs=inputs,
210
+ outputs=[result, mask, download_btn],
211
+ fn=run,
212
+ cache_examples=CACHE_EXAMPLES,
213
+ )
214
+
215
+ run_button.click(fn=run, inputs=inputs, outputs=[result, mask, download_btn], api_name="run")
216
+
217
+ return demo
218
+
219
+
220
+ badges_text = r"""
221
+ <div style="text-align: center; display: flex; justify-content: center; gap: 5px; flex-wrap: wrap;">
222
+ <a href="https://gorluxor.github.io/part-edit/">
223
+ <img alt="Project Page" src="https://img.shields.io/badge/%F0%9F%8C%90%20Project%20Page-PartEdit-blue">
224
+ </a>
225
+ <a href="https://arxiv.org/abs/2502.04050">
226
+ <img alt="arXiv" src="https://img.shields.io/badge/arXiv-2502.04050-b31b1b.svg">
227
+ </a>
228
+ <a href="https://huggingface.co/datasets/Aleksandar/PartEdit-Bench">
229
+ <img alt="HF Dataset: PartEdit-Bench" src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-PartEdit--Bench-blue">
230
+ </a>
231
+ <a href="https://huggingface.co/datasets/Aleksandar/PartEdit-extra">
232
+ <img alt="HF Dataset: PartEdit-extra" src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-PartEdit--extra-blue">
233
+ </a>
234
+ <a href="https://s2025.siggraph.org/">
235
+ <img alt="SIGGRAPH 2025" src="https://img.shields.io/badge/%F0%9F%8E%A8%20Accepted-SIGGRAPH%202025-blueviolet">
236
+ </a>
237
+ <a href="https://github.com/Gorluxor/partedit/blob/main/LICENSE">
238
+ <img alt="Code License" src="https://img.shields.io/badge/license-MIT-blue.svg">
239
+ </a>
240
+ </div>
241
+ """.strip()
242
+
243
+ citation = r"""
244
+ If you use this demo, please cite the following paper:
245
+ ```
246
+ @inproceedings{cvejic2025partedit,
247
+ title={PartEdit: Fine-Grained Image Editing using Pre-Trained Diffusion Models},
248
+ author={Cvejic, Aleksandar and Eldesokey, Abdelrahman and Wonka, Peter},
249
+ booktitle={Proceedings of the Special Interest Group on Computer Graphics and Interactive Techniques Conference Conference Papers},
250
+ pages={1--11},
251
+ year={2025}
252
+ }
253
+ ```
254
+ """
255
+
256
+ DESCRIPTION = title + badges_text
257
+
258
+ if not torch.cuda.is_available():
259
+ DESCRIPTION += "\n<p>Running on CPU 🥶 This demo does not work on CPU. On ZeroGPU Spaces, a GPU will be requested when you click <b>Apply Edit</b>.</p>"
260
+
261
+ def running_in_hf_space() -> bool:
262
+ # Common env vars present on Hugging Face Spaces
263
+ return (
264
+ os.getenv("SYSTEM") == "spaces" or
265
+ any(os.getenv(k) for k in (
266
+ "SPACE_ID", "HF_SPACE_ID", "SPACE_REPO_ID",
267
+ "SPACE_REPO_NAME", "SPACE_AUTHOR_NAME", "SPACE_TITLE"
268
+ ))
269
+ )
270
+
271
+ if __name__ == "__main__":
272
+ model = PartEditSDXLModel()
273
+
274
+ with gr.Blocks(css="style.css") as demo:
275
+ gr.Markdown(DESCRIPTION)
276
+
277
+ # Always show Duplicate button on Spaces
278
+ gr.DuplicateButton(
279
+ value="Duplicate Space for private use",
280
+ elem_id="duplicate-button",
281
+ variant="huggingface",
282
+ size="lg",
283
+ visible=running_in_hf_space(),
284
+ )
285
 
286
+ # Single tab: PartEdit only
287
+ with gr.Tabs():
288
+ with gr.Tab(label="PartEdit", id="edit"):
289
+ edit_demo(model)
290
 
291
+ demo.queue(max_size=20).launch()
 
assets/partedit.png ADDED
assets/teaser.jpg ADDED

Git LFS Details

  • SHA256: 9c58f10d278f9a849d91bd9cfa45eacfae99d036d5fd83fcdbc68ce6c05eacf7
  • Pointer size: 132 Bytes
  • Size of remote file: 1.01 MB
model.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gc
2
+
3
+ import PIL.Image
4
+ import torch
5
+
6
+ from stable_diffusion_xl_partedit import PartEditPipeline, DotDictExtra, Binarization, PaddingStrategy, EmptyControl
7
+ from diffusers import AutoencoderKL
8
+ from diffusers.pipelines.stable_diffusion.safety_checker import StableDiffusionSafetyChecker
9
+ from transformers import CLIPImageProcessor
10
+
11
+ from huggingface_hub import hf_hub_download
12
+
13
+ available_pts = [
14
+ "pt/torso_custom.pt", # this is human torso only
15
+ "pt/chair_custom.pt", # this is seat of the chair only
16
+ "pt/carhood_custom.pt",
17
+ "pt/partimage_biped_head.pt", # this is essentially monkeys
18
+ "pt/partimage_carbody.pt", # this is everything except the wheels
19
+ "pt/partimage_human_hair.pt",
20
+ "pt/partimage_human_head.pt", # this is essentially faces
21
+ "pt/partimage_human_torso.pt", # use custom on in favour of this one
22
+ "pt/partimage_quadruped_head.pt", # this is essentially animals on 4 legs
23
+ ]
24
+
25
+ def download_part(index):
26
+ return hf_hub_download(
27
+ repo_id="Aleksandar/PartEdit-extra",
28
+ repo_type="dataset",
29
+ filename=available_pts[index]
30
+ )
31
+
32
+ PART_TOKENS = {
33
+ "human_head": download_part(6),
34
+ "human_hair": download_part(5),
35
+ "human_torso_custom": download_part(0), # custom one
36
+ "chair_custom": download_part(1),
37
+ "carhood_custom": download_part(2),
38
+ "carbody": download_part(4),
39
+ "biped_head": download_part(8),
40
+ "quadruped_head": download_part(3),
41
+ "human_torso": download_part(7), # based on partimage
42
+ }
43
+
44
+
45
+ class PartEditSDXLModel:
46
+ MAX_NUM_INFERENCE_STEPS = 50
47
+
48
+ def __init__(self):
49
+ if torch.cuda.is_available():
50
+ self.device = torch.device(f"cuda:{torch.cuda.current_device()}" if torch.cuda.is_available() else "cpu")
51
+ self.sd_pipe, self.partedit_pipe = PartEditPipeline.default_pipeline(self.device)
52
+ else:
53
+ self.pipe = None
54
+
55
+ def generate(
56
+ self,
57
+ prompt: str,
58
+ negative_prompt: str = "",
59
+ num_inference_steps: int = 50,
60
+ guidance_scale: float = 7.5,
61
+ seed: int = 0,
62
+ eta: float = 0,
63
+ ) -> PIL.Image.Image:
64
+
65
+ if not torch.cuda.is_available():
66
+ raise RuntimeError("This demo does not work on CPU!")
67
+
68
+ out = self.sd_pipe(
69
+ prompt=prompt,
70
+ # negative_prompt=negative_prompt,
71
+ num_inference_steps=num_inference_steps,
72
+ guidance_scale=guidance_scale,
73
+ eta=eta,
74
+ generator=torch.Generator().manual_seed(seed),
75
+ ).images[0]
76
+
77
+ gc.collect()
78
+ torch.cuda.empty_cache()
79
+ return out
80
+
81
+ def edit(
82
+ self,
83
+ prompt: str,
84
+ subject: str,
85
+ part: str,
86
+ edit: str,
87
+ negative_prompt: str = "",
88
+ num_inference_steps: int = 50,
89
+ guidance_scale: float = 7.5,
90
+ seed: int = 0,
91
+ eta: int = 0,
92
+ t_e: int = 50,
93
+ ) -> PIL.Image.Image:
94
+
95
+ # Sanity Checks
96
+ if not torch.cuda.is_available():
97
+ raise RuntimeError("This demo does not work on CPU!")
98
+
99
+ if part in PART_TOKENS:
100
+ token_path = PART_TOKENS[part]
101
+ else:
102
+ raise ValueError(f"Part `{part}` is not supported!")
103
+
104
+ if subject not in prompt:
105
+ raise ValueError(f"The subject `{subject}` does not exist in the original prompt!")
106
+
107
+ prompts = [
108
+ prompt,
109
+ prompt.replace(subject, edit),
110
+ ]
111
+
112
+ # PartEdit Parameters
113
+ cross_attention_kwargs = {
114
+ "edit_type": "replace",
115
+ "n_self_replace": 0.0,
116
+ "n_cross_replace": {"default_": 1.0, edit: 0.4},
117
+ }
118
+ extra_params = DotDictExtra()
119
+ extra_params.update({"omega": 1.5, "edit_steps": t_e})
120
+
121
+ out = self.partedit_pipe(
122
+ prompt=prompts,
123
+ # negative_prompt=negative_prompt,
124
+ num_inference_steps=num_inference_steps,
125
+ guidance_scale=guidance_scale,
126
+ eta=eta,
127
+ generator=torch.Generator().manual_seed(seed),
128
+ cross_attention_kwargs=cross_attention_kwargs,
129
+ extra_kwargs=extra_params,
130
+ embedding_opt=token_path,
131
+ ).images[:2][::-1]
132
+
133
+ mask = self.partedit_pipe.visualize_map_across_time()
134
+ gc.collect()
135
+ torch.cuda.empty_cache()
136
+ return out, mask
pyproject.toml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ [tool.ruff]
2
+ extend-select = ["C4", "SIM", "TCH"]
3
+ ignore = ["F401"]
4
+ show-fixes = true
5
+ target-version = "py39"
requirements.txt ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Requires Python 3.10.x
2
+ # Pull PyTorch CUDA 11.8 wheels
3
+ --extra-index-url https://download.pytorch.org/whl/cu118
4
+
5
+ setuptools>=61.0
6
+ numpy<1.24
7
+ # ipywidgets
8
+ # black[jupyter]
9
+ # jupyterlab
10
+ # matplotlib
11
+ einops
12
+ ftfy
13
+ regex
14
+ tqdm
15
+
16
+ # Core ML stack (PyTorch 2.1.0 + CUDA 11.8)
17
+ torch==2.1.0
18
+ torchvision==0.16.0
19
+ # torchaudio==2.1.0
20
+
21
+ # UI / HF stack
22
+ gradio<5.0 # tested on 4.29; should work on 4.44.1 with pydantic fix
23
+ huggingface_hub<0.26.0
24
+ pydantic<=2.10.6
25
+
26
+ # Diffusion / training utils
27
+ diffusers==0.27.2
28
+ transformers==4.44.1
29
+ accelerate
30
+ datasets # tested on 3.3.2
31
+ spaces
stable_diffusion_xl_partedit.py ADDED
The diff for this file is too large to render. See raw diff