mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-20 13:38:11 +02:00
8a61879bfde5da9e331d654b53180e7e8e7af1ba
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8f61870224 |
Lot 27 : banc d'essai tenu par la façade (LOKI_BENCH=rust)
Avec LOKI_BENCH=rust (expérimental), la façade sert /api/bench, /api/bench/status, /api/bench/cancel et /api/bench/last, et déroule le protocole de mesure contre le moteur local (rust/loki-rs/src/bench) : mode rapide (préchauffage, ligne courte) et mode complet (prefill à froid à profondeur réelle, trois tours qui reprennent le cache). Corpus, requêtes, calculs et messages sont ceux du Go ; seule une mesure complète est enregistrée (last_bench, bench_presets, empreinte de configuration du Go). 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 « bench ». Le Go note alors benching et donne aux autres le refus du benchmark ; changer de discussion ne rompt pas le bail ; benchRunning() le voit (clients /v1, préchauffage, optimiseur). Un stop du chat, un Reset ou un bail perdu annulent le bench. Le Go prête aussi le travail annexe (effacement du slot à la fin, /internal/v1/engine/sidejob) et la télémétrie (/internal/v1/bench/perf). Correction des tests du Go : trois tests du préchauffage échouaient dix minutes par jour, avant minuit (prewarmNearMidnight lisait l'heure réelle). L'heure du garde-fou devient remplaçable (prewarmNow), fixée à midi dans les tests. Parité : parity_bench_test.go tire du Go un journal rejoué par tests/bench.rs contre le même faux moteur ; chaque requête reçue par le moteur est comparée (longs textes réduits à leur taille et à leur empreinte). Il couvre les refus, les deux modes, les échecs de chaque phase, le raisonnement refusé puis rejoué, la profondeur partielle et l'annulation. Les tests du Go sont portés (bench/tests.rs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv |
||
|
|
9bffff78c2 |
Optimiseur : loki tune et bouton « Optimiser », essais sans perte sur un moteur privé
Chercher à la main le bon micro-lot, les threads ou la marge --fit d'un preset demandait de dupliquer, basculer et comparer des bench complets un par un. L'optimiseur le fait sur un moteur d'essai, sans jamais toucher à config.env ni à ce que calcule le modèle, et n'écrit rien sans un clic. - Isolation : moteur principal arrêté puis relancé ; chaque essai est une copie de la configuration (LOKI_HOME/tune/run), lancée par « loki serve » sur 127.0.0.1 et un port libre, groupe de processus tué en sortie - Verrou exclusif inter-processus (LOKI_HOME/tune.lock, PID + démarrage + binaire) vérifié par serviceAction start/restart et par le chat, les tâches, bash_bg, /v1, le bench, la bascule et l'enregistrement de preset, GPU, clé d'API, moteur ; essai orphelin arrêté avant tout démarrage du moteur - Essais : lots, threads, délestage, marges --fit, files CUDA ; placement --fit et SPEC/CUDA_GRAPH_OPT/--backend-sampling seulement sur demande - EXTRA_ARGS jeton par jeton, liste blanche seulement ; ligne de commande de chaque essai composée à blanc et comparée à la référence (« dénature »), contexte, slots et cache KV recontrôlés une fois chargé - Mesure : bench complet du lot 1 à profondeur fixe ; score = durée d'un tour type (médianes de la télémétrie) ; gain > max(3 %, écart entre passages) - Application sur clic : copie du preset, ou preset actuel sauvegardé, réécrit clé par clé, vérifié par une sonde et rétabli en cas d'échec Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
28ba44eb46 |
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> |
||
|
|
7a57322a62 |
Slots : SIDE_SLOT ouvre un second slot pour les travaux annexes, en opt-in
En --parallel 1, une vérification, un sous-agent, une tâche ou un bench prennent le slot de la discussion : son état part dans le cache RAM et en revient, ou se recalcule s'il n'y tient plus. Avec SIDE_SLOT=on (off par défaut), le moteur ouvre deux slots et la discussion garde le sien. Dimensionnement choisi pour qu'un débordement concurrent soit impossible par construction : cache KV NON unifié (--no-kv-unified) et -c 2×CTX, soit deux flux séparés de CTX jetons. Sous cache unifié, les deux slots partagent le pool et, plein, llama.cpp renvoie « Context size has been exceeded. » aux deux — que Loki prenait pour un débordement de la conversation. Chaque slot garde la fenêtre entière : ctxWindow et la compaction restent sur CTX, rien n'est raccourci. --cache-idle-slots ne vide les slots au repos que sous cache unifié : rien à régler. - lancement : refus (un slot, ligne d'avant, note au journal) si modèle + deux états dépassent 90 % de la VRAM, VRAM ou GGUF inconnus, poids sur CPU, moteur sans --no-kv-unified, PARALLEL≠2, ou -c/-np/-kvu/--no-kv-unified/ --kv-unified-per-slot/--cache-idle-slots dans EXTRA_ARGS (ou leurs LLAMA_ARG_*) ; note de VRAM en plus, avertissement si NGL imposé - routage id_slot seulement si /props annonce 2 slots d'au moins CTX jetons : 0 pour le tour, ses étapes, le préchauffage et le résumé en continuation ; 1 pour vérification, sous-agents, tâches, bench, résumé sur transcription - clients /v1 (proxy et relais) : corps réécrit en id_slot 1, quel qu'il soit - cohérence lot 1 : l'effacement de slot s'abstient (2 slots) ; une requête du slot 1 n'avance pas le numéro d'engineSlotHolds, la continuation de compaction reste possible après une vérification - « Context size has been exceeded. » sans nombre de jetons, deux slots en service : requête rejouée telle quelle, jamais compaction ni réduction - préchauffage permis sur les deux slots de SIDE_SLOT, vers le slot 0 - éditeur de preset : VRAM du second slot ou raison du refus - tests : ligne identique sans la clé, chaque conflit refuse sans changer la ligne, routage par nature, aucun id_slot sur un slot / preset externe / fenêtre partagée, rejeu sans compaction, proxy forcé, préchauffage Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2097c9f915 |
Compaction : COMPACT_CONTINUATION résume dans le prolongement du prompt en cache, en opt-in
Le résumé d'une compaction part aujourd'hui dans une requête à part — prompt du résumeur et transcription des anciens tours — que le moteur local calcule à froid : des dizaines de secondes sur un 27B, des minutes sur un MoE, à chaque compaction. Nouvelle clé COMPACT_CONTINUATION (off par défaut) : quand le slot porte encore le prompt de la discussion, la requête de résumé est celle du tour telle qu'elle est partie, suivie d'une seule demande de résumé ; le moteur ne calcule qu'elle. Sans la clé, requêtes de compaction identiques à l'octet près (prompt du résumeur comparé à une copie figée, testé). - vue MODÈLE pour tout ce qui est rangé : bornes, archives recall, demande réinjectée, garantie de réduction et sortie ne changent pas ; la vue d'envoi (turnViewDry, wireMessages, buildChatPayload) ne sert qu'à la requête, rien d'injecté n'entre dans l'historique (testé) - frontière recalée sur la vue envoyée (messages non système un pour un, vérifiés rôle par rôle), désignée par le nombre de messages gardés et le début du premier ; tout résumer avant, dater l'avancement à la frontière - mêmes règles de résumé (+ mode Code), même budget, température 0.2 sans l'échantillonnage du preset, enable_thinking=false ajouté aux arguments du tour, reasoning_effort du tour, tool_choice « none », sans flux - messages utilisateur de fin hors de la vue : pas en cache, et pas deux `user` d'affilée pour les gabarits stricts - slot vérifié : tampon posé par une étape de tour acceptée (llm_slots.go, sous le verrou du compteur en vol), perdu dès qu'une autre requête part — vérification, sous-agent, tâche, préchauffage, résumé, bench, /v1 — ou que le modèle ou la fenêtre changent ; relu à l'envoi - marge en jetons réels (dernier compte + non vu + demande + budget + 5 %) - repli sur la transcription au moindre écart : refus du moteur, réseau, appel d'outil émis (tool_calls décodés) ou écrit en texte, raisonnement seul, résumé vide ; refus du gabarit ou appel d'outil = suspendue pour le modèle jusqu'au redémarrage, deux échecs de suite aussi - avec la clé : pas de résumé quand même un vide ne réduirait pas de 20 % (borne exacte, avant tout archivage) ; après un refus faute de réduction, pas de nouvel essai avant +10 % de contexte, jamais à 90 % de la fenêtre, oublié quand le contexte baisse - réactif, fenêtre pleine, bouton manuel, tâches, sous-agents, terminal, preset externe : chemin d'avant ; télémétrie kind=compact avec la discussion Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
630e84cc08 |
Cache : PREWARM prépare le prochain tour pendant que l'utilisateur lit, en opt-in
Une compaction, un dernier message rendu autrement au tour suivant ou une tâche planifiée qui a pris le slot laissent au message suivant un recalcul inévitable : des secondes sur un 27B, des dizaines sur un MoE aux experts en RAM, avant le premier mot. Nouvelle clé PREWARM (off par défaut) : dès que le moteur local est libre, Loki lui envoie la requête du prochain tour suivie d'un message utilisateur « . », max_tokens 1, sans flux. Le moteur calcule le préfixe et pose un point de reprise au début de ce message ; le vrai tour ne calcule plus que le sien. Sans la clé, aucune requête de plus (testé). - assemblage partagé, contenu vivant : turnViewDry (même code que turnView, sans rien toucher à la discussion, décision PROJ_SNAPSHOT via projSnapDecide), wireMessages, turnReasoning et buildChatPayload, extraits de runChat ; corps identique à l'octet près à celui d'avant (matrice d'options et de modes, testée contre une copie de l'ancien code) - jamais devant un vrai travail : toute requête de Loki l'annule au départ (compteur de llm_slots.go, sous son verrou), sauf un tour de chat dont les messages sérialisés, outils et arguments du gabarit prolongent exactement le préfixe préchauffé - moteur local, un seul slot (/props total_slots), pas pendant un tour, une tâche, un bench, un travail annexe ni une requête en vol ; un seul à la fois ; pas si le prochain tour compactera, ni à moins de 10 min de minuit - requête brute : ni compaction, ni relance, ni effort appris, ni CtxUsed, ni stats ; erreurs lâchées (une ligne de journal par statut) ; rien persisté - déclencheurs : fin de tour sans file d'attente, fin de tâche (projet forcé levé, slot effacé) ; full = aussi changement de discussion après 3 s - capacités du dernier tour gardées en mémoire par discussion ; mode Code = rôle d'un message ordinaire, une demande de plan diverge et annule - télémétrie kind=prewarm ; la vérification du cache RAM après une tâche se fait sur lui Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |