# THOX Mesh Node — free CPU Space image. # # Two-stage: llama-cpp-python is compiled in a builder that has a toolchain, and # only the resulting wheel is carried into the slim runtime. That keeps gcc, # cmake and the 64 MB source tarball out of the shipped image. # # Why compile at all: llama-cpp-python publishes no manylinux wheel on PyPI, and # the project's CPU wheel index carries nothing newer than 0.1.30 for cp311. A # plain `pip install` therefore falls back to the sdist and dies on # "CMAKE_C_COMPILER not set" in a slim base. Compiling is the supported path. # # ThoxLLM-327M-v2 has `architectures: null` in its config, so transformers' # AutoModel cannot load it — GGUF via llama.cpp is the only way to serve this # model, which is why the build is worth doing rather than routed around. # Base is pinned to bookworm (Debian 12 / gcc 12) on BOTH stages, for two reasons: # trixie's gcc 14 refuses to compile this llama.cpp's ggml-cpu-aarch64.cpp # ("invalid conversion from const ggml_half*", -fpermissive), and a builder on a # newer glibc than the runtime produces a wheel the runtime cannot load. # # ── builder ────────────────────────────────────────────────────────────── FROM python:3.11-slim-bookworm AS builder RUN apt-get update \ && apt-get install -y --no-install-recommends build-essential cmake ninja-build git \ && rm -rf /var/lib/apt/lists/* # GGML_NATIVE=OFF is load-bearing, not tidiness. With it on, ggml compiles for # the *builder's* CPU and can emit AVX-512 that the Space's runtime CPU does not # implement — the binary then dies with SIGILL at model load, long after the # build looked green. Off gives a portable baseline build. # # Nothing beyond NATIVE is overridden. An earlier attempt set AVX2=ON with # FMA=OFF, which is self-contradictory: ggml's AVX2 kernels call # _mm256_fmadd_ps, and gcc then fails with "inlining failed in call to # always_inline _mm256_fmadd_ps: target specific option mismatch". ggml's own # defaults (AVX/AVX2/FMA/F16C on, AVX-512 off) are coherent and portable across # every x86 host Spaces run on. ENV CMAKE_ARGS="-DGGML_NATIVE=OFF -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_EXAMPLES=OFF" \ FORCE_CMAKE=1 RUN pip install --no-cache-dir --upgrade pip wheel setuptools scikit-build-core RUN pip wheel --no-cache-dir --wheel-dir /wheels llama-cpp-python==0.3.5 # ── runtime ────────────────────────────────────────────────────────────── FROM python:3.11-slim-bookworm ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ # HF mounts a writable /data only on paid tiers; keep caches under /tmp. HF_HOME=/tmp/hf \ XDG_CACHE_HOME=/tmp/cache # libgomp1 is REQUIRED, not optional. ggml builds with OpenMP, so libllama.so # links libgomp.so.1; that library ships with gcc in the builder but not in the # slim runtime. Without it the image builds and starts, then dies at model load # with "libgomp.so.1: cannot open shared object file" — a failure no build-time # check catches, only actually running the thing. RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates curl libgomp1 \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=builder /wheels /wheels COPY space/requirements.txt /app/requirements.txt # --find-links prefers the wheel we just built; nothing else needs compiling. RUN pip install --no-cache-dir --find-links /wheels -r /app/requirements.txt \ && rm -rf /wheels COPY thoxmesh_node /app/thoxmesh_node COPY space/app.py /app/app.py RUN useradd -m -u 1000 thox && mkdir -p /tmp/hf /tmp/cache && chown -R thox /app /tmp/hf /tmp/cache USER thox EXPOSE 7860 # start-period is generous: first boot downloads the GGUF before it can serve. HEALTHCHECK --interval=30s --timeout=10s --start-period=420s --retries=5 \ CMD curl -fsS http://127.0.0.1:7860/health || exit 1 CMD ["python", "/app/app.py"]