mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Merge pull request #17 from R0m1k3/fix/ngl-sentinelle-999-auto
NGL=999 : la sentinelle « toutes les couches » devient -ngl auto
This commit is contained in:
5 files changed
+91
-20
No files matched your search
@@ -84,6 +84,41 @@ func binSupportsNGLAuto(bin string) bool {
|
||||
return strings.Contains(h[i:end], "'auto'")
|
||||
}
|
||||
|
||||
// binFitsLayersItself : ce moteur sait-il répartir les couches tout seul ?
|
||||
//
|
||||
// La lecture fine de l'aide (binSupportsNGLAuto) reste la source de vérité, mais
|
||||
// elle dépend de la mise en page d'un texte d'aide — une description reformulée
|
||||
// ou une colonne plus large, et on conclut « non » sur un moteur parfaitement
|
||||
// capable, donc on lui réimpose 999 et l'abandon revient. --load-mode est arrivé
|
||||
// dans la même vague que « -ngl auto » : sa présence sert de second témoin, plus
|
||||
// grossier mais insensible à la mise en page.
|
||||
func binFitsLayersItself(bin string) bool {
|
||||
return binSupportsNGLAuto(bin) || binSupportsLoadMode(bin)
|
||||
}
|
||||
|
||||
// nglArgs traduit la valeur NGL du preset en arguments, et renvoie au passage la
|
||||
// note à afficher quand Loki a substitué quelque chose. Fonction pure : la seule
|
||||
// question qui demande le moteur (« sait-il répartir les couches tout seul ? »)
|
||||
// arrive déjà tranchée, ce qui la rend testable sans lancer llama-server.
|
||||
func nglArgs(ngl string, fitsItself bool) ([]string, string) {
|
||||
ngl = strings.TrimSpace(ngl)
|
||||
switch {
|
||||
case strings.EqualFold(ngl, "auto"):
|
||||
return nil, "" // rien du tout : le moteur décide seul
|
||||
case ngl == "999" && fitsItself:
|
||||
return []string{"-ngl", "auto"},
|
||||
"NGL=999 (sentinelle « toutes les couches ») → -ngl auto : ce moteur mesure lui-même la " +
|
||||
"VRAM libre. NGL=all pour forcer l'ancien comportement."
|
||||
case ngl != "":
|
||||
return []string{"-ngl", ngl}, ""
|
||||
case fitsItself:
|
||||
return []string{"-ngl", "auto"}, ""
|
||||
default:
|
||||
// Moteur ancien : omettre -ngl le ferait tourner 100 % CPU.
|
||||
return []string{"-ngl", "999"}, ""
|
||||
}
|
||||
}
|
||||
|
||||
// hasAnyFlag dit si l'utilisateur a déjà posé l'un de ces drapeaux dans
|
||||
// EXTRA_ARGS. Loki ajoute plusieurs valeurs par défaut (--parallel, -ngl) : les
|
||||
// ajouter EN PLUS de celles de l'utilisateur fait râler le moteur (« argument
|
||||
@@ -240,31 +275,32 @@ func cmdServe(args []string) error {
|
||||
if !hasAnyFlag(extra, "--parallel", "-np") {
|
||||
llmArgs = append(llmArgs, "--parallel", get("PARALLEL", "1"))
|
||||
}
|
||||
// Couches GPU. Trois cas, dans cet ordre :
|
||||
// Couches GPU. Quatre cas, dans cet ordre :
|
||||
//
|
||||
// NGL=<nombre> → -ngl <nombre> (l'utilisateur tranche)
|
||||
// NGL=auto → rien du tout (compat : anciens presets)
|
||||
// NGL=auto → rien du tout (le moteur décide seul)
|
||||
// NGL=999 → -ngl auto sur un moteur récent (voir plus bas)
|
||||
// NGL=<nombre> → -ngl <nombre> (l'utilisateur tranche pour de vrai)
|
||||
// clé absente → -ngl auto si le moteur le propose, sinon -ngl 999
|
||||
//
|
||||
// Imposer un nombre désarme common_fit_params, qui mesure la VRAM libre et
|
||||
// Imposer un NOMBRE désarme common_fit_params, qui mesure la VRAM libre et
|
||||
// choisit combien de couches y tiennent : « n_gpu_layers already set by user
|
||||
// to 999, abort ». Le moteur pousse alors tout sur le GPU, échoue en
|
||||
// cudaMalloc ou se replie à moitié sur le CPU — débit effondré, GPU à 100 %.
|
||||
// D'où « auto » par défaut dès que le moteur sait le faire. Sur un moteur
|
||||
// plus ancien, qui ne connaît pas la valeur, on garde 999 : omettre -ngl le
|
||||
// ferait tourner 100 % CPU.
|
||||
//
|
||||
// 999 est traité à part parce que ce n'a JAMAIS été un nombre de couches :
|
||||
// c'est la sentinelle historique « toutes », semée dans config.env par
|
||||
// defaultConfig() sur chaque installation neuve. La quasi-totalité des
|
||||
// configurations la portent donc sans que personne ne l'ait choisie — la
|
||||
// traiter comme un choix délibéré, c'est condamner tout le monde à l'abandon
|
||||
// ci-dessus. Sur un moteur qui connaît « auto », 999 devient donc auto, et on
|
||||
// le DIT sur stderr plutôt que de le faire en douce. Qui veut réellement
|
||||
// forcer tout sur le GPU écrit NGL=all (ou un nombre qui n'est pas 999).
|
||||
if !hasAnyFlag(extra, "-ngl", "--n-gpu-layers", "--gpu-layers") {
|
||||
ngl := get("NGL", "")
|
||||
switch {
|
||||
case strings.EqualFold(ngl, "auto"):
|
||||
// rien : le moteur décide seul
|
||||
case ngl != "":
|
||||
llmArgs = append(llmArgs, "-ngl", ngl)
|
||||
case binSupportsNGLAuto(bin):
|
||||
llmArgs = append(llmArgs, "-ngl", "auto")
|
||||
default:
|
||||
llmArgs = append(llmArgs, "-ngl", "999")
|
||||
args, note := nglArgs(get("NGL", ""), binFitsLayersItself(bin))
|
||||
if note != "" {
|
||||
fmt.Fprintln(os.Stderr, "[loki serve] "+note)
|
||||
}
|
||||
llmArgs = append(llmArgs, args...)
|
||||
}
|
||||
if ktv != "" {
|
||||
llmArgs = append(llmArgs, "-ctk", ktv)
|
||||
|
||||
@@ -56,3 +56,38 @@ func TestNormalizeLoadFlags(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNGLArgs(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
ngl string
|
||||
fitsItself bool
|
||||
want []string
|
||||
wantNote bool
|
||||
}{
|
||||
// Le cas qui motive tout : defaultConfig() sème NGL=999 sur chaque
|
||||
// installation neuve. Personne ne l'a choisi, et le moteur récent
|
||||
// abandonne son calcul de VRAM dès qu'on lui impose un nombre.
|
||||
{"sentinelle 999, moteur récent", "999", true, []string{"-ngl", "auto"}, true},
|
||||
{"sentinelle 999, moteur ancien", "999", false, []string{"-ngl", "999"}, false},
|
||||
{"nombre choisi, jamais touché", "28", true, []string{"-ngl", "28"}, false},
|
||||
{"nombre choisi, moteur ancien", "28", false, []string{"-ngl", "28"}, false},
|
||||
{"all reste all", "all", true, []string{"-ngl", "all"}, false},
|
||||
{"auto : aucun drapeau", "auto", true, nil, false},
|
||||
{"auto insensible à la casse", "AUTO", true, nil, false},
|
||||
{"espaces parasites autour de la sentinelle", " 999 ", true, []string{"-ngl", "auto"}, true},
|
||||
{"clé absente, moteur récent", "", true, []string{"-ngl", "auto"}, false},
|
||||
{"clé absente, moteur ancien", "", false, []string{"-ngl", "999"}, false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
got, note := nglArgs(c.ngl, c.fitsItself)
|
||||
if !reflect.DeepEqual(got, c.want) {
|
||||
t.Fatalf("args = %q, want %q", got, c.want)
|
||||
}
|
||||
if (note != "") != c.wantNote {
|
||||
t.Fatalf("note = %q, en voulait-on une ? %v", note, c.wantNote)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ var configTemplate = []struct{ key, help string }{
|
||||
{"HOST", "adresse d'écoute du moteur (défaut 0.0.0.0)"},
|
||||
{"PORT", "port du moteur (défaut 8080)"},
|
||||
{"CTX", "taille du contexte (défaut 32768)"},
|
||||
{"NGL", "couches déportées sur le GPU (défaut 999 = tout ; auto = ce qui tient en VRAM)"},
|
||||
{"NGL", "couches déportées sur le GPU (999 ou auto = ce qui tient en VRAM ; all = tout, quitte à saturer)"},
|
||||
{"BATCH", "batch (défaut 2048)"},
|
||||
{"UBATCH", "micro-batch (défaut 512)"},
|
||||
{"THREADS", "threads CPU, 0 = auto"},
|
||||
|
||||
@@ -3121,7 +3121,7 @@ html[data-files="1"] #files-btn{color:var(--accent)}
|
||||
<span class="pe-row-c"><input id="s-ctx" class="pe-val" type="number" min="0" step="1024" placeholder="32768" oninput="cfgWriteKey('CTX', this.value)"><span class="pe-unit">tok</span></span>
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
<span class="pe-row-l">Couches sur GPU<span class="pe-sub">999 = tout sur le GPU · auto = ce qui tient en VRAM</span></span>
|
||||
<span class="pe-row-l">Couches sur GPU<span class="pe-sub">999 ou auto = ce qui tient en VRAM · all = tout, quitte à saturer</span></span>
|
||||
<span class="pe-row-c"><input id="s-ngl" class="pe-val" type="text" inputmode="numeric" placeholder="999" oninput="cfgWriteKey('NGL', this.value)"></span>
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
|
||||
@@ -984,7 +984,7 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
|
||||
<span class="pe-row-c"><input id="s-ctx" class="pe-val" type="number" min="0" step="1024" placeholder="32768" oninput="cfgWriteKey('CTX', this.value)"><span class="pe-unit">tok</span></span>
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
<span class="pe-row-l">Couches sur GPU<span class="pe-sub">999 = tout sur le GPU · auto = ce qui tient en VRAM</span></span>
|
||||
<span class="pe-row-l">Couches sur GPU<span class="pe-sub">999 ou auto = ce qui tient en VRAM · all = tout, quitte à saturer</span></span>
|
||||
<span class="pe-row-c"><input id="s-ngl" class="pe-val" type="text" inputmode="numeric" placeholder="999" oninput="cfgWriteKey('NGL', this.value)"></span>
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
|
||||
Reference in new issue
Block a user