Commit graph

16 commits

Author SHA1 Message Date
Daniel Han
42e69031b9 Compress PR comments to essentials (comment-only; AST/token-verified)
Comment-compression sweep over comments this PR added, mirroring the
sweep already done on main. No non-comment token changed: .py verified
by AST equality (docstrings normalized), .sh by non-comment-line
equality + bash -n, .ps1 by token-stream equality minus comments.
test_spark_oom_guard.py: 13 passed before and after.

Files touched:
- install.ps1
- install.sh
- scripts/uninstall.ps1
- studio/backend/core/training/worker.py
- studio/scripts/provision_llama_cuda.sh
- studio/setup.sh
- unsloth/kernels/flex_attention.py
- unsloth/models/_utils.py

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 00:34:01 -07:00
Daniel Han
b3135ec7dc uninstall.ps1: scope WSL cleanup to evidenced fallback installs
The in-distro cleanup probed a hardcoded candidate set ('', Ubuntu,
Ubuntu-24.04, Ubuntu-22.04, Debian) on every Windows uninstall, wiping
/root/.unsloth in any reachable distro even when the WoA fallback never
ran -- on an x86 AMD box this deletes a ROCm-on-WSL Studio the AMD flow
installed. Use the evidence the installer already records: clean only
the wsl-distro.txt marker distro or UNSLOTH_WSL_DISTRO; keep the broad
candidate probe solely for legacy marker-less installs, which can only
exist on ARM64 hosts.

Addresses the open Codex P1 on this path. Verified gating matrix:
x86+no-marker -> no cleanup; marker/env -> that distro only;
ARM64+no-marker -> legacy broad probe unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 00:05:07 -07:00
Daniel Han
5c2aefc6d1 fix(install,studio): address review round 5 (3 real of 10; 5 PS-5.1 claims disproven on hardware)
Real fixes:

- uninstall.ps1: scope the WSL process kill to argv referencing
  /root/.unsloth/ (the fallback's install dir, which its Studio server,
  llama-server, and build runner all reference) instead of the bare
  '[l]lama-server' / '[u]nsloth_studio' name patterns -- uninstalling the
  Windows shim must not kill a user's own unrelated llama.cpp server or a
  /home Studio in a probed distro. Proven live: the path pattern matched
  exactly the three fallback processes while a planted /tmp/llama-server
  decoy matched the old pattern and not the new one. The backslash in
  '/root/\.unslot[h]/' keeps the pattern from matching the cleanup
  command's own argv.

- install.ps1: bridge UNSLOTH_LLAMA_TAG / UNSLOTH_LLAMA_PR into the
  background CUDA-build runner -- the provisioner honors both pins, but
  Windows env vars don't cross into WSL on their own, so a user's pin was
  silently ignored by the deferred build. (Deliberately NOT forwarded into
  the inner install.sh env: setup.sh skips its deferral when a PR pin is
  visible there, which would CPU-build the pin in the foreground.)

- kernels/flex_attention.py: make _flex_is_dgx_spark() CUDA-free
  (nvidia-smi device names, mirroring _is_dgx_spark_no_cuda_init) -- it
  runs at module import and called torch.cuda.get_device_name(), which
  initializes the CUDA allocator before patch_dgx_spark_memory_config()
  can set PYTORCH_CUDA_ALLOC_CONF on exactly the Spark hosts it targets
  (reachable via vision.py importing ..kernels before ._utils). Verified
  on the N1X: detects the machine with torch.cuda.is_initialized() still
  False.

- _utils.py: the TrainingArguments __post_init__ wrapper now forwards
  *args/**kwargs (robustness against future InitVar signatures).

Disproven on hardware (no change): the five "high" PS-5.1 claims --
String.TrimEnd('\', '/') with multiple char args binds fine to
params char[] (verified on PS 5.1.28000.1737, and the uninstaller's PATH
cleanup using exactly that code ran successfully this same day), and
[Text.Encoding] resolves via the System namespace prefix (the background
build dispatch using it has run in every install this week). The worker
"_sp possibly undefined" claim is false: `import subprocess as _sp` is at
worker.py line 25.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:56:31 -07:00
Daniel Han
c31a6e876d fix(install,studio): address Codex round-4 review (6 of 7 comments real)
- install.sh: gate the new aarch64 bitsandbytes block on SKIP_TORCH=false --
  with --no-torch/UNSLOTH_NO_TORCH (GGUF-only install) it would have pulled
  torch back into the venv through bitsandbytes' dependencies.

- studio worker: in the new Spark OOM-guard section, decide
  PYTORCH_CUDA_ALLOC_CONF (expandable_segments) BEFORE the guard's first CUDA
  touch -- get_device_properties initializes the CUDA allocator, after which
  the env var is ignored, and the later `import unsloth`
  (patch_dgx_spark_memory_config) is too late for the worker process. Uses
  the same CUDA-free nvidia-smi name sniff, append-don't-override, and
  UNSLOTH_NO_EXPANDABLE_SEGMENTS opt-out as the library patch. Live-verified
  on the N1X: env set while torch.cuda.is_initialized() is still False.

- uninstall.ps1: only run `fuser -k 8888/tcp` in a probed WSL distro when an
  Unsloth install actually exists there (checked BEFORE the rm deletes the
  marker) -- an unrelated listener on 8888 (e.g. Jupyter) in a clean distro
  must survive a Windows-side uninstall. The Unsloth-specific pkills stay
  unconditional.

- install.ps1 + uninstall.ps1: persist the chosen WSL distro to
  %LOCALAPPDATA%\Unsloth\wsl-distro.txt at install; uninstall reads it
  (before removing the directory) and prepends it to the cleanup candidates,
  so a custom UNSLOTH_WSL_DISTRO install is cleaned without the env var
  being set again at uninstall time.

- provision_llama_cuda.sh: honor UNSLOTH_LLAMA_PR (numeric-validated,
  best-effort fetch of pull/N/head after clone) so a provisioned tree
  matches a PR pin the way setup.sh does; and require only llama-server in
  the main cmake build (mirroring setup.sh), building the helper targets
  (llama-cli/quantize/mtmd-cli/gguf-split) best-effort afterwards -- an
  older UNSLOTH_LLAMA_TAG pin lacking a newer helper target no longer fails
  the whole provision.

Not changed: the "--tauri rejection doesn't restore the venv rollback"
comment is incorrect -- the rejection returns through Exit-InstallFailure,
which itself calls Restore-StudioVenvRollback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:12:47 -07:00
Daniel Han
ad77ae6cae fix(install): address PR review (Codex + Gemini) — exit codes, over-broad uninstall, Spark allocator, provision robustness
install.ps1 (WoA WSL fallback):
- report failure (non-zero) + restore the rolled-aside venv when the WSL GPU
  install fails (torch.cuda absent) or when WSL needs enabling+reboot, instead of
  returning success — so -File/Tauri callers don't see a broken install as complete
- on WSL success, Complete-StudioVenvRollback so the previous-venv backup isn't orphaned
- refuse under --tauri with a clear "use the CLI installer" message (the desktop
  launcher resolves a Windows-venv backend, which a WSL-only install can't provide)
- reset $LASTEXITCODE before each wsl.exe / python probe (a stale 0 could mark WSL
  ready / torch OK if the native command fails to launch)
- torch-availability probe: --reinstall so an already-installed CPU torch in a
  migrated venv isn't accepted as "satisfied" (would wrongly skip the WSL path)
- treat a null HKCU PATH as empty (fresh profile) so shim PATH update can't throw
- keep apt stderr visible inside WSL (only stdout -> /dev/null) for diagnosability

scripts/uninstall.ps1:
- scope WSL cleanup to /root (the fallback's install location); stop deleting
  /home/*/.unsloth, which could erase an unrelated WSL user's own Unsloth/cache

studio/setup.sh:
- direct (non-install.ps1) WSL installs now provision CUDA llama.cpp themselves
  instead of being left with no GGUF server: install.ps1 exports
  UNSLOTH_WSL_LLAMA_DEFERRED=1, and the aarch64+NVIDIA provision block runs under
  WSL only when that marker is absent
- mark a provisioner-built llama.cpp as Studio-owned in custom-STUDIO_HOME mode so
  the next setup's _assert_studio_owned_or_absent doesn't abort
- glibc>=2.41 check: also match a future major>2 (e.g. 3.0)

studio/scripts/provision_llama_cuda.sh:
- install base tools (cmake/git/curl) in their own apt transaction before the
  best-effort gcc-14/g++-14 (unavailable on Ubuntu 22.04 / Debian 12, where bundling
  them aborted the whole transaction and left no build tools)
- back up an existing (e.g. CPU-only) llama.cpp before the destructive clone and
  restore it on clone failure, so a failed clone doesn't leave the user with no server
- honor a pinned llama.cpp ref via UNSLOTH_LLAMA_TAG instead of always tracking main

unsloth/models/_utils.py:
- set PYTORCH_CUDA_ALLOC_CONF (expandable_segments) via a CUDA-free Spark detector
  (nvidia-smi, not torch.cuda.get_device_name) so it takes effect before CUDA/the
  caching allocator initialize — previously it was a silent no-op on auto-detected Spark

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 07:07:00 -07:00
Daniel Han
e3f0581e38 install.ps1: put WoA shortcut icon outside %LOCALAPPDATA% (real blank-icon fix)
Root cause (diagnosed live on an N1X WoA box, confirmed by on-screen checks):
the Windows shell's sandboxed icon-extraction broker cannot read a standalone
.ico stored under %LOCALAPPDATA% (it gets a redirected/virtualized view), so
the Desktop + Start Menu shortcuts render BLANK -- regardless of icon format
(BMP vs PNG frames), ACLs, icon cache, or shortcut-creation method, all of
which were ruled out. The IDENTICAL .ico renders correctly from a path under
the user profile. Fix: write unsloth.ico to %USERPROFILE%\.unsloth instead of
%LOCALAPPDATA%\Unsloth (shim/launcher stay in %LOCALAPPDATA%). uninstall.ps1
removes the icon at the new location. Also drops the speculative SHGetFileInfo
"image-list prime" block added while chasing the wrong (format/cache) theory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 03:18:22 -07:00
Daniel Han
61a902542a Merge origin/main into woa-nvidia-wsl-fallback
Only install.ps1 conflicted (header comment block): kept main's fuller
header (usage examples + install-dir priority + SPDX); UNSLOTH_INSTALL_REF
stays documented at Get-UnslothInstallRef. install.sh, pyproject.toml,
scripts/uninstall.ps1, scripts/uninstall.sh, unsloth/models/_utils.py
auto-merged. Verified: all WoA changes survived (--cd /root, zoo fix,
mem-aware/nice CUDA build, skip-CPU, shortcut robustness, uninstall exit-0)
and PowerShell AST / bash -n / python ast all pass.
2026-06-03 07:39:46 -07:00
Daniel Han
0946d5d37f Trim verbose PR comments to be succinct
Shorten the multi-line rationale comments added by this PR across the
remaining changed files to 1-2 lines each, preserving intent (gotchas,
workarounds, why-notes). Comment-only changes; no code, strings, or
behavior altered. Verified: PowerShell AST parser, bash -n, and python
ast.parse all pass; diffs confirmed comment-only.

Files: install.ps1, scripts/uninstall.ps1, scripts/uninstall.sh,
studio/setup.sh, unsloth/models/_utils.py, unsloth/kernels/flex_attention.py

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 06:24:07 -07:00
Daniel Han
c6e86d5e77
Update Install Scripts (#5968)
* Update Install Scripts

Add SPDX AGPL-3.0 headers to the installer scripts and let the piped web
installs take their common options from the environment.

- install.sh / install.ps1: read UNSLOTH_NO_TORCH (and UNSLOTH_PYTHON for
  install.sh) so a piped install needs no positional flags. Flags and the
  pipe forms still work; an explicit flag wins.
- Fix the UNSLOTH_STUDIO_HOME example so the variable sits after the pipe
  and reaches sh instead of curl.
- Add SPDX headers to install.sh, install.ps1, the uninstall scripts, and
  the MLX install scripts.
- Drop the internal test package names from the studio install comments.

* Mirror UNSLOTH_PYTHON env var to install.ps1

install.ps1 now reads UNSLOTH_PYTHON to pin the Python version, matching
install.sh, and lists all three env vars (UNSLOTH_NO_TORCH, UNSLOTH_PYTHON,
UNSLOTH_STUDIO_HOME) in the header examples. The requested version is
preferred during detection and used as the winget install target; behavior
is unchanged when the variable is unset.
2026-06-03 05:39:42 -07:00
Daniel Han
27f045a412 uninstall.ps1: exit 0 on success (do not leak WSL probe exit code)
The WSL distro-probe loop tries a candidate list that intentionally
includes distros that may not exist; the last failed `wsl -d <name> -- true`
probe left $LASTEXITCODE=255, so `& .\uninstall.ps1` returned non-zero even
when every cleanup step succeeded. Reset $global:LASTEXITCODE=0 at the end
(not `exit 0`, so the `irm ... | iex` usage does not kill the caller shell).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 05:29:31 -07:00
Daniel Han
5ecadb8512 uninstall.ps1: kill llama-server too (pkill self-match made it a no-op)
The WSL cleanup ran `pkill -9 -f unsloth_studio` then `pkill -9 -f llama-server`,
but the `bash -lc <cmd>` shell's own argv contains those literal patterns, so the
first pkill SIGKILLed the shell before the llama-server pkill (and trailing `true`)
ever ran -- leaving a running llama-server (dynamic port, not covered by
`fuser -k 8888`) alive after uninstall. Use the [x]-regex self-exclusion trick
('[u]nsloth_studio' / '[l]lama-server') so the shell's argv no longer contains the
matched substring; real target processes still match. Verified in WSL: shell
survives, both dummy processes are killed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 03:53:14 -07:00
Daniel Han
f102eccaa4 install.ps1/uninstall.ps1: add UNSLOTH_INSTALL_REF + fix WSL symlink uninstall hole
install.ps1: fetch repo-versioned WSL-fallback assets (provision_llama_cuda.sh,
unsloth.ico) from a configurable git ref via new UNSLOTH_INSTALL_REF env var
(defaults to main, so existing users are byte-for-byte unaffected). Lets the
ARM64+NVIDIA WSL-fallback GPU path be exercised end-to-end on a branch before it
merges (provision_llama_cuda.sh does not exist on main until then).

uninstall.ps1: the WSL cleanup rm -rf'd /root/.unsloth but left the
~/.local/bin/unsloth launcher symlink dangling, so `unsloth` still resolved on
PATH after an uninstall. Also remove /root/.local/bin/unsloth and
/home/*/.local/bin/unsloth.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 01:08:44 -07:00
Daniel Han
689032b7b5 uninstall.ps1: encoding-proof WSL distro detection for cleanup
The WSL-distro cleanup parsed 'wsl --list --quiet', whose UTF-16 output PowerShell
often mis-parses into an EMPTY list, so the WSL install (/root/.unsloth + CUDA
llama build) was silently never removed. Probe a candidate set ('' = default
distro, Ubuntu, Ubuntu-24.04, ...) by 'wsl -d <d> -- true' exit code instead
(encoding-proof; same idiom install.ps1 uses), then run the idempotent cleanup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:44:06 -07:00
Daniel Han
c87550cb3b uninstall: fix WSL rm self-kill (rm before pkill) + clean native-Linux llama.cpp
- uninstall.ps1: the WSL-distro cleanup ran 'pkill -f "unsloth studio"' before the
  rm inside a single bash -lc, but that pattern matches the bash -lc's own argv ->
  pkill SIGKILLs the shell before rm runs, so /root/.unsloth survived. Reorder: rm
  FIRST (guaranteed), then non-self-matching fuser -k 8888/tcp + pkill best-effort;
  also remove the fetched provision script + build log.
- uninstall.sh: also remove ~/.unsloth/llama.cpp (CUDA build from provision on
  native-Linux Spark) + the fetched provision_llama_cuda.sh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:37:06 -07:00
Daniel Han
b8f8fbffbf WSL fallback: fix blank shortcut icons + complete uninstall of WSL-fallback artifacts
- install.ps1: refresh the shell icon cache (ie4uinit -show) right after creating the
  Desktop/Start Menu shortcuts, so the (valid) .ico renders immediately instead of showing
  a blank icon (Explorer caches per-.lnk icons; programmatically-created links need a poke).
- scripts/uninstall.ps1 + scripts/uninstall.sh: also remove the WSL-fallback artifacts the
  native uninstall missed -- the %LOCALAPPDATA%\Unsloth shim/launcher/icon dir, its user-PATH
  entry, and the real Studio install inside each WSL distro (rm ~/.unsloth + any CUDA llama
  build). Previously the native uninstaller only cleaned the (empty) native venv + .lnk files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 04:46:30 -07:00
Daniel Han
a74a1080e0
Move uninstall scripts into scripts/ and fix references (#5644)
* Move uninstall scripts into scripts/ and fix all references

Relocates `uninstall.sh` and `uninstall.ps1` from the repo root into
the existing `scripts/` directory, alongside the other helper scripts.

Reference fixes:
* `README.md`: Studio uninstall instructions now point at the raw
  GitHub URLs under `scripts/`. The previous `unsloth.ai/uninstall.*`
  short URLs currently 404 (unlike `unsloth.ai/install.sh`, which
  301s to the raw github URL), so the raw URL is the working entry
  point until that redirect is configured.
* `scripts/uninstall.sh` header `Usage:` example updated to the new
  raw GitHub path.
* `scripts/uninstall.ps1` header `Usage:` example updated to the new
  raw GitHub path.
* `.github/workflows/studio-update-smoke.yml`: `paths:` trigger and
  round-trip exec/exists checks now use `scripts/uninstall.sh`.
* `.github/workflows/studio-mac-update-smoke.yml`: same.
* `.github/workflows/studio-windows-update-smoke.yml`: `paths:`
  trigger and round-trip exec/exists checks now use
  `scripts/uninstall.ps1`.

The in-script help hints (e.g. `sh uninstall.sh`, `.\uninstall.ps1`)
are left unchanged because they are user-facing examples shown after
the user already has the file locally, and the basename form works
regardless of which directory the user downloaded the script into.

Follow-up note for unsloth.ai: once this lands, please add the
`unsloth.ai/uninstall.sh` and `unsloth.ai/uninstall.ps1` short-URL
redirects to `raw.githubusercontent.com/unslothai/unsloth/main/scripts/...`
(matching the existing `unsloth.ai/install.sh` redirect pattern).

* Update remaining uninstall script help hints for new scripts/ path

Three user-facing strings inside the uninstall scripts still showed
the old basename form, which became misleading after the move:

* `scripts/uninstall.ps1` header `# Local:` example: now references
  `.\scripts\uninstall.ps1` (the actual path from the cloned repo
  root).
* `scripts/uninstall.sh` env-var re-run hint: now shows the canonical
  curl-pipe form documented in README, since callers who came via
  `curl -fsSL ... | sh` never had a local `uninstall.sh` to invoke.
* `scripts/uninstall.ps1` env-var re-run hint: same, switched to the
  `irm ... | iex` form documented in README.

Pure string changes, no behavior change.

---------

Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
2026-05-20 04:42:03 -07:00
Renamed from uninstall.ps1 (Browse further)