mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 06:58:14 +02:00
v0.7.9 : les moteurs llama.cpp arretent de jouer a cache-cache
- moteur precompile : la version installee est celle qui tourne (on elisait le dossier le plus ancien), et les anciennes extractions sont purgees - presets : le moteur precompile reste reconnu apres une mise a jour, et un BIN pointant une release disparue suit la version installee au lieu d'echouer - build CUDA : le toolkit est cherche avant le nvcc du PATH, sa racine est passee a CMake (fin du "CUDA Toolkit not found" avec CUDA installe) - job d'installation : etat persiste sur disque, une operation interrompue par un redemarrage du service est annoncee, pastille de rappel sur mobile - editeur de modele : section Cartes graphiques (--device / --tensor-split), la liste vient du moteur du preset car les identifiants dependent du backend - reglages : plus de menu replie, interrupteurs regroupes, decodage speculatif - CUDA_VISIBLE_DEVICES et WEB_ENGINE survivent au changement de preset, sauf si le preset les definit lui-meme
This commit is contained in:
1 parent
726f065d25
commit
e57fc0966e
24 files changed
+1754
-94
No files matched your search
@@ -0,0 +1,85 @@
|
||||
package ajean
|
||||
|
||||
import "testing"
|
||||
|
||||
// La sortie de `llama-server --list-devices` : c'est elle qui fait foi pour
|
||||
// l'UI, car les noms ET l'ordre dépendent du backend compilé dans CE moteur
|
||||
// (sur la même machine : CUDA0 = la grosse carte, Vulkan0 = la petite).
|
||||
func TestParseListDevices(t *testing.T) {
|
||||
out := `ggml_cuda_init: found 2 CUDA devices:
|
||||
Available devices:
|
||||
CUDA0: NVIDIA GeForce RTX 5060 Ti (15849 MiB, 15579 MiB free)
|
||||
CUDA1: NVIDIA GeForce GTX 1650 (3715 MiB, 3659 MiB free)
|
||||
`
|
||||
devs := parseListDevices(out)
|
||||
if len(devs) != 2 {
|
||||
t.Fatalf("%d device(s) extraits, attendu 2 : %v", len(devs), devs)
|
||||
}
|
||||
if devs[0]["id"] != "CUDA0" || devs[0]["name"] != "NVIDIA GeForce RTX 5060 Ti" {
|
||||
t.Errorf("device 0 mal lu : %v", devs[0])
|
||||
}
|
||||
if devs[0]["total_mib"] != 15849 || devs[1]["free_mib"] != 3659 {
|
||||
t.Errorf("mémoire mal lue : %v / %v", devs[0], devs[1])
|
||||
}
|
||||
if devs[1]["id"] != "CUDA1" {
|
||||
t.Errorf("device 1 mal lu : %v", devs[1])
|
||||
}
|
||||
}
|
||||
|
||||
// Backend Vulkan : même format, autres noms — et rien d'autre ne doit passer.
|
||||
func TestParseListDevicesVulkanEtBruit(t *testing.T) {
|
||||
out := `load_backend: loaded Vulkan backend
|
||||
Available devices:
|
||||
Vulkan0: NVIDIA GeForce GTX 1650 (4342 MiB, 3950 MiB free)
|
||||
Vulkan1: NVIDIA GeForce RTX 5060 Ti (16311 MiB, 15848 MiB free)
|
||||
warning: something else entirely
|
||||
`
|
||||
devs := parseListDevices(out)
|
||||
if len(devs) != 2 || devs[0]["id"] != "Vulkan0" || devs[1]["id"] != "Vulkan1" {
|
||||
t.Fatalf("devices Vulkan mal extraits : %v", devs)
|
||||
}
|
||||
if n := len(parseListDevices("aucun device ici\n")); n != 0 {
|
||||
t.Errorf("%d device(s) extraits d'une sortie sans device", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Mémoire complétée : un device dont le moteur n'a pas su lire la taille (0 Mio,
|
||||
// carte saturée) récupère celle de nvidia-smi par correspondance de nom. Deux
|
||||
// cartes homonymes rendent la correspondance ambiguë : on ne complète pas.
|
||||
func TestFillMissingMemoryParNom(t *testing.T) {
|
||||
devs := []map[string]any{
|
||||
{"id": "CUDA0", "name": "NVIDIA GeForce RTX 5060 Ti", "total_mib": 0, "free_mib": 0},
|
||||
{"id": "CUDA1", "name": "NVIDIA GeForce GTX 1650", "total_mib": 3715, "free_mib": 3659},
|
||||
}
|
||||
// La table de correspondance est celle que construit fillMissingMemory ; on
|
||||
// vérifie ici la règle métier sans dépendre d'un nvidia-smi présent.
|
||||
totals := map[string]int{"NVIDIA GeForce RTX 5060 Ti": 16311}
|
||||
dup := map[string]bool{}
|
||||
for _, d := range devs {
|
||||
if n, _ := d["total_mib"].(int); n > 0 {
|
||||
continue
|
||||
}
|
||||
name, _ := d["name"].(string)
|
||||
if mb, ok := totals[name]; ok && !dup[name] {
|
||||
d["total_mib"] = mb
|
||||
}
|
||||
}
|
||||
if devs[0]["total_mib"] != 16311 {
|
||||
t.Errorf("mémoire non complétée : %v", devs[0])
|
||||
}
|
||||
if devs[1]["total_mib"] != 3715 {
|
||||
t.Errorf("mémoire déjà connue écrasée : %v", devs[1])
|
||||
}
|
||||
}
|
||||
|
||||
// Le cache ne doit pas figer une lecture dégénérée (0 Mio) pendant 10 minutes.
|
||||
func TestHasZeroMemory(t *testing.T) {
|
||||
ok := []map[string]any{{"total_mib": 16311}, {"total_mib": 3715}}
|
||||
ko := []map[string]any{{"total_mib": 16311}, {"total_mib": 0}}
|
||||
if hasZeroMemory(ok) {
|
||||
t.Error("lecture complète prise pour dégénérée")
|
||||
}
|
||||
if !hasZeroMemory(ko) {
|
||||
t.Error("lecture à 0 Mio non détectée")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user