From f117a466af2ee822f3842724184f8819de0584db Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Mon, 28 Sep 2026 00:12:23 +0200 Subject: [PATCH] =?UTF-8?q?Presets=20:=20fini=20le=20benchmark=20fant?= =?UTF-8?q?=C3=B4me?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Repris d'AJEAN 0.16.3. Les benchmarks sont rangés par id de preset. Un preset dont on changeait le modèle — ou supprimé puis recréé sous le même nom — affichait les mesures d'un AUTRE modèle, qui n'avaient rien à voir. - benchMatchesPreset : un bench n'est affiché que si le modèle mesuré est celui du preset (le nom de fichier est enregistré avec la mesure depuis toujours, il ne servait simplement à rien). - DeletePreset oublie le bench, comme il oubliait déjà le prompt système. Co-Authored-By: Claude Opus 5.5 --- internal/loki/backend_presets.go | 3 +++ internal/loki/llm_bench.go | 18 ++++++++++++++++++ internal/loki/llm_bench_match_test.go | 17 +++++++++++++++++ internal/loki/web_api.go | 5 +++-- 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 internal/loki/llm_bench_match_test.go diff --git a/internal/loki/backend_presets.go b/internal/loki/backend_presets.go index 15670ee..264d07c 100644 --- a/internal/loki/backend_presets.go +++ b/internal/loki/backend_presets.go @@ -432,6 +432,9 @@ func DeletePreset(id string) error { // sans ce ménage, il resterait orphelin et ressusciterait sur un preset recréé // sous le même id. _ = putStr(bkState, sysPromptKeyPrefix+id, "") + // Même ménage pour son benchmark : un preset recréé sous cet id en + // hériterait, alors qu'il a été mesuré sur un autre modèle. + deletePresetBench(id) return nil } diff --git a/internal/loki/llm_bench.go b/internal/loki/llm_bench.go index 53b84dc..5c51ad7 100644 --- a/internal/loki/llm_bench.go +++ b/internal/loki/llm_bench.go @@ -158,6 +158,24 @@ func loadLastBench() *savedBench { return &sb } +// benchMatchesPreset : le bench a-t-il été mesuré sur le modèle ACTUEL du +// preset ? Les benchs sont rangés par id de preset : sans ce contrôle, un +// preset dont le modèle a changé affichait les mesures d'un autre modèle. +// Repris d'AJEAN 0.16.3. +func benchMatchesPreset(sb savedBench, cfg map[string]string) bool { + m := strings.TrimSpace(cfg["MODEL"]) + return m != "" && sb.Model == filepath.Base(m) +} + +// deletePresetBench oublie le bench d'un preset supprimé. +func deletePresetBench(id string) { + m := loadBenchStore() + if _, ok := m[id]; ok { + delete(m, id) + _ = putJSON(bkState, "bench_presets", m) + } +} + // loadBenchStore renvoie les benchmarks par preset (vide s'il n'y en a pas). func loadBenchStore() map[string]savedBench { m := map[string]savedBench{} diff --git a/internal/loki/llm_bench_match_test.go b/internal/loki/llm_bench_match_test.go new file mode 100644 index 0000000..01dd104 --- /dev/null +++ b/internal/loki/llm_bench_match_test.go @@ -0,0 +1,17 @@ +package loki + +import "testing" + +// Un bench n'est affiché que pour le modèle sur lequel il a été mesuré. +func TestBenchMatchesPreset(t *testing.T) { + sb := savedBench{Model: "Qwen3-27B-Q4_K_M.gguf"} + if !benchMatchesPreset(sb, map[string]string{"MODEL": "/models/Qwen3-27B-Q4_K_M.gguf"}) { + t.Fatal("même modèle : le bench doit s'afficher") + } + if benchMatchesPreset(sb, map[string]string{"MODEL": "/models/Autre.gguf"}) { + t.Fatal("autre modèle : le bench ne doit pas s'afficher") + } + if benchMatchesPreset(sb, map[string]string{}) { + t.Fatal("preset sans modèle : pas de bench") + } +} diff --git a/internal/loki/web_api.go b/internal/loki/web_api.go index efb492e..3215abe 100644 --- a/internal/loki/web_api.go +++ b/internal/loki/web_api.go @@ -399,7 +399,8 @@ func handlePresets(w http.ResponseWriter, r *http.Request) { out := []map[string]any{} for _, p := range list { item := map[string]any{"id": p.ID, "name": p.Name, "active": p.Active} - if content, err := ReadPreset(p.ID); err == nil { + content, _ := ReadPreset(p.ID) + if content != "" { // Preset externe : ni quant, ni raisonnement local à annoncer — on // l'étiquette et on donne le nom du modèle distant à afficher. if cfg := parseEnv(content); isExternalConfig(cfg) { @@ -417,7 +418,7 @@ func handlePresets(w http.ResponseWriter, r *http.Request) { item["reasoning"] = strings.ToLower(r) } } - if sb, ok := store[p.ID]; ok { + if sb, ok := store[p.ID]; ok && benchMatchesPreset(sb, parseEnv(content)) { item["bench"] = map[string]any{ "prefill": sb.Result.PromptPerSecond, "decode": sb.Result.PredictedPerSec,