diff --git a/install.sh b/install.sh index 8a0326b49d..f6c6c59ad0 100755 --- a/install.sh +++ b/install.sh @@ -1263,12 +1263,16 @@ elif [ -n "$TORCH_INDEX_URL" ]; then run_install_cmd "install PyTorch" uv pip install --python "$_VENV_PY" \ "$TORCH_CONSTRAINT" torchvision torchaudio \ --index-url "$TORCH_INDEX_URL" + substep "installing bitsandbytes for AMD ROCm..." + run_install_cmd "install bitsandbytes (AMD)" uv pip install --python "$_VENV_PY" "bitsandbytes>=0.49.1" fi else substep "[WARN] Radeon GPU detected but could not detect full ROCm version; falling back to ROCm index" "$C_WARN" run_install_cmd "install PyTorch" uv pip install --python "$_VENV_PY" \ "$TORCH_CONSTRAINT" torchvision torchaudio \ --index-url "$TORCH_INDEX_URL" + substep "installing bitsandbytes for AMD ROCm..." + run_install_cmd "install bitsandbytes (AMD)" uv pip install --python "$_VENV_PY" "bitsandbytes>=0.49.1" fi else substep "installing PyTorch ($TORCH_INDEX_URL)..." diff --git a/studio/backend/utils/hardware/__init__.py b/studio/backend/utils/hardware/__init__.py index 17d731d7b2..400b5dd066 100644 --- a/studio/backend/utils/hardware/__init__.py +++ b/studio/backend/utils/hardware/__init__.py @@ -8,6 +8,8 @@ Hardware detection and GPU utilities from . import hardware as _hardware from .hardware import ( DeviceType, + DEVICE, + CHAT_ONLY, detect_hardware, get_device, is_apple_silicon, @@ -84,8 +86,8 @@ __all__ = [ def __getattr__(name: str): - """Resolve mutable module-level flags (DEVICE, CHAT_ONLY, IS_ROCM) at access - time so callers always see the current value after detect_hardware() runs.""" - if name in {"DEVICE", "CHAT_ONLY", "IS_ROCM"}: - return getattr(_hardware, name) + """Resolve IS_ROCM at access time so callers always see the live value + after detect_hardware() runs (it flips the flag in hardware.py).""" + if name == "IS_ROCM": + return getattr(_hardware, "IS_ROCM") raise AttributeError(name) diff --git a/studio/install_llama_prebuilt.py b/studio/install_llama_prebuilt.py index 98e076962f..75c6ae8f54 100755 --- a/studio/install_llama_prebuilt.py +++ b/studio/install_llama_prebuilt.py @@ -2549,11 +2549,17 @@ def detect_host() -> HostInfo: pass # Detect AMD ROCm (HIP) -- require actual GPU, not just tools installed + import re as _re + + def _amd_smi_has_gpu(stdout: str) -> bool: + """Check for 'GPU: ' data rows, not just a table header.""" + return bool(_re.search(r"(?im)^gpu\s*:\s*\d", stdout)) + has_rocm = False if is_linux: - for _cmd, _marker in ( - (["rocminfo"], "gfx"), - (["amd-smi", "list"], "gpu"), + for _cmd, _check in ( + (["rocminfo"], lambda out: "gfx" in out.lower()), + (["amd-smi", "list"], _amd_smi_has_gpu), ): _exe = shutil.which(_cmd[0]) if not _exe: @@ -2563,14 +2569,14 @@ def detect_host() -> HostInfo: except Exception: continue if _result.returncode == 0 and _result.stdout.strip(): - if _marker in _result.stdout.lower(): + if _check(_result.stdout): has_rocm = True break elif is_windows: # Windows: prefer active probes that validate GPU presence - for _cmd, _marker in ( - (["hipinfo"], "gcnarchname"), - (["amd-smi", "list"], "gpu"), + for _cmd, _check in ( + (["hipinfo"], lambda out: "gcnarchname" in out.lower()), + (["amd-smi", "list"], _amd_smi_has_gpu), ): _exe = shutil.which(_cmd[0]) if not _exe: @@ -2580,7 +2586,7 @@ def detect_host() -> HostInfo: except Exception: continue if _result.returncode == 0 and _result.stdout.strip(): - if _marker in _result.stdout.lower(): + if _check(_result.stdout): has_rocm = True break # Note: amdhip64.dll presence alone is NOT treated as GPU evidence @@ -4750,10 +4756,21 @@ def runtime_payload_health_groups(choice: AssetChoice) -> list[list[str]]: ["libggml*.dylib"], ["libmtmd*.dylib"], ] + if choice.install_kind == "linux-rocm": + return [ + ["libllama.so*"], + ["libggml.so*"], + ["libggml-base.so*"], + ["libggml-cpu-*.so*"], + ["libmtmd.so*"], + ["libggml-hip.so*"], + ] if choice.install_kind == "windows-cpu": return [["llama.dll"]] if choice.install_kind == "windows-cuda": return [["llama.dll"], ["ggml-cuda.dll"]] + if choice.install_kind == "windows-hip": + return [["llama.dll"], ["*hip*.dll"]] return [] diff --git a/studio/install_python_stack.py b/studio/install_python_stack.py index d5f89239e5..1b74c9737b 100644 --- a/studio/install_python_stack.py +++ b/studio/install_python_stack.py @@ -106,9 +106,13 @@ def _detect_rocm_version() -> tuple[int, int] | None: def _has_rocm_gpu() -> bool: """Return True only if an actual AMD GPU is visible (not just ROCm tools installed).""" - for cmd, marker in ( - (["rocminfo"], "gfx"), - (["amd-smi", "list"], "gpu"), + import re + + for cmd, check_fn in ( + # rocminfo: look for "Name: gfxNNNN" indicating an actual GPU agent + (["rocminfo"], lambda out: "gfx" in out.lower()), + # amd-smi list: require "GPU: " data rows, not just a header + (["amd-smi", "list"], lambda out: bool(re.search(r"(?im)^gpu\s*:\s*\d", out))), ): exe = shutil.which(cmd[0]) if not exe: @@ -124,7 +128,7 @@ def _has_rocm_gpu() -> bool: except Exception: continue if result.returncode == 0 and result.stdout.strip(): - if marker in result.stdout.lower(): + if check_fn(result.stdout): return True return False