window.AutoTestUI=(()=>{ const e=x=>String(x??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); async function api(path,data){const r=await fetch('/api/v1/'+path,data===undefined?{}:{method:'POST',headers:{'Content-Type':'application/json','X-Athena-Deck':'1'},body:JSON.stringify(data)});const v=await r.json();if(!r.ok)throw Error(v.error||'Anfrage fehlgeschlagen');return v;} function html(){return `

Automatische Einpassung & Leistungstest

Priorität: RTX 5080 allein → möglichst kleiner Anteil auf RTX 3060 → erst zuletzt CPU-Auslagerung. Nach den Grundverteilungen aller gewählten Kontextstufen wird die 5080 für passende Dual-GPU-Kandidaten in Ein-Layer-Schritten weiter gefüllt. Synthetische Tests belegen die Deck-Laufzeit exklusiv; API-Anfragen warten. Fremde GPU-Dienste werden nicht beendet.

Ein Slot, Batch 2048, Microbatch 128 / 64 / 256. Nur Kontextstufen im gewählten Bereich; pro Kandidat werden bis nahe an das volle Kontextbudget Eingabetoken geprüft und 64 Token erzeugt. Alle Grundverteilungen 5080 allein sowie 98:2, 95:5, 90:10, 85:15, 75:25 und 50:50 werden je Stufe vor der Layer-Feinsuche geprüft. Höchstens 300 Kandidaten oder zwei Stunden; bei Abbruch wird die Stufe als unvollständig markiert. Kein absichtliches Übergehen der Speicherreserve.

Dies ist eine begrenzte Suche, kein Beweis des absoluten Optimums oder der Stabilität bei vollem Kontext und paralleler Last. Erfolgreiche Profile werden nur auf Wunsch gespeichert, nicht am Endpunkt freigegeben.

`;} function bind(){const root=document.querySelector('#auto-test'),el=x=>root.querySelector('#'+x);let job=null,last='';const msg=x=>{if(root.isConnected)el('auto-message').textContent=x;}; api('catalog').then(s=>{if(root.isConnected)el('auto-model').innerHTML=s.entries.filter(x=>x.kind==='chat'&&x.profile_eligible&&x.file.endsWith('.gguf')).map(x=>``).join('');}).catch(x=>msg(x.message)); async function refresh(){try{const s=await api('auto-tests');if(!root.isConnected)return;job=s.job;const running=job?.state==='running';el('auto-start').disabled=running;el('auto-stop').disabled=!running;el('auto-phase').textContent=job?`${job.state} · ${job.phase} · ${job.attempts}/${job.max_candidates||96} Kandidaten · vollständig geprüfte Stufen: ${(job.completed_contexts||[]).map(x=>x.toLocaleString('de-DE')).join(', ')||'keine'}${job.error?' · '+job.error:''}${job.fine_search_note?' · '+job.fine_search_note:''}`:'Noch kein Auto-Test.';const rows=job?.results||[],signature=JSON.stringify(rows);if(last!==signature){last=signature;const best=rows.reduce((a,r,i)=>r.success&&(!a||r.timings.predicted_per_second>a.speed)?{i,speed:r.timings.predicted_per_second}:a,null);el('auto-results').innerHTML=rows.map((r,i)=>`

${r.context.toLocaleString('de-DE')} Kontext · ${e(r.tier)} ${best?.i===i?'· schnellster gemessener Kandidat':''}

Verteilung ${e(r.parameters.tensor_split.map(v=>Number(v.toFixed(3))).join(':')||'nur 5080')} · Microbatch ${r.parameters.ubatch} · KV ${e(r.parameters.cache_type_k||"q4_0")}/${e(r.parameters.cache_type_v||"q4_0")}${r.primary_gpu_layers?` · geplant ${r.primary_gpu_layers} GPU-Layer auf der 5080 (inkl. Ausgabe/MTP gemäß GGUF)`:""}

${r.success?`

Prefill ${Number(r.timings.prompt_per_second).toFixed(1)} Token/s · Ausgabe ${Number(r.timings.predicted_per_second).toFixed(1)} Token/s · ${Number(r.timings.prompt_n||0).toLocaleString('de-DE')} / ${r.context.toLocaleString('de-DE')} Eingabe-Token geprüft (${(100*(r.tested_context_fraction||0)).toFixed(1)} %)

GPU-Layerlimit: ${r.memory_plan.gpu_layers===999?'alle':r.memory_plan.gpu_layers}

`:`

${r.failure_stage==='prediction'?'Speicherprognose abgelehnt · kein Modellstart':r.failure_stage==='model_start'?'Modellstart fehlgeschlagen · Ursache nicht als GPU-OOM bewiesen':'Messung fehlgeschlagen · Ursache nicht als GPU-OOM bewiesen'}: ${e(r.error)}

`}
`).join('');root.querySelectorAll('[data-save]').forEach(b=>b.onclick=async()=>{try{await api('auto-tests/save',{job_id:job.id,index:Number(b.dataset.save),name:el('auto-name').value});msg('Profil gespeichert.');}catch(x){msg(x.message);}});}}catch(x){msg(x.message);}finally{if(root.isConnected)setTimeout(refresh,2000);}} el('auto-form').onsubmit=async ev=>{ev.preventDefault();try{await api('auto-tests/start',{model_id:el('auto-model').value,start_context:Number(el('auto-start-context').value),max_context:Number(el('auto-context').value),mtp:el('auto-mtp').checked,cache_type_k:el('auto-cache-k').value,cache_type_v:el('auto-cache-v').value});msg('Auto-Test gestartet.');}catch(x){msg(x.message);}}; el('auto-stop').onclick=()=>api('auto-tests/cancel',{}).then(()=>msg('Abbruch angefordert.')).catch(x=>msg(x.message));refresh(); }return {html,bind}; })();