DOC / Dockerfile
RoyalityAi's picture
Update Dockerfile
c537e8c verified
Raw
History Blame Contribute Delete
7.59 kB
# 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"]