mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-20 21:48:47 +02:00
Moteur : garde-fous de fidélité — un cache KV quantifié ou un cache approché se voit, Loki n'en pose jamais
Le cache KV en q8_0 d'un preset MoE vivait dans EXTRA_ARGS : ni l'avertissement de lenteur ni la liste de l'interface ne le voyaient, qui affichait « f16 (max qualité) » pendant que le moteur tournait en q8_0. Rien n'empêchait non plus un --context-shift ou un --cache-reuse de modifier en douce ce que voit le modèle. Aucun drapeau n'est ajouté ni retiré : on DIT ce que la ligne finale change. - Type de cache effectif (effectiveKVTypes) : KV_TYPE*, puis -ctk/-ctv et --cache-type-k/v d'EXTRA_ARGS par-dessus, la dernière occurrence gagne comme dans llama-server. warnSlowKV le reçoit désormais. - Note au lancement quand ce cache n'est pas f16 : q8_0 modifie légèrement les sorties, q4_0 perte mesurable, bf16 numérique différente. Avec -ot ou --n-cpu-moe, --fit ne tourne pas : repasser en f16 demandera sans doute de relever --n-cpu-moe. Pas d'estimation de VRAM sans les métadonnées du GGUF. - Avertissement pour --context-shift (jamais --no-context-shift) et --cache-reuse N>0 ; --swa-full, sans perte, n'en déclenche aucun. Vision chargée : llama.cpp les ignore, on le précise. - Interface : options du cache KV étiquetées, sous-titre qui montre le type effectif (« défini par EXTRA_ARGS ») et les drapeaux de cache approché. - Tests : notes et type effectif en table, aucun -ctk/-ctv sans KV_TYPE, corps réels du chat et de la compaction sans cache_prompt:false ni n_cache_reuse, et ces clés réservées au benchmark dans tout le paquet (arbre syntaxique). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a42c184ed2
commit
2bf388f7b7
8 files changed
+545
-19
No files matched your search
@@ -1234,13 +1234,16 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
|
||||
<span class="pe-row-c"><input id="s-ubatch" class="pe-val" type="number" min="0" step="128" placeholder="512" oninput="cfgWriteKey('UBATCH', this.value)"></span>
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
<span class="pe-row-l">Cache KV<span class="pe-sub">compression du contexte</span></span>
|
||||
<span class="pe-row-c"><span class="pe-selc"><select id="s-kv" onchange="cfgWriteKey('KV_TYPE', this.value)">
|
||||
<!-- Seul f16 laisse les calculs du modèle intacts : chaque autre
|
||||
option le dit. Le sous-titre montre le type EFFECTIF — un
|
||||
-ctk/-ctv d'EXTRA_ARGS l'emporte sur cette liste (syncKVSub). -->
|
||||
<span class="pe-row-l">Cache KV<span class="pe-sub" id="s-kv-sub">compression du contexte</span></span>
|
||||
<span class="pe-row-c"><span class="pe-selc"><select id="s-kv" onchange="cfgWriteKey('KV_TYPE', this.value); syncKVSub()">
|
||||
<option value="">f16 (max qualité)</option>
|
||||
<option value="q8_0">q8_0 (léger)</option>
|
||||
<option value="q4_0">q4_0 (très léger)</option>
|
||||
<option value="q5_1">q5_1 (lent sur CUDA)</option>
|
||||
<option value="bf16">bf16</option>
|
||||
<option value="q8_0">q8_0 (léger · modifie légèrement les sorties)</option>
|
||||
<option value="q4_0">q4_0 (très léger · perte mesurable)</option>
|
||||
<option value="q5_1">q5_1 (lent sur CUDA · modifie les sorties)</option>
|
||||
<option value="bf16">bf16 (numérique différente de f16)</option>
|
||||
</select></span></span>
|
||||
</div>
|
||||
<!-- Décodage spéculatif : le type vient de la liste que llama-server
|
||||
@@ -1353,7 +1356,7 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
|
||||
<span class="pe-row-c"><span id="m-raw-caret" class="pe-caret"></span></span>
|
||||
</div>
|
||||
<div id="m-raw-body" class="pe-row stack" style="display:none">
|
||||
<textarea id="m-content" class="pe-inp" spellcheck="false"></textarea>
|
||||
<textarea id="m-content" class="pe-inp" spellcheck="false" oninput="syncKVSub()"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -856,7 +856,7 @@ function cfgWriteKey(key, val){
|
||||
// jeton par jeton pour les interrupteurs (mlock, flash-attn, n-cpu-moe…), sans
|
||||
// toucher aux autres drapeaux (--jinja, --device…) qui restent en config brute.
|
||||
function eaTokens(){ return cfgReadKey('EXTRA_ARGS').split(/\s+/).filter(Boolean); }
|
||||
function eaSetTokens(t){ cfgWriteKey('EXTRA_ARGS', t.join(' ')); }
|
||||
function eaSetTokens(t){ cfgWriteKey('EXTRA_ARGS', t.join(' ')); syncKVSub(); }
|
||||
function eaHasFlag(flag){ return eaTokens().includes(flag); }
|
||||
function eaToggleFlag(flag, on){
|
||||
const t = eaTokens().filter(x=>x!==flag);
|
||||
@@ -884,6 +884,7 @@ function populateSettings(){
|
||||
set('s-ubatch', cfgReadKey('UBATCH'));
|
||||
set('s-tbatch', cfgReadKey('THREADS_BATCH'));
|
||||
set('s-kv', cfgReadKey('KV_TYPE'));
|
||||
syncKVSub();
|
||||
// Échantillonnage : envoyé PAR REQUÊTE (applySampling côté serveur), donc pas
|
||||
// besoin de redémarrer le moteur pour qu'un changement prenne effet.
|
||||
set('s-temp', cfgReadKey('TEMP'));
|
||||
@@ -931,6 +932,57 @@ function populateSettings(){
|
||||
set('s-loadmode', lm);
|
||||
syncLoadModeSub(lm);
|
||||
}
|
||||
// Cache KV : le sous-titre dit ce que le moteur utilisera VRAIMENT, comme
|
||||
// effectiveKVTypes côté Go. EXTRA_ARGS ferme la ligne de commande et la dernière
|
||||
// occurrence gagne : un --cache-type-k q8_0 écrit à la main l'emporte sur la
|
||||
// liste, qui afficherait sinon « f16 » pendant que le moteur tourne en q8_0.
|
||||
// Les drapeaux de cache qui changent ce que voit le modèle (--context-shift,
|
||||
// --cache-reuse > 0) sont signalés au même endroit. Rien n'est jamais modifié
|
||||
// ici : c'est un affichage.
|
||||
const KV_FIDELITY = {
|
||||
'bf16': 'numérique différente de f16',
|
||||
'q8_0': 'modifie légèrement les sorties', 'q5_0': 'modifie légèrement les sorties', 'q5_1': 'modifie légèrement les sorties',
|
||||
'q4_0': 'perte mesurable', 'q4_1': 'perte mesurable', 'iq4_nl': 'perte mesurable',
|
||||
};
|
||||
const KV_RANK = {'':0, 'f16':0, 'f32':0, 'bf16':1, 'q4_0':3, 'q4_1':3, 'iq4_nl':3};
|
||||
function eaLastValue(flags){
|
||||
let v = '';
|
||||
const t = eaTokens();
|
||||
t.forEach((a, i) => {
|
||||
const eq = a.indexOf('='), name = eq > 0 ? a.slice(0, eq) : a;
|
||||
if(!flags.includes(name)) return;
|
||||
if(eq > 0) v = a.slice(eq+1);
|
||||
else if(i+1 < t.length) v = t[i+1];
|
||||
});
|
||||
return v;
|
||||
}
|
||||
function syncKVSub(){
|
||||
const el = document.getElementById('s-kv-sub');
|
||||
if(!el) return;
|
||||
const kv = cfgReadKey('KV_TYPE');
|
||||
const xk = eaLastValue(['-ctk','--cache-type-k']), xv = eaLastValue(['-ctv','--cache-type-v']);
|
||||
const k = (xk || cfgReadKey('KV_TYPE_K') || kv).toLowerCase();
|
||||
const v = (xv || cfgReadKey('KV_TYPE_V') || kv).toLowerCase();
|
||||
const rank = x => (x in KV_RANK) ? KV_RANK[x] : 2;
|
||||
const worst = rank(v) > rank(k) ? v : k;
|
||||
const parts = [];
|
||||
if(rank(worst) === 0){
|
||||
parts.push(xk || xv ? 'f16 (défini par EXTRA_ARGS)' : 'compression du contexte');
|
||||
} else {
|
||||
const label = KV_FIDELITY[worst] || 'modifie les sorties';
|
||||
parts.push((xk || xv ? 'défini par EXTRA_ARGS : ' : '') + (k||'f16')+'/'+(v||'f16')+' — '+label);
|
||||
// Placement figé à la main : --fit ne tourne pas et n'absorbera pas le
|
||||
// surplus d'un retour en f16.
|
||||
if(eaTokens().some(a => ['-ot','--override-tensor','--n-cpu-moe','-ncmoe','--cpu-moe','-cmoe'].includes(a.split('=')[0])))
|
||||
parts.push('repasser en f16 : plus de VRAM, --n-cpu-moe à relever');
|
||||
}
|
||||
let shift = false;
|
||||
eaTokens().forEach(a => { if(a === '--context-shift') shift = true; else if(a === '--no-context-shift') shift = false; });
|
||||
if(shift) parts.push('--context-shift : jette des jetons quand le contexte est plein');
|
||||
const reuse = parseInt(eaLastValue(['--cache-reuse']), 10);
|
||||
if(reuse > 0) parts.push('--cache-reuse : cache réutilisé de façon approchée');
|
||||
el.textContent = parts.join(' · ');
|
||||
}
|
||||
// Chargement du modèle. llama.cpp récent a REMPLACÉ --mlock / --no-mmap par
|
||||
// --load-mode (auto, none, mmap, mlock, mmap+mlock, dio). L'éditeur écrit la
|
||||
// forme moderne ; au lancement, loki serve la retraduit pour un moteur ancien
|
||||
|
||||
Reference in new issue
Block a user