Compare commits

..
Author SHA1 Message Date
Claude 895aa67366 Presets : le bouton « + » ne s'affichait jamais
.preset-add est en display:none par défaut, et n'était révélé que par
« details[open]>summary>.preset-add ». Les panneaux de réglages ont
migré vers <section class="set-pane"><div class="set-pane-h">, donc ce
sélecteur ne matchait plus : le « + » des Presets restait invisible et
il n'y avait plus aucun moyen d'en créer un depuis l'interface.

Le même bouton dans « Discussions » est resté visible, lui, parce qu'il
vit encore dans un <details open><summary> — d'où un défaut qui ne
touchait que les presets.

Règle ajoutée pour le nouveau conteneur, puis UI réassemblée
(tools/assemble-ui).

Vérifié dans l'application lancée : display passe de none à block, et le
« + » apparaît dans l'en-tête du volet Presets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVay7z3y7q2gEe54ByAE6N
2026-08-23 12:56:17 +00:00
LogiFlow 08eaf10a34 Merge pull request #23 from R0m1k3/fix/arg-scope-dockerfile
Image : l'ARG des drapeaux whisper était hors de portée — cmake tournait à nu
2026-08-22 04:16:09 +02:00
MichaelandClaude Fable 5 e177d54e39 Image : l'ARG des drapeaux whisper était hors de portée — cmake tournait à nu
Le build de 51 minutes a échoué au lien final : « libcuda.so.1 not found »,
références cuMem* non résolues, et une libggml-cuda.so PARTAGÉE alors que
BUILD_SHARED_LIBS=OFF est censé être passé. Ce dernier détail était le vrai
indice : les drapeaux n'atteignaient pas cmake du tout.

ARG WHISPER_CMAKE_FLAGS="…" était déclaré entre deux étapes. Règle Docker :
un ARG posé après un FROM appartient à l'étape où il apparaît ; les « ARG »
nus des étapes whisperbuild-* héritent, eux, du scope GLOBAL — où rien
n'était défini. Valeur vide, cmake sans aucun drapeau : ggml en bibliothèques
partagées (échec de lien contre les stubs du pilote), et surtout
-march=native — le SIGILL de la PR #18 revenu en silence sur les deux
binaires. Les tests du Dockerfile n'y voyaient rien : ils vérifiaient le
texte, pas les règles de portée de Docker.

- L'ARG remonte avant le premier FROM, à côté de LLAMACPP_IMAGE.
- Chaque étape vérifie désormais SON binaire : un ldd qui montre libggml ou
  libwhisper en dynamique fait échouer le build sur-le-champ, au lieu de
  laisser partir un binaire qui ne trouvera pas ses .so dans l'image finale.
- TestDockerfileArgFlagsGlobal verrouille la position de l'ARG, ancré en
  début de ligne — une première version se laissait berner par une
  occurrence en commentaire, sa contre-épreuve l'a montré.

libcuda.so.1 reste une dépendance dynamique normale du binaire CUDA : c'est
le pilote, injecté à l'exécution par le NVIDIA Container Toolkit, et
l'édition de liens la résout via les stubs du toolkit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W3ewMAsXhkw9RY11kb9Dc9
2026-08-22 04:12:52 +02:00
LogiFlow 66b53c8255 Merge pull request #22 from R0m1k3/fix/workflow-yaml-double-cle
Workflow : clé YAML dupliquée, plus aucun build ne partait
2026-08-21 23:07:17 +02:00
MichaelandClaude Fable 5 3991e68fc9 Workflow : clé YAML dupliquée, plus aucun build ne partait
Depuis la fusion de la PR #21, chaque push sur main échouait en moins d'une
minute avec zéro job lancé : le YAML du workflow était devenu invalide.

La PR #21 ajoutait cache-from/cache-to après build-args, alors que le bloc
with: les portait DÉJÀ en fin de liste. Une clé dupliquée dans un mapping
YAML fait rejeter le workflow avant même son démarrage — d'où des échecs
immédiats, sans le moindre journal.

Rectification au passage : le cache n'était pas absent, il était déjà actif.
Les trente-sept minutes venaient de la nouveauté de l'étape CUDA (cache
froid) et de l'absence de borne d'architectures, corrigée elle pour de bon.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W3ewMAsXhkw9RY11kb9Dc9
2026-08-21 22:36:37 +02:00
LogiFlow cc218ccfd7 Merge pull request #21 from R0m1k3/fix/cuda-blackwell-et-cache
Image : CUDA 12.8 pour Blackwell, architectures bornées, cache des couches
2026-08-21 22:33:06 +02:00
5 changed files with 59 additions and 14 deletions

No files matched your search

+3 -7
View File
@@ -54,14 +54,10 @@ jobs:
push: true
build-args: |
LOKI_VERSION=${{ github.sha }}
# Sans cache, chaque push recompilait whisper.cpp avec CUDA — une
# quarantaine de minutes — alors que ce binaire ne dépend d'AUCUN
# fichier du dépôt. Les étapes whisperbuild-* sont désormais réutilisées
# tant que leurs lignes du Dockerfile ne bougent pas ; seul le code Go
# et l'assemblage de l'image se refont.
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# Le cache de couches réutilise les étapes whisperbuild-* (compilation
# whisper.cpp CUDA, ~35 min) tant que leurs lignes du Dockerfile ne
# bougent pas : seul le code Go et l'assemblage de l'image se refont.
cache-from: type=gha
cache-to: type=gha,mode=max
+23 -7
View File
@@ -14,6 +14,18 @@
# Déclaré avant le premier FROM : requis pour être utilisable dans un FROM.
ARG LLAMACPP_IMAGE=ghcr.io/ggml-org/llama.cpp:server-cuda
# ⚠️ AVANT le premier FROM, obligatoirement. Un ARG posé entre deux étapes
# appartient à l'étape où il apparaît ; les « ARG WHISPER_CMAKE_FLAGS » nus des
# étapes whisperbuild-* héritent du scope GLOBAL — c'est-à-dire d'ici. Placé
# plus bas, ils héritaient d'une valeur VIDE : cmake tournait sans aucun
# drapeau, ggml se construisait en bibliothèques partagées (échec de lien sur
# libcuda.so.1) et surtout en -march=native — le SIGILL de la PR #18 revenu en
# silence. Un test (TestDockerfileArgFlagsGlobal) verrouille cette position.
ARG WHISPER_CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF \
-DWHISPER_BUILD_TESTS=OFF -DWHISPER_BUILD_EXAMPLES=ON \
-DGGML_NATIVE=OFF -DGGML_AVX512=OFF -DGGML_AMX_TILE=OFF \
-DGGML_AMX_INT8=OFF -DGGML_AMX_BF16=OFF"
# ── Étape 1 : binaire Go loki ───────────────────────────────────────────
FROM golang:1.25 AS gobuild
WORKDIR /src
@@ -50,11 +62,6 @@ RUN GOBIN=/out GOTOOLCHAIN=auto go install golang.org/x/tools/gopls@latest
# pleine transcription : « AMX is not ready to be used! », puis plus rien,
# l'interface affichant un échec sans raison. OFF retombe sur la ligne de base
# AVX2/FMA/F16C de ggml, présente sur tout x86-64 depuis 2013.
ARG WHISPER_CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF \
-DWHISPER_BUILD_TESTS=OFF -DWHISPER_BUILD_EXAMPLES=ON \
-DGGML_NATIVE=OFF -DGGML_AVX512=OFF -DGGML_AMX_TILE=OFF \
-DGGML_AMX_INT8=OFF -DGGML_AMX_BF16=OFF"
# Ubuntu 22.04 : glibc plus ancienne que l'image runtime, donc compatible quoi
# qu'elle embarque.
FROM ubuntu:22.04 AS whisperbuild-cpu
@@ -62,9 +69,13 @@ ARG WHISPER_CMAKE_FLAGS
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential cmake git ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Le grep final vérifie que ggml est bien lié EN STATIQUE : l'image finale ne
# reçoit que le binaire, une .so ggml manquante ne se verrait qu'au premier
# clic sur le micro. Des libs partagées ici = drapeaux non transmis.
RUN git clone --depth 1 https://github.com/ggml-org/whisper.cpp /w \
&& cmake -S /w -B /w/build ${WHISPER_CMAKE_FLAGS} \
&& cmake --build /w/build -j"$(nproc)" --target whisper-server
&& cmake --build /w/build -j"$(nproc)" --target whisper-server \
&& ( ! ldd /w/build/bin/whisper-server | grep -E "libggml|libwhisper" )
# Version CUDA : la MÊME que celle de l'image amont (llama.cpp bâtit avec
# CUDA 12.8.1 sur Ubuntu 24.04). Le binaire est lié dynamiquement à libcudart,
@@ -93,11 +104,16 @@ ARG CUDA_ARCHS="75;86;89;120"
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential cmake git ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Même vérification statique que l'étape CPU. libcuda.so.1 (le PILOTE) reste
# elle une dépendance dynamique normale : absente du runner de build, injectée
# à l'exécution par le NVIDIA Container Toolkit — l'édition de liens la
# résout via les stubs du toolkit.
RUN git clone --depth 1 https://github.com/ggml-org/whisper.cpp /w \
&& cmake -S /w -B /w/build ${WHISPER_CMAKE_FLAGS} -DGGML_CUDA=ON \
-DCMAKE_CUDA_ARCHITECTURES="${CUDA_ARCHS}" \
&& cmake --build /w/build -j"$(nproc)" --target whisper-server \
&& strip /w/build/bin/whisper-server
&& strip /w/build/bin/whisper-server \
&& ( ! ldd /w/build/bin/whisper-server | grep -E "libggml|libwhisper" )
# ── Étape 2 : runtime sur l'image serveur CUDA officielle ───────────────
FROM ${LLAMACPP_IMAGE} AS runtime
+4
View File
@@ -311,6 +311,10 @@ details>summary::-webkit-details-marker{display:none}
.preset-add{display:none;font-size:14px;padding:0 8px;margin:0 8px 0 auto;line-height:1.4;background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:3px;cursor:pointer}
.preset-add:hover{border-color:var(--accent);color:var(--accent)}
details[open]>summary>.preset-add{display:inline-block}
/* Les panneaux de réglages ne sont plus des <details>/<summary> mais des
<section class="set-pane"> : sans cette règle, le « + » des Presets restait
en display:none et il n'y avait plus aucun moyen d'en créer un. */
.set-pane-h>.preset-add{display:inline-block}
.tag{display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;background:var(--panel);border:1px solid var(--border)}
.tag.ok{color:var(--ok);border-color:var(--ok)}
.tag.err{color:var(--err);border-color:var(--err)}
+4
View File
@@ -280,6 +280,10 @@ details>summary::-webkit-details-marker{display:none}
.preset-add{display:none;font-size:14px;padding:0 8px;margin:0 8px 0 auto;line-height:1.4;background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:3px;cursor:pointer}
.preset-add:hover{border-color:var(--accent);color:var(--accent)}
details[open]>summary>.preset-add{display:inline-block}
/* Les panneaux de réglages ne sont plus des <details>/<summary> mais des
<section class="set-pane"> : sans cette règle, le « + » des Presets restait
en display:none et il n'y avait plus aucun moyen d'en créer un. */
.set-pane-h>.preset-add{display:inline-block}
.tag{display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;background:var(--panel);border:1px solid var(--border)}
.tag.ok{color:var(--ok);border-color:var(--ok)}
.tag.err{color:var(--err);border-color:var(--err)}
+25
View File
@@ -155,6 +155,31 @@ func TestDockerfileCudaAssezRecent(t *testing.T) {
}
}
// L'ARG qui porte les drapeaux doit être déclaré AVANT le premier FROM. Un ARG
// posé entre deux étapes appartient à l'étape où il apparaît ; les « ARG » nus
// des étapes whisperbuild-* héritent alors du scope global — vide. cmake a
// tourné sans aucun drapeau : ggml en bibliothèques partagées (échec de lien),
// et -march=native — le SIGILL de la PR #18 revenu en silence. 51 minutes de
// build pour le découvrir.
func TestDockerfileArgFlagsGlobal(t *testing.T) {
b, err := os.ReadFile("../../Dockerfile")
if err != nil {
t.Fatalf("lecture du Dockerfile : %v", err)
}
src := string(b)
// Ancré en début de ligne : une occurrence dans un commentaire ne compte
// pas — c'est précisément ainsi qu'une première version de ce test s'est
// laissée berner par sa propre contre-épreuve.
argLoc := regexp.MustCompile(`(?m)^ARG WHISPER_CMAKE_FLAGS=`).FindStringIndex(src)
fromLoc := regexp.MustCompile(`(?m)^FROM `).FindStringIndex(src)
if argLoc == nil {
t.Fatal("ARG WHISPER_CMAKE_FLAGS= introuvable dans le Dockerfile")
}
if fromLoc != nil && argLoc[0] > fromLoc[0] {
t.Error("ARG WHISPER_CMAKE_FLAGS= est déclaré APRÈS un FROM : les étapes whisperbuild-* hériteront d'une valeur vide et cmake tournera sans aucun drapeau")
}
}
func clefs(m map[string]string) []string {
out := make([]string, 0, len(m))
for k := range m {