Spéculation : SPEC=ngram et mtp+ngram, n-grammes du contexte en opt-in

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>
This commit is contained in:
MichaelandClaude Opus 5.5 committed 2026-10-04 10:28:25 +02:00
1 parent 28ba44eb46
commit 539e36ea49
11 files changed
+495 -67

No files matched your search

+4 -1
View File
@@ -1260,7 +1260,8 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
<option value="bf16">bf16 (numérique différente de f16)</option>
</select></span></span>
</div>
<!-- Décodage spéculatif : « auto » et « MTP » écrivent la clé SPEC,
<!-- Décodage spéculatif : « auto », « MTP », « n-grammes du contexte » et
« MTP + n-grammes » écrivent la clé SPEC,
que Loki traduit au lancement (tête MTP détectée dans le fichier,
garde-fous VRAM) ; les autres types vont tels quels dans
--spec-type. « non » écrit SPEC=off. Le nombre de jetons anticipés
@@ -1271,6 +1272,8 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
<span class="pe-row-c"><span class="pe-selc"><select id="s-spec" onchange="onSpecType()">
<option value="">non</option>
<option value="auto">auto (MTP si le modèle en a une et que la VRAM suit)</option>
<option value="ngram">n-grammes du contexte (expérimental · mode code, à mesurer)</option>
<option value="mtp+ngram">MTP + n-grammes (expérimental · à mesurer)</option>
<optgroup label="Modèle brouillon">
<option value="draft-mtp">MTP (imposé)</option>
<option value="draft-eagle3">EAGLE-3</option>
+11 -6
View File
@@ -1108,10 +1108,14 @@ function syncLoadModeSub(mode){
// « auto » et « MTP » passent par la clé SPEC : Loki cherche la tête MTP dans
// le fichier et pose les garde-fous au lancement. Les autres types restent des
// --spec-type d'EXTRA_ARGS, qui ont toujours le dernier mot côté serveur.
// « ngram » et « mtp+ngram » aussi : Loki écrit lui-même les bornes de
// ngram-mod et refuse là où les longs lots de vérification coûteraient cher.
function specFromKey(v){
v = String(v||'').trim().toLowerCase();
return v === 'auto' ? 'auto' : v === 'mtp' ? 'draft-mtp' : '';
if(v === 'ngram+mtp') v = 'mtp+ngram';
return v === 'auto' ? 'auto' : v === 'mtp' ? 'draft-mtp' : (v === 'ngram' || v === 'mtp+ngram') ? v : '';
}
const SPEC_KEY_VALUES = {'auto': 'auto', 'draft-mtp': 'mtp', 'ngram': 'ngram', 'mtp+ngram': 'mtp+ngram'};
// Sélectionne le type courant. --spec-type accepte en réalité une LISTE séparée
// par des virgules ; une valeur composée (ou un type sorti après cette version
// de loki) ne correspondrait à aucune option et serait silencieusement effacée
@@ -1136,20 +1140,21 @@ function syncSpecRow(){
const row = document.getElementById('s-spec-n-row');
if(!sel || !row) return;
const on = !!sel.value;
row.style.display = on ? '' : 'none';
// SPEC=ngram n'a pas de brouillon : un --spec-draft-n-max le ferait refuser.
row.style.display = on && sel.value !== 'ngram' ? '' : 'none';
// Le brouillon ne sert qu'à SPEC (auto / MTP) ; un brouillon déjà posé reste
// visible pour qu'on puisse le retirer.
const dr = document.getElementById('s-draft-row');
if(dr) dr.style.display = (sel.value === 'auto' || sel.value === 'draft-mtp' || cfgReadKey('MODEL_DRAFT')) ? '' : 'none';
if(dr) dr.style.display = (sel.value === 'auto' || sel.value === 'draft-mtp' || sel.value === 'mtp+ngram' || cfgReadKey('MODEL_DRAFT')) ? '' : 'none';
return on;
}
function onSpecType(){
const v = document.getElementById('s-spec').value;
const viaKey = v === 'auto' || v === 'draft-mtp';
const viaKey = v in SPEC_KEY_VALUES;
// « non » écrit SPEC=off : explicite, et identique au défaut du serveur.
cfgWriteKey('SPEC', v === 'auto' ? 'auto' : v === 'draft-mtp' ? 'mtp' : v ? '' : 'off');
cfgWriteKey('SPEC', viaKey ? SPEC_KEY_VALUES[v] : v ? '' : 'off');
eaSetValued('--spec-type', viaKey ? '' : v);
if(!v){
if(!v || v === 'ngram'){
eaSetValued('--spec-draft-n-max', '');
document.getElementById('s-spec-n').value = '';
}