mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-23 23:18:13 +02:00
Slots : SLOT_PERSIST garde l'état de la discussion à la bascule de preset, en opt-in
Passer de A à B puis revenir à A relance llama-server deux fois, et la conversation de A est recalculée en entier au retour. Avec SLOT_PERSIST=on (off par défaut), Loki demande au moteur d'écrire l'état du slot 0 juste avant la bascule, et le recharge au retour avant le premier message de la discussion — seulement si tout concorde, sinon calcul normal, en silence. llama.cpp ne vérifie à la relecture que types et tailles : rien ne dit quel build ni quels réglages ont calculé ce cache. La clé de validité est donc l'empreinte de tout ce qui touche au calcul, prise par « loki serve » au lancement : ligne de commande complète (modèle, CTX, types KV, NGL, lots, gabarit, SPEC, EXTRA_ARGS…), LLAMA_ARG_*/GGML_*/CUDA_*, taille et date du modèle et de ses tranches, du projecteur, du brouillon, du binaire et de ses bibliothèques. Pas de cas « mise à jour du moteur » : elle change la clé. - --slot-save-path posé aussi pour SLOT_PERSIST accepté, sous les mêmes conditions de sécurité que l'isolation du lot 1 (boucle locale ou clé d'API) ; refusé avec le décodage spéculatif (le save ne garde pas le brouillon ; /slots speculative revérifié à chaque fois), des poids sur CPU, un --slot-save-path à la main ; la ligne reste alors celle d'avant - sauvegarde depuis l'interface ou une tâche, avant l'arrêt : le slot doit porter un tour de la discussion (tampon d'engineMarkMain), ≥ 4096 jetons, ≤ 8 Gio estimés, double de place libre ; nom provisoire, renommé seulement si aucune requête n'est partie pendant l'écriture - rechargement avant la première requête de la discussion (ou son préchauffage) : même clé de moteur, même discussion, slot 0 vierge (/slots sans id_task) ; une seule tentative, fichier retiré ; toute erreur = calcul normal - deux fichiers au plus ; clé retirée = tout effacé au lancement suivant ; SLOT_PERSIST préservé à la bascule comme HOST (sinon B effaçait l'état de A) - README : SIDE_SLOT, le cache KV plein ne déclenche jamais de compaction - tests : plan et refus, ligne inchangée, empreinte (clé d'API exclue, fichiers et réglages inclus), rotation, séquence save puis restore sur un faux moteur, refus à la sauvegarde et au rechargement, autre clé, défaut sans aucun appel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7a57322a62
commit
28ba44eb46
12 files changed
+1133
-23
No files matched your search
@@ -192,7 +192,10 @@ func safePresetPath(name string) (string, error) {
|
||||
// CUDA_LAUNCH_QUEUES (files de lancement CUDA, voir launchQueuesEnv) suit la
|
||||
// même logique : un « off » posé parce que CETTE machine bloque ne doit pas
|
||||
// disparaître à la bascule suivante.
|
||||
var preservedKeys = []string{"MEM_MODE", "CRAWL4AI_URL", "WEB_ENGINE", "CUDA_VISIBLE_DEVICES", "HOST", "CUDA_LAUNCH_QUEUES"}
|
||||
// SLOT_PERSIST (état du slot gardé à la bascule, backend_serve_persist.go) est
|
||||
// par nature un réglage de bascule : posé sur A seulement, il disparaîtrait en
|
||||
// passant sur B, dont le lancement effacerait l'état gardé de A.
|
||||
var preservedKeys = []string{"MEM_MODE", "CRAWL4AI_URL", "WEB_ENGINE", "CUDA_VISIBLE_DEVICES", "HOST", "CUDA_LAUNCH_QUEUES", "SLOT_PERSIST"}
|
||||
|
||||
// softPreservedKeys : préservées SEULEMENT si le preset d'arrivée ne les définit
|
||||
// pas lui-même. CUDA_VISIBLE_DEVICES est dans ce cas : c'est d'ordinaire un
|
||||
@@ -203,7 +206,7 @@ var preservedKeys = []string{"MEM_MODE", "CRAWL4AI_URL", "WEB_ENGINE", "CUDA_VIS
|
||||
// modèle se retrouvait entièrement sur une seule carte et mourait sur
|
||||
// « cudaMalloc failed: out of memory ». Le preset explicite gagne.
|
||||
// CUDA_LAUNCH_QUEUES aussi : un preset peut l'imposer pour son modèle.
|
||||
var softPreservedKeys = map[string]bool{"CUDA_VISIBLE_DEVICES": true, "HOST": true, "CUDA_LAUNCH_QUEUES": true}
|
||||
var softPreservedKeys = map[string]bool{"CUDA_VISIBLE_DEVICES": true, "HOST": true, "CUDA_LAUNCH_QUEUES": true, "SLOT_PERSIST": true}
|
||||
|
||||
// applyPresetFile installe le preset comme configuration active, en réinjectant
|
||||
// les réglages « appareil » par-dessus. Séparé de SwitchToPreset pour être
|
||||
@@ -264,6 +267,10 @@ func presetImposesEngine(p string) bool {
|
||||
// SwitchToPreset installe le preset et redémarre le service. Les réglages
|
||||
// « appareil » (preservedKeys) sont conservés à travers la bascule.
|
||||
func SwitchToPreset(target string) error {
|
||||
// SLOT_PERSIST : relevé sur la configuration d'avant, gardé juste avant
|
||||
// l'arrêt (llm_slotpersist.go). Sans la clé, ou hors du process web (rien
|
||||
// n'y dit ce que porte le slot) : nil, rien ne se passe.
|
||||
persist := slotPersistPrepare()
|
||||
if err := applyPresetFile(target); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -277,9 +284,11 @@ func SwitchToPreset(target string) error {
|
||||
if !serviceIsActive() {
|
||||
return nil
|
||||
}
|
||||
persist.save()
|
||||
return serviceAction("stop")
|
||||
}
|
||||
fmt.Println(dim("[info] redémarrage du service..."))
|
||||
persist.save()
|
||||
return serviceAction("restart")
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user