mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-21 14:08:11 +02:00
MoE : avis de placement, copie en placement auto et garde du mode de chargement
Un MoE aux experts sur CPU se règle aujourd'hui à la main (-ot, --n-cpu-moe 40, UBATCH 512) sans que Loki dise ce que --fit ferait mieux, ni qu'un --load-mode none/mlock trop gros pour la RAM mène au swap ou à l'OOM (llama.cpp #26110). Rien n'est réécrit en douce : des avis, une copie sur demande, un refus seulement quand l'échec est certain. - moeNotes (pure, comme nglArgs) : experts placés à la main → --fit ne les place pas, et ne pas monter UBATCH seul (tampon plus gros sur chaque carte) ; placement auto, MoE plus gros que la VRAM, UBATCH ≤ 512 → « UBATCH 2048+ » ; moteur sans --fit → « garde --n-cpu-moe » ; --fit coupé par un autre -ot. Le détecteur cpuExperts ne compte un -ot que s'il vise les experts (exps) vers le CPU : celui de per_layer_token_embd n'en est pas. - « Dupliquer en placement auto… » (éditeur, /api/preset/autoplace) : COPIE du preset affiché, sans -ot des experts, --n-cpu-moe, --cpu-moe, -ngl, --tensor-split, --fit off, -b/-ub ni drapeaux de chargement ; NGL retiré, UBATCH 2048, BATCH 4096, --load-mode mmap ; CTX, cache KV, échantillonnage intacts. Refusée si --fit resterait inactif ou si CTX vaut 0. L'original n'est pas touché, la copie n'est pas activée. - loadModeRisk : none, mlock, dio, mmap+mlock (et --no-mmap, --mlock, LLAMA_ARG_*) face à la RAM effective (limite cgroup comprise), en comptant modèle moins VRAM (tout le modèle sur macOS) : avertissement au-delà de 80 %, refus au lancement au-delà de 90 % de la borne basse seulement ; LOAD_GUARD=off le lève. VRAM inconnue : jamais de refus. - Éditeur : avis sous « Experts MoE sur CPU » et sous « Chargement ». Ligne de commande et environnement du moteur inchangés (test de non-régression) ; presets externes ignorés. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
986a636c20
commit
f87c7b615b
11 files changed
+1001
-8
No files matched your search
@@ -1225,7 +1225,14 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
<span class="pe-row-l">Experts MoE sur CPU<span class="pe-sub">vide = non · sur 2 GPU, coupe le pipeline entre cartes (prompt plus lent)</span></span>
|
||||
<span class="pe-row-c"><input id="s-moe" class="pe-val" type="number" min="0" step="1" placeholder="—" oninput="eaSetValued('--n-cpu-moe', this.value)"></span>
|
||||
<span class="pe-row-c"><input id="s-moe" class="pe-val" type="number" min="0" step="1" placeholder="—" oninput="eaSetValued('--n-cpu-moe', this.value); refreshMoeSoon()"></span>
|
||||
</div>
|
||||
<!-- Avis MoE (refreshMoe) : experts placés à la main, UBATCH conseillé,
|
||||
et l'assistant « Dupliquer en placement auto » — une COPIE du
|
||||
preset, l'original reste tel quel. Masqué tant qu'il n'y a rien à dire. -->
|
||||
<div class="pe-row stack" id="m-moe-row" style="display:none">
|
||||
<div class="pe-note" id="m-moe-note"></div>
|
||||
<button class="pe-link" id="m-moe-dup" onclick="dupAutoPlacement()" hidden>Dupliquer en placement auto…</button>
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
<span class="pe-row-l">Threads CPU<span class="pe-sub">vide ou 0 = cœurs physiques</span></span>
|
||||
@@ -1241,7 +1248,7 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
<span class="pe-row-l">UBATCH</span>
|
||||
<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>
|
||||
<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); refreshMoeSoon()"></span>
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
<!-- Cache de prompts en RAM hôte (--cache-ram, Mio) : copie exacte de
|
||||
@@ -1329,7 +1336,7 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
|
||||
(normalizeLoadFlags). -->
|
||||
<div class="pe-row">
|
||||
<span class="pe-row-l">Chargement<span class="pe-sub" id="s-loadmode-sub"></span></span>
|
||||
<span class="pe-row-c"><span class="pe-selc"><select id="s-loadmode" onchange="eaSetLoadMode(this.value)">
|
||||
<span class="pe-row-c"><span class="pe-selc"><select id="s-loadmode" onchange="eaSetLoadMode(this.value); refreshMoeSoon()">
|
||||
<option value="">auto</option>
|
||||
<option value="mmap">mmap</option>
|
||||
<option value="none">none</option>
|
||||
@@ -1338,6 +1345,11 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
|
||||
<option value="dio">dio</option>
|
||||
</select></span></span>
|
||||
</div>
|
||||
<!-- Mode résident (none, mlock, dio, mmap+mlock) avec trop de poids en
|
||||
RAM : l'avertissement du lancement (loadModeRisk), ou son refus. -->
|
||||
<div class="pe-row stack" id="s-loadmode-warn-row" style="display:none">
|
||||
<div class="pe-note" id="s-loadmode-warn" style="color:var(--warn)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1018,6 +1018,7 @@ function populateSettings(){
|
||||
set('s-ubatch', cfgReadKey('UBATCH'));
|
||||
set('s-cram', cfgReadKey('CACHE_RAM'));
|
||||
refreshCacheRAM();
|
||||
refreshMoe();
|
||||
set('s-tbatch', cfgReadKey('THREADS_BATCH'));
|
||||
set('s-kv', cfgReadKey('KV_TYPE'));
|
||||
syncKVSub();
|
||||
@@ -1115,6 +1116,55 @@ async function refreshCacheRAM(){
|
||||
if(sub) sub.textContent = 'RAM hôte, copie exacte du contexte · jamais la VRAM' +
|
||||
(r.why ? ' · ' + r.why : '') + (r.mib > 0 || fixed ? '' : ' · défaut du moteur') + side;
|
||||
}
|
||||
// Avis MoE et mode de chargement, calculés côté serveur comme au lancement
|
||||
// (backend_serve_moe.go) : experts placés à la main, UBATCH conseillé, moteur
|
||||
// sans --fit, chargement résident trop gros pour la RAM. Des avis seulement :
|
||||
// rien n'est écrit dans le preset. Une demande en vol ; la dernière gagne.
|
||||
let moeSeq = 0, moeTimer = null, moeChanges = null;
|
||||
function refreshMoeSoon(){ clearTimeout(moeTimer); moeTimer = setTimeout(refreshMoe, 400); }
|
||||
async function refreshMoe(){
|
||||
const row = document.getElementById('m-moe-row'), note = document.getElementById('m-moe-note');
|
||||
const dup = document.getElementById('m-moe-dup');
|
||||
const lrow = document.getElementById('s-loadmode-warn-row'), lw = document.getElementById('s-loadmode-warn');
|
||||
if(!row) return;
|
||||
const seq = ++moeSeq;
|
||||
let r = {};
|
||||
try{ r = await jpost('/api/preset/moe', {content: document.getElementById('m-content').value}); }
|
||||
catch(_){ r = {}; }
|
||||
if(seq !== moeSeq) return;
|
||||
const ap = r.ok ? r.autoplace : null;
|
||||
const parts = (r.ok && r.notes) ? r.notes.slice() : [];
|
||||
if(ap && !ap.ok) parts.push('placement auto impossible : ' + ap.why);
|
||||
note.textContent = parts.join(' · ');
|
||||
moeChanges = (ap && ap.ok) ? (ap.changes || []) : null;
|
||||
dup.hidden = !moeChanges;
|
||||
row.style.display = (parts.length || moeChanges) ? '' : 'none';
|
||||
if(lrow && lw){
|
||||
lw.textContent = (r.ok && r.load) || '';
|
||||
lrow.style.display = lw.textContent ? '' : 'none';
|
||||
}
|
||||
}
|
||||
// « Dupliquer en placement auto » : une COPIE du preset tel qu'affiché, sans
|
||||
// les experts placés à la main (--fit les répartit carte par carte), UBATCH
|
||||
// 2048 / BATCH 4096, NGL auto, chargement mmap, CTX et cache KV intacts. Le
|
||||
// preset d'origine ne bouge pas : c'est le repli si --fit échoue.
|
||||
async function dupAutoPlacement(){
|
||||
if(!moeChanges) return;
|
||||
const msg = 'Créer une COPIE de ce preset en placement automatique (--fit place les experts carte par carte) :\n\n'
|
||||
+ moeChanges.map(c => '• ' + c).join('\n')
|
||||
+ '\n\nLe preset d\'origine reste tel quel : c\'est le repli. Après la bascule sur la copie, le journal doit dire '
|
||||
+ '« successfully fit params » — « failed to fit » met tous les experts sur GPU : revenir à l\'original. '
|
||||
+ 'Puis comparer les deux au « bench complet ».';
|
||||
if(!await askConfirm(msg, {title:'Placement auto', okText:'Créer la copie'})) return;
|
||||
let r = {};
|
||||
try{
|
||||
r = await jpost('/api/preset/autoplace', {id: editingKey || '', name: document.getElementById('m-name').value.trim(),
|
||||
content: document.getElementById('m-content').value});
|
||||
}catch(e){ r = {ok:false, error:e.message}; }
|
||||
if(!r.ok){ toast('erreur : ' + (r.error||'')); return; }
|
||||
toast('copie créée : ' + r.name);
|
||||
KINDS.preset.reload();
|
||||
}
|
||||
function syncKVSub(){
|
||||
const el = document.getElementById('s-kv-sub');
|
||||
if(!el) return;
|
||||
|
||||
Reference in new issue
Block a user