From b4310b8cd153e02e1e66109fd2f1070e6724cec2 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 25 Mar 2026 15:51:45 +0000 Subject: [PATCH 1/3] Fix Colab Studio launch and setup.ps1 box alignment - colab.py: when the Studio venv is missing on Colab, pip-install backend dependencies (structlog, fastapi, etc.) from studio.txt into the current Python instead of failing with ModuleNotFoundError - setup.sh: on Colab without a venv, install backend deps into system Python and skip venv-dependent sections (Python stack update, llama.cpp build) that would otherwise fail - setup.ps1: use PadRight(47) for the done-line so "Setup Complete!" and "Update Complete!" both align with the box border --- studio/backend/colab.py | 29 +++++++++++++++++++++++++++++ studio/setup.ps1 | 3 ++- studio/setup.sh | 38 ++++++++++++++++++++++++++++++++------ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/studio/backend/colab.py b/studio/backend/colab.py index ecf9fc2907..885bb3961a 100644 --- a/studio/backend/colab.py +++ b/studio/backend/colab.py @@ -18,6 +18,28 @@ if _backend_dir not in sys.path: import _platform_compat # noqa: F401 +def _is_colab() -> bool: + """Detect Google Colab by checking for COLAB_ prefixed env vars.""" + import os + return any(k.startswith("COLAB_") for k in os.environ) + + +def _pip_install_backend_deps() -> None: + """Install Studio backend dependencies directly into the current Python. + + Used on Colab when the Studio venv does not exist (install.sh was not + run). Reads the requirements from studio.txt next to this file. + """ + import subprocess + req_file = Path(__file__).parent / "requirements" / "studio.txt" + if not req_file.exists(): + return + print("Installing Studio backend dependencies ...") + subprocess.check_call( + [sys.executable, "-m", "pip", "install", "-q", "-r", str(req_file)], + ) + + def _bootstrap_studio_venv() -> None: """Expose the Studio venv's site-packages to the current interpreter. @@ -25,9 +47,16 @@ def _bootstrap_studio_venv() -> None: installing the full stack into system Python, we prepend the venv's site-packages so that packages like structlog, fastapi, etc. are importable from notebook cells and take priority over system copies. + + If the venv does not exist and we are running on Colab, fall back to + pip-installing the backend dependencies into the current environment + so that imports like structlog and fastapi succeed. """ venv_lib = Path.home() / ".unsloth" / "studio" / "unsloth_studio" / "lib" if not venv_lib.exists(): + if _is_colab(): + _pip_install_backend_deps() + return import warnings warnings.warn( diff --git a/studio/setup.ps1 b/studio/setup.ps1 index 0ac54d3866..42bae42819 100644 --- a/studio/setup.ps1 +++ b/studio/setup.ps1 @@ -1746,8 +1746,9 @@ if (-not $NeedLlamaSourceBuild) { # ============================================ Write-Host "" $doneLine = if ($env:SKIP_STUDIO_BASE -eq "1") { "Setup Complete!" } else { "Update Complete!" } +$doneContent = " $doneLine" Write-Host "+===============================================+" -ForegroundColor Green -Write-Host "| $doneLine |" -ForegroundColor Green +Write-Host ("|" + $doneContent.PadRight(47) + "|") -ForegroundColor Green Write-Host "| |" -ForegroundColor Green Write-Host "| Launch with: |" -ForegroundColor Green Write-Host "| unsloth studio -H 0.0.0.0 -p 8888 |" -ForegroundColor Green diff --git a/studio/setup.sh b/studio/setup.sh index a7991b83be..dd758e49e8 100755 --- a/studio/setup.sh +++ b/studio/setup.sh @@ -292,15 +292,23 @@ VENV_T5_DIR="$STUDIO_HOME/.venv_t5" [ -d "$REPO_ROOT/.venv_t5" ] && rm -rf "$REPO_ROOT/.venv_t5" # Note: do NOT delete $STUDIO_HOME/.venv here — install.sh handles migration +_COLAB_NO_VENV=false if [ ! -x "$VENV_DIR/bin/python" ]; then - echo "❌ ERROR: Virtual environment not found at $VENV_DIR" - echo " Run install.sh first to create the environment:" - echo " curl -fsSL https://unsloth.ai/install.sh | sh" - exit 1 + if [ "$IS_COLAB" = true ]; then + # On Colab there is no Studio venv -- install backend deps into system Python + echo " Colab detected, installing Studio backend dependencies..." + pip install -q -r "$SCRIPT_DIR/backend/requirements/studio.txt" 2>/dev/null || true + _COLAB_NO_VENV=true + else + echo "❌ ERROR: Virtual environment not found at $VENV_DIR" + echo " Run install.sh first to create the environment:" + echo " curl -fsSL https://unsloth.ai/install.sh | sh" + exit 1 + fi +else + source "$VENV_DIR/bin/activate" fi -source "$VENV_DIR/bin/activate" - install_python_stack() { python "$SCRIPT_DIR/install_python_stack.py" } @@ -324,6 +332,24 @@ fast_install() { cd "$SCRIPT_DIR" +# On Colab without a venv, skip all venv-dependent sections (Python deps +# update, llama.cpp build) -- the backend deps were already installed above. +if [ "$_COLAB_NO_VENV" = true ]; then + echo "✅ Studio backend dependencies installed into system Python" + + echo "" + echo "╔══════════════════════════════════════╗" + echo "║ Setup Complete! ║" + echo "╠══════════════════════════════════════╣" + echo "║ Unsloth Studio is ready to start ║" + echo "║ in your Colab notebook! ║" + echo "║ ║" + echo "║ from colab import start ║" + echo "║ start() ║" + echo "╚══════════════════════════════════════╝" + exit 0 +fi + # ── Check if Python deps need updating ── # Compare installed package version against PyPI latest. # Skip all Python dependency work if versions match (fast update path). From 06b2ac61f448b1d3b3b13eb18d9c2c9a6ae49584 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 25 Mar 2026 16:17:33 +0000 Subject: [PATCH 2/3] Fix Colab huggingface-hub conflict and pip bootstrap on uv venvs - colab.py / setup.sh: relax == pins to >= when installing studio.txt on Colab so huggingface-hub does not clobber Colab's bundled version (which breaks transformers is_offline_mode import) - install_python_stack.py: when uv is unavailable and pip is missing (uv-created venvs), bootstrap via ensurepip before attempting upgrade --- studio/backend/colab.py | 19 ++++++++++++++++++- studio/install_python_stack.py | 23 +++++++++++++++++++---- studio/setup.sh | 7 +++++-- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/studio/backend/colab.py b/studio/backend/colab.py index 885bb3961a..19bdc2a2d8 100644 --- a/studio/backend/colab.py +++ b/studio/backend/colab.py @@ -29,14 +29,31 @@ def _pip_install_backend_deps() -> None: Used on Colab when the Studio venv does not exist (install.sh was not run). Reads the requirements from studio.txt next to this file. + + Strict ``==`` version pins are relaxed to ``>=`` so we do not clobber + Colab's pre-installed packages (e.g. huggingface-hub, datasets) with + versions that are incompatible with its bundled transformers. """ + import re import subprocess req_file = Path(__file__).parent / "requirements" / "studio.txt" if not req_file.exists(): return + + packages = [] + for line in req_file.read_text().splitlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + # Relax exact pins (==) to >= so pip keeps existing compatible versions + line = re.sub(r"==", ">=", line) + packages.append(line) + + if not packages: + return print("Installing Studio backend dependencies ...") subprocess.check_call( - [sys.executable, "-m", "pip", "install", "-q", "-r", str(req_file)], + [sys.executable, "-m", "pip", "install", "-q"] + packages, ) diff --git a/studio/install_python_stack.py b/studio/install_python_stack.py index 39fec2e6f5..603ac162c9 100644 --- a/studio/install_python_stack.py +++ b/studio/install_python_stack.py @@ -373,10 +373,25 @@ def install_python_stack() -> int: ], ) else: - run( - "Upgrading pip", - [sys.executable, "-m", "pip", "install", "--upgrade", "pip"], - ) + # pip may not exist yet (uv-created venvs omit it). Try ensurepip + # first, then upgrade. Only fall back to a direct upgrade when pip + # is already present. + _has_pip = subprocess.run( + [sys.executable, "-m", "pip", "--version"], + stdout = subprocess.DEVNULL, + stderr = subprocess.DEVNULL, + ).returncode == 0 + + if not _has_pip: + run( + "Bootstrapping pip via ensurepip", + [sys.executable, "-m", "ensurepip", "--upgrade"], + ) + else: + run( + "Upgrading pip", + [sys.executable, "-m", "pip", "install", "--upgrade", "pip"], + ) # 3. Core packages: unsloth-zoo + unsloth (or custom package name) if skip_base: diff --git a/studio/setup.sh b/studio/setup.sh index dd758e49e8..682b5cb01a 100755 --- a/studio/setup.sh +++ b/studio/setup.sh @@ -295,9 +295,12 @@ VENV_T5_DIR="$STUDIO_HOME/.venv_t5" _COLAB_NO_VENV=false if [ ! -x "$VENV_DIR/bin/python" ]; then if [ "$IS_COLAB" = true ]; then - # On Colab there is no Studio venv -- install backend deps into system Python + # On Colab there is no Studio venv -- install backend deps into system Python. + # Relax strict == pins to >= so we don't clobber Colab's pre-installed + # packages (huggingface-hub, datasets) with incompatible versions. echo " Colab detected, installing Studio backend dependencies..." - pip install -q -r "$SCRIPT_DIR/backend/requirements/studio.txt" 2>/dev/null || true + sed 's/==/>=/' "$SCRIPT_DIR/backend/requirements/studio.txt" \ + | pip install -q -r /dev/stdin 2>/dev/null || true _COLAB_NO_VENV=true else echo "❌ ERROR: Virtual environment not found at $VENV_DIR" From 27f218a099aa1885395a929837e67286cefc8a62 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Wed, 25 Mar 2026 16:18:37 +0000 Subject: [PATCH 3/3] Bump version to 2026.3.14 and installer min version pins --- install.ps1 | 6 +++--- install.sh | 6 +++--- unsloth/models/_utils.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/install.ps1 b/install.ps1 index bb0acf1237..3ef251715e 100644 --- a/install.ps1 +++ b/install.ps1 @@ -607,7 +607,7 @@ shell.Run cmd, 0, False # 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..." - uv pip install --python $VenvPython --reinstall-package unsloth --reinstall-package unsloth-zoo "unsloth>=2026.3.11" unsloth-zoo + uv pip install --python $VenvPython --reinstall-package unsloth --reinstall-package unsloth-zoo "unsloth>=2026.3.14" unsloth-zoo if ($StudioLocalInstall) { Write-Host "==> Overlaying local repo (editable)..." uv pip install --python $VenvPython -e $RepoRoot --no-deps @@ -622,7 +622,7 @@ shell.Run cmd, 0, False Write-Host "==> Installing unsloth (this may take a few minutes)..." if ($StudioLocalInstall) { - uv pip install --python $VenvPython --upgrade-package unsloth "unsloth>=2026.3.11" unsloth-zoo + uv pip install --python $VenvPython --upgrade-package unsloth "unsloth>=2026.3.14" unsloth-zoo Write-Host "==> Overlaying local repo (editable)..." uv pip install --python $VenvPython -e $RepoRoot --no-deps } else { @@ -632,7 +632,7 @@ shell.Run cmd, 0, False # Fallback: GPU detection failed to produce a URL -- let uv resolve torch Write-Host "==> Installing unsloth (this may take a few minutes)..." if ($StudioLocalInstall) { - uv pip install --python $VenvPython unsloth-zoo "unsloth>=2026.3.11" --torch-backend=auto + uv pip install --python $VenvPython unsloth-zoo "unsloth>=2026.3.14" --torch-backend=auto Write-Host "==> Overlaying local repo (editable)..." uv pip install --python $VenvPython -e $RepoRoot --no-deps } else { diff --git a/install.sh b/install.sh index 6f60c23d27..a0f6ef2ee5 100755 --- a/install.sh +++ b/install.sh @@ -767,7 +767,7 @@ if [ "$_MIGRATED" = true ]; then echo "==> Upgrading unsloth in migrated environment..." uv pip install --python "$_VENV_PY" \ --reinstall-package unsloth --reinstall-package unsloth-zoo \ - "unsloth>=2026.3.11" unsloth-zoo + "unsloth>=2026.3.14" unsloth-zoo if [ "$STUDIO_LOCAL_INSTALL" = true ]; then echo "==> Overlaying local repo (editable)..." uv pip install --python "$_VENV_PY" -e "$_REPO_ROOT" --no-deps @@ -781,7 +781,7 @@ elif [ -n "$TORCH_INDEX_URL" ]; then echo "==> Installing unsloth (this may take a few minutes)..." if [ "$STUDIO_LOCAL_INSTALL" = true ]; then uv pip install --python "$_VENV_PY" \ - --upgrade-package unsloth "unsloth>=2026.3.11" unsloth-zoo + --upgrade-package unsloth "unsloth>=2026.3.14" unsloth-zoo echo "==> Overlaying local repo (editable)..." uv pip install --python "$_VENV_PY" -e "$_REPO_ROOT" --no-deps else @@ -792,7 +792,7 @@ else # Fallback: GPU detection failed to produce a URL -- let uv resolve torch echo "==> Installing unsloth (this may take a few minutes)..." if [ "$STUDIO_LOCAL_INSTALL" = true ]; then - uv pip install --python "$_VENV_PY" unsloth-zoo "unsloth>=2026.3.11" --torch-backend=auto + uv pip install --python "$_VENV_PY" unsloth-zoo "unsloth>=2026.3.14" --torch-backend=auto echo "==> Overlaying local repo (editable)..." uv pip install --python "$_VENV_PY" -e "$_REPO_ROOT" --no-deps else diff --git a/unsloth/models/_utils.py b/unsloth/models/_utils.py index 02e2170b70..da912dec76 100644 --- a/unsloth/models/_utils.py +++ b/unsloth/models/_utils.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "2026.3.12" +__version__ = "2026.3.14" __all__ = [ "SUPPORTS_BFLOAT16",