xinjjj commited on
Commit
13c7678
·
1 Parent(s): 2e5dcda
Files changed (2) hide show
  1. app.py +2 -2
  2. common.py +410 -34
app.py CHANGED
@@ -27,6 +27,7 @@ from common import (
27
  MAX_SEED,
28
  VERSION,
29
  active_btn_by_text_content,
 
30
  end_session,
31
  extract_3d_representations_v3,
32
  extract_urdf,
@@ -35,7 +36,6 @@ from common import (
35
  get_selected_image,
36
  image_to_3d,
37
  start_session,
38
- text2image_fn,
39
  )
40
 
41
  app_name = os.getenv("GRADIO_APP")
@@ -395,7 +395,7 @@ with gr.Blocks(delete_cache=(43200, 43200), theme=custom_theme) as demo:
395
  image_sample3,
396
  ],
397
  ).success(
398
- text2image_fn,
399
  inputs=[
400
  text_prompt,
401
  img_guidance_scale,
 
27
  MAX_SEED,
28
  VERSION,
29
  active_btn_by_text_content,
30
+ dispatch_text2image_fn,
31
  end_session,
32
  extract_3d_representations_v3,
33
  extract_urdf,
 
36
  get_selected_image,
37
  image_to_3d,
38
  start_session,
 
39
  )
40
 
41
  app_name = os.getenv("GRADIO_APP")
 
395
  image_sample3,
396
  ],
397
  ).success(
398
+ dispatch_text2image_fn,
399
  inputs=[
400
  text_prompt,
401
  img_guidance_scale,
common.py CHANGED
@@ -28,12 +28,15 @@ _disable_xformers_flash3()
28
  monkey_path_trellis()
29
 
30
 
 
31
  import gc
32
  import logging
33
  import os
34
  import shutil
35
  import subprocess
36
  import sys
 
 
37
  from glob import glob
38
 
39
  import cv2
@@ -91,6 +94,166 @@ logger = logging.getLogger(__name__)
91
  os.environ["GRADIO_ANALYTICS_ENABLED"] = "false"
92
  os.environ.setdefault("OPENAI_API_KEY", "sk-placeholder")
93
  MAX_SEED = 100000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  # Global variables for lazy initialization
96
  _RBG_REMOVER = None
@@ -117,6 +280,8 @@ if os.getenv("GRADIO_APP").startswith("imageto3d"):
117
  )
118
  os.makedirs(TMP_DIR, exist_ok=True)
119
  elif os.getenv("GRADIO_APP").startswith("textto3d"):
 
 
120
  if "sam3d" in os.getenv("GRADIO_APP"):
121
  PIPELINE = Sam3dInference(device="cuda")
122
  else:
@@ -124,9 +289,39 @@ elif os.getenv("GRADIO_APP").startswith("textto3d"):
124
  "microsoft/TRELLIS-image-large"
125
  )
126
  # PIPELINE.cuda()
 
 
 
 
 
 
127
  text_model_dir = "weights/Kolors"
 
 
128
  PIPELINE_IMG_IP = build_text2img_ip_pipeline(text_model_dir, ref_scale=0.3)
 
 
 
 
 
 
 
 
129
  PIPELINE_IMG = build_text2img_pipeline(text_model_dir)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  SEG_CHECKER = ImageSegChecker(GPT_CLIENT)
131
  GEO_CHECKER = MeshGeoChecker(GPT_CLIENT)
132
  AESTHETIC_CHECKER = ImageAestheticChecker()
@@ -167,9 +362,21 @@ def preprocess_image_fn(
167
  rmbg_tag: str = "rembg",
168
  preprocess: bool = True,
169
  ) -> tuple[Image.Image, Image.Image]:
170
- """Preprocess image with lazy model initialization to avoid CUDA init at import time."""
171
  global _RBG_REMOVER, _RBG14_REMOVER
172
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  if isinstance(image, str):
174
  image = Image.open(image)
175
  elif isinstance(image, np.ndarray):
@@ -180,18 +387,34 @@ def preprocess_image_fn(
180
  # Lazy initialization - models are created on first call within @spaces.GPU context
181
  if rmbg_tag == "rembg":
182
  if _RBG_REMOVER is None:
 
183
  _RBG_REMOVER = RembgRemover()
 
184
  bg_remover = _RBG_REMOVER
185
  else:
186
  if _RBG14_REMOVER is None:
 
187
  _RBG14_REMOVER = BMGG14Remover()
 
188
  bg_remover = _RBG14_REMOVER
189
 
 
190
  image = bg_remover(image)
 
191
  image = keep_largest_connected_component(image)
192
 
193
  if preprocess:
 
194
  image = trellis_preprocess(image)
 
 
 
 
 
 
 
 
 
195
 
196
  return image, image_cache
197
 
@@ -581,60 +804,213 @@ def extract_urdf(
581
  )
582
 
583
 
584
- @spaces.GPU
585
  def text2image_fn(
586
  prompt: str,
587
  guidance_scale: float,
588
  infer_step: int = 50,
589
  ip_image: Image.Image | str = None,
590
  ip_adapt_scale: float = 0.3,
591
- image_wh: int | tuple[int, int] = [1024, 1024],
592
  rmbg_tag: str = "rembg",
593
  seed: int = None,
594
  enable_pre_resize: bool = True,
595
  n_sample: int = 3,
596
  req: gr.Request = None,
597
- ):
598
- if isinstance(image_wh, int):
599
- image_wh = (image_wh, image_wh)
600
- output_root = TMP_DIR
601
- if req is not None:
602
- output_root = os.path.join(output_root, str(req.session_hash))
603
- os.makedirs(output_root, exist_ok=True)
604
-
605
- pipeline = PIPELINE_IMG if ip_image is None else PIPELINE_IMG_IP
606
- if ip_image is not None:
607
- pipeline.set_ip_adapter_scale([ip_adapt_scale])
608
-
609
- images = text2img_gen(
610
- prompt=prompt,
611
- n_sample=n_sample,
612
  guidance_scale=guidance_scale,
613
- pipeline=pipeline,
614
- ip_image=ip_image,
615
- image_wh=image_wh,
616
  infer_step=infer_step,
 
 
 
 
617
  seed=seed,
 
 
 
 
618
  )
 
619
 
620
- for idx in range(len(images)):
621
- image = images[idx]
622
- images[idx], _ = preprocess_image_fn(
623
- image, rmbg_tag, enable_pre_resize
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
624
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
 
626
- save_paths = []
627
- for idx, image in enumerate(images):
628
- save_path = f"{output_root}/sample_{idx}.png"
629
- image.save(save_path)
630
- save_paths.append(save_path)
 
 
 
 
 
 
 
631
 
632
- logger.info(f"Images saved to {output_root}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
633
 
634
- gc.collect()
635
- torch.cuda.empty_cache()
636
 
637
- return save_paths + save_paths
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
 
639
 
640
  @spaces.GPU
 
28
  monkey_path_trellis()
29
 
30
 
31
+ import functools
32
  import gc
33
  import logging
34
  import os
35
  import shutil
36
  import subprocess
37
  import sys
38
+ import time
39
+ import traceback
40
  from glob import glob
41
 
42
  import cv2
 
94
  os.environ["GRADIO_ANALYTICS_ENABLED"] = "false"
95
  os.environ.setdefault("OPENAI_API_KEY", "sk-placeholder")
96
  MAX_SEED = 100000
97
+ DIAG_PREFIX = "[T2I-DIAG]"
98
+
99
+
100
+ def _diag(event: str, **fields: object) -> None:
101
+ timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
102
+ details = " ".join(f"{key}={value!r}" for key, value in fields.items())
103
+ message = f"{DIAG_PREFIX} {timestamp} event={event}"
104
+ if details:
105
+ message = f"{message} {details}"
106
+ print(message, flush=True)
107
+
108
+
109
+ def _diag_cuda(stage: str) -> None:
110
+ try:
111
+ cuda_available = torch.cuda.is_available()
112
+ _diag(
113
+ "CUDA_STATUS",
114
+ stage=stage,
115
+ pid=os.getpid(),
116
+ cuda_available=cuda_available,
117
+ cuda_visible_devices=os.getenv("CUDA_VISIBLE_DEVICES"),
118
+ device_count=torch.cuda.device_count() if cuda_available else 0,
119
+ )
120
+ if not cuda_available:
121
+ return
122
+
123
+ device_index = torch.cuda.current_device()
124
+ free_bytes, total_bytes = torch.cuda.mem_get_info(device_index)
125
+ properties = torch.cuda.get_device_properties(device_index)
126
+ _diag(
127
+ "CUDA_MEMORY",
128
+ stage=stage,
129
+ device_index=device_index,
130
+ device_name=properties.name,
131
+ capability=f"{properties.major}.{properties.minor}",
132
+ free_gib=round(free_bytes / 1024**3, 3),
133
+ total_gib=round(total_bytes / 1024**3, 3),
134
+ allocated_gib=round(
135
+ torch.cuda.memory_allocated(device_index) / 1024**3, 3
136
+ ),
137
+ reserved_gib=round(
138
+ torch.cuda.memory_reserved(device_index) / 1024**3, 3
139
+ ),
140
+ max_allocated_gib=round(
141
+ torch.cuda.max_memory_allocated(device_index) / 1024**3, 3
142
+ ),
143
+ )
144
+ except Exception as exc:
145
+ _diag(
146
+ "CUDA_STATUS_FAILED",
147
+ stage=stage,
148
+ exception_type=type(exc).__name__,
149
+ exception=str(exc),
150
+ )
151
+
152
+
153
+ def _diag_pipeline(name: str, pipeline: object) -> None:
154
+ component_details = []
155
+ components = getattr(pipeline, "components", None)
156
+ if isinstance(components, dict):
157
+ for component_name, component in components.items():
158
+ device = getattr(component, "device", None)
159
+ dtype = getattr(component, "dtype", None)
160
+ component_details.append(
161
+ f"{component_name}:{type(component).__name__}@{device}/{dtype}"
162
+ )
163
+
164
+ _diag(
165
+ "PIPELINE_STATUS",
166
+ name=name,
167
+ pipeline_type=type(pipeline).__name__,
168
+ device=getattr(pipeline, "device", None),
169
+ components=";".join(component_details),
170
+ )
171
+
172
+
173
+ def _install_zerogpu_diagnostics() -> None:
174
+ try:
175
+ from spaces.zero import client as zero_client
176
+ from spaces.zero import wrappers as zero_wrappers
177
+ except Exception as exc:
178
+ _diag(
179
+ "ZEROGPU_DIAGNOSTICS_INSTALL_FAILED",
180
+ exception_type=type(exc).__name__,
181
+ exception=str(exc),
182
+ )
183
+ return
184
+
185
+ original_schedule = zero_client.schedule
186
+ if not getattr(original_schedule, "_embodiedgen_diagnostic", False):
187
+
188
+ @functools.wraps(original_schedule)
189
+ def diagnostic_schedule(*args, **kwargs):
190
+ started = time.monotonic()
191
+ _diag(
192
+ "ZEROGPU_SCHEDULE_ENTER",
193
+ pid=os.getpid(),
194
+ task_id=kwargs.get("task_id"),
195
+ duration=str(kwargs.get("duration")),
196
+ gpu_size=kwargs.get("gpu_size"),
197
+ )
198
+ try:
199
+ response = original_schedule(*args, **kwargs)
200
+ except Exception as exc:
201
+ _diag(
202
+ "ZEROGPU_SCHEDULE_EXCEPTION",
203
+ exception_type=type(exc).__name__,
204
+ exception=str(exc)[:2000],
205
+ elapsed_seconds=round(time.monotonic() - started, 3),
206
+ )
207
+ raise
208
+ _diag(
209
+ "ZEROGPU_SCHEDULE_READY",
210
+ nvidia_index=getattr(response, "nvidiaIndex", None),
211
+ idle=getattr(response, "idle", None),
212
+ elapsed_seconds=round(time.monotonic() - started, 3),
213
+ )
214
+ return response
215
+
216
+ diagnostic_schedule._embodiedgen_diagnostic = True
217
+ zero_client.schedule = diagnostic_schedule
218
+
219
+ original_worker_init = zero_wrappers.worker_init
220
+ if not getattr(original_worker_init, "_embodiedgen_diagnostic", False):
221
+
222
+ @functools.wraps(original_worker_init)
223
+ def diagnostic_worker_init(*args, **kwargs):
224
+ started = time.monotonic()
225
+ _diag(
226
+ "ZEROGPU_WORKER_INIT_ENTER",
227
+ pid=os.getpid(),
228
+ ppid=os.getppid(),
229
+ cuda_visible_devices=os.getenv("CUDA_VISIBLE_DEVICES"),
230
+ )
231
+ try:
232
+ result = original_worker_init(*args, **kwargs)
233
+ except BaseException as exc:
234
+ _diag(
235
+ "ZEROGPU_WORKER_INIT_EXCEPTION",
236
+ exception_type=type(exc).__name__,
237
+ exception=str(exc)[:2000],
238
+ elapsed_seconds=round(time.monotonic() - started, 3),
239
+ )
240
+ traceback.print_exc()
241
+ sys.stderr.flush()
242
+ raise
243
+ _diag(
244
+ "ZEROGPU_WORKER_INIT_READY",
245
+ result_type=type(result).__name__,
246
+ elapsed_seconds=round(time.monotonic() - started, 3),
247
+ )
248
+ return result
249
+
250
+ diagnostic_worker_init._embodiedgen_diagnostic = True
251
+ zero_wrappers.worker_init = diagnostic_worker_init
252
+
253
+ _diag("ZEROGPU_DIAGNOSTICS_INSTALLED", spaces_version="0.51-compatible")
254
+
255
+
256
+ _install_zerogpu_diagnostics()
257
 
258
  # Global variables for lazy initialization
259
  _RBG_REMOVER = None
 
280
  )
281
  os.makedirs(TMP_DIR, exist_ok=True)
282
  elif os.getenv("GRADIO_APP").startswith("textto3d"):
283
+ _pipeline_init_started = time.monotonic()
284
+ _diag("IMPORT_MODEL_START", name="PIPELINE", model="Sam3dInference")
285
  if "sam3d" in os.getenv("GRADIO_APP"):
286
  PIPELINE = Sam3dInference(device="cuda")
287
  else:
 
289
  "microsoft/TRELLIS-image-large"
290
  )
291
  # PIPELINE.cuda()
292
+ _diag(
293
+ "IMPORT_MODEL_READY",
294
+ name="PIPELINE",
295
+ model_type=type(PIPELINE).__name__,
296
+ elapsed_seconds=round(time.monotonic() - _pipeline_init_started, 3),
297
+ )
298
  text_model_dir = "weights/Kolors"
299
+ _pipeline_img_ip_started = time.monotonic()
300
+ _diag("IMPORT_MODEL_START", name="PIPELINE_IMG_IP", model="Kolors-IP")
301
  PIPELINE_IMG_IP = build_text2img_ip_pipeline(text_model_dir, ref_scale=0.3)
302
+ _diag(
303
+ "IMPORT_MODEL_READY",
304
+ name="PIPELINE_IMG_IP",
305
+ model_type=type(PIPELINE_IMG_IP).__name__,
306
+ elapsed_seconds=round(time.monotonic() - _pipeline_img_ip_started, 3),
307
+ )
308
+ _pipeline_img_started = time.monotonic()
309
+ _diag("IMPORT_MODEL_START", name="PIPELINE_IMG", model="Kolors")
310
  PIPELINE_IMG = build_text2img_pipeline(text_model_dir)
311
+ _diag(
312
+ "IMPORT_MODEL_READY",
313
+ name="PIPELINE_IMG",
314
+ model_type=type(PIPELINE_IMG).__name__,
315
+ elapsed_seconds=round(time.monotonic() - _pipeline_img_started, 3),
316
+ )
317
+ _diag(
318
+ "IMPORT_MODELS_COMPLETE",
319
+ global_cuda_pipeline_count=3,
320
+ note=(
321
+ "Sam3D plus two full Kolors pipelines are resident before "
322
+ "ZeroGPU dispatch"
323
+ ),
324
+ )
325
  SEG_CHECKER = ImageSegChecker(GPT_CLIENT)
326
  GEO_CHECKER = MeshGeoChecker(GPT_CLIENT)
327
  AESTHETIC_CHECKER = ImageAestheticChecker()
 
362
  rmbg_tag: str = "rembg",
363
  preprocess: bool = True,
364
  ) -> tuple[Image.Image, Image.Image]:
365
+ """Preprocess an image with lazily initialized background removal."""
366
  global _RBG_REMOVER, _RBG14_REMOVER
367
 
368
+ started = time.monotonic()
369
+ _diag(
370
+ "PREPROCESS_ENTER",
371
+ pid=os.getpid(),
372
+ rmbg_tag=rmbg_tag,
373
+ preprocess=preprocess,
374
+ input_type=type(image).__name__,
375
+ rembg_cached=_RBG_REMOVER is not None,
376
+ rmbg14_cached=_RBG14_REMOVER is not None,
377
+ )
378
+ _diag_cuda("preprocess_enter")
379
+
380
  if isinstance(image, str):
381
  image = Image.open(image)
382
  elif isinstance(image, np.ndarray):
 
387
  # Lazy initialization - models are created on first call within @spaces.GPU context
388
  if rmbg_tag == "rembg":
389
  if _RBG_REMOVER is None:
390
+ _diag("PREPROCESS_MODEL_INIT_START", model="RembgRemover")
391
  _RBG_REMOVER = RembgRemover()
392
+ _diag("PREPROCESS_MODEL_INIT_READY", model="RembgRemover")
393
  bg_remover = _RBG_REMOVER
394
  else:
395
  if _RBG14_REMOVER is None:
396
+ _diag("PREPROCESS_MODEL_INIT_START", model="BMGG14Remover")
397
  _RBG14_REMOVER = BMGG14Remover()
398
+ _diag("PREPROCESS_MODEL_INIT_READY", model="BMGG14Remover")
399
  bg_remover = _RBG14_REMOVER
400
 
401
+ _diag("PREPROCESS_INFERENCE_START", model=type(bg_remover).__name__)
402
  image = bg_remover(image)
403
+ _diag("PREPROCESS_INFERENCE_READY", model=type(bg_remover).__name__)
404
  image = keep_largest_connected_component(image)
405
 
406
  if preprocess:
407
+ _diag("PREPROCESS_TRELLIS_START")
408
  image = trellis_preprocess(image)
409
+ _diag("PREPROCESS_TRELLIS_READY")
410
+
411
+ _diag_cuda("preprocess_exit")
412
+ _diag(
413
+ "PREPROCESS_EXIT",
414
+ elapsed_seconds=round(time.monotonic() - started, 3),
415
+ output_mode=image.mode,
416
+ output_size=image.size,
417
+ )
418
 
419
  return image, image_cache
420
 
 
804
  )
805
 
806
 
807
+ @spaces.GPU(duration=180)
808
  def text2image_fn(
809
  prompt: str,
810
  guidance_scale: float,
811
  infer_step: int = 50,
812
  ip_image: Image.Image | str = None,
813
  ip_adapt_scale: float = 0.3,
814
+ image_wh: int | tuple[int, int] = (1024, 1024),
815
  rmbg_tag: str = "rembg",
816
  seed: int = None,
817
  enable_pre_resize: bool = True,
818
  n_sample: int = 3,
819
  req: gr.Request = None,
820
+ ) -> list[str]:
821
+ started = time.monotonic()
822
+ _diag(
823
+ "WORKER_ENTER",
824
+ function="text2image_fn",
825
+ pid=os.getpid(),
826
+ ppid=os.getppid(),
827
+ prompt_length=len(prompt) if prompt is not None else None,
 
 
 
 
 
 
 
828
  guidance_scale=guidance_scale,
 
 
 
829
  infer_step=infer_step,
830
+ has_reference_image=ip_image is not None,
831
+ ip_adapt_scale=ip_adapt_scale,
832
+ image_wh=image_wh,
833
+ rmbg_tag=rmbg_tag,
834
  seed=seed,
835
+ enable_pre_resize=enable_pre_resize,
836
+ n_sample=n_sample,
837
+ session_hash=getattr(req, "session_hash", None),
838
+ configured_duration_seconds=180,
839
  )
840
+ _diag_cuda("worker_enter")
841
 
842
+ try:
843
+ if isinstance(image_wh, int):
844
+ image_wh = (image_wh, image_wh)
845
+ output_root = TMP_DIR
846
+ if req is not None:
847
+ output_root = os.path.join(output_root, str(req.session_hash))
848
+ os.makedirs(output_root, exist_ok=True)
849
+ _diag("OUTPUT_DIRECTORY_READY", output_root=output_root)
850
+
851
+ pipeline_name = "PIPELINE_IMG" if ip_image is None else "PIPELINE_IMG_IP"
852
+ pipeline = PIPELINE_IMG if ip_image is None else PIPELINE_IMG_IP
853
+ _diag_pipeline(pipeline_name, pipeline)
854
+ if ip_image is not None:
855
+ _diag("IP_ADAPTER_SCALE_START", scale=ip_adapt_scale)
856
+ pipeline.set_ip_adapter_scale([ip_adapt_scale])
857
+ _diag("IP_ADAPTER_SCALE_READY", scale=ip_adapt_scale)
858
+
859
+ generation_started = time.monotonic()
860
+ _diag("TEXT2IMAGE_GENERATION_START", pipeline=pipeline_name)
861
+ images = text2img_gen(
862
+ prompt=prompt,
863
+ n_sample=n_sample,
864
+ guidance_scale=guidance_scale,
865
+ pipeline=pipeline,
866
+ ip_image=ip_image,
867
+ image_wh=image_wh,
868
+ infer_step=infer_step,
869
+ seed=seed,
870
+ )
871
+ _diag(
872
+ "TEXT2IMAGE_GENERATION_READY",
873
+ image_count=len(images),
874
+ elapsed_seconds=round(time.monotonic() - generation_started, 3),
875
  )
876
+ _diag_cuda("after_text2image_generation")
877
+
878
+ for idx, image in enumerate(images):
879
+ preprocess_started = time.monotonic()
880
+ _diag(
881
+ "IMAGE_PREPROCESS_START",
882
+ image_index=idx,
883
+ image_mode=image.mode,
884
+ image_size=image.size,
885
+ )
886
+ images[idx], _ = preprocess_image_fn(
887
+ image, rmbg_tag, enable_pre_resize
888
+ )
889
+ _diag(
890
+ "IMAGE_PREPROCESS_READY",
891
+ image_index=idx,
892
+ elapsed_seconds=round(
893
+ time.monotonic() - preprocess_started, 3
894
+ ),
895
+ )
896
 
897
+ save_paths = []
898
+ for idx, image in enumerate(images):
899
+ save_path = f"{output_root}/sample_{idx}.png"
900
+ _diag("IMAGE_SAVE_START", image_index=idx, save_path=save_path)
901
+ image.save(save_path)
902
+ save_paths.append(save_path)
903
+ _diag(
904
+ "IMAGE_SAVE_READY",
905
+ image_index=idx,
906
+ save_path=save_path,
907
+ file_size=os.path.getsize(save_path),
908
+ )
909
 
910
+ _diag(
911
+ "WORKER_SUCCESS",
912
+ output_root=output_root,
913
+ output_count=len(save_paths),
914
+ elapsed_seconds=round(time.monotonic() - started, 3),
915
+ )
916
+ return save_paths + save_paths
917
+ except Exception as exc:
918
+ _diag(
919
+ "WORKER_EXCEPTION",
920
+ exception_type=type(exc).__name__,
921
+ exception=str(exc)[:2000],
922
+ elapsed_seconds=round(time.monotonic() - started, 3),
923
+ )
924
+ traceback.print_exc()
925
+ sys.stderr.flush()
926
+ _diag_cuda("worker_exception")
927
+ raise
928
+ finally:
929
+ cleanup_started = time.monotonic()
930
+ _diag("WORKER_CLEANUP_START")
931
+ try:
932
+ gc.collect()
933
+ if torch.cuda.is_available():
934
+ torch.cuda.empty_cache()
935
+ except Exception as exc:
936
+ _diag(
937
+ "WORKER_CLEANUP_EXCEPTION",
938
+ exception_type=type(exc).__name__,
939
+ exception=str(exc)[:2000],
940
+ )
941
+ _diag_cuda("worker_cleanup_complete")
942
+ _diag(
943
+ "WORKER_EXIT",
944
+ total_elapsed_seconds=round(time.monotonic() - started, 3),
945
+ cleanup_elapsed_seconds=round(
946
+ time.monotonic() - cleanup_started, 3
947
+ ),
948
+ )
949
 
 
 
950
 
951
+ def dispatch_text2image_fn(
952
+ prompt: str,
953
+ guidance_scale: float,
954
+ infer_step: int = 50,
955
+ ip_image: Image.Image | str = None,
956
+ ip_adapt_scale: float = 0.3,
957
+ image_wh: int | tuple[int, int] = (1024, 1024),
958
+ rmbg_tag: str = "rembg",
959
+ seed: int = None,
960
+ enable_pre_resize: bool = True,
961
+ n_sample: int = 3,
962
+ req: gr.Request = None,
963
+ ) -> list[str]:
964
+ started = time.monotonic()
965
+ _diag(
966
+ "DISPATCH_ENTER",
967
+ pid=os.getpid(),
968
+ ppid=os.getppid(),
969
+ prompt_length=len(prompt) if prompt is not None else None,
970
+ guidance_scale=guidance_scale,
971
+ infer_step=infer_step,
972
+ has_reference_image=ip_image is not None,
973
+ image_wh=image_wh,
974
+ rmbg_tag=rmbg_tag,
975
+ seed=seed,
976
+ n_sample=n_sample,
977
+ session_hash=getattr(req, "session_hash", None),
978
+ )
979
+ try:
980
+ result = text2image_fn(
981
+ prompt=prompt,
982
+ guidance_scale=guidance_scale,
983
+ infer_step=infer_step,
984
+ ip_image=ip_image,
985
+ ip_adapt_scale=ip_adapt_scale,
986
+ image_wh=image_wh,
987
+ rmbg_tag=rmbg_tag,
988
+ seed=seed,
989
+ enable_pre_resize=enable_pre_resize,
990
+ n_sample=n_sample,
991
+ req=req,
992
+ )
993
+ _diag(
994
+ "DISPATCH_SUCCESS",
995
+ output_count=len(result),
996
+ elapsed_seconds=round(time.monotonic() - started, 3),
997
+ )
998
+ return result
999
+ except Exception as exc:
1000
+ _diag(
1001
+ "DISPATCH_EXCEPTION",
1002
+ exception_type=type(exc).__name__,
1003
+ exception=str(exc)[:2000],
1004
+ elapsed_seconds=round(time.monotonic() - started, 3),
1005
+ )
1006
+ traceback.print_exc()
1007
+ sys.stderr.flush()
1008
+ raise
1009
+ finally:
1010
+ _diag(
1011
+ "DISPATCH_EXIT",
1012
+ elapsed_seconds=round(time.monotonic() - started, 3),
1013
+ )
1014
 
1015
 
1016
  @spaces.GPU