Commit graph

4,719 commits

Author SHA1 Message Date
danielhanchen
2773f98357 Gate run_server re-exec behind allow_reexec so embedders are not restarted
run_server is a library/embed entry point (colab.start calls it directly), so the
unconditional os.execv for the torch CUDA LD_LIBRARY_PATH fix would replace the live
Colab/Jupyter kernel and drop in-memory state. Gate the re-exec behind a new
allow_reexec flag defaulting to False; the run.py __main__ path already re-execs
before calling run_server, and the unsloth_cli studio/ui entrypoints opt in with
allow_reexec=True so the CLI keeps the CUDA LD fix.
2026-07-06 10:32:31 +00:00
Daniel Han
e235df6d2a Fix review issues: no module-level execv, Linux-only, use sys.orig_argv
Addresses all reviewer feedback:

1. Moved os.execv out of module-level code into a helper function
   _maybe_reexec_for_cuda_ld_path() that is called explicitly from
   run_server() and __main__. Importing run.py no longer replaces the
   host process -- safe for CLI, notebooks, tests, and embedders.

2. Changed platform guard from "not win32" to "linux only", since
   LD_LIBRARY_PATH is a Linux-specific linker mechanism.

3. Use sys.orig_argv (Python 3.10+) when available to preserve the
   original interpreter invocation (python -m, -c, -X flags, etc.).
   Falls back to [sys.executable] + sys.argv for older Python.
2026-03-18 05:13:44 +00:00
pre-commit-ci[bot]
35f3465d86 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-03-18 05:00:42 +00:00
Daniel Han
58c640dfe5 Fix torch CUDA symbol errors caused by user LD_LIBRARY_PATH
When a user has LD_LIBRARY_PATH pointing at system CUDA libs (e.g.
/usr/local/cuda-13/lib64), the dynamic linker loads those instead of
the CUDA libs bundled with the torch wheel (in nvidia/*/lib/). This
causes symbol version mismatches and crashes on import.

Fix: before importing anything, detect torch's bundled CUDA lib paths
(without importing torch itself) and prepend them to LD_LIBRARY_PATH
so they take priority. Then re-exec so the dynamic linker picks up
the corrected path. A sentinel env var prevents infinite re-exec.

The user's original paths are preserved (just deprioritized), so
non-torch tools that need system CUDA still work.
2026-03-18 04:58:10 +00:00
Daniel Han
3a28446a54
Trim ~255 MB of unused packages from Studio setup (#4395)
* Comment out large unused packages from Studio setup requirements

Audited all packages installed by `unsloth studio setup` against actual
imports in unsloth, unsloth_zoo, and studio/backend. The following have
zero imports anywhere and are the largest offenders by disk size:

- gradio (148 MB) in studio.txt -- Studio uses React + FastAPI, not Gradio
- executorch (41.5 MB) in extras-no-deps.txt -- no imports found
- scikit-learn (31.8 MB) in extras.txt -- no imports found
- MeCab (19.9 MB) in extras.txt -- Japanese tokenizer, no imports found
- coremltools (10.2 MB) in extras.txt -- Apple CoreML, no imports found
- uroman (4.0 MB) in extras.txt -- romanization tool, no imports found

Total savings: ~255 MB (~32% of the 805 MB installed by setup).

Each line is commented out with the package size annotated so they can be
re-enabled easily if needed in the future.

* Restore scikit-learn -- needed by sentence_transformers

sentence_transformers is installed with --no-deps in extras-no-deps.txt,
so its sklearn dependency is not auto-resolved. Multiple modules in
sentence_transformers import sklearn at the top level (evaluation,
util/similarity), so removing scikit-learn would break embedding jobs.
2026-03-17 21:32:38 -07:00
Coenraad Loubser
ca87669937
Unused return value causes build failures (#4385)
* Unused return value causes build failures

* Update toast messages to include model loading status
2026-03-17 20:57:27 -07:00
DoubleMathew
fd72376a7e
Fix/studio full finetuning (#4391)
* Wire Studio full finetuning into training loaders

* Preserve load_model positional compatibility
2026-03-17 20:47:26 -07:00
Daniel Han
0c8d407793
Rename cli/ to unsloth_cli/ to fix namespace collision with stringzilla (#4393)
* Rename cli/ to unsloth_cli/ to fix namespace collision with stringzilla

stringzilla installs a namespace package at cli/ (cli/split.py, cli/wc.py)
in site-packages without an __init__.py. When unsloth is installed as an
editable package (pip install -e .), the entry point script does
`from cli import app` which finds stringzilla's namespace cli/ first and
fails with `ImportError: cannot import name 'app' from 'cli'`.

Non-editable installs happened to work because unsloth's cli/__init__.py
overwrites the namespace directory, but this is fragile and breaks if
stringzilla is installed after unsloth.

Renaming to unsloth_cli/ avoids the collision entirely and fixes both
editable and non-editable install paths.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update stale cli/ references in comments and license files

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-17 20:40:21 -07:00
Michael Han
75da2e00c2
Update install instructions.md 2026-03-17 20:04:04 -07:00
Michael Han
8bca62aa78
Dual License clarification.md 2026-03-17 18:48:00 -07:00
Michael Han
e138a3d48b
Update install instructions.md 2026-03-17 16:08:40 -07:00
Wasim Yousef Said
03736a82ba
Relax frontend unused local check (#4388) 2026-03-17 16:04:11 -07:00
Michael Han
523ebf1e2f
Update Unsloth_Studio_Colab.ipynb 2026-03-17 15:42:38 -07:00
Manan Shah
93ab09d195
[Feature] compare for 2 diff models (#4356)
* compare for 2 diff models

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* resolving gemini comments

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(studio): refine model-load toast stop action and compare selector sizing (#4369)

Co-authored-by: imagineer99 <samleejackson0@gmail.com>

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Daniel Han <danielhanchen@gmail.com>
Co-authored-by: imagineer99 <samleejackson0@gmail.com>
2026-03-17 22:58:34 +04:00
Michael Han
2a8d6b2b82
Update Unsloth_Studio_Colab.ipynb 2026-03-17 11:31:09 -07:00
Michael Han
01dfbab5a8
Update Unsloth_Studio_Colab.ipynb 2026-03-17 11:27:04 -07:00
Michael Han
a46cb120bb
Update Unsloth_Studio_Colab.ipynb 2026-03-17 11:24:54 -07:00
Michael Han
051b6f27f9
Update Unsloth_Studio_Colab.ipynb 2026-03-17 11:16:20 -07:00
Michael Han
a943705b4c
Update Unsloth_Studio_Colab.ipynb 2026-03-17 11:14:45 -07:00
Michael Han
685a0348e1
Update Unsloth_Studio_Colab.ipynb 2026-03-17 10:00:57 -07:00
Michael Han
881e057964
Unsloth Studio update.md 2026-03-17 08:42:03 -07:00
Daniel Han
880b59a301 Update README.md March-2026 2026-03-17 08:03:32 -07:00
Michael Han
deb76dfa1d
Update README.md 2026-03-17 07:57:46 -07:00
Daniel Han
1fffd0e17a Merge branch 'main' of https://github.com/unslothai/unsloth 2026-03-17 07:54:41 -07:00
Daniel Han
ebfaa18094 Update pyproject.toml 2026-03-17 07:54:32 -07:00
Michael Han
c60636695c
Unsloth Studio.md 2026-03-17 07:53:50 -07:00
Daniel Han
0acd1c7eec
studio: improve onboarding UX, tooltips, and training defaults (#4355)
* studio: improve onboarding UX, tooltips, and training defaults

- Change splash text to "Train and run LLMs locally"
- Add "Chat Only" card with BubbleChatIcon to skip directly to chat
- Add Skip/Skip to Chat buttons in sidebar and footer
- Back button on step 1 returns to splash screen instead of being disabled
- Change "Watch video guide" to "Get started with our guide" with new URL
- Update intro text to mention all model types + chat
- Make all tooltips clickable (in addition to hover) via React context
- Strip surrounding quotes from pasted HF tokens
- Rename "Eval Split" to "Evaluation Split"
- Add SparklesIcon to "Auto Detect" format option
- Change step 4 heading to "Choose your training parameters"
- Default max_steps to 60
- Learning rate displayed in scientific notation with +/- stepper
- Context length options capped by model's max_position_embeddings (via AutoConfig)
- Fix "QLORA"/"LORA" to "QLoRA"/"LoRA" in summary step
- Backend: add max_position_embeddings to model config endpoint

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* compare for 2 diff models

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* resolving gemini comments

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: disable thinking for Qwen3.5 <9B and always for AI Assist

- Change Qwen3.5 thinking threshold from <=2B to <9B (0.8B, 2B, 4B
  all disable thinking by default; 9B+ enables it)
- Always pass enable_thinking=False in AI Assist helper calls
  (_run_with_helper and _generate_with_backend) regardless of chat
  thinking settings

* studio: address PR review comments

- Extract _get_max_position_embeddings helper to DRY config extraction
- Fix "Skip to Chat" to navigate to /chat on step 1 (was /studio)

* fix: comment out debug print statements

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: skip Shiki highlighting for incomplete SVG code fences

While streaming SVG content, the syntax highlighter (Shiki) re-parses
the entire growing SVG on every token, blocking the main thread and
freezing the code area until the fence closes. Show a plain-text
preview for incomplete SVG fences instead, similar to how Mermaid
diagrams show a placeholder while streaming.

* studio: fix default top_k from 50/40 to 20 for chat inference

Per Qwen3.5 docs (unsloth.ai/docs/models/qwen3.5), top_k should be 20
for both thinking and non-thinking modes. The model-specific config in
inference_defaults.json already had top_k=20 for Qwen3.5, but the
generic fallback defaults were wrong:
- Frontend DEFAULT_INFERENCE_PARAMS.topK: 50 -> 20
- Backend generate_chat_completion top_k: 40 -> 20
- Backend generate_chat_completion_with_tools top_k: 40 -> 20
- Frontend title generation top_k: 40 -> 20

* studio: set universal inference defaults for unknown models

Default params for any model without specific config:
  temperature=0.6, top_p=0.95, top_k=20, min_p=0.01,
  presence_penalty=0.0, repetition_penalty=1.0

Models with entries in inference_defaults.json (Qwen3.5, Gemma-3,
Llama, etc.) override these with their recommended values.

Updated in: frontend DEFAULT_INFERENCE_PARAMS, backend Pydantic
request models, and backend generate_chat_completion defaults.

* studio: only trust_remote_code for unsloth/ models in AutoConfig

Only set trust_remote_code=True when the model name starts with
"unsloth/". All other models default to False for safety.

* studio: move Generating spinner above the composer

The "Generating" spinner was below the send message bar, causing
the bar to jump up and down. Move it above the composer in both
the regular thread view and the welcome/empty view.

* studio: adjust toast close button position away from edge

Move the X close button on toasts (like "Starting model...") from
top-1.5 to top-3 and add right-3, giving more breathing room from
the top-right corner.

* studio: make Think button smaller with tighter icon-text gap

Reduce gap from 1.5 to 0.5, padding from px-2.5/py-1 to px-2/py-0.5,
and icon from size-3.5 to size-3.

* studio: multiple onboarding and chat UX improvements

- Move Generating spinner above composer (fixes jumping send bar)
- Make Think button smaller with tighter icon-text gap
- Chat card now inside grid (same size as Audio/Embeddings cards)
- Rename "Chat Only" to "Chat"
- Chat card requires Continue to proceed (no auto-advance)
- Continue on Chat selection skips onboarding and goes to /chat
- Tooltip (i) click on Chat card doesn't trigger navigation
- Step 1 footer Back button goes back to splash (label is "Back")
- Splash "Skip Onboarding" renamed to "Skip to Chat", navigates to /chat
- Toast close button moved away from edge

* studio: align Skip to Chat button, add Skip to footer

- Sidebar "Skip to Chat" now uses primary (green) Button style with
  arrow icon, full width, aligned like step items. Shows on all steps.
- Footer: added "Skip" outline button next to Continue that goes
  directly to /studio with progress saved (markOnboardingDone)

* studio: change default max steps from 30 to 60 in toggle hook

The DEFAULT_MAX_STEPS in use-max-steps-epochs-toggle.ts was still 30,
used as fallback when toggling from epochs back to max steps.

* studio: extend context length options to 262K

CONTEXT_LENGTHS now includes 65536, 131072, 262144 in addition to
the existing 512-32768 range. The onboarding step filters these by
the model's max_position_embeddings (e.g. Nemotron-3-Nano-4B has
262144), showing powers of 2 up to the model's maximum.

* studio: auto-select LoRA vs QLoRA based on model size and GPU memory

After selecting a model in onboarding, detect the total model weight
file size from HF Hub (safetensors/bin files). Then estimate memory
needed: model_size_gb * 1.5 * context_scale, where context_scale is:
  - <=8192 tokens: 1.0x
  - >8192 tokens: 1.7x
  - >=16384 tokens: 2.0x
  - >=32768 tokens: 4.0x

If the estimate fits in free GPU VRAM, default to LoRA (16-bit).
Otherwise default to QLoRA (4-bit).

Backend changes:
- Add model_size_bytes to ModelDetails (models.py)
- Add _get_model_size_bytes() using HfApi.repo_info (routes/models.py)
- Add vram_free_gb to get_gpu_summary (hardware.py)

Frontend changes:
- Add autoSelectTrainingMethod() in training-config-store.ts
- Called after model defaults are loaded
- Add model_size_bytes to ModelConfigResponse type
- Add vramFreeGb to HardwareInfo hook

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: rename "Importing ML libraries..." to "Importing Unsloth..."

* studio: show model/dataset in training status, fix LoRA/QLoRA casing

- Training status now shows 'Training "model_name"' and 'Dataset = ...'
  instead of generic "Starting training..."
- Fix Studio progress section to show QLoRA/LoRA instead of QLORA/LORA

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: rename 'Skip to Chat' to 'Skip Onboarding' on splash screen

* studio: add presence_penalty support for chat inference

Add presence_penalty as a parameter across the full stack:
- Backend: llama_cpp.py generate_chat_completion/with_tools, Pydantic
  models (inference.py), routes/inference.py pass-through
- Frontend: InferenceParams type, DEFAULT_INFERENCE_PARAMS (0.0),
  chat-adapter.ts payload, chat-settings-sheet.tsx slider (0-2),
  model defaults loading from inference_defaults.json
- Set Qwen3.5 default presence_penalty to 1.5 per official docs
- Default for unknown models is 0.0 (off)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: fix Chat card deselecting Text and aligning with other cards

* studio: fix presence_penalty not loading from inference defaults

The inference_config.py load_inference_config() was not including
presence_penalty in the returned config dict, so the Qwen3.5
default of 1.5 from inference_defaults.json never reached the
frontend. Added it to the config builder.

* studio: add delete button for cached models in model selector

Add trash icon on each downloaded model row (GGUF and safetensors) with
confirmation dialog. Backend DELETE /api/models/delete-cached endpoint
uses huggingface_hub scan_cache_dir + delete_revisions to cleanly remove
cached repos, refusing if the model is currently loaded.

* studio: restore inference defaults, reasoning, and tools on page refresh

On page refresh with a model already loaded, the frontend was not
re-applying model-specific inference defaults (presence_penalty,
temperature, etc.) or restoring reasoning/tools support flags.

Backend: Add inference config, supports_reasoning, supports_tools,
and context_length to InferenceStatusResponse.

Frontend: In the refresh callback, when an active model is detected,
apply mergeRecommendedInference and restore reasoning/tools flags
with proper Qwen3.5 size-based defaults.

* studio: fix delete dialog closing before async completes

Prevent AlertDialogAction's default close behavior with
e.preventDefault() so the dialog stays open during deletion.
Also block onOpenChange dismiss while deleting is in progress.

* fix: add Dict and Any imports to inference models

* studio: fix Qwen3.5 reasoning threshold in frontend load path

The frontend loadModel handler had the old threshold (<=2) for
disabling reasoning on small Qwen3.5 models. Changed to <9 to
match the backend. This was causing 4B to not properly disable
thinking by default when auto-loaded.

* studio: move GGUF delete to per-variant level

For GGUF repos, the trash icon now appears on each downloaded variant
row inside the quantization expander instead of on the repo-level row.
Backend accepts optional variant param to delete specific GGUF files
(blob + symlink) rather than the entire repo cache.

* studio: restore ggufContextLength on page refresh

The Max Tokens slider was capped at 32768 on page refresh because
ggufContextLength was not restored from the status response.
Now set it from statusRes.context_length on reconnect.

* fix: remove <think> from Qwen3.5 response template marker

The train-on-responses-only feature uses template markers to find
where the assistant response starts. The Qwen3.5 response marker
included '<think>\n' which is only present when thinking mode is
enabled. With thinking disabled (default for <9B), the marker
never matched, causing 100% of samples to be dropped.

Changed response marker from '<|im_start|>assistant\n<think>\n'
to '<|im_start|>assistant\n' which works regardless of thinking mode.

* studio: fix sloth ASCII art alignment in training overlay

* fix: correct sloth ASCII art alignment to match Unsloth banner

* studio: add Python and terminal tool calling to chat

Register python and terminal tools alongside web search. Python
executor validates imports (stdlib only) via unsloth_zoo
rl_environments, runs code in a subprocess sandbox with 5-min
timeout and cancel support. Terminal executor blocks dangerous
commands (rm, sudo, etc.) and runs in a temp directory.

Update llama_cpp tool loop to show tool-specific status messages
and pass cancel_event through to executors. Rename composer
toggle from "Search" to "Tools" and show TerminalIcon for
execution status pills.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: fix Nemotron/transformers 5.x support, onboarding navigation, port binding

Backend:
- Dynamic transformers 5.x detection via tokenizer_config.json fetch
  (checks for TokenizersBackend class, cached per-model)
- Bump transformers 5.x version from 5.2.0 to 5.3.0 across all workers,
  setup scripts (setup.sh, setup.ps1)
- Auto-enable trust_remote_code for unsloth/* models needing transformers 5.x
  (workaround for NemotronH config parsing bug in transformers)
- Auto-install mamba-ssm/causal-conv1d for SSM models (NemotronH, Falcon-H1)
  with --no-build-isolation --no-deps to avoid torch version conflicts
- Add SO_REUSEADDR to port check in run.py (fixes Colab proxy stale connection
  falsely reporting port as in-use)

Frontend:
- Fix "Skip to Chat" navigation: use window.location.href instead of React
  Router navigate() to bypass useEffect redirect race
- Fix "Skip Onboarding" on splash: navigates to /studio (not /chat)
- Fix onboarding guard: only check isOnboardingDone() on initial mount
- Fix Chat card on step 1: add sr-only spacer for consistent alignment
- Fix Chat+Text both selected: clear RadioGroup value when Chat is selected

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: split tools toggle into Search and Code buttons

Replace the single "Tools" toggle with two independent toggles:
- "Search" (globe icon) enables web search only
- "Code" (terminal icon) enables Python and terminal execution

Add enabled_tools list field to the inference payload so the
backend only registers the tools the user has toggled on. Both
toggles appear in the main composer and the compare composer.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: fix tool calling import validation and error logging

Replace unsloth_zoo-dependent import checker with a standalone
ast-based validator using sys.stdlib_module_names. This properly
blocks non-stdlib imports (numpy, requests, etc.) and returns a
clear error message to the model so it can rewrite using only
stdlib.

Add full traceback to tool streaming error logs for debugging.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: parse gpt-oss harmony channels for clean safetensors chat output

gpt-oss models emit multi-channel output via harmony protocol tokens
(<|channel|>analysis<|message|>... and <|channel|>final<|message|>...).
TextIteratorStreamer with skip_special_tokens=True strips the special
tokens but leaves channel names concatenated with content, producing
garbled output like "analysisWe need to...assistantfinalHello!".

Add HarmonyTextStreamer that decodes with skip_special_tokens=False,
parses harmony markup via regex, and emits <think>analysis</think>
for the analysis channel and plain text for the final channel --
reusing the existing frontend reasoning UI.

Also expose supports_reasoning=True for non-GGUF gpt-oss models in
the /status endpoint so the frontend enables the Think toggle.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: use unsloth_zoo for Python sandbox validation

Set UNSLOTH_IS_PRESENT=1 and import check_python_modules and
check_signal_escape_patterns directly from unsloth_zoo instead
of a standalone fallback. This gives us the full Unsloth
validation including stdlib-only import checks and signal/timeout
escape pattern detection.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* studio: allow all imports in Python tool sandbox

Remove stdlib-only import restriction. Keep signal escape
pattern detection via unsloth_zoo for safety.

* studio: fix ReadTimeout on tool streaming final pass

The 0.5s read timeout used for cancel-checking during streaming
also fires when waiting for the first response from llama-server
(e.g. reasoning model thinking for 15+ seconds). Add
_stream_with_retry() context manager that retries on ReadTimeout
while checking cancel_event, so the model has unlimited time to
think before producing the first token. Applied to both the
regular streaming path and the tool-calling final pass.

* fix: rewrite HarmonyTextStreamer with stateful incremental parsing

The delta-on-transformed approach had two critical bugs:

1. Before the full <|channel|>X<|message|> pattern was complete, the
   strip-tokens fallback emitted "analysis" as plain text. Then when
   the regex matched, _transform returned a completely different format
   (<think>...</think>) and the delta was computed against the wrong
   base string, producing fragments like "think>", "nk>", ">".

2. Even with full matches, the closing </think> tag shifted position
   as content grew, so text[prev_len:] produced garbled deltas.

Replace with stateful incremental parsing that:
- Buffers until a complete channel+message pair is seen
- Emits <think> once when analysis channel first appears
- Streams analysis content deltas (computed on channel content directly)
- Emits </think> once when final channel first appears
- Streams final content deltas
- Closes open think tags in end()

Also skip the generic all_special_tokens stripping in
_clean_generated_text for gpt-oss since HarmonyTextStreamer already
produces clean output and the generic stripping was mangling <think>
tags.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: strip all <|...|> tokens in gpt-oss cleanup, not just harmony subset

The gpt-oss tokenizer has added tokens like <|return|> (id=200002) that
are not part of the harmony channel protocol but can leak into output.
The previous regex only stripped channel|message|start|end tokens.

Broaden the _clean_generated_text regex for gpt-oss to <\|[a-z_]+\|>
which catches all pipe-delimited tokens (return, constrain, reserved,
etc.) without matching <think>/<\/think> tags.

Verified: gpt-oss all_special_tokens are only <|return|>,
<|reserved_200017|>, <|startoftext|> -- none overlap with <think>.
The harmony tokens (channel, message, start, end) are added_tokens
but not in all_special_tokens.

* fix: hide config-only model repos from cached models list

Repos that only have metadata/config files cached (no .safetensors or
.bin weight files) were showing up in the Downloaded list with tiny
sizes like "1.8 KB" or "24 KB". These are just leftover config
snapshots from architecture checks, not usable models.

Filter the cached-models endpoint to only include repos that contain
actual model weight files (.safetensors or .bin).

* studio: fix toast description text contrast in dark mode

Add explicit !text-muted-foreground to toast description classNames
so secondary text (e.g. "Releases VRAM and resets inference state.")
is readable in dark mode.

* studio: fix Chat card icon alignment with size-4 spacer

Replace sr-only span (takes no space) with a size-4 shrink-0 div
matching the RadioGroupItem dimensions in other cards, so the Chat
icon aligns vertically with Text/Audio/Vision/Embeddings icons.

---------

Co-authored-by: workspace <user@workspace.local>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Manan17 <shahmanan170602@gmail.com>
Co-authored-by: Roland Tannous <rolandtannous@gravityq.ai>
2026-03-17 07:46:07 -07:00
Daniel Han
29f7fddac6 Studio UI 2026-03-17 07:44:54 -07:00
Michael Han
f3b6e0e486
Add files via upload 2026-03-17 06:42:25 -07:00
Roland Tannous
c6bd55ec61
fix(llm_assist): disable thinking mode for helper model JSON output (#4358)
* fix(llm_assist): disable thinking mode for helper model JSON output

Pass enable_thinking=False to generate_chat_completion() in both
_run_with_helper() and _generate_with_backend() so the Qwen3.5-4B
helper model produces clean JSON instead of wrapping responses in
<think> tags.

* fix(llm_assist): log per-request enable_thinking=False override

Add info-level log lines so the user can see that each helper/advisor
request overrides the server-level thinking default to False.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-17 15:58:08 +04:00
Roland Tannous
a0aba96ebd
fix: comment out debug print statements (#4357) 2026-03-17 15:43:27 +04:00
Daniel Han
37fe04f7bf
studio: add SVG preview, fix streaming bug and model selector state (#4354)
- Add SVG preview rendering below code blocks using safe data URI
  in <img> tag. Includes sanitization to block script/event handlers.
- Fix GGUF streaming crash: cache response.iter_text() iterator
  instead of creating a new one on every loop iteration.
- Fix model selector showing "Select model..." after auto-load by
  re-reading store state after setCheckpoint before setParams.
- Remove unused warmupToastShown variable (TS6133 build error).
- Change default suggestion to "Draw an SVG of a cute sloth".
2026-03-17 02:34:05 -07:00
Datta Nimmaturi
33dc47da72
Fix spacing in setup.sh echo statements 2026-03-17 14:53:55 +05:30
Roland Tannous
df01a139a0
fix: remove unused warmupToastShown variable to fix TS6133 build error (#4353) 2026-03-17 02:03:15 -07:00
Daniel Han
fe05b700dc
studio: fix slow cancellation of GGUF generation (#4352)
The streaming loop used response.iter_text() with timeout=None, which
blocks until the next chunk arrives from llama-server. On large models
like Qwen3.5-27B where each token takes seconds, pressing Stop in the
UI would not take effect until the next token was produced.

Fix by using a 0.5s read timeout and a new _iter_text_cancellable()
helper that checks cancel_event between timeout windows and explicitly
closes the response when cancelled. Applied to both the regular chat
completion and tool-calling streaming paths.
2026-03-17 01:47:21 -07:00
Daniel Han
b437c9a36d
studio: update Creative/Precise presets, show "Off" for disabled samplers (#4350)
Creative: temperature=1.5, min_p=0.1, top_p=Off (1.0), top_k=Off (0)
Precise: temperature=0.1, top_p=0.95, top_k=80, min_p=0.01

Also show "Off" in the slider label for top_p=1.0, top_k=0, and
repetition_penalty=1.0 since those values disable their respective
samplers. Changed top_k slider min from -1 to 0.
2026-03-17 01:32:18 -07:00
Daniel Han
ee6f057cc2
studio: show "Off" for repetition penalty = 1 (#4349) 2026-03-17 01:28:33 -07:00
Daniel Han
c00a993a68
studio: fix stale GGUF metadata, update helper model, auth improvements (#4346)
* studio: switch helper model to Qwen3.5-4B-GGUF

Replace Qwen3-4B-Instruct-2507-GGUF with Qwen3.5-4B-GGUF as the
default helper model for LLM-assisted dataset detection. Same
UD-Q4_K_XL variant.

* studio: fix stale GGUF metadata when switching models (#4347)

Reset _supports_reasoning, _supports_tools, _context_length, and
_chat_template at the start of _read_gguf_metadata() to prevent
stale settings from a previous model leaking into the next load.

Co-authored-by: Daniel Han <daniel@unsloth.ai>

* studio: change login error to "Incorrect password", add reset-password CLI

- Login error now says "Incorrect password" instead of the generic
  "Incorrect username or password" since Studio only has one account.
- Add `unsloth studio reset-password` command that deletes the auth
  database so a fresh admin account with a new random password is
  created on the next server start.

* studio: include reset command in login error message

* studio: change password setup subtitle wording
2026-03-17 01:22:08 -07:00
Daniel Han
eeffa4c065
studio: web search, KV cache dtype, training progress, inference fixes
## Summary
- Add web search tool calling for GGUF models (Search toggle, DuckDuckGo via ddgs)
- Add KV cache dtype dropdown (f16/bf16/q8_0/q5_1/q4_1) in Chat Settings
- Fix Qwen3/3.5 inference defaults per official docs (thinking on/off params)
- Enable reasoning by default for Qwen3.5 4B and 9B
- Replace "Generating" toast with inline spinner
- Fix stop button via asyncio.to_thread (event loop no longer blocked)
- Fix CUDA 12 compat lib paths for llama-server on CUDA 13 systems
- Fix auto-load model name not appearing in selector
- Training progress messages + dataset_num_proc fix

Integrated PRs:
- #4327 (imagineer99): BETA badge alignment (already in tree)
- #4340 (Manan Shah): prioritize training models in model selection
- #4344 (Roland Tannous): setup.sh macOS python version compatibility
- #4345 (Manan Shah): revamp model+dataset checking logic
2026-03-17 00:30:01 -07:00
pluesclues
f5e1f52b48
Add check to disable xformers on newer GPUs (#4342)
Disable xformers for GPUs with compute capability >= 12 to ensure compatibility with newer hardware.
2026-03-16 22:42:38 -07:00
Michael Han
a804325171
Update Unsloth_Studio_Colab.ipynb 2026-03-16 22:30:12 -07:00
Michael Han
674ce29131
Update Unsloth_Studio_Colab.ipynb 2026-03-16 22:28:58 -07:00
Michael Han
f0afafd4ba
Update Unsloth_Studio_Colab.ipynb 2026-03-16 22:16:39 -07:00
Michael Han
227759df61
Update Unsloth_Studio_Colab.ipynb 2026-03-16 22:15:07 -07:00
Datta Nimmaturi
bbf6414caf
Fix formatting of launch command in setup.ps1 2026-03-17 10:19:16 +05:30
Leo Borcherding
df98569f12
studio: improve Colab notebook, redesign ready popup, and clean up install output (#4339)
* Removing .precommit config

* edited colab comments

* studio: update Unsloth_Studio_Colab.ipynb

* studio: update Unsloth_Studio_Colab.ipynb

* studio: add Colab T4 GPU metadata to force T4 instance

* style: update colab popup to black/white theme with gem icon and play button

* feat: center landscape image in colab notebook

* style: shrink popup to fit content, truncate URL display

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* feat: center landscape image in colab notebook

* feat: use GitHub raw URL for studio landscape image in notebook

* chore: update colab notebook

* feat: add studio landscape colab display image and update notebook

* feat: update notebook with studio landscape image

* style: remove colors, add progress bar, add VERBOSE flag to install output

* docs: add comments explaining VERBOSE flag and progress bar

* chore: update colab notebook

* fix: define VERBOSE, _STEP, _TOTAL at module level to fix NameError

---------

Co-authored-by: LeoBorcherding <LeoBorcherding@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-16 21:39:25 -07:00
Daniel Han
dc2879a048
Fix xformers Blackwell guard: broader coverage and root cause docs (#4338)
* Remove outdated xformers Blackwell version guard

The guard at _utils.py:976-989 blocked xformers 0.0.32.post2 on
Blackwell/RTX 50x/Jetson GPUs (SM 10.0/11.0/12.0) due to a FA3
dispatch bug that caused CUDA errors (issue #1329).

This is no longer needed because:

1. xformers fixed the FA3 dispatch in 0.0.33.post2 by capping it
   at SM <= 9.0, so FA3 is never attempted on Blackwell. The FA2
   backend works correctly via PTX forward compatibility.

2. The only blocked version (0.0.32.post2) was built for torch 2.8.0
   and cannot load on torch 2.9+ due to ABI mismatch, so the guard
   never actually triggers for any current user.

3. The existing _register_extensions() check plus the except Exception
   fallback already handle broken xformers installs gracefully by
   falling back to SDPA.

Verified on NVIDIA RTX PRO 6000 Blackwell (SM 12.0) with both
pre-built wheels (0.0.33.post2) and source builds -- all attention
tests pass with exact numerical match vs SDPA.

* Update xformers Blackwell guard with root cause and broader coverage

Changes to the xformers version guard for Blackwell/RTX 50x/Jetson GPUs:

1. Broaden version check from `in (0.0.32.post2,)` to `<= 0.0.32.post2`
   to cover all versions with the broken FA3 dispatch, not just one.

2. Add `DEVICE_TYPE == "cuda"` guard to avoid calling
   `get_device_capability()` on non-CUDA devices (XPU, etc.).

3. Document the root cause: xformers <= 0.0.32.post2 used
   `capability >= (9, 0)` in the FA3 dispatch, which matched
   Blackwell SM 12.0 and attempted sm_90a Hopper kernels on it.
   Fixed upstream in 0.0.33 with `<= (9, 0)`.

4. Update error message to include the installed version, mention
   the fix (upgrade to >= 0.0.33), and keep the build-from-source
   fallback. The raise is caught by `except Exception` which shows
   the message when UNSLOTH_ENABLE_LOGGING is set and falls back
   to SDPA.

Verified on NVIDIA RTX PRO 6000 Blackwell (SM 12.0):
- xformers 0.0.33.post2 pre-built wheel: works (FA2 via PTX)
- xformers source build: works (FA2 native)
- Both have exact numerical match vs SDPA

---------

Co-authored-by: Daniel Han <danielhanchen@users.noreply.github.com>
2026-03-16 21:30:03 -07:00
Daniel Han
6912a15a42
fix: add Qwen3.5 version gate in loader dispatch (#4335)
* fix: add Qwen3.5 version gate in loader dispatch (#4188)

Qwen3.5 (model_type qwen3_5) only exists in transformers >= 5.0.0.
Without this gate, loading a Qwen3.5 model on transformers 4.x gives
an unhelpful generic error. This adds a clear version check before the
qwen3 dispatch to prevent substring misrouting and give a useful error
message pointing users to upgrade.

No dedicated FastQwen3_5Model is needed -- the compiler already applies
fused CE automatically via apply_fused_lm_head for both
Qwen3_5ForCausalLM and Qwen3_5ForConditionalGeneration. The generic
FastModel fallback path handles everything.

FORCE_FLOAT32 already has qwen3_5 on main.

Tested on transformers 5.3.0: Qwen3.5-0.8B 4bit, 1.38 GB peak memory.
Backwards compatible: import unsloth works on transformers 4.57.6.

* fix: update FORCE_FLOAT32 comment for qwen3_5

The (1+w) RMSNorm pattern does not overflow float16 since Qwen3_5RMSNorm
computes in float32 internally. The actual reason FORCE_FLOAT32 is needed
is that Qwen3.5 GDN layers produce NaN grad norms during float16 training.
Updated the comment to reflect the real reason.

* fix: move qwen3_5 version check before dispatch chain

The elif block intercepted qwen3_5 on transformers >= 5.0.0 without
setting dispatch_model, causing UnboundLocalError at line 715.

Move the version check before the if/elif dispatch chain so on
transformers >= 5.0.0 the model_type falls through to the generic
FastModel path as intended.

* fix: qwen3_5 requires transformers >= 5.2.0, not 5.0.0

Checked all 5.x releases:
- 5.0.0: no qwen3_5 module
- 5.1.0: no qwen3_5 module
- 5.2.0: qwen3_5 available

* fix: move qwen3_5 version check into AutoConfig error handler

The previous version check at the dispatch chain was unreachable --
AutoConfig.from_pretrained fails first with a generic "does not
recognize this architecture" error on transformers < 5.2.0, so
execution never reached the check.

Move the qwen3_5-specific error message into the AutoConfig exception
handler where "architecture" errors are caught. This intercepts the
error before the generic message and gives users a clear upgrade path.

Also remove the now-redundant check before the dispatch chain.
Both FastLanguageModel and FastModel paths are covered.

Tested: transformers 4.57.6 shows the Qwen3.5-specific error,
transformers 5.3.0 loads and trains normally.

---------

Co-authored-by: Daniel Han <danielhanchen@users.noreply.github.com>
2026-03-16 20:37:42 -07:00
Leo Borcherding
262271a20d
Fix/colab comment edits (#4317)
* Removing .precommit config

* edited colab comments

* studio: update Unsloth_Studio_Colab.ipynb

* studio: update Unsloth_Studio_Colab.ipynb

* studio: add Colab T4 GPU metadata to force T4 instance

* style: update colab popup to black/white theme with gem icon and play button

* feat: center landscape image in colab notebook

* style: shrink popup to fit content, truncate URL display

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* feat: center landscape image in colab notebook

* feat: use GitHub raw URL for studio landscape image in notebook

* chore: update colab notebook

---------

Co-authored-by: LeoBorcherding <LeoBorcherding@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-16 16:15:46 -07:00
pre-commit-ci[bot]
1c3f201943
[pre-commit.ci] pre-commit autoupdate (#4332)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.15.5 → v0.15.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.5...v0.15.6)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-16 14:41:49 -07:00