Avec LOKI_TUNE=rust (expérimental, Unix seulement), la façade sert /api/tune, /api/tune/status, /api/tune/cancel, /api/tune/apply et /api/tune/last, et déroule l'optimisation sans perte (rust/loki-rs/src/tune) : vrai moteur arrêté, essais composés à blanc puis lancés par les « loki serve » du Go (LOKI_TUNE_TRIAL), chacun dans son groupe de processus, mesurés par le bench complet à profondeur fixe, retenus au-delà du bruit ; vrai moteur relancé. Rien n'est écrit sans un clic : copie du preset, ou le preset lui-même — redémarrage, sonde, et ancienne version rétablie si elle échoue. - tune/core.rs : la partie pure (EXTRA_ARGS, réglages, essais de chaque étape, garde-fous, diff et réécriture du preset, score) ; - tune/lock.rs : le verrou tune.lock au format du Go, identité des processus comme procIdentity (la reprise du Go reconnaît la façade vivante, et écarte son verrou si elle meurt), ménage d'un verrou périmé (essai orphelin arrêté, application interrompue défaite) ; - tune/job.rs : routes, job, essais et application. Le verrou de génération reste celui du Go, pris par le bail du moteur au motif « tune » (refus de l'optimiseur pour les autres, stop du chat qui annule). Le Go prête /internal/v1/tune/context (bench, génération, jobs du mode code, état du moteur, télémétrie) et le démarrage ou l'arrêt du moteur sans le refus de l'optimiseur (service/action « os »). Hors Unix, la façade passe LOKI_TUNE vide au Go, qui garde l'optimiseur. serde_json lit désormais les flottants à l'arrondi exact (float_roundtrip), comme le Go. Parité : parity_tune_test.go tire du Go un journal (partie pure, contenu du verrou, résultat enregistré, vérification après application) rejoué par tests/tune_core.rs. tests/tune.rs déroule de vraies optimisations, le binaire de test jouant « loki serve » ; les tests du verrou du Go sont portés ; TestFacadeTune côté Go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
7.5 KiB
Lot 28 — Optimiseur tenu par la façade
Contexte
L'optimiseur sans perte (backend_tune*.go) cherche des réglages du moteur
plus rapides sans rien changer à ce que le modèle calcule : même
contexte, mêmes slots, mêmes types de cache, même échantillonnage. Il
procède ainsi :
- Il arrête le vrai moteur.
- Il lance chaque essai sur une COPIE de la configuration :
- posée dans
LOKI_HOME/tune/run/<essai>/config.env, jamaisconfig.env; - composée par « loki serve » à blanc ;
- puis lancée sur 127.0.0.1 et un port libre.
- posée dans
- Il mesure chaque essai par le bench complet, à une profondeur fixe.
- Il garde ce qui gagne au-delà du bruit.
- Il relance le vrai moteur.
Rien n'est écrit dans un preset sans un geste de l'utilisateur : dans une copie, ou dans le preset lui-même — moteur redémarré, sondé, et ancienne version rétablie si la sonde échoue.
Cinq routes :
POST /api/tunelance (202) ;GET /api/tune/statusdit la phase, les essais, l'ETA, puis le résultat ;POST /api/tune/cancelannule ;POST /api/tune/applyécrit le résultat, sur un clic (copyoupreset) ;GET /api/tune/lastrend le dernier résultat d'un preset, et si le preset ou le moteur ont changé depuis.
Le moteur, pendant une optimisation, appartient aux essais. Le verrou est un
fichier de LOKI_HOME (tune.lock), créé de façon exclusive, que tout
le monde lit :
- le Go, dans tous ses refus (
tuneGuard) ; - « loki tune » en ligne de commande ;
- désormais la façade.
Le lot
Avec LOKI_TUNE=rust (expérimental, Unix seulement), la façade
(rust/loki-rs/src/tune) sert les cinq routes et déroule l'optimisation :
tune/core.rs: la partie pure, portée à l'octet près :- découpe et réécriture d'
EXTRA_ARGS; - réglages par clé ou par drapeau ;
- essais de chaque étape selon la machine et les cases cochées ;
- garde-fous : cœur de la ligne, dénature, clés permises ;
- diff et réécriture du preset ;
- journal d'un essai ;
- score et départage ;
- découpe et réécriture d'
tune/lock.rs: le verrou, au format du Go :- contenu du fichier, clé de prise, binaires comparés par leur nom ;
- identité d'un processus comme
procIdentityl'écrit : champ 22 de/proc/<pid>/stat, préfixé de l'identifiant du démarrage ;psailleurs ; - écriture d'un bloc ;
- rendu neutre avant retrait ;
- ménage par déplacement-relecture ;
tune/job.rs: les routes, le job, les essais et l'application.
La reprise reste au Go. Sa reprise (tuneRecoverWatch, toutes les
30 s) lit le verrou de la façade et la reconnaît vivante, par la même
identité. Si la façade meurt en plein essai, le Go écarte son verrou comme
celui d'un « loki tune » tué :
- l'essai orphelin est arrêté (identité complète vérifiée) ;
- une application interrompue est défaite ;
- le moteur est relancé s'il tournait.
La façade fait le même ménage quand elle trouve un verrou périmé en prenant le sien.
Les essais restent des « loki serve » du Go, lancés par la façade avec
LOKI_TUNE_TRIAL (et LOKI_TUNE_DRYRUN à blanc), dans leur propre groupe de
processus. Le groupe est arrêté en sortie, quoi qu'il arrive. L'essai est
noté dans le verrou avant de charger quoi que ce soit.
Le verrou de génération reste celui de la conversation du Go. La façade le
prend par le bail du moteur, avec le motif tune :
- le Go note alors
benchinget donne aux autres le refus de l'optimiseur ; - changer de discussion ne rompt pas le bail ;
- un stop du chat, un Reset ou un bail perdu annulent l'optimisation.
Le Go prête à la façade ce qu'il est seul à voir
(/internal/v1/tune/context) :
- le refus du processus web : un benchmark (le sien ou celui de la façade), une génération, des jobs d'arrière-plan du mode code ;
- l'état du vrai moteur (
engineNeedsStop) ; - la télémétrie, d'où viennent les poids d'un tour type.
Il prête aussi le démarrage et l'arrêt du moteur sans le refus de
l'optimiseur (/internal/v1/service/action, os), puisque c'est la
façade qui tient le verrou. Si la façade pilote elle-même le moteur
(LOKI_ENGINE=rust), elle passe par son superviseur.
Le preset est réécrit et appliqué par les fonctions des presets
(save_applying, mode apply : la configuration, sans redémarrage). Le
redémarrage, la sonde et le retour arrière sont ceux de l'optimiseur.
La ligne de commande (loki tune) reste au Go.
Hors Unix, la façade ne tient pas l'optimiseur. Elle passe alors
LOKI_TUNE vide au Go, qui le garde et ne relaie rien.
Parité
internal/loki/parity_tune_test.go tire du Go un journal
(tests/parity_tune/core.json) rejoué par tests/tune_core.rs. Il couvre :
- toute la partie pure ;
- le verrou : contenu du fichier octet pour octet, clé de prise, comparaison des binaires ;
- le résultat tel qu'enregistré et montré (listes vides écrites
nullcomme une tranche nil du Go) ; - la vérification après application (la configuration est-elle l'essai retenu ?).
tests/tune.rs déroule de vraies optimisations, essais compris : le binaire
de test joue « loki serve ».
- À blanc, il écrit la ligne de commande de l'essai.
- Pour de vrai, il sert un faux llama-server dont le prefill est d'autant plus rapide que le micro-lot est petit.
Les tests couvrent :
- une optimisation entière :
- bail « tune » et verrou au nom de la façade ;
- vrai moteur arrêté puis relancé sans le refus de l'optimiseur, dictée coupée ;
- quatre essais composés, lancés, mesurés, l'un retenu ;
- copies de configuration sur une adresse privée ;
- résultat enregistré par preset et rendu par
/api/tune/last;
- l'application :
- dans une copie (rien d'autre ne bouge) ;
- dans le preset (réécrit, appliqué, moteur redémarré et sondé) ;
- refusée sur un preset changé depuis la mesure ;
- une sonde qui échoue (contexte perdu) : preset et configuration rétablis, moteur redémarré dessus, sauvegarde faite avant d'écrire ;
- les essais refusés : à la composition, au chargement (mémoire insuffisante) ; la référence qui ne se compose pas ; la relance qui échoue, dite dans l'erreur ;
- l'annulation, par la route et par le stop du chat ;
- les refus d'entrée, avec les messages du Go :
- preset externe, Strata, aucun preset actif ;
- jobs du mode code, moteur occupé, génération en cours ;
- optimisation d'un autre processus (et
elsewheredans le statut) ;
- un verrou périmé :
- l'essai orphelin arrêté seulement si son identité concorde ;
- une application interrompue défaite ;
- les routes sans la façade.
Les tests du verrou du Go sont portés (tune/tests.rs) :
- prise, refus, essai noté, rendu ;
- propriétaire mort ;
- verrou à notre PID qui n'est pas l'un des nôtres ;
- illisible neuf ou vieux ;
- ménage jamais sur un verrou vivant ;
- binaire remplacé ;
- identité d'un processus ;
- arrêt du groupe.
Côté Go, TestFacadeTune vérifie :
- les cinq routes partent à la façade, et elles seules ;
- le bail « tune » : refus, bascule de discussion, libération ;
- le contexte : au repos, pendant l'optimisation, pendant un bench ;
- le démarrage et l'arrêt sans le refus de l'optimiseur.
Écarts assumés
- Une sortie à blanc qui échoue est lue dans un fichier où vont les deux
sorties (comme
CombinedOutput), mais une erreur de lecture delaunch.jsonou d'une requête garde le texte de Rust. - Un niveau de raisonnement appris pendant les essais n'est pas transmis au chat du Go quand le Go tient la conversation.