Spaces:
Paused
Paused
v1.1.0: CPU-safe GPU detection, real GPU offload, hardened fallible calls, doctor command
dc03fa5 verified | # 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"] | |