| #!/usr/bin/env bash |
| |
|
|
| SUDO="" |
| if [ "$(id -u)" -ne 0 ]; then SUDO="sudo"; fi |
|
|
| |
| |
| ensure_hf_home () { |
| local dest="/dev/shm/hf_home" |
| local ws="${WORKSPACE:-/workspace}" |
| mkdir -p "$dest" |
| if [ -d "${ws}/.hf_home" ] && [ ! -L "${ws}/.hf_home" ]; then |
| |
| cp -a "${ws}/.hf_home/." "$dest/" 2>/dev/null || true |
| rm -rf "${ws}/.hf_home" |
| fi |
| ln -sfn "$dest" "${ws}/.hf_home" |
| export HF_HOME="$dest" |
| export HUGGINGFACE_HUB_CACHE="$dest/hub" |
| |
| if [ -d "$ws" ] && ! grep -q '^HF_HOME=' "${ws}/.env" 2>/dev/null; then |
| printf 'HF_HOME="%s"\nHUGGINGFACE_HUB_CACHE="%s/hub"\n' "$dest" "$dest" >> "${ws}/.env" |
| fi |
| } |
|
|
| |
| |
| ensure_toolchain () { |
| if ! command -v nvcc >/dev/null 2>&1; then |
| echo "[bootstrap] nvcc not found -- installing CUDA toolkit (this can take a few minutes)" |
| $SUDO apt-get update -y |
| wget -q https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb -O /tmp/cuda-keyring.deb |
| $SUDO dpkg -i /tmp/cuda-keyring.deb |
| $SUDO apt-get update -y |
| $SUDO apt-get install -y cuda-toolkit-13-0 |
| fi |
|
|
| |
| |
| local gcc_major |
| gcc_major="$(gcc -dumpversion | cut -d. -f1)" |
| local cc1plus_path |
| cc1plus_path="$(gcc -print-prog-name=cc1plus)" |
| if [ ! -f "$cc1plus_path" ]; then |
| echo "[bootstrap] cc1plus missing for gcc-$gcc_major -- installing g++-$gcc_major" |
| $SUDO apt-get update -y |
| $SUDO apt-get install -y "g++-${gcc_major}" build-essential |
| fi |
| } |
|
|
| |
| |
| |
| ensure_venv () { |
| local name="$1"; shift |
| local venv_dir="$HOME/${name}-env" |
| if [ ! -f "$venv_dir/bin/activate" ]; then |
| echo "[bootstrap] creating venv: $venv_dir" |
| python3 -m venv "$venv_dir" |
| fi |
| |
| source "$venv_dir/bin/activate" |
| |
| export PIP_NO_CACHE_DIR=1 |
| export UV_NO_CACHE=1 |
| pip install --upgrade pip -q |
| if [ "$#" -gt 0 ]; then |
| echo "[bootstrap] pip install: $*" |
| pip install "$@" -q |
| fi |
| } |
|
|
| |
| |
| |
| ensure_sglang_omni () { |
| local venv_dir="$HOME/sglang-env" |
| local src="/dev/shm/sglang-omni-src" |
| local overrides="/tmp/sgl-omni-overrides.txt" |
|
|
| ensure_hf_home |
| if [ ! -f "$venv_dir/bin/activate" ]; then |
| echo "[bootstrap] creating venv: $venv_dir" |
| python3 -m venv "$venv_dir" |
| fi |
| |
| source "$venv_dir/bin/activate" |
| export PIP_NO_CACHE_DIR=1 |
| export UV_NO_CACHE=1 |
|
|
| if [ ! -d "$src/.git" ]; then |
| echo "[bootstrap] cloning sglang-omni -> $src" |
| rm -rf "$src" |
| git clone --depth 1 https://github.com/sgl-project/sglang-omni.git "$src" |
| fi |
|
|
| |
| _patch_moss_blackwell "$src" |
|
|
| if command -v sgl-omni >/dev/null 2>&1 && python3 -c "import sglang" 2>/dev/null; then |
| return 0 |
| fi |
|
|
| |
| printf 'protobuf>=6.31.1,<7.0.0\n' > "$overrides" |
|
|
| echo "[bootstrap] uv pip install -e sglang-omni (protobuf override)" |
| uv pip install --python "$venv_dir/bin/python" -e "$src" --override "$overrides" |
| } |
|
|
| _patch_moss_blackwell () { |
| local src="$1" |
| local vocoder="$src/sglang_omni/models/moss_tts_local/vocoder_decoder.py" |
| local tokenizer="$src/sglang_omni/models/moss_tts_local/audio_tokenizer.py" |
|
|
| if [ -f "$vocoder" ] && ! grep -q 'major >= 10' "$vocoder" 2>/dev/null; then |
| python3 - "$vocoder" <<'PY' |
| from pathlib import Path |
| import sys |
| path = Path(sys.argv[1]) |
| text = path.read_text() |
| old = """try: |
| from sglang.jit_kernel.flash_attention import flash_attn_varlen_func |
| except ImportError: |
| flash_attn_varlen_func = None |
| """ |
| new = """try: |
| from sglang.jit_kernel.flash_attention import flash_attn_varlen_func |
| |
| # FA3 (sgl-kernel) rejects Blackwell (sm_120). FA4 cute varlen is not API- |
| # compatible with the FA2 call site used when FA3 is disabled. Fall back to |
| # the dense SDPA path in resolve_attention_implementation(). |
| if torch.cuda.is_available(): |
| _major, _ = torch.cuda.get_device_capability() |
| if _major >= 10: |
| flash_attn_varlen_func = None |
| except ImportError: |
| flash_attn_varlen_func = None |
| """ |
| if old not in text: |
| raise SystemExit(f"patch target not found in {path}") |
| path.write_text(text.replace(old, new, 1)) |
| print(f"[bootstrap] patched Moss vocoder for Blackwell: {path}") |
| PY |
| fi |
|
|
| if [ -f "$tokenizer" ] && ! grep -q 'Blackwell: flash-attn' "$tokenizer" 2>/dev/null; then |
| python3 - "$tokenizer" <<'PY' |
| from pathlib import Path |
| import sys |
| path = Path(sys.argv[1]) |
| text = path.read_text() |
| needle = " model.eval()\n model.to(device)\n return MossTTSLocalAudioTokenizer(" |
| insert = """ model.eval() |
| model.to(device) |
| # Blackwell: flash-attn FA2/FA3/FA4 paths are broken for this codec; force SDPA. |
| if hasattr(model, "set_attention_implementation"): |
| model.set_attention_implementation("sdpa") |
| for module in model.modules(): |
| if hasattr(module, "attn_implementation"): |
| module.attn_implementation = "sdpa" |
| if hasattr(module, "attention_implementation"): |
| module.attention_implementation = "sdpa" |
| return MossTTSLocalAudioTokenizer(""" |
| if needle not in text: |
| raise SystemExit(f"patch target not found in {path}") |
| path.write_text(text.replace(needle, insert, 1)) |
| print(f"[bootstrap] patched Moss audio tokenizer for Blackwell: {path}") |
| PY |
| fi |
| } |
|
|
|
|