Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,62 +1,128 @@
|
|
| 1 |
import os
|
| 2 |
-
import subprocess
|
| 3 |
import shutil
|
|
|
|
| 4 |
import threading
|
| 5 |
import time
|
| 6 |
|
| 7 |
FOOOCUS_REPO = "https://github.com/lllyasviel/Fooocus.git"
|
| 8 |
FOOOCUS_DIR = "Fooocus"
|
| 9 |
|
| 10 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
TMP_OUTPUTS = "/tmp/fooocus_outputs"
|
|
|
|
| 12 |
|
| 13 |
-
# CIVITAI MODEL (Realism by Stable Yogi – Pony)
|
| 14 |
-
# You must be logged in to Civitai to get a direct file URL if required
|
| 15 |
-
MODEL_URL = "PASTE_DIRECT_DOWNLOAD_URL_HERE"
|
| 16 |
-
MODEL_NAME = "realism_by_stable_yogi_pony.safetensors"
|
| 17 |
|
| 18 |
-
def
|
| 19 |
-
print(f"[
|
| 20 |
-
subprocess.run(cmd, shell=True, cwd=cwd, check=
|
| 21 |
|
| 22 |
-
def setup():
|
| 23 |
-
# Clone Fooocus
|
| 24 |
-
if not os.path.exists(FOOOCUS_DIR):
|
| 25 |
-
run(f"git clone {FOOOCUS_REPO}")
|
| 26 |
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
shutil.rmtree(TMP_OUTPUTS, ignore_errors=True)
|
| 29 |
-
|
|
|
|
| 30 |
|
|
|
|
|
|
|
| 31 |
outputs_path = os.path.join(FOOOCUS_DIR, "outputs")
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
shutil.rmtree(outputs_path, ignore_errors=True)
|
|
|
|
| 34 |
os.symlink(TMP_OUTPUTS, outputs_path)
|
|
|
|
| 35 |
|
| 36 |
-
# Install dependencies once
|
| 37 |
-
marker = os.path.join(FOOOCUS_DIR, ".installed")
|
| 38 |
-
if not os.path.exists(marker):
|
| 39 |
-
run("pip install -r requirements_versions.txt", cwd=FOOOCUS_DIR)
|
| 40 |
-
open(marker, "w").close()
|
| 41 |
|
| 42 |
-
|
| 43 |
ckpt_dir = os.path.join(FOOOCUS_DIR, "models", "checkpoints")
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
-
# Download model if missing
|
| 47 |
-
model_path = os.path.join(ckpt_dir, MODEL_NAME)
|
| 48 |
-
if not os.path.exists(model_path):
|
| 49 |
-
run(f"wget -O {model_path} {MODEL_URL}")
|
| 50 |
|
| 51 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
while True:
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
-
def start():
|
| 58 |
-
setup()
|
| 59 |
-
threading.Thread(target=cleaner, daemon=True).start()
|
| 60 |
-
run("python entry_with_update.py --listen 0.0.0.0 --port 7860", cwd=FOOOCUS_DIR)
|
| 61 |
|
| 62 |
-
|
|
|
|
|
|
| 1 |
import os
|
|
|
|
| 2 |
import shutil
|
| 3 |
+
import subprocess
|
| 4 |
import threading
|
| 5 |
import time
|
| 6 |
|
| 7 |
FOOOCUS_REPO = "https://github.com/lllyasviel/Fooocus.git"
|
| 8 |
FOOOCUS_DIR = "Fooocus"
|
| 9 |
|
| 10 |
+
# Your direct download URL to the .safetensors file
|
| 11 |
+
MODEL_URL = "PASTE_YOUR_DIRECT_DOWNLOAD_URL_HERE"
|
| 12 |
+
MODEL_FILENAME = "realism_by_stable_yogi_pony.safetensors"
|
| 13 |
+
|
| 14 |
+
# Save outputs to /tmp so nothing persists
|
| 15 |
TMP_OUTPUTS = "/tmp/fooocus_outputs"
|
| 16 |
+
CLEAN_EVERY_SECONDS = 60
|
| 17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
+
def sh(cmd, cwd=None, check=True):
|
| 20 |
+
print(f"\n[CMD] {cmd}\n", flush=True)
|
| 21 |
+
return subprocess.run(cmd, shell=True, cwd=cwd, check=check)
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
def ensure_dir(path):
|
| 25 |
+
os.makedirs(path, exist_ok=True)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def reset_tmp_outputs():
|
| 29 |
shutil.rmtree(TMP_OUTPUTS, ignore_errors=True)
|
| 30 |
+
ensure_dir(TMP_OUTPUTS)
|
| 31 |
+
|
| 32 |
|
| 33 |
+
def link_outputs_to_tmp():
|
| 34 |
+
# Fooocus writes to Fooocus/outputs — redirect to /tmp
|
| 35 |
outputs_path = os.path.join(FOOOCUS_DIR, "outputs")
|
| 36 |
+
|
| 37 |
+
# remove existing outputs folder/symlink
|
| 38 |
+
if os.path.islink(outputs_path):
|
| 39 |
+
os.unlink(outputs_path)
|
| 40 |
+
elif os.path.exists(outputs_path):
|
| 41 |
shutil.rmtree(outputs_path, ignore_errors=True)
|
| 42 |
+
|
| 43 |
os.symlink(TMP_OUTPUTS, outputs_path)
|
| 44 |
+
print(f"[OK] outputs -> {TMP_OUTPUTS}", flush=True)
|
| 45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
+
def download_checkpoint():
|
| 48 |
ckpt_dir = os.path.join(FOOOCUS_DIR, "models", "checkpoints")
|
| 49 |
+
ensure_dir(ckpt_dir)
|
| 50 |
+
|
| 51 |
+
dst = os.path.join(ckpt_dir, MODEL_FILENAME)
|
| 52 |
+
|
| 53 |
+
if os.path.exists(dst) and os.path.getsize(dst) > 50_000_000:
|
| 54 |
+
print(f"[OK] Model already exists: {dst}", flush=True)
|
| 55 |
+
return
|
| 56 |
+
|
| 57 |
+
# Download (fails loudly if URL is wrong/403)
|
| 58 |
+
print(f"[INFO] Downloading model to: {dst}", flush=True)
|
| 59 |
+
sh(f"wget -O '{dst}' '{MODEL_URL}'", check=True)
|
| 60 |
+
|
| 61 |
+
# Sanity check: make sure it’s not HTML
|
| 62 |
+
size = os.path.getsize(dst)
|
| 63 |
+
print(f"[INFO] Downloaded size: {size} bytes", flush=True)
|
| 64 |
+
if size < 50_000_000:
|
| 65 |
+
print("[WARN] File looks too small for a checkpoint. Likely not a direct .safetensors download link or got blocked (403/HTML).", flush=True)
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
+
def install_fooocus_once():
|
| 69 |
+
marker = os.path.join(FOOOCUS_DIR, ".installed")
|
| 70 |
+
if os.path.exists(marker):
|
| 71 |
+
print("[OK] Fooocus deps already installed.", flush=True)
|
| 72 |
+
return
|
| 73 |
+
|
| 74 |
+
sh("pip install -r requirements_versions.txt", cwd=FOOOCUS_DIR, check=True)
|
| 75 |
+
with open(marker, "w") as f:
|
| 76 |
+
f.write("ok\n")
|
| 77 |
+
print("[OK] Fooocus deps installed.", flush=True)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def cleaner_loop():
|
| 81 |
while True:
|
| 82 |
+
try:
|
| 83 |
+
# wipe outputs every minute
|
| 84 |
+
for name in os.listdir(TMP_OUTPUTS):
|
| 85 |
+
p = os.path.join(TMP_OUTPUTS, name)
|
| 86 |
+
if os.path.isdir(p):
|
| 87 |
+
shutil.rmtree(p, ignore_errors=True)
|
| 88 |
+
else:
|
| 89 |
+
try:
|
| 90 |
+
os.remove(p)
|
| 91 |
+
except FileNotFoundError:
|
| 92 |
+
pass
|
| 93 |
+
print("[CLEAN] Cleared /tmp outputs", flush=True)
|
| 94 |
+
except Exception as e:
|
| 95 |
+
print(f"[CLEAN-WARN] {e}", flush=True)
|
| 96 |
+
time.sleep(CLEAN_EVERY_SECONDS)
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def main():
|
| 100 |
+
print("[BOOT] Starting Space…", flush=True)
|
| 101 |
+
|
| 102 |
+
# Clone Fooocus if missing
|
| 103 |
+
if not os.path.exists(FOOOCUS_DIR):
|
| 104 |
+
sh(f"git clone {FOOOCUS_REPO}", check=True)
|
| 105 |
+
|
| 106 |
+
# outputs -> /tmp (non-persistent)
|
| 107 |
+
reset_tmp_outputs()
|
| 108 |
+
link_outputs_to_tmp()
|
| 109 |
+
|
| 110 |
+
# install once
|
| 111 |
+
install_fooocus_once()
|
| 112 |
+
|
| 113 |
+
# download your model (only works if URL is direct and not blocked)
|
| 114 |
+
if MODEL_URL and "PASTE_" not in MODEL_URL:
|
| 115 |
+
download_checkpoint()
|
| 116 |
+
else:
|
| 117 |
+
print("[INFO] MODEL_URL not set. Skipping model download.", flush=True)
|
| 118 |
+
|
| 119 |
+
# start cleaner
|
| 120 |
+
threading.Thread(target=cleaner_loop, daemon=True).start()
|
| 121 |
+
|
| 122 |
+
# launch Fooocus
|
| 123 |
+
print("[BOOT] Launching Fooocus…", flush=True)
|
| 124 |
+
sh("python entry_with_update.py --listen 0.0.0.0 --port 7860", cwd=FOOOCUS_DIR, check=True)
|
| 125 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
|
| 127 |
+
if __name__ == "__main__":
|
| 128 |
+
main()
|