specimba commited on
Commit
06b550f
Β·
verified Β·
1 Parent(s): 8117149

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -76
app.py CHANGED
@@ -1,7 +1,5 @@
1
  """NEXUS Visual Weaver - Build Small Hackathon command center."""
2
-
3
  from __future__ import annotations
4
-
5
  import os
6
  import sys
7
  import hashlib
@@ -9,7 +7,6 @@ import secrets
9
  from pathlib import Path
10
  from typing import Any
11
  from urllib.parse import urlparse
12
-
13
  import gradio as gr
14
 
15
  ROOT = Path(__file__).resolve().parent
@@ -18,8 +15,8 @@ if str(SRC) not in sys.path:
18
  sys.path.insert(0, str(SRC))
19
 
20
  try:
21
- import spaces # type: ignore # noqa: F401
22
- except Exception: # pragma: no cover - local development does not require Spaces.
23
  spaces = None
24
 
25
  from nexus_visual_weaver.catalog import catalog_summary
@@ -28,12 +25,10 @@ from nexus_visual_weaver.hf_runtime import generate_flux_image
28
  from nexus_visual_weaver.model_relay import WeaverModelRelay
29
  from nexus_visual_weaver.planner import build_command_center_run
30
  from nexus_visual_weaver.provider_runtime import judge_with_minicpm, judge_with_nemotron
31
- from nexus_visual_weaver.render import render_catalog_table, render_command_header, render_dashboard_regions
32
  from nexus_visual_weaver.security import scan_file
33
  from nexus_visual_weaver.styles import APP_CSS
34
 
35
- # Use default theme to avoid Gradio 6.18 Font comparison bug
36
- # Custom theme with any parameter triggers: AttributeError: 'str' object has no attribute 'name'
37
  APP_THEME = gr.themes.Soft()
38
 
39
  DEFAULT_PROMPT = (
@@ -55,7 +50,6 @@ ASPECT_DIMENSIONS = {
55
  "Portrait": (832, 1216),
56
  }
57
 
58
-
59
  def _default_operator_state() -> dict[str, Any]:
60
  return {
61
  "provider_state": "idle",
@@ -64,18 +58,15 @@ def _default_operator_state() -> dict[str, Any]:
64
  "message": "No operator action yet.",
65
  }
66
 
67
-
68
  def _zero_gpu_entrypoint(fn: Any) -> Any:
69
  gpu_decorator = getattr(spaces, "GPU", None) if spaces is not None else None
70
  if gpu_decorator is None:
71
  return fn
72
  return gpu_decorator(duration=300)(fn)
73
 
74
-
75
  def _relay_snapshot(adult_mode: bool = False) -> dict[str, Any]:
76
  return MODEL_RELAY.dashboard_snapshot(public_demo=not adult_mode)
77
 
78
-
79
  def _file_path(uploaded: Any) -> str | None:
80
  if uploaded is None:
81
  return None
@@ -84,7 +75,6 @@ def _file_path(uploaded: Any) -> str | None:
84
  path = getattr(uploaded, "name", None)
85
  return str(path) if path else None
86
 
87
-
88
  def _safe_file_hash(path: str | None) -> tuple[str | None, int | None]:
89
  if not path:
90
  return None, None
@@ -100,7 +90,6 @@ def _safe_file_hash(path: str | None) -> tuple[str | None, int | None]:
100
  return None, None
101
  return sha256.hexdigest(), size
102
 
103
-
104
  def _safe_reference_url_metadata(reference_url: str | None) -> dict[str, Any] | None:
105
  if not reference_url:
106
  return None
@@ -116,30 +105,26 @@ def _safe_reference_url_metadata(reference_url: str | None) -> dict[str, Any] |
116
  "message": "URL stored as metadata only; Space runtime does not crawl or copy shop images.",
117
  }
118
 
119
-
120
  def _reference_metadata(uploaded: Any, reference_url: str | None, scan: dict[str, Any]) -> list[dict[str, Any]]:
121
  records: list[dict[str, Any]] = []
122
  path = _file_path(uploaded)
123
  if path:
124
  file_hash, size = _safe_file_hash(path)
125
- records.append(
126
- {
127
- "source": "upload",
128
- "basename": Path(path).name,
129
- "sha256": file_hash,
130
- "size_bytes": size,
131
- "st3gg_status": scan.get("status"),
132
- "export_gate": scan.get("export_gate"),
133
- "magic": scan.get("magic"),
134
- "extension": scan.get("extension"),
135
- }
136
- )
137
  url_record = _safe_reference_url_metadata(reference_url)
138
  if url_record:
139
  records.append(url_record)
140
  return records
141
 
142
-
143
  def _creator_controls(
144
  reasoning_mode: str,
145
  video_preset: str,
@@ -178,7 +163,6 @@ def _creator_controls(
178
  },
179
  }
180
 
181
-
182
  def _resolve_seed(seed_value: Any) -> int:
183
  try:
184
  if seed_value is None or str(seed_value).strip() == "":
@@ -188,15 +172,12 @@ def _resolve_seed(seed_value: Any) -> int:
188
  return secrets.randbelow(1_000_000_000)
189
  return secrets.randbelow(1_000_000_000) if seed < 0 else seed
190
 
191
-
192
  def _generation_dimensions(aspect: str | None) -> tuple[int, int]:
193
  return ASPECT_DIMENSIONS.get(str(aspect or "Portrait"), ASPECT_DIMENSIONS["Portrait"])
194
 
195
-
196
  def _style_modifier(style_strength: str | None) -> str:
197
  return STYLE_MODIFIERS.get(str(style_strength or "High Fashion"), STYLE_MODIFIERS["High Fashion"])
198
 
199
-
200
  def _prompt_with_controls(prompt: str, controls: dict[str, Any]) -> str:
201
  wardrobe = controls.get("wardrobe", {})
202
  additions = [
@@ -215,13 +196,11 @@ def _prompt_with_controls(prompt: str, controls: dict[str, Any]) -> str:
215
  prompt = f"{prompt}\nWardrobe controls: {suffix}" if suffix else prompt
216
  return f"{prompt}\nStyle direction: {style}"
217
 
218
-
219
  def _generated_output_path(operator_state: dict[str, Any] | None) -> str | None:
220
  generation = (operator_state or {}).get("generation") or {}
221
  output_path = generation.get("output_path")
222
  return str(output_path) if output_path else None
223
 
224
-
225
  def _authoritative_generated_scan(operator_state: dict[str, Any] | None) -> dict[str, Any]:
226
  output_path = _generated_output_path(operator_state)
227
  if output_path:
@@ -229,7 +208,6 @@ def _authoritative_generated_scan(operator_state: dict[str, Any] | None) -> dict
229
  stored_scan = (operator_state or {}).get("generated_scan")
230
  return stored_scan if isinstance(stored_scan, dict) else scan_file(None)
231
 
232
-
233
  def _checkpoint_seed(checkpoint_id: str) -> int:
234
  suffix = "".join(char for char in checkpoint_id[-8:] if char in "0123456789abcdefABCDEF")
235
  if not suffix:
@@ -239,7 +217,6 @@ def _checkpoint_seed(checkpoint_id: str) -> int:
239
  except ValueError:
240
  return 0
241
 
242
-
243
  def _wardrobe_summary(run: Any) -> str:
244
  slots = getattr(getattr(run, "outfit", None), "slots", []) or []
245
  return "; ".join(
@@ -247,10 +224,8 @@ def _wardrobe_summary(run: Any) -> str:
247
  for slot in slots
248
  )
249
 
250
-
251
  SECTIONS = ["Forge", "Wardrobe", "Lore", "Models", "Security", "Runs"]
252
 
253
-
254
  def _button_updates(run: Any | None, operator_state: dict[str, Any] | None) -> tuple[Any, Any, Any]:
255
  state = operator_state or {}
256
  generated = bool(_generated_output_path(state)) and (state.get("generation") or {}).get("status") == "success"
@@ -262,7 +237,6 @@ def _button_updates(run: Any | None, operator_state: dict[str, Any] | None) -> t
262
  gr.update(interactive=False),
263
  )
264
 
265
-
266
  def _dashboard_regions(
267
  run: Any | None = None,
268
  adult_mode: bool = False,
@@ -279,7 +253,6 @@ def _dashboard_regions(
279
  operator_state=operator_state,
280
  )
281
 
282
-
283
  # ─── Modal Integration ───
284
  MODAL_AVAILABLE = False
285
  try:
@@ -288,7 +261,6 @@ try:
288
  except ImportError:
289
  pass
290
 
291
- # LoRA Registry (mirrors modal_nexus_refine_v2.py)
292
  LORA_ADAPTERS = {
293
  "garment": {"repo": "NO8D/BodyControl", "desc": "Body/garment shape control", "weight": 0.75},
294
  "hardware": {"repo": "NO8D/ExpressionControl", "desc": "Expression/hardware detail", "weight": 0.70},
@@ -307,15 +279,12 @@ GPU_OPTIONS = {
307
 
308
  MODAL_COST_TRACKER = {"credits_remaining": 250.88, "total_spent": 0.0, "refinements": 0}
309
 
310
-
311
  def _modal_refine_image(image_bytes: bytes, user_addition: str, gpu_type: str = "A100-80GB",
312
  strength: float = 0.58, steps: int = 32, guidance_scale: float = 3.8,
313
  seed: int = -1, lora_adapters: list | None = None,
314
  negative_prompt: str = "blurry, low quality, deformed, extra limbs") -> tuple:
315
- """Real Modal refinement call β€” wires to nexus-couture-refine-v2 on Modal."""
316
  if not MODAL_AVAILABLE:
317
- return None, "❌ Modal not installed. Add 'modal' to requirements.txt"
318
-
319
  try:
320
  fn = modal.Function.lookup("nexus-couture-refine-v2", "refine_couture")
321
  result_bytes = fn.remote(
@@ -329,28 +298,24 @@ def _modal_refine_image(image_bytes: bytes, user_addition: str, gpu_type: str =
329
  negative_prompt=negative_prompt,
330
  gpu_type=gpu_type,
331
  )
332
- # Update cost tracker
333
  gpu_info = GPU_OPTIONS.get(gpu_type, GPU_OPTIONS["A100-80GB"])
334
  est_cost = round(gpu_info["price"] * (steps / 60), 4)
335
  MODAL_COST_TRACKER["total_spent"] += est_cost
336
  MODAL_COST_TRACKER["credits_remaining"] -= est_cost
337
  MODAL_COST_TRACKER["refinements"] += 1
338
- return result_bytes, f"βœ… Modal refinement complete on {gpu_type} (est. ${est_cost:.4f})"
339
  except Exception as e:
340
  return None, f"❌ Modal error: {str(e)[:200]}"
341
 
342
-
343
  def _modal_health_check() -> dict:
344
- """Check Modal connectivity and GPU availability."""
345
  if not MODAL_AVAILABLE:
346
- return {"status": "unavailable", "message": "Modal package not installed"}
347
  try:
348
  fn = modal.Function.lookup("nexus-couture-refine-v2", "check_modal_health")
349
  return fn.remote()
350
  except Exception as e:
351
  return {"status": "error", "message": str(e)[:200]}
352
 
353
-
354
  @_zero_gpu_entrypoint
355
  def run_weave(
356
  prompt, reasoning_mode, video_preset, adult_mode, upload, active_section,
@@ -390,6 +355,7 @@ def run_weave(
390
  provider_state = generation.provider_state
391
  else:
392
  provider_state = "checkpointed"
 
393
  operator_state = {
394
  "provider_state": provider_state,
395
  "checkpoint": "pending_review",
@@ -417,7 +383,6 @@ def run_weave(
417
  *_button_updates(run, operator_state),
418
  )
419
 
420
-
421
  def toggle_adult_visibility(adult_mode, active_section, upload):
422
  scan = scan_file(_file_path(upload))
423
  operator_state = {
@@ -431,7 +396,6 @@ def toggle_adult_visibility(adult_mode, active_section, upload):
431
  render_catalog_table(adult_mode=adult_mode), catalog_summary(adult_mode), scan, operator_state,
432
  )
433
 
434
-
435
  def refresh_section(active_section, adult_mode, run, scan, operator_state):
436
  scan = scan or scan_file(None)
437
  regions = _dashboard_regions(
@@ -440,7 +404,6 @@ def refresh_section(active_section, adult_mode, run, scan, operator_state):
440
  )
441
  return regions["command_rail"], regions["operations"], regions["inspector"], regions["artifacts"], regions["providers"], scan
442
 
443
-
444
  def _render_stateful(run, adult_mode, scan, active_section, operator_state):
445
  scan = scan or scan_file(None)
446
  regions = _dashboard_regions(
@@ -457,7 +420,6 @@ def _render_stateful(run, adult_mode, scan, active_section, operator_state):
457
  *_button_updates(run, operator_state),
458
  )
459
 
460
-
461
  def scan_reference(run, adult_mode, upload, active_section, operator_state, reference_url=None):
462
  state = operator_state or _default_operator_state()
463
  reference_path = _file_path(upload)
@@ -486,7 +448,6 @@ def scan_reference(run, adult_mode, upload, active_section, operator_state, refe
486
  rendered = _render_stateful(run, adult_mode, generated_scan, active_section, next_state)
487
  return (*rendered, generated_scan)
488
 
489
-
490
  def approve_checkpoint(run, adult_mode, scan, active_section, operator_state):
491
  state = operator_state or _default_operator_state()
492
  scan = _authoritative_generated_scan(state)
@@ -508,7 +469,6 @@ def approve_checkpoint(run, adult_mode, scan, active_section, operator_state):
508
  }
509
  return _render_stateful(run, adult_mode, scan, active_section, next_state)
510
 
511
-
512
  def export_packet(run, adult_mode, scan, active_section, operator_state, override_reason=None):
513
  state = operator_state or _default_operator_state()
514
  scan = _authoritative_generated_scan(state)
@@ -533,7 +493,6 @@ def export_packet(run, adult_mode, scan, active_section, operator_state, overrid
533
  }
534
  return _render_stateful(run, adult_mode, scan, active_section, next_state)
535
 
536
-
537
  def stop_provider_job(run, adult_mode, scan, active_section, operator_state):
538
  scan = scan or scan_file(None)
539
  next_state = {
@@ -543,7 +502,6 @@ def stop_provider_job(run, adult_mode, scan, active_section, operator_state):
543
  }
544
  return _render_stateful(run, adult_mode, scan, active_section, next_state)
545
 
546
-
547
  def reset_demo(adult_mode, active_section):
548
  scan = scan_file(None)
549
  operator_state = _default_operator_state()
@@ -557,11 +515,8 @@ def reset_demo(adult_mode, active_section):
557
  gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False),
558
  )
559
 
560
-
561
  # ─── Modal Tab Handlers ───
562
-
563
  def modal_refine_handler(input_image, user_addition, gpu_type, strength, steps, guidance, seed, lora_choices, negative_prompt):
564
- """Handle Modal refinement from the Space UI."""
565
  if input_image is None:
566
  return None, "❌ No input image provided"
567
  from PIL import Image as PILImage
@@ -573,7 +528,6 @@ def modal_refine_handler(input_image, user_addition, gpu_type, strength, steps,
573
  img = PILImage.open(input_image)
574
  img.save(buf, format="PNG")
575
  image_bytes = buf.getvalue()
576
-
577
  result_bytes, message = _modal_refine_image(
578
  image_bytes=image_bytes, user_addition=user_addition,
579
  gpu_type=gpu_type, strength=strength, steps=int(steps),
@@ -587,18 +541,15 @@ def modal_refine_handler(input_image, user_addition, gpu_type, strength, steps,
587
  return result_img, f"{message}\n{cost_info}"
588
  return None, message
589
 
590
-
591
  def modal_health_handler():
592
- """Check Modal connectivity."""
593
  result = _modal_health_check()
594
  if result.get("status") == "healthy":
595
- return f"βœ… Modal connected\nGPU: {result.get('gpu', 'N/A')}\nVRAM: {result.get('gpu_memory_gb', 0)}GB\nLoRAs: {', '.join(result.get('lora_registry', []))}"
596
  elif result.get("status") == "unavailable":
597
  return f"⚠️ {result.get('message', 'Modal not available')}"
598
  else:
599
  return f"❌ Modal error: {result.get('message', 'Unknown')}"
600
 
601
-
602
  initial_operator_state = _default_operator_state()
603
  initial_regions = _dashboard_regions(scan=scan_file(None), operator_state=initial_operator_state)
604
 
@@ -609,7 +560,7 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
609
  topbar_html = gr.HTML(initial_regions["topbar"], container=False, visible=False)
610
 
611
  with gr.Tabs():
612
- # ═══ Tab 1: Studio (existing creator workbench) ═══
613
  with gr.Tab("🧡 Studio"):
614
  with gr.Row(elem_id="nw-creator-workbench", elem_classes=["nw-creator-workbench"]):
615
  with gr.Column(scale=5, min_width=520, elem_id="nw-creator-panel"):
@@ -644,7 +595,6 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
644
  with gr.Row():
645
  scan_btn = gr.Button("Scan Uploaded File", scale=1)
646
  stop_btn = gr.Button("Stop Job", variant="stop", interactive=False, scale=1)
647
-
648
  with gr.Column(scale=4, min_width=460, elem_id="nw-output-panel"):
649
  gr.Markdown("### Output")
650
  artifact_html = gr.HTML(initial_regions["artifacts"], container=False)
@@ -658,7 +608,7 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
658
  )
659
  gr.Markdown("Generation is not export. Every artifact stays behind ST3GG review and human checkpoint.")
660
 
661
- # ═══ Tab 2: Modal Refinement ═══
662
  with gr.Tab("⚑ Modal"):
663
  gr.Markdown("## ⚑ Modal GPU Refinement")
664
  gr.Markdown("Send a generated image to Modal for FLUX.1-Kontext-dev refinement with multi-LoRA on dedicated GPU.")
@@ -694,7 +644,7 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
694
  )
695
  modal_health_btn.click(fn=modal_health_handler, inputs=[], outputs=[modal_status])
696
 
697
- # ═══ Tab 3: LoRA Lab ═══
698
  with gr.Tab("πŸ§ͺ LoRA Lab"):
699
  gr.Markdown("## πŸ§ͺ LoRA Training Lab")
700
  gr.Markdown("Train custom LoRA adapters on Modal GPU. Connect a dataset repo and configure training parameters.")
@@ -719,7 +669,6 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
719
  for k, v in LORA_ADAPTERS.items()
720
  )
721
  gr.Markdown(lora_catalog_md)
722
-
723
  def lora_train_handler(dataset_repo, output_name, rank, lr, steps, batch, push, hub_repo):
724
  if not MODAL_AVAILABLE:
725
  return "❌ Modal not installed"
@@ -733,7 +682,6 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
733
  return f"βœ… Training triggered on Modal!\nDataset: {dataset_repo}\nOutput: {output_name}\nRank: {rank}, Steps: {steps}, LR: {lr}"
734
  except Exception as e:
735
  return f"❌ Training error: {str(e)[:300]}"
736
-
737
  lora_train_btn.click(
738
  fn=lora_train_handler,
739
  inputs=[lora_dataset_repo, lora_output_name, lora_rank, lora_lr,
@@ -781,6 +729,7 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
781
  outputs=stateful_outputs, api_name="run_active_weave",
782
  concurrency_limit=1, concurrency_id="flux-gpu",
783
  )
 
784
  run_submit = prompt.submit(
785
  fn=run_weave,
786
  inputs=[prompt, reasoning_mode, video_preset, adult_mode, upload, section_nav,
@@ -789,6 +738,7 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
789
  outputs=stateful_outputs, api_name=False,
790
  concurrency_limit=1, concurrency_id="flux-gpu",
791
  )
 
792
  adult_mode.change(
793
  fn=toggle_adult_visibility,
794
  inputs=[adult_mode, section_nav, upload],
@@ -796,47 +746,53 @@ with gr.Blocks(title="NEXUS Visual Weaver") as demo:
796
  artifact_html, provider_html, catalog_html, catalog_json, scan_json, operator_state],
797
  api_name="toggle_adult_catalog", queue=False,
798
  )
 
799
  section_nav.change(
800
  fn=refresh_section,
801
  inputs=[section_nav, adult_mode, active_run_state, scan_state, operator_state],
802
  outputs=[command_rail_html, operations_html, inspector_html, artifact_html, provider_html, scan_json],
803
  api_name=False, queue=False,
804
  )
 
805
  scan_btn.click(
806
  fn=scan_reference,
807
  inputs=[active_run_state, adult_mode, upload, section_nav, operator_state, reference_url],
808
  outputs=dashboard_outputs + [operator_state, checkpoint_btn, export_btn, stop_btn, scan_state],
809
  api_name="scan_reference", queue=False,
810
  )
 
811
  checkpoint_btn.click(
812
  fn=approve_checkpoint,
813
  inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state],
814
  outputs=operator_outputs, api_name="approve_checkpoint", queue=False,
815
  )
 
816
  export_btn.click(
817
  fn=export_packet,
818
  inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state, override_reason],
819
  outputs=operator_outputs, api_name="prepare_export_packet", queue=False,
820
  )
 
821
  stop_btn.click(
822
  fn=stop_provider_job,
823
  inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state],
824
  outputs=operator_outputs, api_name="stop_provider_job", queue=False,
825
  cancels=[run_click, run_submit],
826
  )
 
827
  reset_btn.click(
828
  fn=reset_demo,
829
  inputs=[adult_mode, section_nav],
830
  outputs=stateful_outputs, api_name="reset_demo_state", queue=False,
831
  cancels=[run_click, run_submit],
832
  )
 
833
  demo.load(
834
  fn=lambda: (render_catalog_table(False), catalog_summary(False), scan_file(None), scan_file(None), _default_operator_state()),
835
  outputs=[catalog_html, catalog_json, scan_json, scan_state, operator_state],
836
  api_name=False,
837
  )
838
 
839
-
840
  if __name__ == "__main__":
841
  if hasattr(sys.stdout, "reconfigure"):
842
  sys.stdout.reconfigure(encoding="utf-8", errors="replace")
@@ -845,6 +801,8 @@ if __name__ == "__main__":
845
  demo.launch(
846
  server_name="0.0.0.0",
847
  server_port=int(os.environ.get("NEXUS_PORT", os.environ.get("PORT", "7860"))),
848
- quiet=True, mcp_server=True, ssr_mode=False,
 
 
849
  css=APP_CSS,
850
- )
 
1
  """NEXUS Visual Weaver - Build Small Hackathon command center."""
 
2
  from __future__ import annotations
 
3
  import os
4
  import sys
5
  import hashlib
 
7
  from pathlib import Path
8
  from typing import Any
9
  from urllib.parse import urlparse
 
10
  import gradio as gr
11
 
12
  ROOT = Path(__file__).resolve().parent
 
15
  sys.path.insert(0, str(SRC))
16
 
17
  try:
18
+ import spaces
19
+ except Exception:
20
  spaces = None
21
 
22
  from nexus_visual_weaver.catalog import catalog_summary
 
25
  from nexus_visual_weaver.model_relay import WeaverModelRelay
26
  from nexus_visual_weaver.planner import build_command_center_run
27
  from nexus_visual_weaver.provider_runtime import judge_with_minicpm, judge_with_nemotron
28
+ from nexus_visual_weaver.render import render_catalog_table, render_dashboard_regions
29
  from nexus_visual_weaver.security import scan_file
30
  from nexus_visual_weaver.styles import APP_CSS
31
 
 
 
32
  APP_THEME = gr.themes.Soft()
33
 
34
  DEFAULT_PROMPT = (
 
50
  "Portrait": (832, 1216),
51
  }
52
 
 
53
  def _default_operator_state() -> dict[str, Any]:
54
  return {
55
  "provider_state": "idle",
 
58
  "message": "No operator action yet.",
59
  }
60
 
 
61
  def _zero_gpu_entrypoint(fn: Any) -> Any:
62
  gpu_decorator = getattr(spaces, "GPU", None) if spaces is not None else None
63
  if gpu_decorator is None:
64
  return fn
65
  return gpu_decorator(duration=300)(fn)
66
 
 
67
  def _relay_snapshot(adult_mode: bool = False) -> dict[str, Any]:
68
  return MODEL_RELAY.dashboard_snapshot(public_demo=not adult_mode)
69
 
 
70
  def _file_path(uploaded: Any) -> str | None:
71
  if uploaded is None:
72
  return None
 
75
  path = getattr(uploaded, "name", None)
76
  return str(path) if path else None
77
 
 
78
  def _safe_file_hash(path: str | None) -> tuple[str | None, int | None]:
79
  if not path:
80
  return None, None
 
90
  return None, None
91
  return sha256.hexdigest(), size
92
 
 
93
  def _safe_reference_url_metadata(reference_url: str | None) -> dict[str, Any] | None:
94
  if not reference_url:
95
  return None
 
105
  "message": "URL stored as metadata only; Space runtime does not crawl or copy shop images.",
106
  }
107
 
 
108
  def _reference_metadata(uploaded: Any, reference_url: str | None, scan: dict[str, Any]) -> list[dict[str, Any]]:
109
  records: list[dict[str, Any]] = []
110
  path = _file_path(uploaded)
111
  if path:
112
  file_hash, size = _safe_file_hash(path)
113
+ records.append({
114
+ "source": "upload",
115
+ "basename": Path(path).name,
116
+ "sha256": file_hash,
117
+ "size_bytes": size,
118
+ "st3gg_status": scan.get("status"),
119
+ "export_gate": scan.get("export_gate"),
120
+ "magic": scan.get("magic"),
121
+ "extension": scan.get("extension"),
122
+ })
 
 
123
  url_record = _safe_reference_url_metadata(reference_url)
124
  if url_record:
125
  records.append(url_record)
126
  return records
127
 
 
128
  def _creator_controls(
129
  reasoning_mode: str,
130
  video_preset: str,
 
163
  },
164
  }
165
 
 
166
  def _resolve_seed(seed_value: Any) -> int:
167
  try:
168
  if seed_value is None or str(seed_value).strip() == "":
 
172
  return secrets.randbelow(1_000_000_000)
173
  return secrets.randbelow(1_000_000_000) if seed < 0 else seed
174
 
 
175
  def _generation_dimensions(aspect: str | None) -> tuple[int, int]:
176
  return ASPECT_DIMENSIONS.get(str(aspect or "Portrait"), ASPECT_DIMENSIONS["Portrait"])
177
 
 
178
  def _style_modifier(style_strength: str | None) -> str:
179
  return STYLE_MODIFIERS.get(str(style_strength or "High Fashion"), STYLE_MODIFIERS["High Fashion"])
180
 
 
181
  def _prompt_with_controls(prompt: str, controls: dict[str, Any]) -> str:
182
  wardrobe = controls.get("wardrobe", {})
183
  additions = [
 
196
  prompt = f"{prompt}\nWardrobe controls: {suffix}" if suffix else prompt
197
  return f"{prompt}\nStyle direction: {style}"
198
 
 
199
  def _generated_output_path(operator_state: dict[str, Any] | None) -> str | None:
200
  generation = (operator_state or {}).get("generation") or {}
201
  output_path = generation.get("output_path")
202
  return str(output_path) if output_path else None
203
 
 
204
  def _authoritative_generated_scan(operator_state: dict[str, Any] | None) -> dict[str, Any]:
205
  output_path = _generated_output_path(operator_state)
206
  if output_path:
 
208
  stored_scan = (operator_state or {}).get("generated_scan")
209
  return stored_scan if isinstance(stored_scan, dict) else scan_file(None)
210
 
 
211
  def _checkpoint_seed(checkpoint_id: str) -> int:
212
  suffix = "".join(char for char in checkpoint_id[-8:] if char in "0123456789abcdefABCDEF")
213
  if not suffix:
 
217
  except ValueError:
218
  return 0
219
 
 
220
  def _wardrobe_summary(run: Any) -> str:
221
  slots = getattr(getattr(run, "outfit", None), "slots", []) or []
222
  return "; ".join(
 
224
  for slot in slots
225
  )
226
 
 
227
  SECTIONS = ["Forge", "Wardrobe", "Lore", "Models", "Security", "Runs"]
228
 
 
229
  def _button_updates(run: Any | None, operator_state: dict[str, Any] | None) -> tuple[Any, Any, Any]:
230
  state = operator_state or {}
231
  generated = bool(_generated_output_path(state)) and (state.get("generation") or {}).get("status") == "success"
 
237
  gr.update(interactive=False),
238
  )
239
 
 
240
  def _dashboard_regions(
241
  run: Any | None = None,
242
  adult_mode: bool = False,
 
253
  operator_state=operator_state,
254
  )
255
 
 
256
  # ─── Modal Integration ───
257
  MODAL_AVAILABLE = False
258
  try:
 
261
  except ImportError:
262
  pass
263
 
 
264
  LORA_ADAPTERS = {
265
  "garment": {"repo": "NO8D/BodyControl", "desc": "Body/garment shape control", "weight": 0.75},
266
  "hardware": {"repo": "NO8D/ExpressionControl", "desc": "Expression/hardware detail", "weight": 0.70},
 
279
 
280
  MODAL_COST_TRACKER = {"credits_remaining": 250.88, "total_spent": 0.0, "refinements": 0}
281
 
 
282
  def _modal_refine_image(image_bytes: bytes, user_addition: str, gpu_type: str = "A100-80GB",
283
  strength: float = 0.58, steps: int = 32, guidance_scale: float = 3.8,
284
  seed: int = -1, lora_adapters: list | None = None,
285
  negative_prompt: str = "blurry, low quality, deformed, extra limbs") -> tuple:
 
286
  if not MODAL_AVAILABLE:
287
+ return None, "❌ Modal not installed"
 
288
  try:
289
  fn = modal.Function.lookup("nexus-couture-refine-v2", "refine_couture")
290
  result_bytes = fn.remote(
 
298
  negative_prompt=negative_prompt,
299
  gpu_type=gpu_type,
300
  )
 
301
  gpu_info = GPU_OPTIONS.get(gpu_type, GPU_OPTIONS["A100-80GB"])
302
  est_cost = round(gpu_info["price"] * (steps / 60), 4)
303
  MODAL_COST_TRACKER["total_spent"] += est_cost
304
  MODAL_COST_TRACKER["credits_remaining"] -= est_cost
305
  MODAL_COST_TRACKER["refinements"] += 1
306
+ return result_bytes, f"βœ… Modal refinement complete on {gpu_type}"
307
  except Exception as e:
308
  return None, f"❌ Modal error: {str(e)[:200]}"
309
 
 
310
  def _modal_health_check() -> dict:
 
311
  if not MODAL_AVAILABLE:
312
+ return {"status": "unavailable", "message": "Modal not installed"}
313
  try:
314
  fn = modal.Function.lookup("nexus-couture-refine-v2", "check_modal_health")
315
  return fn.remote()
316
  except Exception as e:
317
  return {"status": "error", "message": str(e)[:200]}
318
 
 
319
  @_zero_gpu_entrypoint
320
  def run_weave(
321
  prompt, reasoning_mode, video_preset, adult_mode, upload, active_section,
 
355
  provider_state = generation.provider_state
356
  else:
357
  provider_state = "checkpointed"
358
+
359
  operator_state = {
360
  "provider_state": provider_state,
361
  "checkpoint": "pending_review",
 
383
  *_button_updates(run, operator_state),
384
  )
385
 
 
386
  def toggle_adult_visibility(adult_mode, active_section, upload):
387
  scan = scan_file(_file_path(upload))
388
  operator_state = {
 
396
  render_catalog_table(adult_mode=adult_mode), catalog_summary(adult_mode), scan, operator_state,
397
  )
398
 
 
399
  def refresh_section(active_section, adult_mode, run, scan, operator_state):
400
  scan = scan or scan_file(None)
401
  regions = _dashboard_regions(
 
404
  )
405
  return regions["command_rail"], regions["operations"], regions["inspector"], regions["artifacts"], regions["providers"], scan
406
 
 
407
  def _render_stateful(run, adult_mode, scan, active_section, operator_state):
408
  scan = scan or scan_file(None)
409
  regions = _dashboard_regions(
 
420
  *_button_updates(run, operator_state),
421
  )
422
 
 
423
  def scan_reference(run, adult_mode, upload, active_section, operator_state, reference_url=None):
424
  state = operator_state or _default_operator_state()
425
  reference_path = _file_path(upload)
 
448
  rendered = _render_stateful(run, adult_mode, generated_scan, active_section, next_state)
449
  return (*rendered, generated_scan)
450
 
 
451
  def approve_checkpoint(run, adult_mode, scan, active_section, operator_state):
452
  state = operator_state or _default_operator_state()
453
  scan = _authoritative_generated_scan(state)
 
469
  }
470
  return _render_stateful(run, adult_mode, scan, active_section, next_state)
471
 
 
472
  def export_packet(run, adult_mode, scan, active_section, operator_state, override_reason=None):
473
  state = operator_state or _default_operator_state()
474
  scan = _authoritative_generated_scan(state)
 
493
  }
494
  return _render_stateful(run, adult_mode, scan, active_section, next_state)
495
 
 
496
  def stop_provider_job(run, adult_mode, scan, active_section, operator_state):
497
  scan = scan or scan_file(None)
498
  next_state = {
 
502
  }
503
  return _render_stateful(run, adult_mode, scan, active_section, next_state)
504
 
 
505
  def reset_demo(adult_mode, active_section):
506
  scan = scan_file(None)
507
  operator_state = _default_operator_state()
 
515
  gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False),
516
  )
517
 
 
518
  # ─── Modal Tab Handlers ───
 
519
  def modal_refine_handler(input_image, user_addition, gpu_type, strength, steps, guidance, seed, lora_choices, negative_prompt):
 
520
  if input_image is None:
521
  return None, "❌ No input image provided"
522
  from PIL import Image as PILImage
 
528
  img = PILImage.open(input_image)
529
  img.save(buf, format="PNG")
530
  image_bytes = buf.getvalue()
 
531
  result_bytes, message = _modal_refine_image(
532
  image_bytes=image_bytes, user_addition=user_addition,
533
  gpu_type=gpu_type, strength=strength, steps=int(steps),
 
541
  return result_img, f"{message}\n{cost_info}"
542
  return None, message
543
 
 
544
  def modal_health_handler():
 
545
  result = _modal_health_check()
546
  if result.get("status") == "healthy":
547
+ return f"βœ… Modal connected\nGPU: {result.get('gpu', 'N/A')}"
548
  elif result.get("status") == "unavailable":
549
  return f"⚠️ {result.get('message', 'Modal not available')}"
550
  else:
551
  return f"❌ Modal error: {result.get('message', 'Unknown')}"
552
 
 
553
  initial_operator_state = _default_operator_state()
554
  initial_regions = _dashboard_regions(scan=scan_file(None), operator_state=initial_operator_state)
555
 
 
560
  topbar_html = gr.HTML(initial_regions["topbar"], container=False, visible=False)
561
 
562
  with gr.Tabs():
563
+ # ═══ Tab 1: Studio ═══
564
  with gr.Tab("🧡 Studio"):
565
  with gr.Row(elem_id="nw-creator-workbench", elem_classes=["nw-creator-workbench"]):
566
  with gr.Column(scale=5, min_width=520, elem_id="nw-creator-panel"):
 
595
  with gr.Row():
596
  scan_btn = gr.Button("Scan Uploaded File", scale=1)
597
  stop_btn = gr.Button("Stop Job", variant="stop", interactive=False, scale=1)
 
598
  with gr.Column(scale=4, min_width=460, elem_id="nw-output-panel"):
599
  gr.Markdown("### Output")
600
  artifact_html = gr.HTML(initial_regions["artifacts"], container=False)
 
608
  )
609
  gr.Markdown("Generation is not export. Every artifact stays behind ST3GG review and human checkpoint.")
610
 
611
+ # ═══ Tab 2: Modal Refinement (ACTIVE) ═══
612
  with gr.Tab("⚑ Modal"):
613
  gr.Markdown("## ⚑ Modal GPU Refinement")
614
  gr.Markdown("Send a generated image to Modal for FLUX.1-Kontext-dev refinement with multi-LoRA on dedicated GPU.")
 
644
  )
645
  modal_health_btn.click(fn=modal_health_handler, inputs=[], outputs=[modal_status])
646
 
647
+ # ═══ Tab 3: LoRA Lab (ACTIVE) ═══
648
  with gr.Tab("πŸ§ͺ LoRA Lab"):
649
  gr.Markdown("## πŸ§ͺ LoRA Training Lab")
650
  gr.Markdown("Train custom LoRA adapters on Modal GPU. Connect a dataset repo and configure training parameters.")
 
669
  for k, v in LORA_ADAPTERS.items()
670
  )
671
  gr.Markdown(lora_catalog_md)
 
672
  def lora_train_handler(dataset_repo, output_name, rank, lr, steps, batch, push, hub_repo):
673
  if not MODAL_AVAILABLE:
674
  return "❌ Modal not installed"
 
682
  return f"βœ… Training triggered on Modal!\nDataset: {dataset_repo}\nOutput: {output_name}\nRank: {rank}, Steps: {steps}, LR: {lr}"
683
  except Exception as e:
684
  return f"❌ Training error: {str(e)[:300]}"
 
685
  lora_train_btn.click(
686
  fn=lora_train_handler,
687
  inputs=[lora_dataset_repo, lora_output_name, lora_rank, lora_lr,
 
729
  outputs=stateful_outputs, api_name="run_active_weave",
730
  concurrency_limit=1, concurrency_id="flux-gpu",
731
  )
732
+
733
  run_submit = prompt.submit(
734
  fn=run_weave,
735
  inputs=[prompt, reasoning_mode, video_preset, adult_mode, upload, section_nav,
 
738
  outputs=stateful_outputs, api_name=False,
739
  concurrency_limit=1, concurrency_id="flux-gpu",
740
  )
741
+
742
  adult_mode.change(
743
  fn=toggle_adult_visibility,
744
  inputs=[adult_mode, section_nav, upload],
 
746
  artifact_html, provider_html, catalog_html, catalog_json, scan_json, operator_state],
747
  api_name="toggle_adult_catalog", queue=False,
748
  )
749
+
750
  section_nav.change(
751
  fn=refresh_section,
752
  inputs=[section_nav, adult_mode, active_run_state, scan_state, operator_state],
753
  outputs=[command_rail_html, operations_html, inspector_html, artifact_html, provider_html, scan_json],
754
  api_name=False, queue=False,
755
  )
756
+
757
  scan_btn.click(
758
  fn=scan_reference,
759
  inputs=[active_run_state, adult_mode, upload, section_nav, operator_state, reference_url],
760
  outputs=dashboard_outputs + [operator_state, checkpoint_btn, export_btn, stop_btn, scan_state],
761
  api_name="scan_reference", queue=False,
762
  )
763
+
764
  checkpoint_btn.click(
765
  fn=approve_checkpoint,
766
  inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state],
767
  outputs=operator_outputs, api_name="approve_checkpoint", queue=False,
768
  )
769
+
770
  export_btn.click(
771
  fn=export_packet,
772
  inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state, override_reason],
773
  outputs=operator_outputs, api_name="prepare_export_packet", queue=False,
774
  )
775
+
776
  stop_btn.click(
777
  fn=stop_provider_job,
778
  inputs=[active_run_state, adult_mode, scan_state, section_nav, operator_state],
779
  outputs=operator_outputs, api_name="stop_provider_job", queue=False,
780
  cancels=[run_click, run_submit],
781
  )
782
+
783
  reset_btn.click(
784
  fn=reset_demo,
785
  inputs=[adult_mode, section_nav],
786
  outputs=stateful_outputs, api_name="reset_demo_state", queue=False,
787
  cancels=[run_click, run_submit],
788
  )
789
+
790
  demo.load(
791
  fn=lambda: (render_catalog_table(False), catalog_summary(False), scan_file(None), scan_file(None), _default_operator_state()),
792
  outputs=[catalog_html, catalog_json, scan_json, scan_state, operator_state],
793
  api_name=False,
794
  )
795
 
 
796
  if __name__ == "__main__":
797
  if hasattr(sys.stdout, "reconfigure"):
798
  sys.stdout.reconfigure(encoding="utf-8", errors="replace")
 
801
  demo.launch(
802
  server_name="0.0.0.0",
803
  server_port=int(os.environ.get("NEXUS_PORT", os.environ.get("PORT", "7860"))),
804
+ quiet=True,
805
+ mcp_server=True,
806
+ ssr_mode=False,
807
  css=APP_CSS,
808
+ )