openfree commited on
Commit
a24f281
ยท
verified ยท
1 Parent(s): b982501

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -180
app.py CHANGED
@@ -3,6 +3,7 @@ import gradio as gr
3
  import torch
4
  from einops import rearrange, repeat
5
  from PIL import Image
 
6
 
7
  from flux.sampling import denoise, get_noise, get_schedule, prepare, rf_denoise, rf_inversion, unpack
8
  from flux.util import (
@@ -18,7 +19,16 @@ from pulid.utils import resize_numpy_image_long, seed_everything
18
  # ๊ฐ„๋‹จํ•œ ์ธ์šฉ ์ •๋ณด ์ถ”๊ฐ€
19
  _CITE_ = """PuLID: Person-under-Language Image Diffusion Model"""
20
 
21
- def get_models(name: str, device: torch.device, offload: bool):
 
 
 
 
 
 
 
 
 
22
  t5 = load_t5(device, max_length=128)
23
  clip_model = load_clip(device)
24
  model = load_flow_model(name, device="cpu" if offload else device)
@@ -29,19 +39,36 @@ def get_models(name: str, device: torch.device, offload: bool):
29
 
30
  class FluxGenerator:
31
  def __init__(self):
32
- self.device = torch.device('cuda')
 
33
  self.offload = False
34
  self.model_name = 'flux-dev'
35
- self.model, self.ae, self.t5, self.clip_model = get_models(
36
- self.model_name,
37
- device=self.device,
38
- offload=self.offload,
39
- )
40
- self.pulid_model = PuLIDPipeline(self.model, 'cuda', weight_dtype=torch.bfloat16)
41
- self.pulid_model.load_pretrain()
42
-
43
-
44
- flux_generator = FluxGenerator()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
 
47
  @torch.inference_mode()
@@ -63,87 +90,91 @@ def generate_image(
63
  eta: float = 0.7,
64
  s: float = 0,
65
  tau: float = 5,
66
- perform_inversion: bool = True,
67
- perform_reconstruction: bool = False,
68
- perform_editing: bool = True,
69
- inversion_true_cfg: float = 1.0,
70
  ):
71
- flux_generator.t5.max_length = max_sequence_length
72
-
73
- # ์‹œ๋“œ ์„ค์ •
74
- seed = int(seed)
75
- if seed == -1:
76
- seed = None
77
-
78
- opts = SamplingOptions(
79
- prompt=prompt,
80
- width=width,
81
- height=height,
82
- num_steps=num_steps,
83
- guidance=guidance,
84
- seed=seed,
85
- )
86
-
87
- if opts.seed is None:
88
- opts.seed = torch.Generator(device="cpu").seed()
89
-
90
- seed_everything(opts.seed)
91
- print(f"Generating prompt: '{opts.prompt}' (seed={opts.seed})...")
92
- t0 = time.perf_counter()
93
-
94
- use_true_cfg = abs(true_cfg - 1.0) > 1e-6
95
-
96
- # 1) ์ž…๋ ฅ ๋…ธ์ด์ฆˆ ์ค€๋น„
97
- noise = get_noise(
98
- num_samples=1,
99
- height=opts.height,
100
- width=opts.width,
101
- device=flux_generator.device,
102
- dtype=torch.bfloat16,
103
- seed=opts.seed,
104
- )
105
- bs, c, h, w = noise.shape
106
- noise = rearrange(noise, "b c (h ph) (w pw) -> b (h w) (c ph pw)", ph=2, pw=2)
107
- if noise.shape[0] == 1 and bs > 1:
108
- noise = repeat(noise, "1 ... -> bs ...", bs=bs)
109
-
110
- # ID ์ด๋ฏธ์ง€ ์ธ์ฝ”๋”ฉ
111
- encode_t0 = time.perf_counter()
112
- id_image = id_image.resize((opts.width, opts.height), resample=Image.LANCZOS)
113
- x = torch.from_numpy(np.array(id_image).astype(np.float32))
114
- x = (x / 127.5) - 1.0
115
- x = rearrange(x, "h w c -> 1 c h w")
116
- x = x.to(flux_generator.device)
117
 
118
- with torch.autocast(device_type=flux_generator.device.type, dtype=torch.bfloat16):
119
- x = flux_generator.ae.encode(x)
120
- x = x.to(torch.bfloat16)
121
-
122
- encode_t1 = time.perf_counter()
123
- print(f"Encoded in {encode_t1 - encode_t0:.2f} seconds.")
124
 
125
- timesteps = get_schedule(opts.num_steps, x.shape[-1] * x.shape[-2] // 4, shift=False)
126
-
127
- # 2) ํ…์ŠคํŠธ ์ž„๋ฒ ๋”ฉ ์ค€๋น„
128
- inp = prepare(t5=flux_generator.t5, clip=flux_generator.clip_model, img=x, prompt=opts.prompt)
129
- inp_inversion = prepare(t5=flux_generator.t5, clip=flux_generator.clip_model, img=x, prompt="")
130
- inp_neg = None
131
- if use_true_cfg:
132
- inp_neg = prepare(t5=flux_generator.t5, clip=flux_generator.clip_model, img=x, prompt=neg_prompt)
133
-
134
- # 3) ID ์ž„๋ฒ ๋”ฉ ์ƒ์„ฑ
135
- id_embeddings = None
136
- uncond_id_embeddings = None
137
- if id_image is not None:
138
- id_image = np.array(id_image)
139
- id_image = resize_numpy_image_long(id_image, 1024)
140
- id_embeddings, uncond_id_embeddings = flux_generator.pulid_model.get_id_embedding(id_image, cal_uncond=use_true_cfg)
141
-
142
- y_0 = inp["img"].clone().detach()
143
-
144
- # ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ๊ณผ์ •
145
- inverted = None
146
- if perform_inversion:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  inverted = rf_inversion(
148
  flux_generator.model,
149
  **inp_inversion,
@@ -153,7 +184,7 @@ def generate_image(
153
  id_weight=id_weight,
154
  start_step=start_step,
155
  uncond_id=uncond_id_embeddings,
156
- true_cfg=inversion_true_cfg,
157
  timestep_to_start_cfg=timestep_to_start_cfg,
158
  neg_txt=inp_neg["txt"] if use_true_cfg else None,
159
  neg_txt_ids=inp_neg["txt_ids"] if use_true_cfg else None,
@@ -162,38 +193,10 @@ def generate_image(
162
  y_1=noise,
163
  gamma=gamma
164
  )
165
- img = inverted
166
- else:
167
- img = noise
168
 
169
- inp["img"] = img
170
- inp_inversion["img"] = img
171
-
172
- recon = None
173
- if perform_reconstruction:
174
- recon = rf_denoise(
175
- flux_generator.model,
176
- **inp_inversion,
177
- timesteps=timesteps,
178
- guidance=opts.guidance,
179
- id=id_embeddings,
180
- id_weight=id_weight,
181
- start_step=start_step,
182
- uncond_id=uncond_id_embeddings,
183
- true_cfg=inversion_true_cfg,
184
- timestep_to_start_cfg=timestep_to_start_cfg,
185
- neg_txt=inp_neg["txt"] if use_true_cfg else None,
186
- neg_txt_ids=inp_neg["txt_ids"] if use_true_cfg else None,
187
- neg_vec=inp_neg["vec"] if use_true_cfg else None,
188
- aggressive_offload=False,
189
- y_0=y_0,
190
- eta=eta,
191
- s=s,
192
- tau=tau,
193
- )
194
 
195
- edited = None
196
- if perform_editing:
197
  edited = rf_denoise(
198
  flux_generator.model,
199
  **inp,
@@ -215,46 +218,37 @@ def generate_image(
215
  tau=tau,
216
  )
217
 
218
- # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋””์ฝ”๋”ฉ
219
- if edited is not None:
220
  edited = unpack(edited.float(), opts.height, opts.width)
221
- with torch.autocast(device_type=flux_generator.device.type, dtype=torch.bfloat16):
222
  edited = flux_generator.ae.decode(edited)
223
 
224
- if inverted is not None:
225
- inverted = unpack(inverted.float(), opts.height, opts.width)
226
- with torch.autocast(device_type=flux_generator.device.type, dtype=torch.bfloat16):
227
- inverted = flux_generator.ae.decode(inverted)
228
-
229
- if recon is not None:
230
- recon = unpack(recon.float(), opts.height, opts.width)
231
- with torch.autocast(device_type=flux_generator.device.type, dtype=torch.bfloat16):
232
- recon = flux_generator.ae.decode(recon)
233
-
234
- t1 = time.perf_counter()
235
- print(f"Done in {t1 - t0:.2f} seconds.")
236
 
237
- # PIL ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜
238
- if edited is not None:
239
  edited = edited.clamp(-1, 1)
240
  edited = rearrange(edited[0], "c h w -> h w c")
241
  edited = Image.fromarray((127.5 * (edited + 1.0)).cpu().byte().numpy())
242
 
243
- if inverted is not None:
244
- inverted = inverted.clamp(-1, 1)
245
- inverted = rearrange(inverted[0], "c h w -> h w c")
246
- inverted = Image.fromarray((127.5 * (inverted + 1.0)).cpu().byte().numpy())
247
 
248
- if recon is not None:
249
- recon = recon.clamp(-1, 1)
250
- recon = rearrange(recon[0], "c h w -> h w c")
251
- recon = Image.fromarray((127.5 * (recon + 1.0)).cpu().byte().numpy())
 
252
 
253
- return edited, str(opts.seed), flux_generator.pulid_model.debug_img_list
254
 
255
-
256
- def create_demo(args):
257
- with gr.Blocks(theme="apriel") as demo:
 
 
 
 
 
 
258
  with gr.Row():
259
  with gr.Column():
260
  prompt = gr.Textbox(label="ํ”„๋กฌํ”„ํŠธ", value="portrait, color, cinematic")
@@ -275,31 +269,9 @@ def create_demo(args):
275
 
276
  with gr.Column():
277
  output_image = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€")
278
- seed_output = gr.Textbox(label="์‚ฌ์šฉ๋œ ์‹œ๋“œ")
279
  gr.Markdown(_CITE_)
280
 
281
- # ์˜ˆ์ œ ์ž…๋ ฅ
282
- with gr.Row():
283
- gr.Markdown("## ์˜ˆ์ œ")
284
- example_inps = [
285
- [
286
- 'a portrait of a clown',
287
- 'example_inputs/unsplash/lhon-karwan-11tbHtK5STE-unsplash.jpg',
288
- 0.5, 3.5, 42
289
- ],
290
- [
291
- 'a portrait of a zombie',
292
- 'example_inputs/unsplash/baruk-granda-cfLL_jHQ-Iw-unsplash.jpg',
293
- 0.4, 3.5, 42
294
- ],
295
- [
296
- 'a portrait of an elf',
297
- 'example_inputs/unsplash/masoud-razeghi--qsrZhXPius-unsplash.jpg',
298
- 0.5, 3.5, 42
299
- ]
300
- ]
301
- gr.Examples(examples=example_inps, inputs=[prompt, id_image, id_weight, guidance, seed])
302
-
303
  generate_btn.click(
304
  fn=generate_image,
305
  inputs=[prompt, id_image, 512, 512, num_steps, 0, guidance, seed, id_weight, neg_prompt,
@@ -312,18 +284,12 @@ def create_demo(args):
312
 
313
  if __name__ == "__main__":
314
  import argparse
315
- import numpy as np
316
 
317
  parser = argparse.ArgumentParser(description="PuLID for FLUX.1-dev")
318
  parser.add_argument('--version', type=str, default='v0.9.1')
319
  parser.add_argument("--name", type=str, default="flux-dev")
320
- parser.add_argument("--device", type=str, default="cuda")
321
- parser.add_argument("--offload", action="store_true")
322
  parser.add_argument("--port", type=int, default=8080)
323
  args = parser.parse_args()
324
 
325
- print(f"Using device: {args.device}")
326
- print(f"Offload: {args.offload}")
327
-
328
- demo = create_demo(args)
329
  demo.launch(ssr_mode=False)
 
3
  import torch
4
  from einops import rearrange, repeat
5
  from PIL import Image
6
+ import numpy as np
7
 
8
  from flux.sampling import denoise, get_noise, get_schedule, prepare, rf_denoise, rf_inversion, unpack
9
  from flux.util import (
 
19
  # ๊ฐ„๋‹จํ•œ ์ธ์šฉ ์ •๋ณด ์ถ”๊ฐ€
20
  _CITE_ = """PuLID: Person-under-Language Image Diffusion Model"""
21
 
22
+ # GPU ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธ ๋ฐ ์žฅ์น˜ ์„ค์ •
23
+ def get_device():
24
+ if torch.cuda.is_available():
25
+ return torch.device('cuda')
26
+ else:
27
+ print("CUDA GPU๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. CPU๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.")
28
+ return torch.device('cpu')
29
+
30
+ def get_models(name: str, device, offload: bool):
31
+ print(f"๋ชจ๋ธ์„ {device}์— ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.")
32
  t5 = load_t5(device, max_length=128)
33
  clip_model = load_clip(device)
34
  model = load_flow_model(name, device="cpu" if offload else device)
 
39
 
40
  class FluxGenerator:
41
  def __init__(self):
42
+ # GPU ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์žฅ์น˜ ์„ค์ •
43
+ self.device = get_device()
44
  self.offload = False
45
  self.model_name = 'flux-dev'
46
+
47
+ # ๋ชจ๋ธ ๋กœ๋“œ ์‹œ๋„
48
+ try:
49
+ self.model, self.ae, self.t5, self.clip_model = get_models(
50
+ self.model_name,
51
+ device=self.device,
52
+ offload=self.offload,
53
+ )
54
+ self.pulid_model = PuLIDPipeline(
55
+ self.model,
56
+ 'cuda' if torch.cuda.is_available() else 'cpu',
57
+ weight_dtype=torch.bfloat16 if self.device.type == 'cuda' else torch.float32
58
+ )
59
+ self.pulid_model.load_pretrain()
60
+ self.initialized = True
61
+ except Exception as e:
62
+ print(f"๋ชจ๋ธ ์ดˆ๊ธฐํ™” ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
63
+ self.initialized = False
64
+
65
+ # ๋ชจ๋ธ ์ดˆ๊ธฐํ™” ์‹œ๋„
66
+ try:
67
+ flux_generator = FluxGenerator()
68
+ model_initialized = flux_generator.initialized
69
+ except Exception as e:
70
+ print(f"FluxGenerator ์ดˆ๊ธฐํ™” ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
71
+ model_initialized = False
72
 
73
 
74
  @torch.inference_mode()
 
90
  eta: float = 0.7,
91
  s: float = 0,
92
  tau: float = 5,
 
 
 
 
93
  ):
94
+ # ๋ชจ๋ธ์ด ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์œผ๋ฉด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ๋ฐ˜ํ™˜
95
+ if not model_initialized:
96
+ return None, "GPU ์˜ค๋ฅ˜: CUDA GPU๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์–ด ๋ชจ๋ธ์„ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
+ # ID ์ด๋ฏธ์ง€๊ฐ€ ์—†์œผ๋ฉด ์‹คํ–‰ ๋ถˆ๊ฐ€
99
+ if id_image is None:
100
+ return None, "์˜ค๋ฅ˜: ID ์ด๋ฏธ์ง€๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.", None
 
 
 
101
 
102
+ try:
103
+ flux_generator.t5.max_length = max_sequence_length
104
+
105
+ # ์‹œ๋“œ ์„ค์ •
106
+ seed = int(seed)
107
+ if seed == -1:
108
+ seed = None
109
+
110
+ opts = SamplingOptions(
111
+ prompt=prompt,
112
+ width=width,
113
+ height=height,
114
+ num_steps=num_steps,
115
+ guidance=guidance,
116
+ seed=seed,
117
+ )
118
+
119
+ if opts.seed is None:
120
+ opts.seed = torch.Generator(device="cpu").seed()
121
+
122
+ seed_everything(opts.seed)
123
+ print(f"Generating prompt: '{opts.prompt}' (seed={opts.seed})...")
124
+ t0 = time.perf_counter()
125
+
126
+ use_true_cfg = abs(true_cfg - 1.0) > 1e-6
127
+
128
+ # 1) ์ž…๋ ฅ ๋…ธ์ด์ฆˆ ์ค€๋น„
129
+ noise = get_noise(
130
+ num_samples=1,
131
+ height=opts.height,
132
+ width=opts.width,
133
+ device=flux_generator.device,
134
+ dtype=torch.bfloat16 if flux_generator.device.type == 'cuda' else torch.float32,
135
+ seed=opts.seed,
136
+ )
137
+ bs, c, h, w = noise.shape
138
+ noise = rearrange(noise, "b c (h ph) (w pw) -> b (h w) (c ph pw)", ph=2, pw=2)
139
+ if noise.shape[0] == 1 and bs > 1:
140
+ noise = repeat(noise, "1 ... -> bs ...", bs=bs)
141
+
142
+ # ID ์ด๋ฏธ์ง€ ์ธ์ฝ”๋”ฉ
143
+ encode_t0 = time.perf_counter()
144
+ id_image = id_image.resize((opts.width, opts.height), resample=Image.LANCZOS)
145
+ x = torch.from_numpy(np.array(id_image).astype(np.float32))
146
+ x = (x / 127.5) - 1.0
147
+ x = rearrange(x, "h w c -> 1 c h w")
148
+ x = x.to(flux_generator.device)
149
+
150
+ dtype = torch.bfloat16 if flux_generator.device.type == 'cuda' else torch.float32
151
+ with torch.autocast(device_type=flux_generator.device.type, dtype=dtype):
152
+ x = flux_generator.ae.encode(x)
153
+ x = x.to(dtype)
154
+
155
+ encode_t1 = time.perf_counter()
156
+ print(f"Encoded in {encode_t1 - encode_t0:.2f} seconds.")
157
+
158
+ timesteps = get_schedule(opts.num_steps, x.shape[-1] * x.shape[-2] // 4, shift=False)
159
+
160
+ # 2) ํ…์ŠคํŠธ ์ž„๋ฒ ๋”ฉ ์ค€๋น„
161
+ inp = prepare(t5=flux_generator.t5, clip=flux_generator.clip_model, img=x, prompt=opts.prompt)
162
+ inp_inversion = prepare(t5=flux_generator.t5, clip=flux_generator.clip_model, img=x, prompt="")
163
+ inp_neg = None
164
+ if use_true_cfg:
165
+ inp_neg = prepare(t5=flux_generator.t5, clip=flux_generator.clip_model, img=x, prompt=neg_prompt)
166
+
167
+ # 3) ID ์ž„๋ฒ ๋”ฉ ์ƒ์„ฑ
168
+ id_embeddings = None
169
+ uncond_id_embeddings = None
170
+ if id_image is not None:
171
+ id_image = np.array(id_image)
172
+ id_image = resize_numpy_image_long(id_image, 1024)
173
+ id_embeddings, uncond_id_embeddings = flux_generator.pulid_model.get_id_embedding(id_image, cal_uncond=use_true_cfg)
174
+
175
+ y_0 = inp["img"].clone().detach()
176
+
177
+ # ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ๊ณผ์ •
178
  inverted = rf_inversion(
179
  flux_generator.model,
180
  **inp_inversion,
 
184
  id_weight=id_weight,
185
  start_step=start_step,
186
  uncond_id=uncond_id_embeddings,
187
+ true_cfg=true_cfg,
188
  timestep_to_start_cfg=timestep_to_start_cfg,
189
  neg_txt=inp_neg["txt"] if use_true_cfg else None,
190
  neg_txt_ids=inp_neg["txt_ids"] if use_true_cfg else None,
 
193
  y_1=noise,
194
  gamma=gamma
195
  )
 
 
 
196
 
197
+ inp["img"] = inverted
198
+ inp_inversion["img"] = inverted
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
 
 
200
  edited = rf_denoise(
201
  flux_generator.model,
202
  **inp,
 
218
  tau=tau,
219
  )
220
 
221
+ # ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ๋””์ฝ”๋”ฉ
 
222
  edited = unpack(edited.float(), opts.height, opts.width)
223
+ with torch.autocast(device_type=flux_generator.device.type, dtype=dtype):
224
  edited = flux_generator.ae.decode(edited)
225
 
226
+ t1 = time.perf_counter()
227
+ print(f"Done in {t1 - t0:.2f} seconds.")
 
 
 
 
 
 
 
 
 
 
228
 
229
+ # PIL ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜
 
230
  edited = edited.clamp(-1, 1)
231
  edited = rearrange(edited[0], "c h w -> h w c")
232
  edited = Image.fromarray((127.5 * (edited + 1.0)).cpu().byte().numpy())
233
 
234
+ return edited, str(opts.seed), flux_generator.pulid_model.debug_img_list
 
 
 
235
 
236
+ except Exception as e:
237
+ import traceback
238
+ error_msg = f"์ด๋ฏธ์ง€ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}\n{traceback.format_exc()}"
239
+ print(error_msg)
240
+ return None, error_msg, None
241
 
 
242
 
243
+ def create_demo():
244
+ with gr.Blocks() as demo:
245
+ gr.Markdown("# PuLID: ์ธ๋ฌผ ์ด๋ฏธ์ง€ ๋ณ€ํ™˜ ๋„๊ตฌ")
246
+
247
+ if not model_initialized:
248
+ gr.Markdown("## โš ๏ธ ์˜ค๋ฅ˜: CUDA GPU๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค")
249
+ gr.Markdown("์ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ CUDA ์ง€์› GPU๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. CPU์—์„œ๋Š” ์‹คํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
250
+ return demo
251
+
252
  with gr.Row():
253
  with gr.Column():
254
  prompt = gr.Textbox(label="ํ”„๋กฌํ”„ํŠธ", value="portrait, color, cinematic")
 
269
 
270
  with gr.Column():
271
  output_image = gr.Image(label="์ƒ์„ฑ๋œ ์ด๋ฏธ์ง€")
272
+ seed_output = gr.Textbox(label="๊ฒฐ๊ณผ/์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€")
273
  gr.Markdown(_CITE_)
274
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  generate_btn.click(
276
  fn=generate_image,
277
  inputs=[prompt, id_image, 512, 512, num_steps, 0, guidance, seed, id_weight, neg_prompt,
 
284
 
285
  if __name__ == "__main__":
286
  import argparse
 
287
 
288
  parser = argparse.ArgumentParser(description="PuLID for FLUX.1-dev")
289
  parser.add_argument('--version', type=str, default='v0.9.1')
290
  parser.add_argument("--name", type=str, default="flux-dev")
 
 
291
  parser.add_argument("--port", type=int, default=8080)
292
  args = parser.parse_args()
293
 
294
+ demo = create_demo()
 
 
 
295
  demo.launch(ssr_mode=False)