Nathyboy commited on
Commit
8c037b8
·
verified ·
1 Parent(s): 846e67f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -31
app.py CHANGED
@@ -1,47 +1,162 @@
 
1
  import os
2
  import subprocess
3
- import gradio as gr
 
 
4
  import requests
 
5
 
6
  # -----------------------------
7
- # Runtime downloads
8
  # -----------------------------
9
- downloads = {
10
- "lora": "https://huggingface.co/latent-consistency/lcm-lora-sdv1-5/resolve/main/pytorch_lora_weights.safetensors",
11
- "controlnet_tile": "https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11f1e_sd15_tile.pth",
12
- "temporalnet": "https://huggingface.co/CiaraRowles/TemporalNet/resolve/main/diff_control_sd15_temporalnet_fp16.safetensors",
13
- "civitai_model": "https://civitai.com/api/download/models/143906?type=Model&format=SafeTensor&size=pruned&fp=fp16"
 
 
 
 
 
 
 
 
 
 
 
 
14
  }
15
 
16
- # Ensure persistent folders exist
17
- os.makedirs("stable-diffusion-webui/models/Stable-diffusion", exist_ok=True)
18
- os.makedirs("stable-diffusion-webui/models/Lora", exist_ok=True)
19
- os.makedirs("stable-diffusion-webui/extensions/ControlNet/models", exist_ok=True)
20
-
21
- # Download helper
22
- def download_file(url, dest):
23
- if not os.path.exists(dest):
24
- print(f"Downloading {url} -> {dest}")
25
- response = requests.get(url, stream=True)
26
- with open(dest, "wb") as f:
27
- for chunk in response.iter_content(chunk_size=8192):
28
- f.write(chunk)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  else:
30
- print(f"{dest} already exists, skipping download.")
31
 
32
- # Download models
33
- download_file(downloads["lora"], "stable-diffusion-webui/models/Lora/pytorch_lora_weights.safetensors")
34
- download_file(downloads["controlnet_tile"], "stable-diffusion-webui/extensions/ControlNet/models/control_v11f1e_sd15_tile.pth")
35
- download_file(downloads["temporalnet"], "stable-diffusion-webui/extensions/ControlNet/models/diff_control_sd15_temporalnet_fp16.safetensors")
36
- download_file(downloads["civitai_model"], "stable-diffusion-webui/models/Stable-diffusion/civitai_model.safetensors")
37
 
38
  # -----------------------------
39
- # Install dependencies
40
  # -----------------------------
41
- subprocess.run(["pip", "install", "-r", "requirements.txt"])
 
 
 
 
 
 
 
 
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  # -----------------------------
44
- # Launch WebUI
 
 
 
 
45
  # -----------------------------
46
- os.environ["COMMANDLINE_ARGS"] = "--listen --xformers --enable-insecure-extension-access --medvram"
47
- subprocess.run(["python", "launch.py"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py - HF Space launcher (Option B, HF tree aware)
2
  import os
3
  import subprocess
4
+ import threading
5
+ import shlex
6
+ import time
7
  import requests
8
+ import gradio as gr
9
 
10
  # -----------------------------
11
+ # Configuration (edit if needed)
12
  # -----------------------------
13
+ DOWNLOADS = {
14
+ "lora": {
15
+ "url": "https://huggingface.co/latent-consistency/lcm-lora-sdv1-5/resolve/main/pytorch_lora_weights.safetensors",
16
+ "dest": "stable-diffusion-webui/models/Lora/pytorch_lora_weights.safetensors"
17
+ },
18
+ "controlnet_tile": {
19
+ "url": "https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11f1e_sd15_tile.pth",
20
+ "dest": "stable-diffusion-webui/extensions/ControlNet/models/control_v11f1e_sd15_tile.pth"
21
+ },
22
+ "temporalnet": {
23
+ "url": "https://huggingface.co/CiaraRowles/TemporalNet/resolve/main/diff_control_sd15_temporalnet_fp16.safetensors",
24
+ "dest": "stable-diffusion-webui/extensions/ControlNet/models/diff_control_sd15_temporalnet_fp16.safetensors"
25
+ },
26
+ "civitai_model": {
27
+ "url": "https://civitai.com/api/download/models/143906?type=Model&format=SafeTensor&size=pruned&fp=fp16",
28
+ "dest": "stable-diffusion-webui/models/Stable-diffusion/civitai_model.safetensors"
29
+ }
30
  }
31
 
32
+ WEBUI_ARGS = "--listen --xformers --enable-insecure-extension-access --medvram"
33
+ LAUNCH_PY = "launch.py" # relative to repo root (per HF tree)
34
+
35
+ # -----------------------------
36
+ # Utilities
37
+ # -----------------------------
38
+ def ensure_persistent_folders():
39
+ """Make sure HF tree persistent folders exist (safe no-op if present)."""
40
+ folders = [
41
+ "stable-diffusion-webui/deforum/input",
42
+ "stable-diffusion-webui/deforum/output_committed/frames",
43
+ "stable-diffusion-webui/deforum/output_committed/video",
44
+ "stable-diffusion-webui/models/Stable-diffusion",
45
+ "stable-diffusion-webui/models/Lora",
46
+ "stable-diffusion-webui/extensions/ControlNet/models",
47
+ ]
48
+ for f in folders:
49
+ os.makedirs(f, exist_ok=True)
50
+ print("✅ Persistent folders ensured.")
51
+
52
+
53
+ def download_file_with_retries(url, dest, max_retries=3, backoff=5):
54
+ """Download a file with simple retry/backoff. Skips if dest exists."""
55
+ if os.path.exists(dest):
56
+ print(f"✅ Already exists: {dest}")
57
+ return True
58
+
59
+ os.makedirs(os.path.dirname(dest), exist_ok=True)
60
+ attempt = 1
61
+ while attempt <= max_retries:
62
+ try:
63
+ print(f"⬇️ Download attempt {attempt}: {url} -> {dest}")
64
+ with requests.get(url, stream=True, timeout=60) as r:
65
+ r.raise_for_status()
66
+ with open(dest + ".part", "wb") as f:
67
+ for chunk in r.iter_content(chunk_size=8192):
68
+ if chunk:
69
+ f.write(chunk)
70
+ # atomically move into place
71
+ os.replace(dest + ".part", dest)
72
+ print(f"✅ Downloaded: {dest}")
73
+ return True
74
+ except Exception as e:
75
+ print(f"⚠️ Download failed (attempt {attempt}) for {url}: {e}")
76
+ attempt += 1
77
+ time.sleep(backoff * attempt)
78
+ print(f"❌ Failed to download after {max_retries} attempts: {url}")
79
+ # ensure partial file removed
80
+ try:
81
+ if os.path.exists(dest + ".part"):
82
+ os.remove(dest + ".part")
83
+ except Exception:
84
+ pass
85
+ return False
86
+
87
+
88
+ def fetch_models():
89
+ """Download all configured models into the HF tree persistent paths."""
90
+ print("🔽 Starting runtime model downloads (if missing)...")
91
+ success_all = True
92
+ for name, info in DOWNLOADS.items():
93
+ url = info["url"]
94
+ dest = info["dest"]
95
+ ok = download_file_with_retries(url, dest)
96
+ success_all = success_all and ok
97
+ if success_all:
98
+ print("✅ All runtime downloads done (or already present).")
99
  else:
100
+ print("⚠️ Some runtime downloads failed. Check logs for details.")
101
 
 
 
 
 
 
102
 
103
  # -----------------------------
104
+ # Start WebUI routine (clean)
105
  # -----------------------------
106
+ def start_webui():
107
+ """
108
+ 1) Ensure folders exist
109
+ 2) Fetch runtime models (only if missing)
110
+ 3) Start Automatic1111's launch.py in the same foreground process context
111
+ using a subprocess call built from a proper arg list.
112
+ """
113
+ try:
114
+ ensure_persistent_folders()
115
 
116
+ # Download models (non-blocking safety: we do this before launch so they are present)
117
+ fetch_models()
118
+
119
+ # Build the command safely
120
+ args = ["python", LAUNCH_PY] + shlex.split(WEBUI_ARGS)
121
+ print("▶️ Launching WebUI with:", " ".join(args))
122
+
123
+ # Run launch.py and block this thread until it exits; logs go to HF logs.
124
+ # We run in a separate Python thread (caller keeps main process alive via Gradio).
125
+ subprocess.run(args, check=True)
126
+ print("ℹ️ launch.py exited (subprocess finished). If this happens early, check errors above.")
127
+ except subprocess.CalledProcessError as cpe:
128
+ print(f"❌ launch.py exited with non-zero status: {cpe.returncode}")
129
+ except Exception as e:
130
+ print("❌ Exception in start_webui():", e)
131
+
132
+
133
+ # -----------------------------
134
+ # Kick off WebUI in background thread
135
  # -----------------------------
136
+ threading.Thread(target=start_webui, daemon=True).start()
137
+ print("🧵 WebUI thread started (background).")
138
+
139
+ # -----------------------------
140
+ # Minimal Gradio UI to keep Space alive + quick controls
141
  # -----------------------------
142
+ def show_status():
143
+ msg_lines = [" HF Space running (Option B launcher)."]
144
+ # quick presence checks
145
+ if os.path.exists(LAUNCH_PY):
146
+ msg_lines.append(f"launch.py: found")
147
+ else:
148
+ msg_lines.append(f"launch.py: MISSING at root!")
149
+ # list basic model presence
150
+ for key, info in DOWNLOADS.items():
151
+ present = "yes" if os.path.exists(info["dest"]) else "no"
152
+ msg_lines.append(f"{key}: {present}")
153
+ return "\n".join(msg_lines)
154
+
155
+ with gr.Blocks() as demo:
156
+ gr.Markdown("## Automatic1111 WebUI — HF Space launcher (Option B)")
157
+ gr.Markdown("This Space launches Automatic1111 in a background thread and keeps a small Gradio UI alive so Hugging Face marks the app as initialized.")
158
+ status_btn = gr.Button("Check status")
159
+ status_out = gr.Textbox(lines=10)
160
+ status_btn.click(fn=show_status, inputs=None, outputs=status_out)
161
+
162
+ demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))