Commit graph

79 commits

Author SHA1 Message Date
Daniel Han
f1293fe7d8 studio: respect existing CUDA_VISIBLE_DEVICES in GPU selection
If CUDA_VISIBLE_DEVICES is already set in the environment (e.g.,
by the user or a wrapper script), only consider those GPUs when
selecting devices for llama-server. nvidia-smi reports all physical
GPUs regardless of CUDA_VISIBLE_DEVICES, so we filter its output
to match the allowed set.

Without this, the GPU selector could pick a GPU outside the user's
allowed set, overriding their restriction.
2026-03-15 05:24:06 -07:00
pre-commit-ci[bot]
e885d7308e [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-03-15 05:24:06 -07:00
Daniel Han
12183e0656 studio: smart GPU allocation for GGUF inference
Automatically select the best GPU(s) for a GGUF model based on
file size and available VRAM, instead of relying on hardcoded
-ngl -1 or letting llama-server guess.

Logic:
1. Measure total GGUF file size (including split shards)
2. Query free memory per GPU via nvidia-smi
3. If the model fits in 70% of the most-free GPU's memory,
   pin to that single GPU (CUDA_VISIBLE_DEVICES=X, no --fit)
4. If it needs multiple GPUs, pick the N most-free GPUs
   (CUDA_VISIBLE_DEVICES=X,Y, no --fit)
5. If it's too large for all GPUs combined, omit
   CUDA_VISIBLE_DEVICES and use --fit on to let llama-server
   handle partial offloading

The 70% threshold accounts for KV cache and compute buffers
that sit on top of the model weights.

Removed the -ngl parameter (was hardcoded to -1). llama-server's
default of "auto" handles layer offloading correctly, especially
with --fit on for oversized models.

Tested on 8x B200:
  - 1B model (0.75 GB):  picks 1 GPU, no --fit
  - 27B model (17 GB):   picks 1 GPU, no --fit
  - 405B model (230 GB): picks 2 GPUs, no --fit
  - 2TB model:           all GPUs, --fit on
2026-03-15 05:24:06 -07:00
pre-commit-ci[bot]
7202f81985 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-03-15 05:24:06 -07:00
Daniel Han
80d84a5b5f studio: optimize llama-server flags for single-user studio
Refactor command building (deduplicate HF/local paths) and add
flags for better performance:

- --parallel 1: studio is single-user, so only 1 inference slot
  is needed. The previous auto-detect picked 4 slots, wasting
  VRAM on 3 unused KV caches.
- --flash-attn on: force flash attention for faster inference.
  Default is "auto" which may not always enable it.
- --fit on: auto-adjust parameters to fit in available device
  memory. Already the default but now explicit.

Also cleaned up the duplicated command building for HF vs local
mode into a single block.
2026-03-15 05:24:06 -07:00
Daniel Han
887e7a31c4 studio: don't cap max_tokens for GGUF inference
Remove the hard max_tokens=2048 default and le=4096 cap for GGUF
chat completions. When max_tokens is not set (None), the field is
omitted from the llama-server payload entirely, letting the model
generate until it produces an EOS token or hits the context limit.

This is critical for thinking/reasoning models (Qwen3.5, DeepSeek-R1,
etc.) where the thinking phase alone can consume 1000+ tokens before
the actual answer. With the previous 2048 default, simple questions
like "What is 2+2?" used all tokens on thinking and produced empty
visible responses.

Changes:
- llama_cpp.py: max_tokens default None, only include in payload
  when explicitly set
- models/inference.py: default None, remove le=4096 cap
- routes/inference.py: pass max_tokens directly, no "or 2048" fallback

llama-server handles omitted max_tokens gracefully (generates until
EOS or context limit). The context size (-c flag, default 4096) acts
as the hard upper bound.
2026-03-15 05:24:06 -07:00
Daniel Han
961720c1b1 studio: handle reasoning_content in GGUF streaming
llama-server sends thinking/reasoning tokens as "reasoning_content"
in the SSE delta (separate from "content"). The studio was only
reading delta.content, so all reasoning tokens from models like
Qwen3.5, Qwen3-Thinking, DeepSeek-R1, etc. were silently dropped.

This caused "replies with nothing" for thinking models: the model
would spend its entire token budget on reasoning, produce zero
content tokens, and the user would see an empty response.

Fix: read reasoning_content from the delta and wrap it in
<think>...</think> tags. The frontend already has full support
for these tags (parse-assistant-content.ts splits them into
reasoning parts, reasoning.tsx renders a collapsible "Thinking..."
indicator).

Verified with Qwen3.5-27B-GGUF (UD-Q4_K_XL):
  - Before: "What is 2+2?" -> empty response (all tokens in reasoning)
  - After: shows collapsible thinking + answer "4"
2026-03-15 05:24:06 -07:00
Roland Tannous
477e68675b
Fix: Compare Mode Deadlock, Cancel Event Poisoning & IPC Optimization (#4303)
* fix: resolve compare mode deadlock, cancel_event poisoning, and add dispatcher-based IPC optimization

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

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

* revert to 2048 tokens

* refactor: extract dispatcher timeout values into named constants

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

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

* fix: guard dispatcher shutdown against active compare mailboxes

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-15 16:11:44 +04:00
Daniel Han
88c7b08faa
fix: prevent ai-assist model config RCE via untrusted Hugging Face repos (#4274)
* fix: disable remote code loading for ai-assist model hint lookup

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

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

---------

Co-authored-by: Roland Tannous <115670425+rolandtannous@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-03-13 19:29:11 +04:00
Roland Tannous
e539965740 fix error for chat template 2026-03-13 15:18:04 +00:00
Roland Tannous
47654cb91c Final cleanup 2026-03-12 18:28:04 +00:00
Roland Tannous
a2baf80511 Update license headers 2026-03-12 17:23:10 +00:00
Roland Tannous
6f77c63229 refactor: remove project_root passing, use self-resolved paths and ~/.unsloth/studio
- Workers now compute backend_path and venv_t5 locally via Path(__file__)
- Moved .venv_t5 to ~/.unsloth/studio/.venv_t5
- Added ensure_studio_directories() call on server startup
- Expanded CLI studio command into sub-app with setup subcommand
2026-03-11 20:32:18 +00:00
Roland Tannous
817f2e8dcc feat: integrate structlog, configure workers for prod logging, and migrate print statements 2026-03-11 12:33:16 +00:00
Roland Tannous
b84202e8db fix: restrict shard siblings to exact basename and total count
startswith(prefix) could match unrelated split variants whose names
extend the selected file's prefix (e.g. model-Q8_0-v2-00001-of-...).
Now builds an exact regex from the chosen file's base prefix and shard
total so only true siblings are downloaded.
2026-03-10 19:28:26 +00:00
Roland Tannous
d635846b8d fix: use exact variant matching and shard-prefix discovery for split GGUFs
Substring matching (e.g. "Q8_0" in filename) could match superset
variants like "IQ8_0", causing wrong quantizations to be downloaded.
Now uses word-boundary regex for variant matching and discovers split
shards by shared filename prefix rather than treating all variant
matches as shards.
2026-03-10 19:13:03 +00:00
Roland Tannous
defa761fb2 fix: download all GGUF shards for split models (e.g. 7B Q8_0)
LlamaCppBackend.load_model() only downloaded the first matching GGUF
file. For split models (e.g. 7B Q8_0 with 3 shards), llama-server
needs all shards present. Now collects and downloads all matching files.
2026-03-10 19:04:10 +00:00
Roland Tannous
d882678fe4 Add AGPL-3.0 SPDX headers to all source files 2026-03-09 20:17:45 +00:00
samit
86e94b5844 exposed trust_remote_code through the UI 2026-03-08 16:28:56 -07:00
Manan17
80b704d7b7 Audio_VLM bug fix 2026-03-08 19:14:07 +00:00
Roland Tannous
7ee81dd7df feat: route audio inference (TTS, ASR, Whisper) through orchestrator/worker subprocess 2026-03-08 18:25:27 +00:00
Roland Tannous
1435dbaf59 merge nightly into audio branch (mock test) 2026-03-08 10:23:44 +00:00
Roland Tannous
a7c34b42be fix: clear stale model state on failed inference subprocess reload 2026-03-07 23:32:53 +00:00
Roland Tannous
ef9184c731 fix: prevent training hang on Windows by adding triton-windows support 2026-03-07 17:53:36 +00:00
Roland Tannous
e25705a211 fix: propagate PYTHONPATH to child subprocesses, revert tokenizer patching 2026-03-07 11:28:24 +00:00
Roland Tannous
76c78afb8f fix: patch TokenizersBackend by model name - Qwen3.5→Qwen2Tokenizer, GLM→PreTrainedTokenizer 2026-03-07 10:29:59 +00:00
Roland Tannous
d60cd2843f fix: patch Qwen3.5 broken tokenizer_class TokenizersBackend across all backends 2026-03-07 09:43:25 +00:00
Roland Tannous
bd60562145 fix: bump transformers 5.x pin from 5.1.0 to 5.2.0 for Qwen3.5 support 2026-03-07 09:10:09 +00:00
Roland Tannous
0b3397cc3a fix: fail fast if runtime pip install of transformers 5.x fails 2026-03-07 08:40:25 +00:00
Roland Tannous
728420b290 fix: drain stale events from resp_queue after generation cancel 2026-03-07 08:12:16 +00:00
Roland Tannous
609e3168a1 fix: serialize generation with _gen_lock to prevent concurrent queue readers
Two overlapping /chat/completions requests could both read from the shared
resp_queue, consuming and dropping each other's token events. Replace the
request_id filtering (which silently dropped non-matching messages) with a
threading.Lock that serializes generation — correct for single-GPU inference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 04:06:51 +00:00
Roland Tannous
c3bc19494f fix: pin huggingface_hub==1.3.0 in .venv_t5 (satisfies transformers 5.x) 2026-03-06 06:19:28 +00:00
Roland Tannous
6b32af0bdc feat: subprocess-based export, pin huggingface_hub==0.36.0 2026-03-06 06:03:09 +00:00
Roland Tannous
31334cece1 fix: indentation error in orchestrator load_model 2026-03-05 19:43:30 +00:00
Roland Tannous
5bd6fac80e fix: always spawn fresh subprocess per model load
Reusing a subprocess after unsloth patches torch internals causes
inspect.getsource() failures when loading a different model type.
Each load now gets a clean Python interpreter.
2026-03-05 19:15:37 +00:00
Roland Tannous
7fc563731a fix: use mp.Event for instant cross-process generation cancel
Replaces cmd_queue-based cancel polling with a shared mp.Event.
Fixes two issues:
- Loading a new model while generating no longer hangs (cancel is instant)
- Subprocess shuts down cleanly after explicit stop generation
2026-03-05 18:54:17 +00:00
Roland Tannous
4eabc74f34 feat: subprocess-based inference for transformers version switching
Inference now runs in a persistent subprocess, solving the same
transformers version-switching problem that was fixed for training.
The subprocess stays alive between requests (model in GPU memory)
and is only restarted when switching transformers versions.

New files:
- core/inference/worker.py: subprocess entry point with command loop
- core/inference/orchestrator.py: parent-side proxy with same API

Modified:
- core/inference/__init__.py: exports orchestrator as default backend
- routes/inference.py: removed in-process ensure_transformers_version()
2026-03-05 17:47:57 +00:00
Manan17
9909111982 resolved merge conflicts 2026-03-05 07:59:43 +00:00
Roland Tannous
2d7d3cd27e Merge pull request #287 from unslothai/fix/duplicate-def-inference
Deleted duplicate definitions for load_for_eval, load_adapter, and load_model_simple in core Inference
2026-03-04 10:06:04 +04:00
Roland Tannous
a4d2853fbc fix: align llama-server binary discovery with upstream unsloth-zoo paths 2026-03-03 17:03:01 +00:00
Roland Tannous
87f2b2a9db Merge branch 'nightly' into feature/support-for-audio-models 2026-03-02 15:55:25 +04:00
Roland Tannous
e280e457d1 Move llama.cpp clone/build from in-tree to ~/.unsloth/llama.cpp
- setup.sh: builds at ~/.unsloth/llama.cpp instead of ./llama.cpp
- setup.ps1: builds at %USERPROFILE%/.unsloth/llama.cpp
- inference llama_cpp.py: searches ~/.unsloth/ first, in-tree as legacy
- export.py: updated comments (unsloth-zoo handles path natively)
2026-03-02 04:04:41 +00:00
Roland Tannous
6e5a3d1744 Download GGUF via huggingface_hub instead of llama-server -hf (fixes HTTPS not supported on Windows) 2026-03-01 13:05:10 +00:00
Roland Tannous
12867f701b Auto-add CUDA DLLs to PATH when launching llama-server on Windows 2026-03-01 13:05:10 +00:00
Roland Tannous
3521de7040 Build llama.cpp in-tree, auto-detect driver CUDA version for compatible toolkit 2026-03-01 13:05:10 +00:00
Roland Tannous
f036a70681 Fix llama-server binary lookup for Windows (.exe, Release dir, ~/.unsloth) 2026-03-01 13:05:10 +00:00
Roland Tannous
ff93c97024 fix: support mmproj for local vision GGUF models + fix Windows pipe deadlock 2026-03-01 12:58:38 +00:00
Manan17
c636fd5a42 code cleanup 2026-03-01 08:04:38 +00:00
Manan17
c48437848d revamping up the code and adding inference 2026-03-01 02:30:31 +00:00
samit
862b4100d2 deleted duplicate definitions 2026-02-27 06:00:28 -08:00