Spaces:
Sleeping
Sleeping
ibcplateformes Claude Opus 4.6 commited on
Commit ·
8a7554b
1
Parent(s): a7c6af3
Add GPU worker debug logging to diagnose ZeroGPU import errors
Browse filesZeroGPU only forwards exception class names, not messages. This adds:
- Import tests written to debug_gpu.log before conversion attempt
- Full traceback logged on error
- "Debug GPU" tab in UI to read the log file after an error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- app.py +19 -0
- pipeline/inference.py +54 -5
app.py
CHANGED
|
@@ -409,6 +409,25 @@ with gr.Blocks(
|
|
| 409 |
outputs=[models_delete_status, models_table],
|
| 410 |
)
|
| 411 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
|
| 413 |
if __name__ == "__main__":
|
| 414 |
app.launch(server_name="0.0.0.0")
|
|
|
|
| 409 |
outputs=[models_delete_status, models_table],
|
| 410 |
)
|
| 411 |
|
| 412 |
+
# Tab 4: Debug (temporary)
|
| 413 |
+
with gr.TabItem("Debug GPU"):
|
| 414 |
+
gr.Markdown("### Logs GPU Worker (pour diagnostic)")
|
| 415 |
+
debug_output = gr.Textbox(
|
| 416 |
+
label="Derniers logs GPU",
|
| 417 |
+
interactive=False,
|
| 418 |
+
lines=20,
|
| 419 |
+
)
|
| 420 |
+
debug_btn = gr.Button("Lire les logs", size="sm")
|
| 421 |
+
|
| 422 |
+
def read_debug_log():
|
| 423 |
+
log_path = "/home/user/app/debug_gpu.log"
|
| 424 |
+
if os.path.exists(log_path):
|
| 425 |
+
with open(log_path, "r") as f:
|
| 426 |
+
return f.read()
|
| 427 |
+
return "Aucun log disponible. Lancez d'abord une conversion."
|
| 428 |
+
|
| 429 |
+
debug_btn.click(fn=read_debug_log, outputs=[debug_output])
|
| 430 |
+
|
| 431 |
|
| 432 |
if __name__ == "__main__":
|
| 433 |
app.launch(server_name="0.0.0.0")
|
pipeline/inference.py
CHANGED
|
@@ -169,6 +169,21 @@ def crossfade(chunk1, chunk2, overlap):
|
|
| 169 |
return chunk2
|
| 170 |
|
| 171 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
@spaces.GPU(duration=120)
|
| 173 |
def convert_voice(
|
| 174 |
audio_path,
|
|
@@ -190,9 +205,40 @@ def convert_voice(
|
|
| 190 |
app_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 191 |
if app_dir not in sys.path:
|
| 192 |
sys.path.insert(0, app_dir)
|
| 193 |
-
# Also ensure current working directory is the app directory
|
| 194 |
os.chdir(app_dir)
|
| 195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
try:
|
| 197 |
return _convert_voice_impl(
|
| 198 |
audio_path, reference_path, pitch, index_rate, diffusion_steps
|
|
@@ -200,10 +246,13 @@ def convert_voice(
|
|
| 200 |
except Exception as e:
|
| 201 |
import traceback
|
| 202 |
tb = traceback.format_exc()
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
|
|
|
|
|
|
|
|
|
| 207 |
|
| 208 |
|
| 209 |
def _convert_voice_impl(audio_path, reference_path, pitch, index_rate, diffusion_steps):
|
|
|
|
| 169 |
return chunk2
|
| 170 |
|
| 171 |
|
| 172 |
+
DEBUG_LOG = "/home/user/app/debug_gpu.log"
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def _test_import(name, module_path, subattr=None):
|
| 176 |
+
"""Test a single import and return (ok, error_msg)."""
|
| 177 |
+
try:
|
| 178 |
+
import importlib
|
| 179 |
+
mod = importlib.import_module(module_path)
|
| 180 |
+
if subattr:
|
| 181 |
+
getattr(mod, subattr)
|
| 182 |
+
return True, "OK"
|
| 183 |
+
except Exception as ie:
|
| 184 |
+
return False, "{}: {}".format(type(ie).__name__, ie)
|
| 185 |
+
|
| 186 |
+
|
| 187 |
@spaces.GPU(duration=120)
|
| 188 |
def convert_voice(
|
| 189 |
audio_path,
|
|
|
|
| 205 |
app_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
| 206 |
if app_dir not in sys.path:
|
| 207 |
sys.path.insert(0, app_dir)
|
|
|
|
| 208 |
os.chdir(app_dir)
|
| 209 |
|
| 210 |
+
# Write debug diagnostics BEFORE attempting anything
|
| 211 |
+
try:
|
| 212 |
+
with open(DEBUG_LOG, "w") as f:
|
| 213 |
+
f.write("=== GPU Worker Debug ===\n")
|
| 214 |
+
f.write("app_dir: {}\n".format(app_dir))
|
| 215 |
+
f.write("cwd: {}\n".format(os.getcwd()))
|
| 216 |
+
f.write("sys.path[:5]: {}\n".format(sys.path[:5]))
|
| 217 |
+
f.write("modules/ exists: {}\n".format(os.path.isdir(os.path.join(app_dir, "modules"))))
|
| 218 |
+
f.write("hf_utils.py exists: {}\n".format(os.path.isfile(os.path.join(app_dir, "hf_utils.py"))))
|
| 219 |
+
f.write("cuda available: {}\n".format(torch.cuda.is_available()))
|
| 220 |
+
|
| 221 |
+
# Test each critical import
|
| 222 |
+
tests = [
|
| 223 |
+
("yaml", "yaml", None),
|
| 224 |
+
("munch", "munch", "Munch"),
|
| 225 |
+
("einops", "einops", None),
|
| 226 |
+
("transformers", "transformers", "WhisperModel"),
|
| 227 |
+
("modules.commons", "modules.commons", "build_model"),
|
| 228 |
+
("hf_utils", "hf_utils", "load_custom_model_from_hf"),
|
| 229 |
+
("modules.campplus.DTDNN", "modules.campplus.DTDNN", "CAMPPlus"),
|
| 230 |
+
("modules.bigvgan.bigvgan", "modules.bigvgan.bigvgan", "BigVGAN"),
|
| 231 |
+
("modules.audio", "modules.audio", "mel_spectrogram"),
|
| 232 |
+
("modules.rmvpe", "modules.rmvpe", "RMVPE"),
|
| 233 |
+
]
|
| 234 |
+
for label, mod_path, attr in tests:
|
| 235 |
+
ok, msg = _test_import(label, mod_path, attr)
|
| 236 |
+
f.write("IMPORT {}: {} -> {}\n".format("OK" if ok else "FAIL", label, msg))
|
| 237 |
+
|
| 238 |
+
f.write("=== Import tests done ===\n")
|
| 239 |
+
except Exception:
|
| 240 |
+
pass
|
| 241 |
+
|
| 242 |
try:
|
| 243 |
return _convert_voice_impl(
|
| 244 |
audio_path, reference_path, pitch, index_rate, diffusion_steps
|
|
|
|
| 246 |
except Exception as e:
|
| 247 |
import traceback
|
| 248 |
tb = traceback.format_exc()
|
| 249 |
+
try:
|
| 250 |
+
with open(DEBUG_LOG, "a") as f:
|
| 251 |
+
f.write("\n=== CONVERSION ERROR ===\n")
|
| 252 |
+
f.write(tb)
|
| 253 |
+
except Exception:
|
| 254 |
+
pass
|
| 255 |
+
raise
|
| 256 |
|
| 257 |
|
| 258 |
def _convert_voice_impl(audio_path, reference_path, pitch, index_rate, diffusion_steps):
|