From f1fdca3efd3f1a5f0af2a6af19fc3e12df9410e6 Mon Sep 17 00:00:00 2001 From: Mikei386 <44135113+Mikei386@users.noreply.github.com> Date: Thu, 3 Sep 2026 13:39:13 +0200 Subject: [PATCH] Fix live inference rate display --- platform/llama-dashboard/app.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/platform/llama-dashboard/app.py b/platform/llama-dashboard/app.py index 86e9728..4026ef6 100644 --- a/platform/llama-dashboard/app.py +++ b/platform/llama-dashboard/app.py @@ -651,6 +651,21 @@ const deNum=n=>n==null?'–':Number(n).toLocaleString('de-DE',{maximumFractionDi const bytesRate=n=>n==null?'–':n>=1048576?`${(n/1048576).toFixed(1)} MiB/s`:`${(n/1024).toFixed(1)} KiB/s`; const metric=(value,label)=>`
${value??'–'}${label}
`; const boolLabel=v=>v===true?'ja':v===false?'nein':'–'; +const liveRateState={prompt:{tokens:null,seconds:null,value:null,seen:0},generation:{tokens:null,seconds:null,value:null,seen:0}}; +function stableLiveRate(kind,tokensTotal,secondsTotal,gauge,active){ + const now=Date.now(),state=liveRateState[kind],tokens=Number(tokensTotal),seconds=Number(secondsTotal),raw=Number(gauge); + let measured=Number.isFinite(raw)&&raw>0?raw:null; + if(Number.isFinite(tokens)&&Number.isFinite(seconds)&&state.tokens!=null&&tokens>=state.tokens&&seconds>state.seconds){ + const derived=(tokens-state.tokens)/(seconds-state.seconds); + if(Number.isFinite(derived)&&derived>0) measured=measured??derived; + } + if(Number.isFinite(tokens)&&Number.isFinite(seconds)){ + state.tokens=tokens;state.seconds=seconds; + } + if(measured!=null&&measured<100000){state.value=measured;state.seen=now;} + if(state.value!=null&&(active||now-state.seen<8000)) return {text:`${deNum(state.value)} tok/s`,fresh:now-state.seen<2500}; + return {text:active?'misst …':'–',fresh:false}; +} function slotHtml(s){ let used=s.context_used||0,total=s.n_ctx||0,p=total?Math.min(100,used/total*100):0; let state=s.processing?'arbeitet':'frei'; @@ -660,17 +675,18 @@ async function refreshFull(){ try{ let response=await fetch('/api/status',{cache:'no-store'}); if(!response.ok) return; let d=await response.json(),rt=d.router||{},lt=rt.llama_telemetry||{},met=lt.metrics||{},props=lt.props||{},lr=d.llama_runtime||{},cpu=d.cpu||{},net=cpu.network||{}; - let gen=met.predicted_tokens_seconds,prompt=met.prompt_tokens_seconds; - $('generationRate').textContent=gen==null?'–':`${deNum(gen)} tok/s`; + let running=Number(met.requests_processing??(rt.qwen||{}).active_chats??0),waiting=Number(met.requests_deferred||0),active=running>0; + let gen=stableLiveRate('generation',met.tokens_predicted_total,met.tokens_predicted_seconds_total,met.predicted_tokens_seconds,active); + let prompt=stableLiveRate('prompt',met.prompt_tokens_total,met.prompt_seconds_total,met.prompt_tokens_seconds,active); + $('generationRate').textContent=gen.text; let genAvg=met.tokens_predicted_seconds_total?met.tokens_predicted_total/met.tokens_predicted_seconds_total:null; - $('generationSub').textContent=genAvg==null?'Aktuelle llama.cpp-Messung':`Gesamtdurchschnitt ${deNum(genAvg)} tok/s`; - $('promptRate').textContent=prompt==null?'–':`${deNum(prompt)} tok/s`; + $('generationSub').textContent=active&&!gen.fresh?'Anfrage läuft · letzter Messwert':(genAvg==null?'Aktuelle llama.cpp-Messung':`Gesamtdurchschnitt ${deNum(genAvg)} tok/s`); + $('promptRate').textContent=prompt.text; let promptAvg=met.prompt_seconds_total?met.prompt_tokens_total/met.prompt_seconds_total:null; - $('promptSub').textContent=promptAvg==null?'Aktuelle llama.cpp-Messung':`Gesamtdurchschnitt ${deNum(promptAvg)} tok/s`; + $('promptSub').textContent=active&&!prompt.fresh?'Prompt wird verarbeitet · letzter Messwert':(promptAvg==null?'Aktuelle llama.cpp-Messung':`Gesamtdurchschnitt ${deNum(promptAvg)} tok/s`); let cached=Number(met.prompt_tokens_cached_total||0),processed=Number(met.prompt_tokens_total||0),hit=(cached+processed)?cached/(cached+processed)*100:null; $('cacheHit').textContent=hit==null?'–':`${hit.toFixed(1)} %`;$('cacheBar').style.width=`${hit||0}%`; $('cacheSub').textContent=hit==null?'Keine Cache-Metrik':`${deNum(cached)} wiederverwendet · ${deNum(processed)} neu`; - let running=Number(met.requests_processing??(rt.qwen||{}).active_chats??0),waiting=Number(met.requests_deferred||0); $('requestState').textContent=`${running} aktiv · ${waiting} wartet`; $('requestSub').textContent=`${(lt.slots||[]).filter(s=>!s.processing).length} freie Slots`; $('slotCards').innerHTML=(lt.slots||[]).map(slotHtml).join('')||'
Slot-Telemetrie momentan nicht verfügbar
';