mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-16 03:39:29 +02:00
La dictée n'a jamais transcrit une seule phrase. Le micro enregistrait bien —
contexte HTTPS, autorisation accordée, bouton rouge — mais le serveur répondait
500 sur chaque envoi :
whisper-cli : AMX is not ready to be used!
read_audio_data: reading audio data from '/tmp/loki-dictee-...wav' ...
read_audio_data: trying to decode with miniaudio
Deux indices dans ces trois lignes. « AMX is not ready to be used » ne sort que
d'un binaire COMPILÉ avec les instructions AMX, celles d'un Xeon récent — le
runner GitHub. Et le journal s'arrête net : ni « failed to decode », ni texte
transcrit. Le processus ne renvoie pas une erreur, il meurt.
ggml compile en -march=native par défaut. Le binaire partait donc taillé pour
le processeur qui l'avait construit, et rencontrait une instruction illégale
dès qu'on le posait ailleurs.
- GGML_NATIVE=OFF à l'étape whisperbuild, AVX-512 et AMX explicitement coupés.
Reste la ligne de base AVX2/FMA/F16C de ggml, présente sur tout x86-64 depuis
2013. Un test lit le Dockerfile et garde ces drapeaux : rien à l'exécution ne
rappellerait leur raison d'être au prochain qui touchera cette étape.
- Le handler ne renvoyait que la dernière ligne de stderr. Sur une mort par
signal, cette ligne est celle d'AVANT le coup fatal : elle ressemble à une
explication sans en être une, et envoie chercher du côté de l'audio. Il dit
maintenant comment le processus a fini — « signal: illegal instruction » vaut
diagnostic à lui seul.
L'image doit être reconstruite : whisper-cli y est compilé.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W3ewMAsXhkw9RY11kb9Dc9
49 lines
1.6 KiB
Go
49 lines
1.6 KiB
Go
package loki
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// La dictée est morte en production parce que whisper-cli avait été compilé
|
|
// avec -march=native, donc pour le processeur du runner GitHub (AVX-512, AMX)
|
|
// et pas pour la machine qui fait tourner l'image : SIGILL en pleine
|
|
// transcription. Le drapeau qui l'évite ne se voit pas à l'exécution — rien ne
|
|
// le rappelle au prochain qui touchera cette étape de build. Ce test le fait.
|
|
func TestDockerfileWhisperNonNatif(t *testing.T) {
|
|
b, err := os.ReadFile("../../Dockerfile")
|
|
if err != nil {
|
|
t.Fatalf("lecture du Dockerfile : %v", err)
|
|
}
|
|
src := string(b)
|
|
_, apres, ok := strings.Cut(src, "AS whisperbuild")
|
|
if !ok {
|
|
t.Fatal("étape whisperbuild introuvable dans le Dockerfile")
|
|
}
|
|
// L'étape suivante commence au FROM d'après : ne pas déborder dessus.
|
|
if fin := strings.Index(apres, "\nFROM "); fin >= 0 {
|
|
apres = apres[:fin]
|
|
}
|
|
for _, drapeau := range []string{"-DGGML_NATIVE=OFF", "-DGGML_AMX_TILE=OFF"} {
|
|
if !strings.Contains(apres, drapeau) {
|
|
t.Errorf("l'étape whisperbuild ne passe plus %s : le binaire sera compilé pour le processeur du runner et mourra d'un SIGILL ailleurs", drapeau)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLastLine(t *testing.T) {
|
|
cas := []struct{ in, want string }{
|
|
{"", ""},
|
|
{" \n\n ", ""},
|
|
{"une seule ligne", "une seule ligne"},
|
|
{"AMX is not ready to be used!\nread_audio_data: ...\n", "read_audio_data: ..."},
|
|
{"fin utile\n\n \n", "fin utile"},
|
|
}
|
|
for _, c := range cas {
|
|
if got := lastLine(c.in); got != c.want {
|
|
t.Errorf("lastLine(%q) = %q, attendu %q", c.in, got, c.want)
|
|
}
|
|
}
|
|
}
|