Spaces:
Running
Running
| # syntax=docker/dockerfile:1 | |
| # --------------------------------------------------------------------------- | |
| # Dockerfile for a Hugging Face "Docker Space" that serves a GGUF model | |
| # (empero-ai/Qwythos-9B-Claude-Mythos-5-1M-GGUF) through llama-cpp-python | |
| # with a streaming Gradio chat UI. | |
| # | |
| # Design goals: | |
| # - Small final image -> multi-stage build. All compilers / build tools | |
| # (cmake, ninja, gcc) live ONLY in the builder stage. The runtime stage | |
| # just installs the pre-built wheel. | |
| # - Reliable build -> pin apt/pip behaviour (no interactive prompts, | |
| # no cache dirs left behind, explicit CMake flags for llama.cpp so the | |
| # build never silently falls back to something incompatible with the | |
| # CPU the Space actually runs on). | |
| # - CPU-only -> no CUDA/ROCm toolkits anywhere in the image. | |
| # --------------------------------------------------------------------------- | |
| # =========================== 1. Builder stage =============================== | |
| FROM python:3.11-slim AS builder | |
| # ca-certificates is needed either way (HTTPS to PyPI / abetlen's wheel | |
| # index / the HF Hub later). The heavy compiler toolchain (build-essential, | |
| # cmake, ninja, git) is installed ONLY in the fallback branch below, so the | |
| # common case pays no apt cost either. | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| ca-certificates \ | |
| && rm -rf /var/lib/apt/lists/* | |
| WORKDIR /build | |
| RUN pip install --no-cache-dir --upgrade pip wheel setuptools | |
| # --------------------------------------------------------------------------- | |
| # Fast path vs. fallback path for llama-cpp-python. | |
| # | |
| # The project's maintainer publishes prebuilt CPU-only wheels at a custom | |
| # index (https://abetlen.github.io/llama-cpp-python/whl/cpu). When one | |
| # matches our Python ABI (cp311) / platform (manylinux x86_64), this avoids | |
| # a from-source compile that otherwise takes 15-30+ minutes on a free HF | |
| # Spaces builder. `--only-binary=:all:` makes pip fail fast instead of | |
| # silently falling back to a slow sdist build if no wheel matches, so we | |
| # can detect the miss and switch strategies ourselves. | |
| # | |
| # If no prebuilt wheel is available (e.g. maintainer hasn't published one | |
| # for the current llama-cpp-python release / Python version yet), we fall | |
| # back to the original from-source build: install compilers, then build | |
| # with explicit CMake flags tuned for broad CPU compatibility: | |
| # - GGML_NATIVE=OFF : don't auto-detect the *build* machine's CPU flags. | |
| # The image is built on different hardware than it | |
| # runs on, so "native" builds can crash with | |
| # "illegal instruction" on the actual Space runner. | |
| # - GGML_AVX2/FMA/F16C: supported by virtually all modern x86_64 cloud | |
| # CPUs (including HF's free-tier runners), giving | |
| # good performance without AVX-512-only risk. | |
| # - CMAKE_BUILD_PARALLEL_LEVEL=nproc: the previous Dockerfile left this | |
| # unset, which on some setups serializes the C++ | |
| # compile across hundreds of translation units — | |
| # a big, avoidable chunk of that 20+ minute build. | |
| # - CMAKE_BUILD_TYPE=Release + Ninja: faster/smaller than default Make. | |
| RUN set -eux; \ | |
| if pip wheel --no-cache-dir --only-binary=:all: --wheel-dir /wheels \ | |
| --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cpu \ | |
| "llama-cpp-python"; \ | |
| then \ | |
| echo "==> Installed prebuilt CPU wheel for llama-cpp-python (fast path)"; \ | |
| else \ | |
| echo "==> No prebuilt wheel available; building llama-cpp-python from source"; \ | |
| apt-get update && apt-get install -y --no-install-recommends \ | |
| build-essential cmake ninja-build git \ | |
| && rm -rf /var/lib/apt/lists/*; \ | |
| export CMAKE_ARGS="-DGGML_NATIVE=OFF -DGGML_AVX2=ON -DGGML_FMA=ON -DGGML_F16C=ON -DCMAKE_BUILD_TYPE=Release -GNinja"; \ | |
| export FORCE_CMAKE=1; \ | |
| # Cap parallel compile jobs at 4: the free HF Spaces Docker builder | |
| # may report more cores than it has RAM to back, and a runaway | |
| # `-j$(nproc)` C++ compile is a classic way to get the build OOM-killed. | |
| BUILD_CORES="$(nproc)"; \ | |
| if [ "$BUILD_CORES" -gt 4 ]; then BUILD_CORES=4; fi; \ | |
| export CMAKE_BUILD_PARALLEL_LEVEL="$BUILD_CORES"; \ | |
| pip wheel --no-cache-dir --wheel-dir /wheels "llama-cpp-python"; \ | |
| fi | |
| # ============================ 2. Runtime stage ================================ | |
| FROM python:3.11-slim AS runtime | |
| LABEL maintainer="hf-space" \ | |
| description="Gradio chat UI serving empero-ai/Qwythos-9B-Claude-Mythos-5-1M-GGUF via llama-cpp-python" | |
| # Runtime-only system dependencies: | |
| # - libgomp1: OpenMP runtime required by llama.cpp's multithreaded kernels. | |
| # - ca-certificates: needed for HTTPS downloads from the Hugging Face Hub. | |
| # NOTE: no compilers, no cmake, no git here -> keeps the final image lean. | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| libgomp1 \ | |
| ca-certificates \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # Run as a non-root user (Hugging Face Spaces requirement/best practice). | |
| RUN useradd --create-home --uid 1000 appuser | |
| WORKDIR /app | |
| # Install the pre-built llama-cpp-python wheel from the builder stage. | |
| COPY --from=builder /wheels /wheels | |
| COPY requirements.txt . | |
| RUN pip install --no-cache-dir --upgrade pip && \ | |
| pip install --no-cache-dir /wheels/*.whl && \ | |
| pip install --no-cache-dir -r requirements.txt && \ | |
| rm -rf /wheels /root/.cache/pip ~/.cache/pip | |
| # Application code | |
| COPY app.py . | |
| # --------------------------------------------------------------------------- | |
| # Runtime configuration (all overridable as Space "Variables and secrets" | |
| # without touching the Dockerfile). See README.md for the full list. | |
| # --------------------------------------------------------------------------- | |
| ENV \ | |
| # Where to look for the GGUF model on the Hub. | |
| GGUF_REPO_ID="empero-ai/Qwythos-9B-Claude-Mythos-5-1M-GGUF" \ | |
| # Leave empty to auto-select; set to force an exact filename. | |
| GGUF_FILENAME="" \ | |
| # Quantization to prefer when auto-selecting (falls back automatically | |
| # if this exact quant isn't present in the repo). | |
| PREFERRED_QUANT="Q4_K_M" \ | |
| # Local, persistent-within-container cache for downloaded model files | |
| # and Hub metadata so restarts of a *running* Space don't re-download. | |
| MODEL_CACHE_DIR="/data/models" \ | |
| HF_HOME="/data/hf_home" \ | |
| HF_HUB_ENABLE_HF_TRANSFER="0" \ | |
| # Context window (tokens). The model supports up to 1,048,576 via | |
| # baked-in YaRN scaling, but free CPU Spaces cannot allocate that much | |
| # KV-cache. Default is a safe value for a 16GB-RAM CPU Space; raise it | |
| # via the Space's Variables UI if you have more headroom. | |
| N_CTX="4096" \ | |
| # Free tier has 2 vCPUs; more threads just adds contention. | |
| N_THREADS="2" \ | |
| N_BATCH="256" \ | |
| MAX_NEW_TOKENS="1024" \ | |
| TEMPERATURE="0.6" \ | |
| TOP_P="0.95" \ | |
| TOP_K="20" \ | |
| REPEAT_PENALTY="1.05" \ | |
| SYSTEM_PROMPT="" \ | |
| # Number of retries when downloading the model file from the Hub. | |
| DOWNLOAD_MAX_RETRIES="5" \ | |
| # Gradio server bind settings (must be 0.0.0.0 + 7860 for HF Spaces). | |
| GRADIO_SERVER_NAME="0.0.0.0" \ | |
| GRADIO_SERVER_PORT="7860" \ | |
| PYTHONUNBUFFERED="1" | |
| # Cache/data directories must be writable by the non-root user. | |
| RUN mkdir -p /data/models /data/hf_home && \ | |
| chown -R appuser:appuser /data /app | |
| USER appuser | |
| EXPOSE 7860 | |
| CMD ["python", "app.py"] |