From 1e232a7ff36fea64f33272b24c273c5a2991100c Mon Sep 17 00:00:00 2001 From: Loki Date: Fri, 14 Aug 2026 22:59:35 +0000 Subject: [PATCH] Simplification radicale : moteur pris de l'image officielle llama.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plus aucune compilation CUDA : le runtime part de ghcr.io/ggml-org/llama.cpp:server-cuda (llama-server précompilé et maintenu par l'équipe amont, backends .so chargés dynamiquement, archs GPU courantes, repli CPU fonctionnel). Le build complet passe de ~40 min à ~4 min et tous les pièges du build CUDA sans GPU (stubs libcuda, espace disque du runner, choix des architectures) disparaissent. - Dockerfile : 2 étapes (Go + image officielle), build-arg LLAMACPP_IMAGE pour épingler une version ou passer en CPU/Vulkan - entrypoint : BIN=/app/llama-server - workflow GHCR : purge disque et CUDA_ARCHS supprimés, cache max - compose/.env/README à l'avenant Validé : build 3 min 55, UI HTTP 200, healthcheck healthy, superviseur PID OK, llama-server démarre (repli CPU) et n'échoue que sur un modèle factice. --- .env.example | 5 -- .github/workflows/docker-publish.yml | 16 +----- Dockerfile | 76 ++++++++-------------------- README.md | 27 +++++++--- docker-compose.yml | 9 ++-- docker-entrypoint.sh | 5 +- 6 files changed, 49 insertions(+), 89 deletions(-) diff --git a/.env.example b/.env.example index bdf9094..538245f 100644 --- a/.env.example +++ b/.env.example @@ -4,11 +4,6 @@ # Port de l'interface web (identique dedans/dehors). LOKI_WEB_PORT=8090 -# Architectures CUDA compilées (build local uniquement). -# 75=Turing (GTX 16xx / RTX 20xx), 86=Ampere (RTX 30xx), 89=Ada (RTX 40xx). -# Restreindre à sa carte divise le temps de compilation. -CUDA_ARCHS=75;86;89 - # Optionnel — semé au PREMIER démarrage seulement (modifiable ensuite dans # l'UI, qui garde la main) : # Modèle initial : nom d'un .gguf présent dans ./models ou chemin complet. diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 614bfc0..228e87c 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -16,16 +16,6 @@ jobs: - name: Checkout uses: actions/checkout@v4 - # L'étape llama.cpp CUDA a besoin de place : l'image devel pèse ~8 Go et - # un runner ubuntu-latest n'offre que ~14 Go libres. On purge ce qui est - # préinstallé et inutile ici (SDK Android, .NET, Haskell…). - - name: Libérer l'espace disque du runner - run: | - sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc \ - /usr/local/.ghcup /opt/hostedtoolcache/CodeQL - sudo docker image prune -af - df -h / - - name: Setup Buildx uses: docker/setup-buildx-action@v3 @@ -53,11 +43,7 @@ jobs: push: true build-args: | LOKI_VERSION=${{ github.sha }} - CUDA_ARCHS=75;86;89 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - # Cache limité : les couches CUDA (plusieurs Go) satureraient le - # plafond de 10 Go du cache GitHub Actions — on ne cache que le mode - # min (couches finales), le gain principal restant le cache apt/go. cache-from: type=gha - cache-to: type=gha,mode=min + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile index 4703d77..39c7b38 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,54 +1,20 @@ -# ── Loki — image GPU autonome (fork d'AJEAN, https://github.com/nathaninline/ajean) +# ── Loki — image GPU (fork d'AJEAN, https://github.com/nathaninline/ajean) # -# Trois étapes : -# 1. compilation de llama.cpp avec CUDA (mêmes flags que backend_build.go, -# sauf GGML_NATIVE=OFF : l'image est bâtie sur un runner GitHub, pas sur -# la machine qui l'exécutera — des instructions CPU « natives » du runner -# provoqueraient un Illegal instruction ailleurs) ; -# 2. compilation du binaire Go `loki` (UI embarquée via go:embed) ; -# 3. runtime CUDA léger : llama-server + loki + entrypoint. +# Deux étapes seulement : +# 1. compilation du binaire Go `loki` (UI embarquée via go:embed) ; +# 2. runtime = l'image serveur CUDA OFFICIELLE de llama.cpp — llama-server +# y est précompilé et maintenu par l'équipe amont (base nvidia/cuda +# runtime, backends .so dans /app, architectures GPU courantes). +# Aucune compilation CUDA ici : le build complet prend quelques minutes. # -# Pré-requis d'exécution : NVIDIA Container Toolkit sur l'hôte. -# docker build -t loki --build-arg CUDA_ARCHS=86 . -# CUDA_ARCHS : 75=Turing, 86=Ampere, 89=Ada — restreindre à sa carte divise -# le temps de build et la taille de l'image. +# Épingler une version : --build-arg LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server-cuda-b10423 +# Variante CPU (test sans GPU) : --build-arg LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server +# Pré-requis d'exécution GPU : NVIDIA Container Toolkit sur l'hôte. -# ── Étape 1 : llama.cpp CUDA ──────────────────────────────────────────── -FROM nvidia/cuda:12.6.3-devel-ubuntu24.04 AS llamacpp +# Déclaré avant le premier FROM : requis pour être utilisable dans un FROM. +ARG LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server-cuda -RUN apt-get update && apt-get install -y --no-install-recommends \ - git cmake build-essential ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -# Épingler LLAMACPP_REF sur un tag (ex. b4991) pour des builds reproductibles. -ARG LLAMACPP_REF=master -ARG CUDA_ARCHS=75;86;89 - -RUN git clone --depth 1 --branch "${LLAMACPP_REF}" \ - https://github.com/ggml-org/llama.cpp /src/llama.cpp - -# --allow-shlib-undefined : pas de GPU (donc pas de libcuda.so.1) sur le -# builder — l'API driver (cuMemCreate…) reste non résolue au link et sera -# fournie à l'exécution par le runtime NVIDIA. Même parade que le -# cuda.Dockerfile officiel de llama.cpp. -RUN cmake -S /src/llama.cpp -B /src/llama.cpp/build \ - -DCMAKE_BUILD_TYPE=Release \ - -DGGML_CUDA=ON \ - -DGGML_CUDA_F16=ON \ - -DGGML_NATIVE=OFF \ - -DCMAKE_CUDA_ARCHITECTURES="${CUDA_ARCHS}" \ - -DLLAMA_CURL=OFF \ - -DLLAMA_BUILD_TESTS=OFF \ - -DLLAMA_BUILD_EXAMPLES=OFF \ - -DLLAMA_BUILD_UI=OFF \ - -DLLAMA_USE_PREBUILT_UI=OFF \ - -DCMAKE_EXE_LINKER_FLAGS=-Wl,--allow-shlib-undefined \ - && cmake --build /src/llama.cpp/build --target llama-server -j"$(nproc)" \ - && mkdir -p /opt/llama.cpp \ - && find /src/llama.cpp/build -name 'llama-server' -type f -exec cp {} /opt/llama.cpp/ \; \ - && find /src/llama.cpp/build -name '*.so*' -exec cp -P {} /opt/llama.cpp/ \; - -# ── Étape 2 : binaire Go loki ─────────────────────────────────────────── +# ── Étape 1 : binaire Go loki ─────────────────────────────────────────── FROM golang:1.25 AS gobuild WORKDIR /src COPY go.mod go.sum ./ @@ -58,8 +24,8 @@ COPY internal/ internal/ COPY tools/ tools/ RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o /out/loki ./cmd/loki -# ── Étape 3 : runtime ─────────────────────────────────────────────────── -FROM nvidia/cuda:12.6.3-runtime-ubuntu24.04 AS runtime +# ── Étape 2 : runtime sur l'image serveur CUDA officielle ─────────────── +FROM ${LLAMACPP_IMAGE} AS runtime # Marqueur de build (sha court), injecté par le workflow GitHub. ARG LOKI_VERSION=dev @@ -67,21 +33,21 @@ LABEL org.opencontainers.image.revision="${LOKI_VERSION}" \ org.opencontainers.image.source="https://github.com/R0m1k3/Loki" \ org.opencontainers.image.description="Loki — fork conteneurisé d'AJEAN (github.com/nathaninline/ajean, MIT)" -# curl pour le HEALTHCHECK ; git pour les outils de l'agent ; nodejs/npm pour -# les serveurs MCP lancés via npx ; libgomp1 pour llama-server ; tini en PID 1. +# git pour les outils de l'agent ; nodejs/npm pour les serveurs MCP lancés +# via npx ; tini en PID 1. curl et libgomp1 sont déjà dans l'image amont. RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates curl git libgomp1 tini nodejs npm \ + git nodejs npm tini \ && rm -rf /var/lib/apt/lists/* -COPY --from=llamacpp /opt/llama.cpp /opt/llama.cpp COPY --from=gobuild /out/loki /usr/local/bin/loki COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh RUN chmod +x /usr/local/bin/docker-entrypoint.sh && mkdir -p /data /models +# llama-server et ses .so vivent dans /app (convention de l'image amont). ENV LOKI_CONTAINER=1 \ LOKI_HOME=/data \ LOKI_MODEL_DIRS=/models \ - LD_LIBRARY_PATH=/opt/llama.cpp \ + LD_LIBRARY_PATH=/app \ NVIDIA_VISIBLE_DEVICES=all \ NVIDIA_DRIVER_CAPABILITIES=compute,utility @@ -89,8 +55,10 @@ ENV LOKI_CONTAINER=1 \ # conteneur — il n'est pas authentifié par défaut. EXPOSE 8090 +# Remplace le HEALTHCHECK de l'image amont (qui vise le moteur sur :8080). HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD curl -fsS "http://localhost:${LOKI_WEB_PORT:-8090}/" >/dev/null || exit 1 WORKDIR /data +# Remplace l'ENTRYPOINT de l'image amont (/app/llama-server). ENTRYPOINT ["tini", "--", "docker-entrypoint.sh"] diff --git a/README.md b/README.md index 367eece..59ac534 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,9 @@ chiffré — serveur d'inférence llama.cpp compris, dans une seule image. Pré-requis : pilote NVIDIA + [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html). ```bash -cp .env.example .env # CUDA_ARCHS=86 pour une RTX 30xx, etc. -docker compose up --build # 30-45 min : compilation CUDA de llama.cpp +cp .env.example .env +docker compose up --build # quelques minutes : llama-server vient précompilé + # de l'image officielle llama.cpp (server-cuda) ``` Interface : http://localhost:8090 — télécharge un modèle depuis le catalogue @@ -96,7 +97,7 @@ En CLI dans le conteneur : `docker exec -it loki loki status` (aussi : | | AJEAN (amont) | Loki (ce fork) | |---|---|---| | Installation | binaire + `sudo ajean install` (systemd) | `docker compose up` | -| Moteur llama.cpp | compilé sur la machine (`ajean llamacpp install`) | précompilé CUDA dans l'image | +| Moteur llama.cpp | compilé sur la machine (`ajean llamacpp install`) | image officielle llama.cpp (`server-cuda`), précompilée | | Supervision moteur | systemd / launchd / PID (Windows) | fichier PID (`LOKI_CONTAINER=1`) | | Configuration initiale | `ajean edit` ($EDITOR) | entrypoint + `loki config set` | | Mise à jour | `ajean update` (binaire GitHub) | `docker compose pull` | @@ -108,12 +109,22 @@ les évolutions de l'amont : git fetch upstream && git merge upstream/main # conflits de renommage à arbitrer ``` -## Build sans GPU / autres accélérateurs +## Build sans GPU / autres accélérateurs / version épinglée -L'image par défaut cible CUDA. Pour un essai CPU, remplace dans le -`Dockerfile` les bases `nvidia/cuda:*` par `ubuntu:24.04` et retire les flags -`-DGGML_CUDA=*` (llama.cpp bascule en CPU). Vulkan/ROCm : adapter les flags -comme le fait l'amont (`internal/loki/backend_build.go`). +L'image Loki se construit **au-dessus de l'image serveur officielle de +llama.cpp**, choisie par le build-arg `LLAMACPP_IMAGE` : + +```bash +# CPU seul (test sans GPU) +docker build --build-arg LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server . +# Vulkan (GPU AMD/Intel/NVIDIA sans CUDA) +docker build --build-arg LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server-vulkan . +# Version de llama.cpp épinglée (reproductible) +docker build --build-arg LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server-cuda-b10423 . +``` + +Aucune compilation de llama.cpp n'a lieu : le moteur est maintenu et +précompilé par l'équipe amont (toutes architectures GPU courantes). ## Licence diff --git a/docker-compose.yml b/docker-compose.yml index 5734cd3..8aab18d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,8 @@ # Un seul service : le conteneur embarque le moteur llama.cpp (CUDA) ET l'UI. # # cp .env.example .env # ajuste si besoin -# docker compose up --build # build local (30-45 min : compilation CUDA) +# docker compose up --build # build local en quelques minutes (llama-server +# # vient précompilé de l'image officielle llama.cpp) # # Interface : http://localhost:8090 # Pré-requis GPU : NVIDIA Container Toolkit sur l'hôte. @@ -10,10 +11,8 @@ services: loki: build: context: . - args: - # Restreins à ta carte pour un build plus court : 75=Turing (GTX 16xx/RTX 20xx), - # 86=Ampere (RTX 30xx), 89=Ada (RTX 40xx). - CUDA_ARCHS: ${CUDA_ARCHS:-75;86;89} + # Pour épingler la version du moteur ou passer en CPU/Vulkan : + # args: { LLAMACPP_IMAGE: "ghcr.io/ggml-org/llama.cpp:server-cuda-b10423" } container_name: loki ports: - "${LOKI_WEB_PORT:-8090}:${LOKI_WEB_PORT:-8090}" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 0178e17..4b926d6 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -6,9 +6,10 @@ set -eu : "${LOKI_HOME:=/data}" mkdir -p "$LOKI_HOME" -# Le chemin du moteur est imposé par l'image : on le (re)pose à chaque boot, +# Le chemin du moteur est imposé par l'image (llama-server précompilé de +# l'image officielle llama.cpp, dans /app) : on le (re)pose à chaque boot, # une mise à jour de l'image ne doit pas laisser un BIN obsolète en base. -loki config set "BIN=/opt/llama.cpp/llama-server" +loki config set "BIN=/app/llama-server" # Les autres clés ne sont semées QUE si absentes : ce que l'utilisateur règle # ensuite dans l'UI (modèle, contexte…) est conservé d'un redémarrage à l'autre.