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:
MichaelandClaude Opus 5.5 committed 2026-10-04 11:12:56 +02:00
1 parent 986a636c20
commit f87c7b615b
11 files changed
+1001 -8

No files matched your search

+50
View File
@@ -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;