diff --git a/install.ps1 b/install.ps1 index df80f23716..215c8f6040 100644 --- a/install.ps1 +++ b/install.ps1 @@ -663,14 +663,29 @@ shell.Run cmd, 0, False # CUDA wheels. Missing dependencies (transformers, trl, peft, etc.) # are still pulled in because they are new, not upgrades. # + # ── Helper: find no-torch-runtime.txt ── + function Find-NoTorchRuntimeFile { + if ($StudioLocalInstall -and (Test-Path (Join-Path $RepoRoot "studio\backend\requirements\no-torch-runtime.txt"))) { + return Join-Path $RepoRoot "studio\backend\requirements\no-torch-runtime.txt" + } + $installed = Get-ChildItem -Path $VenvDir -Recurse -Filter "no-torch-runtime.txt" -ErrorAction SilentlyContinue | + Where-Object { $_.FullName -like "*studio*backend*requirements*no-torch-runtime.txt" } | + Select-Object -ExpandProperty FullName -First 1 + return $installed + } + if ($_Migrated) { # Migrated env: force-reinstall unsloth+unsloth-zoo to ensure clean state # in the new venv location, while preserving existing torch/CUDA Write-Host "==> Upgrading unsloth in migrated environment..." if ($SkipTorch) { - # No-torch: install packages without deps to avoid pulling torch. - # Runtime deps are installed by install_python_stack.py via no-torch-runtime.txt. + # No-torch: install unsloth + unsloth-zoo with --no-deps, then + # runtime deps (typer, safetensors, transformers, etc.) with --no-deps. uv pip install --python $VenvPython --no-deps --reinstall-package unsloth --reinstall-package unsloth-zoo "unsloth>=2026.3.14" unsloth-zoo + $NoTorchReq = Find-NoTorchRuntimeFile + if ($NoTorchReq) { + uv pip install --python $VenvPython --no-deps -r $NoTorchReq + } } else { uv pip install --python $VenvPython --reinstall-package unsloth --reinstall-package unsloth-zoo "unsloth>=2026.3.14" unsloth-zoo } @@ -692,9 +707,13 @@ shell.Run cmd, 0, False Write-Host "==> Installing unsloth (this may take a few minutes)..." if ($SkipTorch) { - # No-torch: install packages without deps to avoid pulling torch. - # Runtime deps are installed by install_python_stack.py via no-torch-runtime.txt. + # No-torch: install unsloth + unsloth-zoo with --no-deps, then + # runtime deps (typer, safetensors, transformers, etc.) with --no-deps. uv pip install --python $VenvPython --no-deps --upgrade-package unsloth --upgrade-package unsloth-zoo "unsloth>=2026.3.14" unsloth-zoo + $NoTorchReq = Find-NoTorchRuntimeFile + if ($NoTorchReq) { + uv pip install --python $VenvPython --no-deps -r $NoTorchReq + } if ($StudioLocalInstall) { Write-Host "==> Overlaying local repo (editable)..." uv pip install --python $VenvPython -e $RepoRoot --no-deps @@ -735,9 +754,8 @@ shell.Run cmd, 0, False return } # Tell setup.ps1 to skip base package installation (install.ps1 already did it) - # When no-torch, don't skip base so install_python_stack installs - # no-torch-runtime.txt (the runtime deps that --no-deps skipped). - $env:SKIP_STUDIO_BASE = if ($SkipTorch) { "0" } else { "1" } + # Tell setup.ps1 to skip base package installation (install.ps1 already did it) + $env:SKIP_STUDIO_BASE = "1" $env:STUDIO_PACKAGE_NAME = $PackageName $env:UNSLOTH_NO_TORCH = if ($SkipTorch) { "true" } else { "false" } if ($StudioLocalInstall) { diff --git a/install.sh b/install.sh index 16736b43ee..4c960a129e 100755 --- a/install.sh +++ b/install.sh @@ -891,6 +891,21 @@ fi # ── Resolve repo root (for --local installs) ── _REPO_ROOT="$(cd "$(dirname "$0" 2>/dev/null || echo ".")" && pwd)" +# ── Helper: find no-torch-runtime.txt (local repo or site-packages) ── +_find_no_torch_runtime() { + # Check local repo first (for --local installs) + if [ -f "$_REPO_ROOT/studio/backend/requirements/no-torch-runtime.txt" ]; then + echo "$_REPO_ROOT/studio/backend/requirements/no-torch-runtime.txt" + return + fi + # Check inside installed package + _rt=$(find "$VENV_DIR" -path "*/studio/backend/requirements/no-torch-runtime.txt" -print -quit 2>/dev/null || echo "") + if [ -n "$_rt" ]; then + echo "$_rt" + return + fi +} + # ── Detect GPU and choose PyTorch index URL ── # Mirrors Get-TorchIndexUrl in install.ps1. # On CPU-only machines this returns the cpu index, avoiding the solver @@ -947,12 +962,17 @@ if [ "$_MIGRATED" = true ]; then # in the new venv location, while preserving existing torch/CUDA echo "==> Upgrading unsloth in migrated environment..." if [ "$SKIP_TORCH" = true ]; then - # No-torch: install packages without deps to avoid pulling torch. - # Runtime deps (safetensors, transformers, etc.) are installed by - # install_python_stack.py via no-torch-runtime.txt. + # No-torch: install unsloth + unsloth-zoo with --no-deps (current + # PyPI metadata still declares torch as a hard dep), then install + # runtime deps (typer, safetensors, transformers, etc.) with --no-deps + # to prevent transitive torch resolution. uv pip install --python "$_VENV_PY" --no-deps \ --reinstall-package unsloth --reinstall-package unsloth-zoo \ "unsloth>=2026.3.14" unsloth-zoo + _NO_TORCH_RT="$(_find_no_torch_runtime)" + if [ -n "$_NO_TORCH_RT" ]; then + uv pip install --python "$_VENV_PY" --no-deps -r "$_NO_TORCH_RT" + fi else uv pip install --python "$_VENV_PY" \ --reinstall-package unsloth --reinstall-package unsloth-zoo \ @@ -974,11 +994,15 @@ elif [ -n "$TORCH_INDEX_URL" ]; then # Fresh: Step 2 - install unsloth, preserving pre-installed torch echo "==> Installing unsloth (this may take a few minutes)..." if [ "$SKIP_TORCH" = true ]; then - # No-torch: install packages without deps to avoid pulling torch. - # Runtime deps are installed by install_python_stack.py via no-torch-runtime.txt. + # No-torch: install unsloth + unsloth-zoo with --no-deps, then + # runtime deps (typer, safetensors, transformers, etc.) with --no-deps. uv pip install --python "$_VENV_PY" --no-deps \ --upgrade-package unsloth --upgrade-package unsloth-zoo \ "unsloth>=2026.3.14" unsloth-zoo + _NO_TORCH_RT="$(_find_no_torch_runtime)" + if [ -n "$_NO_TORCH_RT" ]; then + uv pip install --python "$_VENV_PY" --no-deps -r "$_NO_TORCH_RT" + fi if [ "$STUDIO_LOCAL_INSTALL" = true ]; then echo "==> Overlaying local repo (editable)..." uv pip install --python "$_VENV_PY" -e "$_REPO_ROOT" --no-deps @@ -1036,21 +1060,15 @@ if [ -n "$VENV_ABS_BIN" ]; then fi echo "==> Running unsloth setup..." -# When no-torch, don't skip base so install_python_stack installs -# no-torch-runtime.txt (the runtime deps that --no-deps skipped). -_SKIP_BASE=1 -if [ "$SKIP_TORCH" = true ]; then - _SKIP_BASE=0 -fi if [ "$STUDIO_LOCAL_INSTALL" = true ]; then - SKIP_STUDIO_BASE="$_SKIP_BASE" \ + SKIP_STUDIO_BASE=1 \ STUDIO_PACKAGE_NAME="$PACKAGE_NAME" \ STUDIO_LOCAL_INSTALL=1 \ STUDIO_LOCAL_REPO="$_REPO_ROOT" \ UNSLOTH_NO_TORCH="$SKIP_TORCH" \ bash "$SETUP_SH" =0.42.0 packaging numpy diff --git a/studio/install_python_stack.py b/studio/install_python_stack.py index d32e29d0f7..e8ae22f470 100644 --- a/studio/install_python_stack.py +++ b/studio/install_python_stack.py @@ -462,13 +462,25 @@ def install_python_stack() -> int: if skip_base: print(_green(f"✅ {package_name} already installed — skipping base packages")) elif NO_TORCH: - # No-torch mode: unsloth + unsloth-zoo are already installed with - # --no-deps by install.sh/install.ps1. Install the runtime deps - # (safetensors, transformers, datasets, etc.) from no-torch-runtime.txt. + # No-torch update path: install unsloth + unsloth-zoo with --no-deps + # (current PyPI metadata still declares torch as a hard dep), then + # runtime deps with --no-deps (avoids transitive torch). _progress("base packages (no torch)") + pip_install( + f"Updating {package_name} + unsloth-zoo (no-torch mode)", + "--no-cache-dir", + "--no-deps", + "--upgrade-package", + package_name, + "--upgrade-package", + "unsloth-zoo", + package_name, + "unsloth-zoo", + ) pip_install( "Installing no-torch runtime deps", "--no-cache-dir", + "--no-deps", req = REQ_ROOT / "no-torch-runtime.txt", ) if local_repo: