Fix studio setup: venv isolation, centralized .venv_t5, uv targeting
- All platforms (including Colab) now create ~/.unsloth/studio/.venv with --without-pip fallback for broken ensurepip environments - Add --python sys.executable to uv pip install in install_python_stack.py so uv targets the correct venv instead of system Python - Centralize .venv_t5 bootstrap in transformers_version.py with proper validation (checks required packages exist, not just non-empty dir) - Replace ~150 lines of duplicated install code across 3 worker files with calls to the shared _ensure_venv_t5_exists() helper - Use uv-if-present with pip fallback; do not install uv at runtime - Add site.addsitedir() shim in colab.py so notebook cells can import studio packages from the venv without system-Python double-install - Update .venv_t5 packages: huggingface_hub 1.3.0->1.7.1, add hf_xet - Bump transformers pin 4.57.1->4.57.6 in requirements + constraints - Add Fast-Install helper to setup.ps1 with uv+pip fallback - Keep Colab-specific completion banner in setup.sh
This commit is contained in:
parent
f43091bf34
commit
fc2d577d0d
10 changed files with 239 additions and 224 deletions
|
|
@ -7,8 +7,26 @@ Uses Colab's built-in proxy - no external tunneling needed!
|
|||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import site
|
||||
import sys
|
||||
|
||||
|
||||
def _bootstrap_studio_venv() -> None:
|
||||
"""Expose the Studio venv's site-packages to the current interpreter.
|
||||
|
||||
On Colab, notebook cells run outside the venv subshell. Instead of
|
||||
installing the full stack into system Python, we add the venv's
|
||||
site-packages so that packages like structlog, fastapi, etc. are
|
||||
importable from notebook cells.
|
||||
"""
|
||||
venv_lib = Path.home() / ".unsloth" / "studio" / ".venv" / "lib"
|
||||
for sp in venv_lib.glob("python*/site-packages"):
|
||||
if str(sp) not in sys.path:
|
||||
site.addsitedir(str(sp))
|
||||
|
||||
|
||||
_bootstrap_studio_venv()
|
||||
|
||||
# Add backend to path early so local modules like loggers can be imported
|
||||
backend_path = str(Path(__file__).parent)
|
||||
if backend_path not in sys.path:
|
||||
|
|
|
|||
|
|
@ -40,59 +40,25 @@ def _activate_transformers_version(model_name: str) -> None:
|
|||
if backend_path not in sys.path:
|
||||
sys.path.insert(0, backend_path)
|
||||
|
||||
from utils.transformers_version import needs_transformers_5, _resolve_base_model
|
||||
from utils.transformers_version import (
|
||||
needs_transformers_5,
|
||||
_resolve_base_model,
|
||||
_ensure_venv_t5_exists,
|
||||
_VENV_T5_DIR,
|
||||
)
|
||||
|
||||
resolved = _resolve_base_model(model_name)
|
||||
if needs_transformers_5(resolved):
|
||||
venv_t5 = os.path.join(
|
||||
os.path.expanduser("~"), ".unsloth", "studio", ".venv_t5"
|
||||
)
|
||||
if os.path.isdir(venv_t5):
|
||||
sys.path.insert(0, venv_t5)
|
||||
logger.info("Activated transformers 5.x from %s", venv_t5)
|
||||
else:
|
||||
# Fallback: pip install at runtime (slower, ~10-15s)
|
||||
logger.warning(".venv_t5 not found at %s — installing at runtime", venv_t5)
|
||||
import subprocess as sp
|
||||
|
||||
os.makedirs(venv_t5, exist_ok = True)
|
||||
r1 = sp.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--target",
|
||||
venv_t5,
|
||||
"--no-deps",
|
||||
"transformers==5.3.0",
|
||||
],
|
||||
stdout = sp.PIPE,
|
||||
stderr = sp.STDOUT,
|
||||
if not _ensure_venv_t5_exists():
|
||||
raise RuntimeError(
|
||||
f"Cannot activate transformers 5.x: .venv_t5 missing at {_VENV_T5_DIR}"
|
||||
)
|
||||
r2 = sp.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--target",
|
||||
venv_t5,
|
||||
"--no-deps",
|
||||
"huggingface_hub==1.3.0",
|
||||
],
|
||||
stdout = sp.PIPE,
|
||||
stderr = sp.STDOUT,
|
||||
)
|
||||
if r1.returncode != 0 or r2.returncode != 0:
|
||||
raise RuntimeError(
|
||||
f"Failed to install transformers 5.x into {venv_t5}. "
|
||||
f"pip returncode: transformers={r1.returncode}, huggingface_hub={r2.returncode}"
|
||||
)
|
||||
sys.path.insert(0, venv_t5)
|
||||
if _VENV_T5_DIR not in sys.path:
|
||||
sys.path.insert(0, _VENV_T5_DIR)
|
||||
logger.info("Activated transformers 5.x from %s", _VENV_T5_DIR)
|
||||
# Propagate to child subprocesses (e.g. GGUF converter)
|
||||
_pp = os.environ.get("PYTHONPATH", "")
|
||||
os.environ["PYTHONPATH"] = venv_t5 + (os.pathsep + _pp if _pp else "")
|
||||
os.environ["PYTHONPATH"] = _VENV_T5_DIR + (os.pathsep + _pp if _pp else "")
|
||||
else:
|
||||
logger.info("Using default transformers (4.57.x) for %s", model_name)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,59 +42,25 @@ def _activate_transformers_version(model_name: str) -> None:
|
|||
if backend_path not in sys.path:
|
||||
sys.path.insert(0, backend_path)
|
||||
|
||||
from utils.transformers_version import needs_transformers_5, _resolve_base_model
|
||||
from utils.transformers_version import (
|
||||
needs_transformers_5,
|
||||
_resolve_base_model,
|
||||
_ensure_venv_t5_exists,
|
||||
_VENV_T5_DIR,
|
||||
)
|
||||
|
||||
resolved = _resolve_base_model(model_name)
|
||||
if needs_transformers_5(resolved):
|
||||
venv_t5 = os.path.join(
|
||||
os.path.expanduser("~"), ".unsloth", "studio", ".venv_t5"
|
||||
)
|
||||
if os.path.isdir(venv_t5):
|
||||
sys.path.insert(0, venv_t5)
|
||||
logger.info("Activated transformers 5.x from %s", venv_t5)
|
||||
else:
|
||||
# Fallback: pip install at runtime (slower, ~10-15s)
|
||||
logger.warning(".venv_t5 not found at %s — installing at runtime", venv_t5)
|
||||
import subprocess as sp
|
||||
|
||||
os.makedirs(venv_t5, exist_ok = True)
|
||||
r1 = sp.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--target",
|
||||
venv_t5,
|
||||
"--no-deps",
|
||||
"transformers==5.3.0",
|
||||
],
|
||||
stdout = sp.PIPE,
|
||||
stderr = sp.STDOUT,
|
||||
if not _ensure_venv_t5_exists():
|
||||
raise RuntimeError(
|
||||
f"Cannot activate transformers 5.x: .venv_t5 missing at {_VENV_T5_DIR}"
|
||||
)
|
||||
r2 = sp.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--target",
|
||||
venv_t5,
|
||||
"--no-deps",
|
||||
"huggingface_hub==1.3.0",
|
||||
],
|
||||
stdout = sp.PIPE,
|
||||
stderr = sp.STDOUT,
|
||||
)
|
||||
if r1.returncode != 0 or r2.returncode != 0:
|
||||
raise RuntimeError(
|
||||
f"Failed to install transformers 5.x into {venv_t5}. "
|
||||
f"pip returncode: transformers={r1.returncode}, huggingface_hub={r2.returncode}"
|
||||
)
|
||||
sys.path.insert(0, venv_t5)
|
||||
if _VENV_T5_DIR not in sys.path:
|
||||
sys.path.insert(0, _VENV_T5_DIR)
|
||||
logger.info("Activated transformers 5.x from %s", _VENV_T5_DIR)
|
||||
# Propagate to child subprocesses (e.g. GGUF converter)
|
||||
_pp = os.environ.get("PYTHONPATH", "")
|
||||
os.environ["PYTHONPATH"] = venv_t5 + (os.pathsep + _pp if _pp else "")
|
||||
os.environ["PYTHONPATH"] = _VENV_T5_DIR + (os.pathsep + _pp if _pp else "")
|
||||
else:
|
||||
logger.info("Using default transformers (4.57.x) for %s", model_name)
|
||||
|
||||
|
|
|
|||
|
|
@ -36,59 +36,25 @@ def _activate_transformers_version(model_name: str) -> None:
|
|||
if backend_path not in sys.path:
|
||||
sys.path.insert(0, backend_path)
|
||||
|
||||
from utils.transformers_version import needs_transformers_5, _resolve_base_model
|
||||
from utils.transformers_version import (
|
||||
needs_transformers_5,
|
||||
_resolve_base_model,
|
||||
_ensure_venv_t5_exists,
|
||||
_VENV_T5_DIR,
|
||||
)
|
||||
|
||||
resolved = _resolve_base_model(model_name)
|
||||
if needs_transformers_5(resolved):
|
||||
venv_t5 = os.path.join(
|
||||
os.path.expanduser("~"), ".unsloth", "studio", ".venv_t5"
|
||||
)
|
||||
if os.path.isdir(venv_t5):
|
||||
sys.path.insert(0, venv_t5)
|
||||
logger.info("Activated transformers 5.x from %s", venv_t5)
|
||||
else:
|
||||
# Fallback: pip install at runtime (slower, ~10-15s)
|
||||
logger.warning(".venv_t5 not found at %s — installing at runtime", venv_t5)
|
||||
import subprocess as sp
|
||||
|
||||
os.makedirs(venv_t5, exist_ok = True)
|
||||
r1 = sp.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--target",
|
||||
venv_t5,
|
||||
"--no-deps",
|
||||
"transformers==5.3.0",
|
||||
],
|
||||
stdout = sp.PIPE,
|
||||
stderr = sp.STDOUT,
|
||||
if not _ensure_venv_t5_exists():
|
||||
raise RuntimeError(
|
||||
f"Cannot activate transformers 5.x: .venv_t5 missing at {_VENV_T5_DIR}"
|
||||
)
|
||||
r2 = sp.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--target",
|
||||
venv_t5,
|
||||
"--no-deps",
|
||||
"huggingface_hub==1.3.0",
|
||||
],
|
||||
stdout = sp.PIPE,
|
||||
stderr = sp.STDOUT,
|
||||
)
|
||||
if r1.returncode != 0 or r2.returncode != 0:
|
||||
raise RuntimeError(
|
||||
f"Failed to install transformers 5.x into {venv_t5}. "
|
||||
f"pip returncode: transformers={r1.returncode}, huggingface_hub={r2.returncode}"
|
||||
)
|
||||
sys.path.insert(0, venv_t5)
|
||||
if _VENV_T5_DIR not in sys.path:
|
||||
sys.path.insert(0, _VENV_T5_DIR)
|
||||
logger.info("Activated transformers 5.x from %s", _VENV_T5_DIR)
|
||||
# Propagate to child subprocesses (e.g. GGUF converter)
|
||||
_pp = os.environ.get("PYTHONPATH", "")
|
||||
os.environ["PYTHONPATH"] = venv_t5 + (os.pathsep + _pp if _pp else "")
|
||||
os.environ["PYTHONPATH"] = _VENV_T5_DIR + (os.pathsep + _pp if _pp else "")
|
||||
else:
|
||||
logger.info("Using default transformers (4.57.x) for %s", model_name)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,4 +11,4 @@ git+https://github.com/meta-pytorch/OpenEnv.git
|
|||
# executorch>=1.0.1 # 41.5 MB - no imports in unsloth/zoo/studio
|
||||
torch-c-dlpack-ext
|
||||
sentence_transformers==5.2.0
|
||||
transformers==4.57.1
|
||||
transformers==4.57.6
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Single-env pins for unsloth + studio + data-designer
|
||||
# Keep compatible with unsloth transformers bounds.
|
||||
transformers==4.57.1
|
||||
transformers==4.57.6
|
||||
trl==0.23.1
|
||||
huggingface-hub==0.36.2
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import json
|
|||
import structlog
|
||||
from loggers import get_logger
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
|
@ -58,7 +59,7 @@ _tokenizer_class_cache: dict[str, bool] = {}
|
|||
|
||||
# Versions
|
||||
TRANSFORMERS_5_VERSION = "5.3.0"
|
||||
TRANSFORMERS_DEFAULT_VERSION = "4.57.1"
|
||||
TRANSFORMERS_DEFAULT_VERSION = "4.57.6"
|
||||
|
||||
# Pre-installed directory for transformers 5.x — created by setup.sh / setup.ps1
|
||||
_VENV_T5_DIR = str(Path.home() / ".unsloth" / "studio" / ".venv_t5")
|
||||
|
|
@ -216,29 +217,73 @@ def _purge_modules() -> int:
|
|||
return len(to_remove)
|
||||
|
||||
|
||||
_VENV_T5_PACKAGES = (
|
||||
f"transformers=={TRANSFORMERS_5_VERSION}",
|
||||
"huggingface_hub==1.7.1",
|
||||
"hf_xet==1.4.2",
|
||||
)
|
||||
|
||||
|
||||
def _venv_t5_is_valid() -> bool:
|
||||
"""Return True if .venv_t5/ has all required packages installed."""
|
||||
if not os.path.isdir(_VENV_T5_DIR) or not os.listdir(_VENV_T5_DIR):
|
||||
return False
|
||||
# Check that the key package directories actually exist
|
||||
for pkg_spec in _VENV_T5_PACKAGES:
|
||||
pkg_name = pkg_spec.split("==")[0].replace("-", "_")
|
||||
if not any(
|
||||
(Path(_VENV_T5_DIR) / d).is_dir()
|
||||
for d in (pkg_name, pkg_name.replace("_", "-"))
|
||||
):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _install_to_venv_t5(pkg: str) -> bool:
|
||||
"""Install a single package into .venv_t5/, preferring uv then pip."""
|
||||
# Try uv first (faster) if already on PATH -- do NOT install uv at runtime
|
||||
if shutil.which("uv"):
|
||||
result = subprocess.run(
|
||||
[
|
||||
"uv", "pip", "install",
|
||||
"--python", sys.executable,
|
||||
"--target", _VENV_T5_DIR,
|
||||
"--no-deps", pkg,
|
||||
],
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.STDOUT,
|
||||
text = True,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
logger.warning("uv install of %s failed, falling back to pip", pkg)
|
||||
|
||||
# Fallback to pip
|
||||
result = subprocess.run(
|
||||
[
|
||||
sys.executable, "-m", "pip", "install",
|
||||
"--target", _VENV_T5_DIR,
|
||||
"--no-deps", pkg,
|
||||
],
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.STDOUT,
|
||||
text = True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logger.error("install failed:\n%s", result.stdout)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _ensure_venv_t5_exists() -> bool:
|
||||
"""Ensure .venv_t5/ exists. Install at runtime if missing."""
|
||||
if os.path.isdir(_VENV_T5_DIR) and os.listdir(_VENV_T5_DIR):
|
||||
"""Ensure .venv_t5/ exists with all required packages. Install if missing."""
|
||||
if _venv_t5_is_valid():
|
||||
return True
|
||||
|
||||
logger.warning(".venv_t5 not found at %s — installing at runtime", _VENV_T5_DIR)
|
||||
logger.warning(".venv_t5 not found or incomplete at %s -- installing at runtime", _VENV_T5_DIR)
|
||||
os.makedirs(_VENV_T5_DIR, exist_ok = True)
|
||||
for pkg in (f"transformers=={TRANSFORMERS_5_VERSION}", "huggingface_hub==1.3.0"):
|
||||
cmd = [
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--target",
|
||||
_VENV_T5_DIR,
|
||||
"--no-deps",
|
||||
pkg,
|
||||
]
|
||||
result = subprocess.run(
|
||||
cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, text = True
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logger.error("pip install failed:\n%s", result.stdout)
|
||||
for pkg in _VENV_T5_PACKAGES:
|
||||
if not _install_to_venv_t5(pkg):
|
||||
return False
|
||||
logger.info("Installed transformers 5.x to %s", _VENV_T5_DIR)
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -140,15 +140,15 @@ def _bootstrap_uv() -> bool:
|
|||
global UV_NEEDS_SYSTEM
|
||||
if not shutil.which("uv"):
|
||||
return False
|
||||
# Probe: try a dry-run install without --system.
|
||||
# If uv can't find a venv it exits with code 2.
|
||||
# Probe: try a dry-run install targeting the current Python explicitly.
|
||||
# Without --python, uv can ignore the activated venv on some platforms.
|
||||
probe = subprocess.run(
|
||||
["uv", "pip", "install", "--dry-run", "pip"],
|
||||
["uv", "pip", "install", "--dry-run", "--python", sys.executable, "pip"],
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.STDOUT,
|
||||
)
|
||||
if probe.returncode != 0:
|
||||
# Retry with --system to confirm it works
|
||||
# Retry with --system (some envs need it when uv can't find a venv)
|
||||
probe_sys = subprocess.run(
|
||||
["uv", "pip", "install", "--dry-run", "--system", "pip"],
|
||||
stdout = subprocess.PIPE,
|
||||
|
|
@ -204,6 +204,10 @@ def _build_uv_cmd(args: tuple[str, ...]) -> list[str]:
|
|||
cmd = ["uv", "pip", "install"]
|
||||
if UV_NEEDS_SYSTEM:
|
||||
cmd.append("--system")
|
||||
# Always pass --python so uv targets the correct environment.
|
||||
# Without this, uv can ignore an activated venv and install into
|
||||
# the system Python (observed on Colab and similar environments).
|
||||
cmd.extend(["--python", sys.executable])
|
||||
cmd.extend(_translate_pip_args_for_uv(args))
|
||||
cmd.append("--torch-backend=auto")
|
||||
return cmd
|
||||
|
|
|
|||
|
|
@ -872,7 +872,35 @@ $ErrorActionPreference = "Continue"
|
|||
|
||||
$ActivateScript = Join-Path $VenvDir "Scripts\Activate.ps1"
|
||||
. $ActivateScript
|
||||
pip install --upgrade pip 2>&1 | Out-Null
|
||||
|
||||
# Try to use uv (much faster than pip), fall back to pip if unavailable
|
||||
$UseUv = $false
|
||||
if (Get-Command uv -ErrorAction SilentlyContinue) {
|
||||
$UseUv = $true
|
||||
} else {
|
||||
Write-Host " Installing uv package manager..." -ForegroundColor Cyan
|
||||
try {
|
||||
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" 2>&1 | Out-Null
|
||||
Refresh-Environment
|
||||
# Re-activate venv since Refresh-Environment rebuilds PATH from
|
||||
# registry and drops the venv's Scripts directory
|
||||
. $ActivateScript
|
||||
if (Get-Command uv -ErrorAction SilentlyContinue) { $UseUv = $true }
|
||||
} catch { }
|
||||
}
|
||||
|
||||
# Helper: install a package, preferring uv with pip fallback
|
||||
function Fast-Install {
|
||||
param([Parameter(ValueFromRemainingArguments=$true)]$Args_)
|
||||
if ($UseUv) {
|
||||
$VenvPy = (Get-Command python).Source
|
||||
$result = & uv pip install --python $VenvPy @Args_ 2>&1
|
||||
if ($LASTEXITCODE -eq 0) { return }
|
||||
}
|
||||
& python -m pip install @Args_ 2>&1
|
||||
}
|
||||
|
||||
Fast-Install --upgrade pip | Out-Null
|
||||
|
||||
# if (-not $IsPipInstall) {
|
||||
# # Running from repo: copy requirements and do editable install
|
||||
|
|
@ -909,14 +937,14 @@ Write-Host "[OK] TORCHINDUCTOR_CACHE_DIR set to $TorchCacheDir (avoids MAX_PATH
|
|||
|
||||
$CuTag = Get-PytorchCudaTag
|
||||
Write-Host " Installing PyTorch with CUDA support ($CuTag)..." -ForegroundColor Cyan
|
||||
pip install torch torchvision torchaudio --index-url "https://download.pytorch.org/whl/$CuTag" 2>&1 | Out-Null
|
||||
Fast-Install torch torchvision torchaudio --index-url "https://download.pytorch.org/whl/$CuTag" | Out-Null
|
||||
|
||||
# Install Triton for Windows (enables torch.compile — without it training can hang)
|
||||
# Install Triton for Windows (enables torch.compile -- without it training can hang)
|
||||
Write-Host " Installing Triton for Windows..." -ForegroundColor Cyan
|
||||
pip install "triton-windows<3.7" 2>&1 | Out-Null
|
||||
Fast-Install "triton-windows<3.7" | Out-Null
|
||||
Write-Host "[OK] Triton for Windows installed (enables torch.compile)" -ForegroundColor Green
|
||||
|
||||
# Ordered heavy dependency installation — shared cross-platform script
|
||||
# Ordered heavy dependency installation -- shared cross-platform script
|
||||
Write-Host " Running ordered dependency installation..." -ForegroundColor Cyan
|
||||
python "$PSScriptRoot\install_python_stack.py"
|
||||
# Restore ErrorActionPreference after pip/python work
|
||||
|
|
@ -925,7 +953,7 @@ $ErrorActionPreference = $prevEAP
|
|||
# ── Pre-install transformers 5.x into .venv_t5/ ──
|
||||
# Models like GLM-4.7-Flash need transformers>=5.3.0. Instead of pip-installing
|
||||
# at runtime (slow, ~10-15s), we pre-install into a separate directory.
|
||||
# The training subprocess just prepends .venv_t5/ to sys.path — instant switch.
|
||||
# The training subprocess just prepends .venv_t5/ to sys.path -- instant switch.
|
||||
Write-Host ""
|
||||
Write-Host " Pre-installing transformers 5.x for newer model support..." -ForegroundColor Cyan
|
||||
$VenvT5Dir = Join-Path $env:USERPROFILE ".unsloth\studio\.venv_t5"
|
||||
|
|
@ -933,17 +961,13 @@ if (Test-Path $VenvT5Dir) { Remove-Item -Recurse -Force $VenvT5Dir }
|
|||
New-Item -ItemType Directory -Path $VenvT5Dir -Force | Out-Null
|
||||
$prevEAP_t5 = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
pip install --target $VenvT5Dir --no-deps "transformers==5.3.0" 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[FAIL] Could not install transformers 5.3.0 into .venv_t5/" -ForegroundColor Red
|
||||
$ErrorActionPreference = $prevEAP_t5
|
||||
exit 1
|
||||
}
|
||||
pip install --target $VenvT5Dir --no-deps "huggingface_hub==1.3.0" 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[FAIL] Could not install huggingface_hub 1.3.0 into .venv_t5/" -ForegroundColor Red
|
||||
$ErrorActionPreference = $prevEAP_t5
|
||||
exit 1
|
||||
foreach ($pkg in @("transformers==5.3.0", "huggingface_hub==1.7.1", "hf_xet==1.4.2")) {
|
||||
Fast-Install --target $VenvT5Dir --no-deps $pkg | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[FAIL] Could not install $pkg into .venv_t5/" -ForegroundColor Red
|
||||
$ErrorActionPreference = $prevEAP_t5
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
$ErrorActionPreference = $prevEAP_t5
|
||||
Write-Host "[OK] Transformers 5.x pre-installed to .venv_t5/" -ForegroundColor Green
|
||||
|
|
|
|||
102
studio/setup.sh
102
studio/setup.sh
|
|
@ -240,50 +240,73 @@ install_python_stack() {
|
|||
python "$SCRIPT_DIR/install_python_stack.py"
|
||||
}
|
||||
|
||||
if [ "$IS_COLAB" = true ]; then
|
||||
# Colab: install packages directly without venv
|
||||
install_python_stack
|
||||
else
|
||||
# Local: create venv under ~/.unsloth/studio/ (shared location, not in repo)
|
||||
STUDIO_HOME="$HOME/.unsloth/studio"
|
||||
VENV_DIR="$STUDIO_HOME/.venv"
|
||||
VENV_T5_DIR="$STUDIO_HOME/.venv_t5"
|
||||
mkdir -p "$STUDIO_HOME"
|
||||
# Create venv under ~/.unsloth/studio/ (shared location, not in repo).
|
||||
# All platforms (including Colab) use the same isolated venv so that
|
||||
# studio dependencies are never installed into the system Python.
|
||||
STUDIO_HOME="$HOME/.unsloth/studio"
|
||||
VENV_DIR="$STUDIO_HOME/.venv"
|
||||
VENV_T5_DIR="$STUDIO_HOME/.venv_t5"
|
||||
mkdir -p "$STUDIO_HOME"
|
||||
|
||||
# Clean up legacy in-repo venvs if they exist
|
||||
[ -d "$REPO_ROOT/.venv" ] && rm -rf "$REPO_ROOT/.venv"
|
||||
[ -d "$REPO_ROOT/.venv_overlay" ] && rm -rf "$REPO_ROOT/.venv_overlay"
|
||||
[ -d "$REPO_ROOT/.venv_t5" ] && rm -rf "$REPO_ROOT/.venv_t5"
|
||||
# Clean up legacy in-repo venvs if they exist
|
||||
[ -d "$REPO_ROOT/.venv" ] && rm -rf "$REPO_ROOT/.venv"
|
||||
[ -d "$REPO_ROOT/.venv_overlay" ] && rm -rf "$REPO_ROOT/.venv_overlay"
|
||||
[ -d "$REPO_ROOT/.venv_t5" ] && rm -rf "$REPO_ROOT/.venv_t5"
|
||||
|
||||
rm -rf "$VENV_DIR"
|
||||
rm -rf "$VENV_T5_DIR"
|
||||
"$BEST_PY" -m venv "$VENV_DIR"
|
||||
rm -rf "$VENV_DIR"
|
||||
rm -rf "$VENV_T5_DIR"
|
||||
# Try creating venv with pip; fall back to --without-pip + bootstrap
|
||||
# (some environments like Colab have broken ensurepip)
|
||||
if ! "$BEST_PY" -m venv "$VENV_DIR" 2>/dev/null; then
|
||||
"$BEST_PY" -m venv --without-pip "$VENV_DIR"
|
||||
source "$VENV_DIR/bin/activate"
|
||||
cd "$SCRIPT_DIR"
|
||||
install_python_stack
|
||||
curl -sS https://bootstrap.pypa.io/get-pip.py | python > /dev/null
|
||||
else
|
||||
source "$VENV_DIR/bin/activate"
|
||||
fi
|
||||
|
||||
# ── 6b. Pre-install transformers 5.x into .venv_t5/ ──
|
||||
# Models like GLM-4.7-Flash need transformers>=5.3.0. Instead of pip-installing
|
||||
# at runtime (slow, ~10-15s), we pre-install into a separate directory.
|
||||
# The training subprocess just prepends .venv_t5/ to sys.path — instant switch.
|
||||
echo ""
|
||||
echo " Pre-installing transformers 5.x for newer model support..."
|
||||
mkdir -p "$VENV_T5_DIR"
|
||||
run_quiet "pip install transformers 5.x" pip install --target "$VENV_T5_DIR" --no-deps "transformers==5.3.0"
|
||||
run_quiet "pip install huggingface_hub for t5" pip install --target "$VENV_T5_DIR" --no-deps "huggingface_hub==1.3.0"
|
||||
echo "✅ Transformers 5.x pre-installed to $VENV_T5_DIR/"
|
||||
# ── Ensure uv is available (much faster than pip) ──
|
||||
USE_UV=false
|
||||
if command -v uv &>/dev/null; then
|
||||
USE_UV=true
|
||||
elif curl -LsSf https://astral.sh/uv/install.sh | sh > /dev/null 2>&1; then
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
command -v uv &>/dev/null && USE_UV=true
|
||||
fi
|
||||
|
||||
# ── 7. WSL: pre-install GGUF build dependencies ──
|
||||
# On WSL, sudo requires a password and can't be entered during GGUF export
|
||||
# (runs in a non-interactive subprocess). Install build deps here instead.
|
||||
if grep -qi microsoft /proc/version 2>/dev/null; then
|
||||
echo ""
|
||||
echo "⚠️ WSL detected — installing build dependencies for GGUF export..."
|
||||
echo " You may be prompted for your password."
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y build-essential cmake curl git libcurl4-openssl-dev
|
||||
echo "✅ GGUF build dependencies installed"
|
||||
# Helper: install a package, preferring uv with pip fallback
|
||||
fast_install() {
|
||||
if [ "$USE_UV" = true ]; then
|
||||
uv pip install --python "$(command -v python)" "$@" && return 0
|
||||
fi
|
||||
python -m pip install "$@"
|
||||
}
|
||||
|
||||
cd "$SCRIPT_DIR"
|
||||
install_python_stack
|
||||
|
||||
# ── 6b. Pre-install transformers 5.x into .venv_t5/ ──
|
||||
# Models like GLM-4.7-Flash need transformers>=5.3.0. Instead of pip-installing
|
||||
# at runtime (slow, ~10-15s), we pre-install into a separate directory.
|
||||
# The training subprocess just prepends .venv_t5/ to sys.path -- instant switch.
|
||||
echo ""
|
||||
echo " Pre-installing transformers 5.x for newer model support..."
|
||||
mkdir -p "$VENV_T5_DIR"
|
||||
run_quiet "install transformers 5.x" fast_install --target "$VENV_T5_DIR" --no-deps "transformers==5.3.0"
|
||||
run_quiet "install huggingface_hub for t5" fast_install --target "$VENV_T5_DIR" --no-deps "huggingface_hub==1.7.1"
|
||||
run_quiet "install hf_xet for t5" fast_install --target "$VENV_T5_DIR" --no-deps "hf_xet==1.4.2"
|
||||
echo "✅ Transformers 5.x pre-installed to $VENV_T5_DIR/"
|
||||
|
||||
# ── 7. WSL: pre-install GGUF build dependencies ──
|
||||
# On WSL, sudo requires a password and can't be entered during GGUF export
|
||||
# (runs in a non-interactive subprocess). Install build deps here instead.
|
||||
if grep -qi microsoft /proc/version 2>/dev/null; then
|
||||
echo ""
|
||||
echo "⚠️ WSL detected -- installing build dependencies for GGUF export..."
|
||||
echo " You may be prompted for your password."
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y build-essential cmake curl git libcurl4-openssl-dev
|
||||
echo "✅ GGUF build dependencies installed"
|
||||
fi
|
||||
|
||||
# ── 8. Build llama.cpp binaries for GGUF inference + export ──
|
||||
|
|
@ -422,6 +445,9 @@ if [ "$IS_COLAB" = true ]; then
|
|||
echo "╠══════════════════════════════════════╣"
|
||||
echo "║ Unsloth Studio is ready to start ║"
|
||||
echo "║ in your Colab notebook! ║"
|
||||
echo "║ ║"
|
||||
echo "║ from colab import start ║"
|
||||
echo "║ start() ║"
|
||||
echo "╚══════════════════════════════════════╝"
|
||||
else
|
||||
echo "╔══════════════════════════════════════╗"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue