Spaces:
Runtime error
Runtime error
Sync deps: Dockerfile system deps + ffmpeg, single pip flow
Browse files- app.py +7 -2
- scripts/download_sd_model.py +27 -5
- scripts/skybox_generator.py +22 -1
- scripts/text_to_image.py +17 -7
app.py
CHANGED
|
@@ -80,6 +80,11 @@ def main() -> None:
|
|
| 80 |
else:
|
| 81 |
st.caption("TripoSR: not found (mesh tab will show instructions)")
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
tab_mesh, tab_skybox = st.tabs(["π¦ Text β 3D Mesh", "π
Text β Skybox"])
|
| 84 |
|
| 85 |
with tab_mesh:
|
|
@@ -138,7 +143,7 @@ def main() -> None:
|
|
| 138 |
if use_image and (selected_from_outputs and selected_from_outputs.exists() or uploaded):
|
| 139 |
image_path_to_use = str(selected_from_outputs) if (selected_from_outputs and selected_from_outputs.exists()) else "upload"
|
| 140 |
|
| 141 |
-
if st.button("Generate mesh", key="btn_mesh"):
|
| 142 |
if not image_path_to_use and not prompt_mesh.strip():
|
| 143 |
st.warning("Enter a prompt or choose/upload an image.")
|
| 144 |
else:
|
|
@@ -260,7 +265,7 @@ def main() -> None:
|
|
| 260 |
with col2:
|
| 261 |
check_seamless = st.checkbox("Run seamless edge check", value=True, key="seamless")
|
| 262 |
|
| 263 |
-
if st.button("Generate skybox", key="btn_sky"):
|
| 264 |
if not prompt_sky.strip():
|
| 265 |
st.warning("Enter a prompt.")
|
| 266 |
else:
|
|
|
|
| 80 |
else:
|
| 81 |
st.caption("TripoSR: not found (mesh tab will show instructions)")
|
| 82 |
|
| 83 |
+
# In Space, Skybox and textβmesh need Hub access; disable buttons if no token to avoid 403
|
| 84 |
+
can_use_hub = bool(hf_token_env) or not IS_HF_SPACE
|
| 85 |
+
if IS_HF_SPACE and not hf_token_env:
|
| 86 |
+
st.warning("Set **HF_TOKEN** in Settings β Variables and secrets to enable Skybox and textβmesh generation.")
|
| 87 |
+
|
| 88 |
tab_mesh, tab_skybox = st.tabs(["π¦ Text β 3D Mesh", "π
Text β Skybox"])
|
| 89 |
|
| 90 |
with tab_mesh:
|
|
|
|
| 143 |
if use_image and (selected_from_outputs and selected_from_outputs.exists() or uploaded):
|
| 144 |
image_path_to_use = str(selected_from_outputs) if (selected_from_outputs and selected_from_outputs.exists()) else "upload"
|
| 145 |
|
| 146 |
+
if st.button("Generate mesh", key="btn_mesh", disabled=(not can_use_hub and not image_path_to_use)):
|
| 147 |
if not image_path_to_use and not prompt_mesh.strip():
|
| 148 |
st.warning("Enter a prompt or choose/upload an image.")
|
| 149 |
else:
|
|
|
|
| 265 |
with col2:
|
| 266 |
check_seamless = st.checkbox("Run seamless edge check", value=True, key="seamless")
|
| 267 |
|
| 268 |
+
if st.button("Generate skybox", key="btn_sky", disabled=not can_use_hub):
|
| 269 |
if not prompt_sky.strip():
|
| 270 |
st.warning("Enter a prompt.")
|
| 271 |
else:
|
scripts/download_sd_model.py
CHANGED
|
@@ -16,17 +16,39 @@ MODEL_ID = "runwayml/stable-diffusion-v1-5"
|
|
| 16 |
DEFAULT_LOCAL_DIR = ROOT / "weights" / "sd-v1-5"
|
| 17 |
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
def download_sd_model(local_dir: str | Path | None = None, token: str | None = None) -> str:
|
| 20 |
"""Download runwayml/stable-diffusion-v1-5 to local_dir. Returns path on success, raises on failure."""
|
| 21 |
from huggingface_hub import snapshot_download
|
| 22 |
out_dir = Path(local_dir or DEFAULT_LOCAL_DIR)
|
| 23 |
out_dir.mkdir(parents=True, exist_ok=True)
|
| 24 |
tok = token or os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
return str(out_dir.resolve())
|
| 31 |
|
| 32 |
|
|
|
|
| 16 |
DEFAULT_LOCAL_DIR = ROOT / "weights" / "sd-v1-5"
|
| 17 |
|
| 18 |
|
| 19 |
+
def _raise_if_403(err: Exception) -> None:
|
| 20 |
+
"""Re-raise with a clear message if the error is a 403 from the Hub."""
|
| 21 |
+
if getattr(err, "response", None) is not None:
|
| 22 |
+
status = getattr(err.response, "status_code", None)
|
| 23 |
+
if status == 403:
|
| 24 |
+
raise RuntimeError(
|
| 25 |
+
"403 Forbidden from Hugging Face Hub. "
|
| 26 |
+
"Set HF_TOKEN (Settings β Variables and secrets in this Space, or env var locally). "
|
| 27 |
+
"Get a token at huggingface.co/settings/tokens (read access)."
|
| 28 |
+
) from err
|
| 29 |
+
if "403" in str(err).lower() or "forbidden" in str(err).lower():
|
| 30 |
+
raise RuntimeError(
|
| 31 |
+
"403 Forbidden from Hugging Face Hub. "
|
| 32 |
+
"Set HF_TOKEN (Settings β Variables and secrets in this Space, or env var locally). "
|
| 33 |
+
"Get a token at huggingface.co/settings/tokens (read access)."
|
| 34 |
+
) from err
|
| 35 |
+
|
| 36 |
+
|
| 37 |
def download_sd_model(local_dir: str | Path | None = None, token: str | None = None) -> str:
|
| 38 |
"""Download runwayml/stable-diffusion-v1-5 to local_dir. Returns path on success, raises on failure."""
|
| 39 |
from huggingface_hub import snapshot_download
|
| 40 |
out_dir = Path(local_dir or DEFAULT_LOCAL_DIR)
|
| 41 |
out_dir.mkdir(parents=True, exist_ok=True)
|
| 42 |
tok = token or os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
|
| 43 |
+
try:
|
| 44 |
+
snapshot_download(
|
| 45 |
+
repo_id=MODEL_ID,
|
| 46 |
+
local_dir=str(out_dir),
|
| 47 |
+
token=tok,
|
| 48 |
+
)
|
| 49 |
+
except Exception as e:
|
| 50 |
+
_raise_if_403(e)
|
| 51 |
+
raise
|
| 52 |
return str(out_dir.resolve())
|
| 53 |
|
| 54 |
|
scripts/skybox_generator.py
CHANGED
|
@@ -59,6 +59,24 @@ def _get_hf_token():
|
|
| 59 |
return None
|
| 60 |
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
def _resolve_model_path_and_token():
|
| 63 |
"""Use local path if set or default weights/ folder exists, else Hub id. Token from HF_TOKEN or huggingface_hub."""
|
| 64 |
local = os.environ.get("SD_MODEL_PATH", "").strip()
|
|
@@ -96,6 +114,8 @@ def generate_skybox(
|
|
| 96 |
pretrained, token = _resolve_model_path_and_token()
|
| 97 |
load_id = model_id or pretrained
|
| 98 |
local_only = os.path.isdir(load_id)
|
|
|
|
|
|
|
| 99 |
pipe = None
|
| 100 |
last_error = None
|
| 101 |
|
|
@@ -106,12 +126,13 @@ def generate_skybox(
|
|
| 106 |
pid,
|
| 107 |
torch_dtype=dtype,
|
| 108 |
safety_checker=None,
|
| 109 |
-
token=None if local else
|
| 110 |
local_files_only=local,
|
| 111 |
)
|
| 112 |
return True
|
| 113 |
except Exception as err:
|
| 114 |
last_error = err
|
|
|
|
| 115 |
return False
|
| 116 |
|
| 117 |
if _load(load_id, local_only):
|
|
|
|
| 59 |
return None
|
| 60 |
|
| 61 |
|
| 62 |
+
# Message shown when Hub returns 403 (missing/invalid token or gated model).
|
| 63 |
+
HF_403_MESSAGE = (
|
| 64 |
+
"403 Forbidden from Hugging Face Hub. "
|
| 65 |
+
"Add HF_TOKEN in this Space: Settings β Variables and secrets β New secret: HF_TOKEN (get a token at huggingface.co/settings/tokens, read access). "
|
| 66 |
+
"If the model is gated, accept its license on the model page first, then restart the Space."
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _raise_if_403(err: Exception) -> None:
|
| 71 |
+
"""Re-raise with a clear message if the error is a 403 from the Hub."""
|
| 72 |
+
if getattr(err, "response", None) is not None:
|
| 73 |
+
status = getattr(err.response, "status_code", None)
|
| 74 |
+
if status == 403:
|
| 75 |
+
raise RuntimeError(HF_403_MESSAGE) from err
|
| 76 |
+
if "403" in str(err).lower() or "forbidden" in str(err).lower():
|
| 77 |
+
raise RuntimeError(HF_403_MESSAGE) from err
|
| 78 |
+
|
| 79 |
+
|
| 80 |
def _resolve_model_path_and_token():
|
| 81 |
"""Use local path if set or default weights/ folder exists, else Hub id. Token from HF_TOKEN or huggingface_hub."""
|
| 82 |
local = os.environ.get("SD_MODEL_PATH", "").strip()
|
|
|
|
| 114 |
pretrained, token = _resolve_model_path_and_token()
|
| 115 |
load_id = model_id or pretrained
|
| 116 |
local_only = os.path.isdir(load_id)
|
| 117 |
+
# Use explicit token only (no token=True) so we don't rely on get_token() which can be None in Docker/Space
|
| 118 |
+
hub_token = token if token is not True else _get_hf_token()
|
| 119 |
pipe = None
|
| 120 |
last_error = None
|
| 121 |
|
|
|
|
| 126 |
pid,
|
| 127 |
torch_dtype=dtype,
|
| 128 |
safety_checker=None,
|
| 129 |
+
token=None if local else hub_token,
|
| 130 |
local_files_only=local,
|
| 131 |
)
|
| 132 |
return True
|
| 133 |
except Exception as err:
|
| 134 |
last_error = err
|
| 135 |
+
_raise_if_403(err)
|
| 136 |
return False
|
| 137 |
|
| 138 |
if _load(load_id, local_only):
|
scripts/text_to_image.py
CHANGED
|
@@ -9,7 +9,12 @@ from pathlib import Path
|
|
| 9 |
|
| 10 |
import torch
|
| 11 |
|
| 12 |
-
from scripts.skybox_generator import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
|
| 15 |
def get_device() -> str:
|
|
@@ -34,31 +39,36 @@ def text_to_image(
|
|
| 34 |
pretrained, token = _resolve_model_path_and_token()
|
| 35 |
load_id = model_id or pretrained
|
| 36 |
local_only = os.path.isdir(load_id)
|
|
|
|
| 37 |
pipe = None
|
|
|
|
| 38 |
try:
|
| 39 |
pipe = StableDiffusionPipeline.from_pretrained(
|
| 40 |
load_id,
|
| 41 |
torch_dtype=dtype,
|
| 42 |
safety_checker=None,
|
| 43 |
-
token=None if local_only else
|
| 44 |
local_files_only=local_only,
|
| 45 |
)
|
| 46 |
-
except Exception:
|
|
|
|
|
|
|
| 47 |
if not local_only:
|
| 48 |
try:
|
| 49 |
pipe = StableDiffusionPipeline.from_pretrained(
|
| 50 |
FALLBACK_MODEL_ID,
|
| 51 |
torch_dtype=dtype,
|
| 52 |
safety_checker=None,
|
| 53 |
-
token=
|
| 54 |
)
|
| 55 |
-
except Exception:
|
| 56 |
-
|
|
|
|
| 57 |
if pipe is None:
|
| 58 |
raise RuntimeError(
|
| 59 |
"Could not load Stable Diffusion. On Spaces: add HF_TOKEN in Settings β Variables and secrets "
|
| 60 |
"(huggingface.co/settings/tokens). Locally: set HF_TOKEN or download the model first."
|
| 61 |
-
)
|
| 62 |
pipe = pipe.to(device)
|
| 63 |
|
| 64 |
generator = None
|
|
|
|
| 9 |
|
| 10 |
import torch
|
| 11 |
|
| 12 |
+
from scripts.skybox_generator import (
|
| 13 |
+
_get_hf_token,
|
| 14 |
+
_raise_if_403,
|
| 15 |
+
_resolve_model_path_and_token,
|
| 16 |
+
FALLBACK_MODEL_ID,
|
| 17 |
+
)
|
| 18 |
|
| 19 |
|
| 20 |
def get_device() -> str:
|
|
|
|
| 39 |
pretrained, token = _resolve_model_path_and_token()
|
| 40 |
load_id = model_id or pretrained
|
| 41 |
local_only = os.path.isdir(load_id)
|
| 42 |
+
hub_token = token if token is not True else _get_hf_token()
|
| 43 |
pipe = None
|
| 44 |
+
last_error = None
|
| 45 |
try:
|
| 46 |
pipe = StableDiffusionPipeline.from_pretrained(
|
| 47 |
load_id,
|
| 48 |
torch_dtype=dtype,
|
| 49 |
safety_checker=None,
|
| 50 |
+
token=None if local_only else hub_token,
|
| 51 |
local_files_only=local_only,
|
| 52 |
)
|
| 53 |
+
except Exception as err:
|
| 54 |
+
last_error = err
|
| 55 |
+
_raise_if_403(err)
|
| 56 |
if not local_only:
|
| 57 |
try:
|
| 58 |
pipe = StableDiffusionPipeline.from_pretrained(
|
| 59 |
FALLBACK_MODEL_ID,
|
| 60 |
torch_dtype=dtype,
|
| 61 |
safety_checker=None,
|
| 62 |
+
token=hub_token,
|
| 63 |
)
|
| 64 |
+
except Exception as err2:
|
| 65 |
+
last_error = err2
|
| 66 |
+
_raise_if_403(err2)
|
| 67 |
if pipe is None:
|
| 68 |
raise RuntimeError(
|
| 69 |
"Could not load Stable Diffusion. On Spaces: add HF_TOKEN in Settings β Variables and secrets "
|
| 70 |
"(huggingface.co/settings/tokens). Locally: set HF_TOKEN or download the model first."
|
| 71 |
+
) from last_error
|
| 72 |
pipe = pipe.to(device)
|
| 73 |
|
| 74 |
generator = None
|