multimodalart HF Staff commited on
Commit
24f5025
·
1 Parent(s): fc219b8

[Admin maintenance] Support new ZeroGPU hardware (#20)

Browse files

- [Admin maintenance] Support new ZeroGPU hardware (93d601f7ad6176bd32925886e0257f8c889db3dc)

README.md CHANGED
@@ -5,7 +5,7 @@ colorFrom: red
5
  colorTo: purple
6
  sdk: gradio
7
  python_version: 3.10.8
8
- sdk_version: 4.12.0
9
  app_file: app.py
10
  pinned: true
11
  short_description: Create a 1M faces 3D colored model from an image!
 
5
  colorTo: purple
6
  sdk: gradio
7
  python_version: 3.10.8
8
+ sdk_version: 5.49.1
9
  app_file: app.py
10
  pinned: true
11
  short_description: Create a 1M faces 3D colored model from an image!
app.py CHANGED
@@ -1,24 +1,210 @@
1
- import shlex
 
2
  import subprocess
3
- subprocess.run(
4
- shlex.split(
5
- "pip install package/onnxruntime_gpu-1.17.0-cp310-cp310-manylinux_2_28_x86_64.whl --force-reinstall --no-deps"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  )
7
- )
8
- subprocess.run(
9
- shlex.split(
10
- "pip install package/nvdiffrast-0.3.1.torch-cp310-cp310-linux_x86_64.whl --force-reinstall --no-deps"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  )
12
- )
 
 
 
 
 
 
 
 
 
 
13
 
14
  if __name__ == "__main__":
15
- import os
16
  from huggingface_hub import login
17
  hf_token = os.environ.get("HF_TOKEN")
18
- login(token=hf_token)
19
-
20
- import os
21
- import sys
22
  sys.path.append(os.curdir)
23
  import torch
24
  torch.set_float32_matmul_precision('medium')
@@ -51,7 +237,7 @@ _DESCRIPTION = '''
51
 
52
  def launch():
53
  model_zoo.init_models()
54
-
55
  with gr.Blocks(
56
  title=_TITLE,
57
  # theme=gr.themes.Monochrome(),
@@ -63,6 +249,6 @@ def launch():
63
  create_3d_ui("wkl")
64
 
65
  demo.queue().launch(share=True)
66
-
67
  if __name__ == '__main__':
68
  fire.Fire(launch)
 
1
+ import os
2
+ import sys
3
  import subprocess
4
+ import tempfile
5
+ import spaces
6
+
7
+ # Build pytorch3d and nvdiffrast against the installed torch the first time a GPU is allocated.
8
+ # Both packages publish no prebuilt wheels for torch >= 2.8 (Blackwell / CUDA 13 stack).
9
+ CUDA_HOME = "/cuda-image/usr/local/cuda-13.0"
10
+
11
+
12
+ def _build_env():
13
+ env = os.environ.copy()
14
+ env["CUDA_HOME"] = CUDA_HOME
15
+ env["CUDA_PATH"] = CUDA_HOME
16
+ env["PATH"] = os.path.join(CUDA_HOME, "bin") + os.pathsep + env.get("PATH", "")
17
+ env["TORCH_CUDA_ARCH_LIST"] = "12.0"
18
+ return env
19
+
20
+
21
+ def _ensure_pkg(name, install_args):
22
+ try:
23
+ __import__(name)
24
+ return True
25
+ except ImportError:
26
+ pass
27
+ subprocess.check_call(
28
+ [sys.executable, "-m", "pip", "install",
29
+ "--no-build-isolation",
30
+ "--no-deps",
31
+ *install_args],
32
+ env=_build_env(),
33
  )
34
+
35
+
36
+ def _strip_pulsar_from_pytorch3d_src(src):
37
+ """Drop pulsar from a cloned pytorch3d source tree.
38
+
39
+ Pulsar fails to link on modern GCC because the explicit template
40
+ instantiations of pulsar::Renderer::fill_bg<true>/forward<true>/...
41
+ end up as hidden symbols and ld errors with:
42
+
43
+ hidden symbol `..._fill_bg<true>...' isn't defined
44
+ final link failed: bad value
45
+
46
+ Unique3D never imports pulsar (only pytorch3d.renderer.{cameras,mesh,...}
47
+ and pytorch3d.structures). Strip pulsar entirely before building.
48
+ """
49
+ import shutil
50
+
51
+ # 1. Remove the C++/CUDA sources so setup.py's glob skips them.
52
+ pulsar_csrc = os.path.join(src, "pytorch3d", "csrc", "pulsar")
53
+ if os.path.isdir(pulsar_csrc):
54
+ shutil.rmtree(pulsar_csrc)
55
+
56
+ # 2. Remove the python-side pulsar package.
57
+ pulsar_py = os.path.join(src, "pytorch3d", "renderer", "points", "pulsar")
58
+ if os.path.isdir(pulsar_py):
59
+ shutil.rmtree(pulsar_py)
60
+
61
+ # 3. Rewrite ext.cpp to drop every pulsar-related include and the entire
62
+ # pulsar pybind11 registration block. Use the well-defined "Pulsar." comment
63
+ # marker that starts the registration block and run to the matching #endif.
64
+ ext_cpp = os.path.join(src, "pytorch3d", "csrc", "ext.cpp")
65
+ if os.path.isfile(ext_cpp):
66
+ with open(ext_cpp, "r") as f:
67
+ lines = f.readlines()
68
+
69
+ # Phase A: drop the three pulsar include lines (they sit inside
70
+ # `#if !defined(USE_ROCM)` blocks together with non-pulsar includes? No —
71
+ # check the file: the top of ext.cpp has two #if !defined(USE_ROCM)
72
+ # blocks that only contain pulsar includes. Drop the whole #if/#endif
73
+ # pairs that contain only pulsar includes.
74
+ out = []
75
+ i = 0
76
+ while i < len(lines):
77
+ ln = lines[i]
78
+ if ln.strip().startswith("#if !defined(USE_ROCM)"):
79
+ # Look ahead for the matching #endif. Collect block body.
80
+ j = i + 1
81
+ block = []
82
+ while j < len(lines) and not lines[j].strip().startswith("#endif"):
83
+ block.append(lines[j])
84
+ j += 1
85
+ # Decide: if every non-blank/non-comment line in block mentions
86
+ # "pulsar", drop the whole #if..#endif. Otherwise keep as-is.
87
+ meaningful = [
88
+ b for b in block
89
+ if b.strip() and not b.strip().startswith("//")
90
+ ]
91
+ if meaningful and all("pulsar" in b.lower() for b in meaningful):
92
+ # Drop block (and matching #endif).
93
+ i = j + 1
94
+ continue
95
+ out.append(ln)
96
+ i += 1
97
+
98
+ # Phase B: drop the pulsar pybind registration block.
99
+ # Find the "// Pulsar." comment, walk back to its preceding blank line,
100
+ # then forward to the matching #endif (the last #endif before `}`).
101
+ text = "".join(out)
102
+ marker = " // Pulsar."
103
+ idx = text.find(marker)
104
+ if idx >= 0:
105
+ # Find the start of the line containing the marker.
106
+ line_start = text.rfind("\n", 0, idx) + 1
107
+ # Find the trailing `#endif` of the pulsar block. Walk forward; the
108
+ # block ends with a `#endif` on a line by itself, right before `}`.
109
+ end_marker = "\n#endif\n}"
110
+ end_idx = text.find(end_marker, line_start)
111
+ if end_idx < 0:
112
+ # Fall back: just drop to the next `}` on its own line.
113
+ end_idx = text.find("\n}\n", line_start)
114
+ if end_idx < 0:
115
+ raise RuntimeError("could not locate pulsar block end in ext.cpp")
116
+ # Keep the `}`.
117
+ text = text[:line_start] + text[end_idx + 1:]
118
+ else:
119
+ # Drop the `#endif` line but keep the `}`.
120
+ text = text[:line_start] + text[end_idx + len("\n#endif"):]
121
+
122
+ with open(ext_cpp, "w") as f:
123
+ f.write(text)
124
+
125
+ # 4. Patch renderer/points/__init__.py AND renderer/__init__.py: both have a
126
+ # `if not torch.version.hip:` block that imports PulsarPointsRenderer; replace
127
+ # the import with `pass` so the symbol is just absent.
128
+ for init_path in [
129
+ os.path.join(src, "pytorch3d", "renderer", "points", "__init__.py"),
130
+ os.path.join(src, "pytorch3d", "renderer", "__init__.py"),
131
+ ]:
132
+ if not os.path.isfile(init_path):
133
+ continue
134
+ with open(init_path, "r") as f:
135
+ init_lines = f.readlines()
136
+ new_lines = []
137
+ skip_block = False
138
+ for ln in init_lines:
139
+ if "torch.version.hip" in ln and ln.lstrip().startswith("if "):
140
+ indent = " " * (len(ln) - len(ln.lstrip()))
141
+ new_lines.append(ln)
142
+ new_lines.append(indent + " pass # pulsar disabled (Blackwell linker)\n")
143
+ skip_block = True
144
+ continue
145
+ if skip_block:
146
+ # Drop any indented continuation lines of the if-block, including
147
+ # multi-line `from .points import (` parenthesized imports.
148
+ stripped = ln.strip()
149
+ if stripped == "" or ln.startswith(" ") or ln.startswith("\t"):
150
+ if "pulsar" in ln.lower() or stripped == "" or stripped.startswith(")") or stripped.startswith("from ") or stripped.startswith("import "):
151
+ # part of the pulsar import block — drop
152
+ continue
153
+ skip_block = False
154
+ else:
155
+ skip_block = False
156
+ new_lines.append(ln)
157
+ with open(init_path, "w") as f:
158
+ f.writelines(new_lines)
159
+
160
+
161
+ @spaces.GPU(duration=1500)
162
+ def _build_pytorch3d():
163
+ # Probe the actual import path Unique3D uses; if the previously installed
164
+ # pytorch3d still has a broken `renderer/__init__.py` (e.g. left a dangling
165
+ # `from .points import PulsarPointsRenderer`), uninstall and rebuild.
166
+ try:
167
+ from pytorch3d.renderer import TexturesVertex # noqa: F401
168
+ return
169
+ except Exception:
170
+ pass
171
+ subprocess.call(
172
+ [sys.executable, "-m", "pip", "uninstall", "-y", "pytorch3d"],
173
+ )
174
+
175
+ src = tempfile.mkdtemp(prefix="pytorch3d_src_")
176
+ subprocess.check_call(
177
+ ["git", "clone", "--depth=1", "--branch=stable",
178
+ "https://github.com/facebookresearch/pytorch3d.git", src],
179
+ )
180
+ _strip_pulsar_from_pytorch3d_src(src)
181
+
182
+ # Force a fresh wheel build (don't reuse the cached broken wheel from a
183
+ # previous run, which still has the pulsar import in renderer/__init__.py).
184
+ subprocess.check_call(
185
+ [sys.executable, "-m", "pip", "install",
186
+ "--no-build-isolation", "--no-deps",
187
+ "--force-reinstall", "--no-cache-dir", src],
188
+ env=_build_env(),
189
  )
190
+
191
+
192
+ @spaces.GPU(duration=600)
193
+ def _build_nvdiffrast():
194
+ _ensure_pkg("nvdiffrast", ["git+https://github.com/NVlabs/nvdiffrast.git"])
195
+
196
+
197
+ # Run setup before importing anything that needs these packages.
198
+ _build_pytorch3d()
199
+ _build_nvdiffrast()
200
+
201
 
202
  if __name__ == "__main__":
 
203
  from huggingface_hub import login
204
  hf_token = os.environ.get("HF_TOKEN")
205
+ if hf_token:
206
+ login(token=hf_token)
207
+
 
208
  sys.path.append(os.curdir)
209
  import torch
210
  torch.set_float32_matmul_precision('medium')
 
237
 
238
  def launch():
239
  model_zoo.init_models()
240
+
241
  with gr.Blocks(
242
  title=_TITLE,
243
  # theme=gr.themes.Monochrome(),
 
249
  create_3d_ui("wkl")
250
 
251
  demo.queue().launch(share=True)
252
+
253
  if __name__ == '__main__':
254
  fire.Fire(launch)
gradio_app/all_models.py CHANGED
@@ -6,7 +6,7 @@ from diffusers import StableDiffusionControlNetImg2ImgPipeline, StableDiffusionP
6
  class MyModelZoo:
7
  _pipe_disney_controlnet_lineart_ipadapter_i2i: StableDiffusionControlNetImg2ImgPipeline = None
8
 
9
- base_model = "benjamin-paine/stable-diffusion-v1-5"
10
 
11
  def __init__(self, base_model=None) -> None:
12
  if base_model is not None:
 
6
  class MyModelZoo:
7
  _pipe_disney_controlnet_lineart_ipadapter_i2i: StableDiffusionControlNetImg2ImgPipeline = None
8
 
9
+ base_model = "stable-diffusion-v1-5/stable-diffusion-v1-5"
10
 
11
  def __init__(self, base_model=None) -> None:
12
  if base_model is not None:
gradio_app/gradio_3dgen.py CHANGED
@@ -11,14 +11,14 @@ from scripts.utils import save_glb_and_video
11
  # from scripts.multiview_inference import geo_reconstruct
12
  from scripts.multiview_inference import geo_reconstruct_part1, geo_reconstruct_part2, geo_reconstruct_part3
13
 
14
- @spaces.GPU(duration=100)
15
  def run_mv(preview_img, input_processing, seed):
16
  if preview_img.size[0] <= 512:
17
  preview_img = run_sr_fast([preview_img])[0]
18
  rgb_pils, front_pil = run_mvprediction(preview_img, remove_bg=input_processing, seed=int(seed)) # 6s
19
  return rgb_pils, front_pil
20
 
21
- @spaces.GPU(duration=100) # seems split into multiple part will leads to `RuntimeError`, before fix it, still initialize here
22
  def generate3dv2(preview_img, input_processing, seed, render_video=True, do_refine=True, expansion_weight=0.1, init_type="std"):
23
  if preview_img is None:
24
  raise gr.Error("The input image is none!")
 
11
  # from scripts.multiview_inference import geo_reconstruct
12
  from scripts.multiview_inference import geo_reconstruct_part1, geo_reconstruct_part2, geo_reconstruct_part3
13
 
14
+ @spaces.GPU(duration=600)
15
  def run_mv(preview_img, input_processing, seed):
16
  if preview_img.size[0] <= 512:
17
  preview_img = run_sr_fast([preview_img])[0]
18
  rgb_pils, front_pil = run_mvprediction(preview_img, remove_bg=input_processing, seed=int(seed)) # 6s
19
  return rgb_pils, front_pil
20
 
21
+ @spaces.GPU(duration=600) # seems split into multiple part will leads to `RuntimeError`, before fix it, still initialize here
22
  def generate3dv2(preview_img, input_processing, seed, render_video=True, do_refine=True, expansion_weight=0.1, init_type="std"):
23
  if preview_img is None:
24
  raise gr.Error("The input image is none!")
packages.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ libopengl0
2
+ libegl1
3
+ libxkbcommon-x11-0
4
+ libdbus-1-3
requirements.txt CHANGED
@@ -1,7 +1,5 @@
1
- pytorch3d @ https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/py310_cu121_pyt221/pytorch3d-0.7.6-cp310-cp310-linux_x86_64.whl
2
- ort_nightly_gpu @ https://aiinfra.pkgs.visualstudio.com/2692857e-05ef-43b4-ba9c-ccf1c22c437c/_packaging/d3daa2b0-aa56-45ac-8145-2c3dc0661c87/pypi/download/ort-nightly-gpu/1.17.dev20240118002/ort_nightly_gpu-1.17.0.dev20240118002-cp310-cp310-manylinux_2_28_x86_64.whl
3
- onnxruntime_gpu @ https://pkgs.dev.azure.com/onnxruntime/2a773b67-e88b-4c7f-9fc0-87d31fea8ef2/_packaging/7fa31e42-5da1-4e84-a664-f2b4129c7d45/pypi/download/onnxruntime-gpu/1.17/onnxruntime_gpu-1.17.0-cp310-cp310-manylinux_2_28_x86_64.whl
4
- torch==2.2.0
5
  accelerate
6
  datasets
7
  diffusers>=0.26.3
@@ -9,7 +7,7 @@ fire
9
  gradio
10
  jaxtyping
11
  numba
12
- numpy
13
  omegaconf>=2.3.0
14
  opencv_python
15
  opencv_python_headless
@@ -18,12 +16,10 @@ Pillow
18
  pygltflib
19
  pymeshlab>=2023.12
20
  rembg[gpu]
21
- torch>=2.0.1
22
- torch_scatter @ https://data.pyg.org/whl/torch-2.2.0%2Bcu121/torch_scatter-2.1.2%2Bpt22cu121-cp310-cp310-linux_x86_64.whl
23
  tqdm
24
  transformers
25
  trimesh
26
  typeguard
27
  wandb
28
  xformers
29
- ninja
 
1
+ onnxruntime-gpu
2
+ torch_scatter @ https://data.pyg.org/whl/torch-2.11.0+cu130/torch_scatter-2.1.2+pt211cu130-cp310-cp310-linux_x86_64.whl
 
 
3
  accelerate
4
  datasets
5
  diffusers>=0.26.3
 
7
  gradio
8
  jaxtyping
9
  numba
10
+ numpy<2
11
  omegaconf>=2.3.0
12
  opencv_python
13
  opencv_python_headless
 
16
  pygltflib
17
  pymeshlab>=2023.12
18
  rembg[gpu]
 
 
19
  tqdm
20
  transformers
21
  trimesh
22
  typeguard
23
  wandb
24
  xformers
25
+ ninja
scripts/load_onnx.py CHANGED
@@ -1,20 +1,9 @@
1
  import onnxruntime
2
  import torch
3
 
4
- providers = [
5
- # ('TensorrtExecutionProvider', {
6
- # 'device_id': 0,
7
- # 'trt_max_workspace_size': 8 * 1024 * 1024 * 1024,
8
- # 'trt_fp16_enable': True,
9
- # 'trt_engine_cache_enable': True,
10
- # }),
11
- ('CUDAExecutionProvider', {
12
- 'device_id': 0,
13
- 'arena_extend_strategy': 'kSameAsRequested',
14
- 'gpu_mem_limit': 8 * 1024 * 1024 * 1024,
15
- 'cudnn_conv_algo_search': 'HEURISTIC',
16
- })
17
- ]
18
 
19
  def load_onnx(file_path: str):
20
  assert file_path.endswith(".onnx")
 
1
  import onnxruntime
2
  import torch
3
 
4
+ # ZeroGPU containers ship CUDA 13; the onnxruntime-gpu wheel links against
5
+ # libcublasLt.so.12 (CUDA 12) → CUDAExecutionProvider fails to load. Use CPU.
6
+ providers = ['CPUExecutionProvider']
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  def load_onnx(file_path: str):
9
  assert file_path.endswith(".onnx")
scripts/sd_model_zoo.py CHANGED
@@ -4,7 +4,7 @@ import torch
4
  from copy import deepcopy
5
 
6
  ENABLE_CPU_CACHE = False
7
- DEFAULT_BASE_MODEL = "benjamin-paine/stable-diffusion-v1-5"
8
 
9
  cached_models = {} # cache for models to avoid repeated loading, key is model name
10
  def cache_model(func):
 
4
  from copy import deepcopy
5
 
6
  ENABLE_CPU_CACHE = False
7
+ DEFAULT_BASE_MODEL = "stable-diffusion-v1-5/stable-diffusion-v1-5"
8
 
9
  cached_models = {} # cache for models to avoid repeated loading, key is model name
10
  def cache_model(func):
scripts/utils.py CHANGED
@@ -13,14 +13,9 @@ from typing import List, Tuple
13
  from PIL import Image
14
  import trimesh
15
 
16
- providers = [
17
- ('CUDAExecutionProvider', {
18
- 'device_id': 0,
19
- 'arena_extend_strategy': 'kSameAsRequested',
20
- 'gpu_mem_limit': 8 * 1024 * 1024 * 1024,
21
- 'cudnn_conv_algo_search': 'HEURISTIC',
22
- })
23
- ]
24
 
25
  session = new_session(providers=providers)
26
 
 
13
  from PIL import Image
14
  import trimesh
15
 
16
+ # onnxruntime-gpu wheel links against CUDA 12 libs; ZeroGPU containers ship
17
+ # CUDA 13 → CUDAExecutionProvider can't load. Use CPU for rembg.
18
+ providers = ['CPUExecutionProvider']
 
 
 
 
 
19
 
20
  session = new_session(providers=providers)
21