Spaces:
Sleeping
Sleeping
Upload index-6.html
Browse files- templates/index-6.html +23 -96
templates/index-6.html
CHANGED
|
@@ -19,18 +19,18 @@
|
|
| 19 |
header{padding:16px 20px;border-bottom:1px solid var(--border);background:linear-gradient(180deg, #111723, #0f1218);}
|
| 20 |
h1{margin:0;font-size:20px}
|
| 21 |
h2{margin:0 0 10px;font-size:18px}
|
| 22 |
-
h3{margin:
|
| 23 |
-
main{display:grid;grid-template-columns:0.
|
| 24 |
@media (max-width:1100px){main{grid-template-columns:1fr}}
|
| 25 |
.card{background:var(--panel);border:1px solid var(--border);border-radius:10px;overflow:hidden}
|
| 26 |
-
.card header{display:flex;align-items:center;justify-content:space-between;padding:
|
| 27 |
-
.card .content{padding:
|
| 28 |
-
.row{display:grid;grid-template-columns:repeat(12,1fr);gap:
|
| 29 |
.col-12{grid-column:span 12}.col-8{grid-column:span 8}.col-6{grid-column:span 6}.col-4{grid-column:span 4}.col-3{grid-column:span 3}.col-2{grid-column:span 2}
|
| 30 |
-
label{display:block;font-size:
|
| 31 |
-
input[type="text"],input[type="number"],select{width:100%;padding:
|
| 32 |
input[type="checkbox"]{transform:scale(1.1)}
|
| 33 |
-
.hint{font-size:
|
| 34 |
.btn{display:inline-flex;align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--border);border-radius:8px;background:var(--chip);color:var(--fg);cursor:pointer}
|
| 35 |
.btn:hover{filter:brightness(1.08)}
|
| 36 |
.btn-primary{background:var(--accent2);border-color:#2855a3}
|
|
@@ -231,11 +231,11 @@
|
|
| 231 |
</div>
|
| 232 |
|
| 233 |
<div class="col-8" style="display:flex;align-items:flex-end;gap:8px;flex-wrap:wrap;margin-top:8px">
|
|
|
|
| 234 |
<button class="btn" id="mergeBtn">🔗 Fazer Merge</button>
|
| 235 |
<button class="btn" id="continueBtn">🔁 Continuar (+1 Época)</button>
|
| 236 |
<button class="btn" id="testBtn">🧠 Testar Modelo (sem Merge)</button>
|
| 237 |
<button class="btn" id="tensorboardBtn">📈 Ver Gráfico (TensorBoard)</button>
|
| 238 |
-
<button class="btn" id="modelDirBtn">📂 Ver output_dir</button>
|
| 239 |
</div>
|
| 240 |
|
| 241 |
</div>
|
|
@@ -251,41 +251,6 @@
|
|
| 251 |
</div>
|
| 252 |
</div>
|
| 253 |
|
| 254 |
-
<!-- MÉTRICAS EM TEMPO REAL -->
|
| 255 |
-
<h3>📊 Métricas em Tempo Real</h3>
|
| 256 |
-
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-bottom:12px;">
|
| 257 |
-
<div style="background:#0c1117;border:1px solid var(--border);border-radius:8px;padding:10px 12px;">
|
| 258 |
-
<div style="font-size:11px;color:var(--muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em">Estado</div>
|
| 259 |
-
<div id="mv-status" style="font-size:16px;font-weight:700;font-family:var(--mono);color:#79c0ff">—</div>
|
| 260 |
-
</div>
|
| 261 |
-
<div style="background:#0c1117;border:1px solid var(--border);border-radius:8px;padding:10px 12px;">
|
| 262 |
-
<div style="font-size:11px;color:var(--muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em">Gradient Accum.</div>
|
| 263 |
-
<div id="mv-accum" style="font-size:16px;font-weight:700;font-family:var(--mono);color:#ffd479">—</div>
|
| 264 |
-
<div id="mv-accum-origin" style="font-size:10px;color:#7aa2d6;margin-top:2px;"></div>
|
| 265 |
-
</div>
|
| 266 |
-
<div style="background:#0c1117;border:1px solid var(--border);border-radius:8px;padding:10px 12px;">
|
| 267 |
-
<div style="font-size:11px;color:var(--muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em">Effective Batch</div>
|
| 268 |
-
<div id="mv-effbatch" style="font-size:16px;font-weight:700;font-family:var(--mono);color:#7ee787">—</div>
|
| 269 |
-
</div>
|
| 270 |
-
<div style="background:#0c1117;border:1px solid var(--border);border-radius:8px;padding:10px 12px;">
|
| 271 |
-
<div style="font-size:11px;color:var(--muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em">Total Steps</div>
|
| 272 |
-
<div id="mv-steps" style="font-size:16px;font-weight:700;font-family:var(--mono);color:#d2a8ff">—</div>
|
| 273 |
-
</div>
|
| 274 |
-
<div style="background:#0c1117;border:1px solid var(--border);border-radius:8px;padding:10px 12px;position:relative;overflow:hidden;">
|
| 275 |
-
<div style="font-size:11px;color:var(--muted);margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em">RAM Usada</div>
|
| 276 |
-
<div id="mv-ram" style="font-size:16px;font-weight:700;font-family:var(--mono);color:#ff7b72">—</div>
|
| 277 |
-
<div style="position:absolute;bottom:0;left:0;right:0;height:3px;background:#1a1f26;">
|
| 278 |
-
<div id="mv-ram-bar" style="height:100%;width:0%;background:#f85149;transition:width .5s,background .5s;border-radius:0 2px 0 0;"></div>
|
| 279 |
-
</div>
|
| 280 |
-
</div>
|
| 281 |
-
</div>
|
| 282 |
-
|
| 283 |
-
<!-- HISTÓRICO DE AJUSTES DO CALLBACK -->
|
| 284 |
-
<div id="accumHistorySection" style="display:none;margin-bottom:12px;">
|
| 285 |
-
<h3>⚙️ Histórico de Ajustes (DynamicAccumulationCallback)</h3>
|
| 286 |
-
<div id="accumHistoryList" style="background:#0a0e14;border:1px solid var(--border);border-radius:8px;padding:8px;max-height:130px;overflow-y:auto;display:flex;flex-direction:column;gap:4px;"></div>
|
| 287 |
-
</div>
|
| 288 |
-
|
| 289 |
<!-- PASSO ATUAL & ETA -->
|
| 290 |
<div id="currentStepSection" style="display:none;margin-bottom:10px;">
|
| 291 |
<div style="background:#0c1117;border:1px solid var(--border);border-radius:8px;padding:10px 14px;font-family:var(--mono);font-size:13px;display:flex;gap:20px;flex-wrap:wrap;">
|
|
@@ -295,12 +260,6 @@
|
|
| 295 |
</div>
|
| 296 |
</div>
|
| 297 |
|
| 298 |
-
<!-- LOSS POR ÉPOCA -->
|
| 299 |
-
<div id="epochLossSection" style="display:none;margin-bottom:12px;">
|
| 300 |
-
<h3>📉 Loss por Época</h3>
|
| 301 |
-
<div id="epochLossBar" style="display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end;"></div>
|
| 302 |
-
</div>
|
| 303 |
-
|
| 304 |
<!-- LOGS -->
|
| 305 |
<h3>Status do Treino / Logs</h3>
|
| 306 |
<div id="trainingBox" style="height:340px;overflow-y:auto;white-space:pre-wrap;border:1px solid var(--border);padding:10px;font-family:var(--mono);font-size:14px;line-height:1.6;background:#0a0e14;border-radius:8px;color:#c9d1d9;">
|
|
@@ -597,14 +556,15 @@
|
|
| 597 |
if (!section || !bar || !epoch_losses || epoch_losses.length === 0) return;
|
| 598 |
section.style.display = '';
|
| 599 |
bar.innerHTML = '';
|
| 600 |
-
|
| 601 |
-
epoch_losses.
|
| 602 |
-
|
|
|
|
| 603 |
const heightPct = isFinite(val) && maxLoss > 0 ? Math.max(10, (val / maxLoss) * 60) : 30;
|
| 604 |
const chip = document.createElement('div');
|
| 605 |
-
chip.style =
|
| 606 |
chip.innerHTML = `
|
| 607 |
-
<div style="font-size:11px;font-family:var(--mono);color:#ffd479;font-weight:600">${isFinite(val)?val.toFixed(4):
|
| 608 |
<div style="width:28px;height:${heightPct}px;background:linear-gradient(180deg,#1f6feb,#2ea043);border-radius:4px 4px 0 0;min-height:6px;transition:height .4s;"></div>
|
| 609 |
<div style="font-size:10px;color:var(--muted)">É${i+1}</div>
|
| 610 |
`;
|
|
@@ -630,61 +590,28 @@
|
|
| 630 |
if (progressPct) progressPct.textContent = `${pct}%`;
|
| 631 |
}
|
| 632 |
|
| 633 |
-
// —
|
| 634 |
-
const statusColors = { training:'#79c0ff', idle:'var(--muted)', done:'#7ee787', error:'#ff7b72' };
|
| 635 |
-
if (data.status) {
|
| 636 |
-
const el = $('mv-status');
|
| 637 |
-
if (el) { el.textContent = data.status; el.style.color = statusColors[data.status] || '#79c0ff'; }
|
| 638 |
-
}
|
| 639 |
-
|
| 640 |
-
// — Métricas extraídas dos logs (fallback) + campos directos do JSON (prioritários) —
|
| 641 |
const allLogs = data.logs || [];
|
| 642 |
const m = parseMetricsFromLogs(allLogs);
|
| 643 |
|
| 644 |
-
// Gradient Accumulation: JSON > logs
|
| 645 |
-
const accumVal = data.current_accum_steps ?? m.accum;
|
| 646 |
-
if (accumVal != null) updateMetricCard('mv-accum', String(accumVal));
|
| 647 |
-
|
| 648 |
-
// Effective Batch: JSON > logs
|
| 649 |
-
const effVal = data.effective_batch ?? m.effbatch;
|
| 650 |
-
if (effVal != null) updateMetricCard('mv-effbatch', String(effVal));
|
| 651 |
-
|
| 652 |
-
// Total Steps: JSON > logs
|
| 653 |
-
const stepsVal = data.total_train_steps ?? m.steps;
|
| 654 |
-
if (stepsVal != null) updateMetricCard('mv-steps', String(stepsVal));
|
| 655 |
-
|
| 656 |
-
// Origem do accum (só via logs)
|
| 657 |
-
if (m.accumOrigin) { const el=$('mv-accum-origin'); if(el) el.textContent=m.accumOrigin; }
|
| 658 |
-
|
| 659 |
-
// Passo actual & ETA
|
| 660 |
if (m.lastStep || m.eta || m.stepTime) {
|
| 661 |
const sec = $('currentStepSection'); if(sec) sec.style.display='';
|
| 662 |
-
if (m.lastStep)
|
| 663 |
-
if (m.eta)
|
| 664 |
-
if (m.stepTime)
|
| 665 |
-
}
|
| 666 |
-
|
| 667 |
-
// — RAM: JSON > logs —
|
| 668 |
-
const ramVal = data.ram_percent ?? (m.ram ? parseFloat(m.ram) : null);
|
| 669 |
-
if (ramVal != null) {
|
| 670 |
-
updateMetricCard('mv-ram', `${parseFloat(ramVal).toFixed(1)}%`);
|
| 671 |
-
const bar = $('mv-ram-bar');
|
| 672 |
-
if (bar) {
|
| 673 |
-
bar.style.width = `${ramVal}%`;
|
| 674 |
-
bar.style.background = ramVal > 85 ? '#f85149' : ramVal > 70 ? '#ffd479' : '#7ee787';
|
| 675 |
-
}
|
| 676 |
}
|
| 677 |
|
| 678 |
-
// — Histórico de ajustes do callback —
|
| 679 |
updateAccumHistory(m.newAccumEvents);
|
| 680 |
|
| 681 |
// — Epoch losses —
|
| 682 |
updateEpochLosses(data.epoch_losses);
|
| 683 |
|
| 684 |
-
// — Logs (
|
| 685 |
const logsText = allLogs.join('\n');
|
| 686 |
const trainingBox = $('trainingBox');
|
| 687 |
-
if (trainingBox) {
|
|
|
|
| 688 |
const wasAtBottom = trainingBox.scrollHeight - trainingBox.scrollTop <= trainingBox.clientHeight + 40;
|
| 689 |
trainingBox.textContent = logsText;
|
| 690 |
if (wasAtBottom) trainingBox.scrollTop = trainingBox.scrollHeight;
|
|
|
|
| 19 |
header{padding:16px 20px;border-bottom:1px solid var(--border);background:linear-gradient(180deg, #111723, #0f1218);}
|
| 20 |
h1{margin:0;font-size:20px}
|
| 21 |
h2{margin:0 0 10px;font-size:18px}
|
| 22 |
+
h3{margin:10px 0 6px;font-size:13px;color:var(--muted)}
|
| 23 |
+
main{display:grid;grid-template-columns:0.55fr 1fr;gap:12px;padding:12px}
|
| 24 |
@media (max-width:1100px){main{grid-template-columns:1fr}}
|
| 25 |
.card{background:var(--panel);border:1px solid var(--border);border-radius:10px;overflow:hidden}
|
| 26 |
+
.card header{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid var(--border);background:#121720}
|
| 27 |
+
.card .content{padding:12px}
|
| 28 |
+
.row{display:grid;grid-template-columns:repeat(12,1fr);gap:8px}
|
| 29 |
.col-12{grid-column:span 12}.col-8{grid-column:span 8}.col-6{grid-column:span 6}.col-4{grid-column:span 4}.col-3{grid-column:span 3}.col-2{grid-column:span 2}
|
| 30 |
+
label{display:block;font-size:11px;color:var(--muted);margin-bottom:4px}
|
| 31 |
+
input[type="text"],input[type="number"],select{width:100%;padding:6px 8px;border:1px solid var(--border);border-radius:6px;background:#0c1117;color:var(--fg);font-family:var(--mono);font-size:13px}
|
| 32 |
input[type="checkbox"]{transform:scale(1.1)}
|
| 33 |
+
.hint{font-size:10px;color:#7aa2d6;margin-top:3px}
|
| 34 |
.btn{display:inline-flex;align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--border);border-radius:8px;background:var(--chip);color:var(--fg);cursor:pointer}
|
| 35 |
.btn:hover{filter:brightness(1.08)}
|
| 36 |
.btn-primary{background:var(--accent2);border-color:#2855a3}
|
|
|
|
| 231 |
</div>
|
| 232 |
|
| 233 |
<div class="col-8" style="display:flex;align-items:flex-end;gap:8px;flex-wrap:wrap;margin-top:8px">
|
| 234 |
+
<button class="btn" id="modelDirBtn">📂 Ver output_dir</button>
|
| 235 |
<button class="btn" id="mergeBtn">🔗 Fazer Merge</button>
|
| 236 |
<button class="btn" id="continueBtn">🔁 Continuar (+1 Época)</button>
|
| 237 |
<button class="btn" id="testBtn">🧠 Testar Modelo (sem Merge)</button>
|
| 238 |
<button class="btn" id="tensorboardBtn">📈 Ver Gráfico (TensorBoard)</button>
|
|
|
|
| 239 |
</div>
|
| 240 |
|
| 241 |
</div>
|
|
|
|
| 251 |
</div>
|
| 252 |
</div>
|
| 253 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
<!-- PASSO ATUAL & ETA -->
|
| 255 |
<div id="currentStepSection" style="display:none;margin-bottom:10px;">
|
| 256 |
<div style="background:#0c1117;border:1px solid var(--border);border-radius:8px;padding:10px 14px;font-family:var(--mono);font-size:13px;display:flex;gap:20px;flex-wrap:wrap;">
|
|
|
|
| 260 |
</div>
|
| 261 |
</div>
|
| 262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
<!-- LOGS -->
|
| 264 |
<h3>Status do Treino / Logs</h3>
|
| 265 |
<div id="trainingBox" style="height:340px;overflow-y:auto;white-space:pre-wrap;border:1px solid var(--border);padding:10px;font-family:var(--mono);font-size:14px;line-height:1.6;background:#0a0e14;border-radius:8px;color:#c9d1d9;">
|
|
|
|
| 556 |
if (!section || !bar || !epoch_losses || epoch_losses.length === 0) return;
|
| 557 |
section.style.display = '';
|
| 558 |
bar.innerHTML = '';
|
| 559 |
+
// epoch_losses pode ser array de números OU array de {epoch, loss}
|
| 560 |
+
const vals = epoch_losses.map(e => typeof e === 'object' ? parseFloat(e.loss) : parseFloat(e));
|
| 561 |
+
const maxLoss = Math.max(...vals.filter(isFinite));
|
| 562 |
+
vals.forEach((val, i) => {
|
| 563 |
const heightPct = isFinite(val) && maxLoss > 0 ? Math.max(10, (val / maxLoss) * 60) : 30;
|
| 564 |
const chip = document.createElement('div');
|
| 565 |
+
chip.style = 'display:flex;flex-direction:column;align-items:center;gap:4px;';
|
| 566 |
chip.innerHTML = `
|
| 567 |
+
<div style="font-size:11px;font-family:var(--mono);color:#ffd479;font-weight:600">${isFinite(val) ? val.toFixed(4) : '?'}</div>
|
| 568 |
<div style="width:28px;height:${heightPct}px;background:linear-gradient(180deg,#1f6feb,#2ea043);border-radius:4px 4px 0 0;min-height:6px;transition:height .4s;"></div>
|
| 569 |
<div style="font-size:10px;color:var(--muted)">É${i+1}</div>
|
| 570 |
`;
|
|
|
|
| 590 |
if (progressPct) progressPct.textContent = `${pct}%`;
|
| 591 |
}
|
| 592 |
|
| 593 |
+
// — Métricas dos logs: só passo/ETA (os cards de accum/batch/steps foram removidos) —
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 594 |
const allLogs = data.logs || [];
|
| 595 |
const m = parseMetricsFromLogs(allLogs);
|
| 596 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 597 |
if (m.lastStep || m.eta || m.stepTime) {
|
| 598 |
const sec = $('currentStepSection'); if(sec) sec.style.display='';
|
| 599 |
+
if (m.lastStep) updateMetricCard('mv-laststep', m.lastStep);
|
| 600 |
+
if (m.eta) updateMetricCard('mv-eta', m.eta);
|
| 601 |
+
if (m.stepTime) updateMetricCard('mv-steptime', m.stepTime);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
}
|
| 603 |
|
| 604 |
+
// — Histórico de ajustes do callback (persiste na sessão) —
|
| 605 |
updateAccumHistory(m.newAccumEvents);
|
| 606 |
|
| 607 |
// — Epoch losses —
|
| 608 |
updateEpochLosses(data.epoch_losses);
|
| 609 |
|
| 610 |
+
// — Logs: substituir conteúdo (o backend já devolve os últimos 200) —
|
| 611 |
const logsText = allLogs.join('\n');
|
| 612 |
const trainingBox = $('trainingBox');
|
| 613 |
+
if (trainingBox && logsText !== trainingBox.dataset.lastLogs) {
|
| 614 |
+
trainingBox.dataset.lastLogs = logsText;
|
| 615 |
const wasAtBottom = trainingBox.scrollHeight - trainingBox.scrollTop <= trainingBox.clientHeight + 40;
|
| 616 |
trainingBox.textContent = logsText;
|
| 617 |
if (wasAtBottom) trainingBox.scrollTop = trainingBox.scrollHeight;
|