En mode Code, le modèle recopie sans cesse ce qui est déjà dans le
contexte : chemins, diffs, arguments JSON, fichiers réécrits. ngram-mod
de llama.cpp y cherche la suite des 24 derniers jetons et propose d'un
coup les 48 à 64 suivants, sans modèle brouillon. La clé SPEC (off par
défaut, inchangé) gagne deux valeurs : ngram, et mtp+ngram qui y ajoute
la tête MTP. Même vérification exacte que MTP : distribution inchangée,
mais pas le même texte au bit près (vérification par lots), donc on
compare des sessions rejouées, pas des diffs.
- forme explicite seulement : --spec-type ngram-mod
--spec-ngram-mod-n-match 24 --spec-ngram-mod-n-min 48
--spec-ngram-mod-n-max 64 ; jamais --spec-default (TODO amont, contenu
susceptible de changer avec le moteur)
- garde-fou d'aide sur « --spec-ngram-mod-n-match » (pas le simple mot
ngram-mod, encore listé par les moteurs d'avant le renommage) ; absent =
SPEC ignoré, note au journal
- mtp+ngram : --spec-type draft-mtp,ngram-mod seulement avec draft-mtp
dans l'aide ET une tête MTP réelle (tenseur nextn ou MODEL_DRAFT) ;
sinon n-grammes seuls, avec la raison — jamais « failed to create MTP
context » en boucle
- EXTRA_ARGS/LLAMA_ARG_* : mêmes exclusions qu'avant, plus --spec_type et
tout --spec-ngram-* (--spec-type s'additionne sans prévenir) ; pour
ngram seul, un --spec-draft-* fait aussi taire Loki
- poids sur CPU (experts MoE, -ot, NGL partiel) : refusé tant que
GGML_OP_OFFLOAD_MIN_BATCH (env ou OP_OFFLOAD_MIN_BATCH) ne dépasse pas
le lot de vérification de 65 jetons, avec la suggestion
OP_OFFLOAD_MIN_BATCH=128 ; avertissements pour un modèle plus gros que
la RAM, les points de reprise d'un hybride, NGL imposé (logits)
- avec ngram, une tête MTP ou MODEL_DRAFT inutilisés sont signalés
- --spec-synth-len/--spec-synth-rates (et LLAMA_ARG_SPEC_SYNTH_LEN) :
acceptation au hasard, avertissement au lancement ; Loki ne les pose
jamais
- télémétrie : /api/perf/summary donne draft_n, draft_accepted et
draft_rate par nature de requête
- UI : deux options du sélecteur de décodage spéculatif ; README et
configTemplate
- tests : forme explicite, garde d'aide, repli de mtp+ngram, exclusions,
seuil d'offload, ligne inchangée sans SPEC, acceptation par nature
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
La relecture du relevé par complétion a trouvé quatre écarts, tous
d'affichage ou de robustesse ; rien ne touche aux requêtes ni au contexte.
- Compaction : la réponse lue d'un bloc passait de Decoder à Unmarshal,
plus strict (un octet parasite après le JSON faisait échouer une
compaction qui passait). Retour au Decoder, et perfWire fait de même.
- API externe : son cache suit ses propres règles, sans slot ni points de
reprise à surveiller ici. Plus de ligne ambre « recalculés » pour elle ;
le relevé reste dans l'anneau.
- Seuil d'alerte : même priorité qu'au lancement — -cms d'EXTRA_ARGS, puis
LLAMA_ARG_CHECKPOINT_MIN_SPACING_NT, puis CKPT_MIN_STEP ; -ub d'EXTRA_ARGS
avant UBATCH.
- UI : « recalculés après sous-agent, client /v1 » au lieu des identifiants
internes (subagent, foreign).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Jusqu'ici, impossible de savoir si une ligne volatile s'était glissée dans
le prompt, si une mise à jour du moteur avait cassé les points de reprise
ou si l'acceptation du MTP s'était effondrée : le chunk final de llama.cpp
porte ces chiffres (cache_n, draft_n, cached_tokens), on les jetait.
Lecture seule : aucun champ ajouté aux requêtes, et le comptage du
contexte (usage.prompt_tokens → CtxUsed → compaction) ne change pas.
- perf_log.go : décodage à part et tolérant (perfWire) — un compteur mal
typé ne jette plus le chunk final ni ne fait échouer une compaction ;
cached_tokens, strictement entier dans streamChunk, y déménage aussi.
- Inconnu n'est pas 0 : pointeurs, et l'UI garde « prefill N tok » quand
le moteur ne dit rien de son cache.
- Nature (main, subagent, verify, task, compact, bench, foreign) portée
par le contexte, pas par Caps ; TTFT au premier delta de tout type.
- Perte de cache = total précédent − cache_n, seulement quand les messages
prolongent strictement ceux de la complétion précédente de la même
discussion et de la même nature (empreintes cumulées) ; jamais sur un
flux coupé. Ce qui s'est intercalé (sous-agent, client /v1, bench) est
nommé.
- Anneau de 5000 entrées en mémoire, sans texte ; GET /api/perf/summary
(derrière la clé) : taux de cache, recalcul par tour et par nature,
médianes pp/tg par profondeur, acceptation du brouillon.
- Ligne [perf] sur stderr seulement avec LOKI_PERF_LOG.
- UI : « prefill X nouveaux / Y en cache », ambre au-delà d'un seuil
relevé sur un modèle hybride (espacement des points de reprise).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>