Sélecteur de modèle qui charge vraiment ; % de chargement qui bouge

Quatre retouches d'interface :

- Le sélecteur de l'en-tête liste maintenant les MODÈLES du disque (groupe
  « Modèles (.gguf) ») en plus des presets : en choisir un le charge —
  POST /api/models/use écrit MODEL seul (contexte, NGL et échantillonnage
  conservés) et redémarre le service en arrière-plan. Sans preset créé, le
  sélecteur n'offrait aucun choix.

- Pourcentage de chargement : sur un redémarrage à chaud, le modèle est déjà
  dans le cache disque — llama-server ne lit rien (read_bytes reste à 0) et
  la pastille passait de « 0 % » à « prêt » sans jamais monter. On prend le
  plus avancé de read_bytes et de la mémoire résidente (VmRSS), qui grandit
  cache ou pas.

- Discussions triées par date de CRÉATION (récentes en tête) : une
  discussion garde sa place, écrire dans un vieux fil ne le fait plus
  remonter.

- Bouton Réglages ancré en pied de barre latérale, juste au-dessus du
  moniteur Performance — toujours au même endroit, quel que soit le nombre
  de discussions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Fable 5 committed 2026-08-20 22:13:16 +02:00
1 parent ad107ed284
commit 86d711e772
9 files changed
+207 -46

No files matched your search

+32
View File
@@ -940,6 +940,38 @@ func handleMemDelete(w http.ResponseWriter, r *http.Request) {
sendJSON(w, 200, map[string]any{"ok": true})
}
// handleModelUse charge un MODÈLE précis (fichier .gguf) sans passer par un
// preset : seul MODEL change dans la configuration active — contexte, NGL et
// échantillonnage sont conservés — et le service redémarre en arrière-plan,
// même contrat que handleSwitch. C'est ce qui rend le sélecteur de l'en-tête
// utilisable même sans avoir créé de preset.
func handleModelUse(w http.ResponseWriter, r *http.Request) {
var req struct {
Value string `json:"value"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil || strings.TrimSpace(req.Value) == "" {
sendJSON(w, 400, map[string]any{"ok": false, "error": "modèle manquant"})
return
}
// Le fichier doit exister AVANT d'écrire la config : une faute de frappe ne
// doit pas laisser un moteur qui boucle sur un modèle introuvable.
if _, err := resolveServeModelPath(req.Value); err != nil {
sendJSON(w, 400, map[string]any{"ok": false, "error": err.Error()})
return
}
if err := SetConfigKey("MODEL", req.Value); err != nil {
sendJSON(w, 500, map[string]any{"ok": false, "error": err.Error()})
return
}
fmt.Printf("%s MODEL <- %s\n", green("[ok]"), req.Value)
go func() {
if err := serviceAction("restart"); err != nil {
fmt.Println(red("[err] redémarrage : " + err.Error()))
}
}()
sendJSON(w, 200, map[string]any{"ok": true})
}
func handleSwitch(w http.ResponseWriter, r *http.Request) {
var req struct {
N int `json:"n"`