Disable pip cache for Cookbook dependency installs (off the home disk) (#1477)

Cookbook dependency installs (vLLM and friends) build large wheels; pip's
default cache lives under $HOME/.cache/pip, so on a small home filesystem the
build dies mid-way with "[Errno 28] No space left on device" (issue #1219) and
the dependency ends up "installed" but unusable (issue #1459).

Add `--no-cache-dir` to the dependency pip-install command (the maintainer's
suggested PIP_CACHE_DIR= workaround, made the default) via a small
_pip_install_no_cache() helper applied at the install chokepoint. Consistent
with the existing --no-cache-dir on the llama-cpp-python build. Idempotent;
non-pip-install serve commands are untouched.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lekt8
2026-06-03 13:23:49 +08:00
committed by GitHub
parent 1feb2ae7d5
commit ffb8fd16bc
3 changed files with 40 additions and 1 deletions
+15
View File
@@ -148,6 +148,21 @@ def _local_tooling_path_export(executable: str) -> str:
return f'export PATH="{esc}:$PATH"' return f'export PATH="{esc}:$PATH"'
def _pip_install_no_cache(cmd: str) -> str:
"""Add ``--no-cache-dir`` to a pip install command.
Cookbook dependency installs (vLLM, llama-cpp-python, …) build large wheels;
pip's default cache lives under ``$HOME/.cache/pip`` and these builds can fill
a small home filesystem with ``[Errno 28] No space left on device`` mid-build
(issue #1219), leaving the dependency "installed" but unusable (#1459).
Disabling the cache for these one-off installs keeps them off the home disk
(the maintainer's suggested ``PIP_CACHE_DIR=`` workaround, made the default).
Idempotent; leaves non-pip-install commands untouched."""
if not cmd or "pip install" not in cmd or "--no-cache-dir" in cmd:
return cmd
return cmd.replace("pip install", "pip install --no-cache-dir", 1)
def _pip_install_attempt(pip_cmd: str) -> str: def _pip_install_attempt(pip_cmd: str) -> str:
"""Wrap a single pip install command so its exit status survives the """Wrap a single pip install command so its exit status survives the
fallback chain and its stderr is visible in the tmux log on failure. fallback chain and its stderr is visible in the tmux log on failure.
+5 -1
View File
@@ -38,7 +38,7 @@ from routes.cookbook_helpers import (
_ps_squote, _bash_squote, _validate_serve_cmd, _parse_serve_phase, _ps_squote, _bash_squote, _validate_serve_cmd, _parse_serve_phase,
_safe_env_prefix, _local_tooling_path_export, _append_serve_preflight_exit_lines, _safe_env_prefix, _local_tooling_path_export, _append_serve_preflight_exit_lines,
_append_serve_exit_code_lines, _append_llama_cpp_linux_accel_build_lines, _cached_model_scan_script, _append_serve_exit_code_lines, _append_llama_cpp_linux_accel_build_lines, _cached_model_scan_script,
_ollama_bind_from_cmd, _pip_install_fallback_chain, _venv_safe_local_pip_install_cmd, _ollama_bind_from_cmd, _pip_install_fallback_chain, _pip_install_no_cache, _venv_safe_local_pip_install_cmd,
ModelDownloadRequest, ServeRequest, ModelDownloadRequest, ServeRequest,
) )
@@ -841,6 +841,10 @@ def setup_cookbook_routes() -> APIRouter:
) )
is_pip_install = bool(req.cmd and "pip install" in req.cmd) is_pip_install = bool(req.cmd and "pip install" in req.cmd)
if is_pip_install: if is_pip_install:
# Keep big dependency wheel builds (vLLM, …) off the home filesystem's
# pip cache so they don't fail mid-build with "No space left" (#1219)
# and leave the dep installed-but-unusable (#1459).
req.cmd = _pip_install_no_cache(req.cmd)
# PEP-508-style package spec — letters, digits, `.-_` for the # PEP-508-style package spec — letters, digits, `.-_` for the
# name; `[` `]` for extras; `<>=!~,` for version specifiers. # name; `[` `]` for extras; `<>=!~,` for version specifiers.
# v2 review HIGH-14: tightened from the previous regex which # v2 review HIGH-14: tightened from the previous regex which
+20
View File
@@ -415,3 +415,23 @@ def test_cached_model_scan_reports_plain_dir_gguf(tmp_path):
assert ggufs[1]["size_bytes"] == len(b"part1part2part3") assert ggufs[1]["size_bytes"] == len(b"part1part2part3")
assert ggufs[2]["quant"] == "Q6_K_XL" assert ggufs[2]["quant"] == "Q6_K_XL"
assert ggufs[3]["quant"] == "BF16" assert ggufs[3]["quant"] == "BF16"
# ── #1219 / #1459: keep big dependency wheel builds off the home pip cache ──
def test_pip_install_no_cache_injects_flag():
from routes.cookbook_helpers import _pip_install_no_cache
assert _pip_install_no_cache("python -m pip install vllm") == \
"python -m pip install --no-cache-dir vllm"
assert _pip_install_no_cache("pip install -q huggingface-hub") == \
"pip install --no-cache-dir -q huggingface-hub"
def test_pip_install_no_cache_is_idempotent_and_scoped():
from routes.cookbook_helpers import _pip_install_no_cache
# already present -> unchanged
already = "pip install --no-cache-dir vllm"
assert _pip_install_no_cache(already) == already
# not a pip install -> unchanged
assert _pip_install_no_cache("vllm serve --model x") == "vllm serve --model x"
assert _pip_install_no_cache("") == ""