ReVID / sample /trace_viewer.html
GuoruiSong's picture
Add files using upload-large-folder tool
b50f36e verified
Raw
History Blame Contribute Delete
7.32 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Trace Viewer</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
:root { --fg:#111; --muted:#888; --new:#0a7f2e; --mask:#aaa; --border:#ddd; }
body { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; margin:16px; color:var(--fg); }
h1 { font-size:18px; margin:0 0 12px 0; }
.controls { display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-bottom:12px; }
.controls > * { font-size:14px; }
#viewer { border:1px solid var(--border); padding:12px; height:60vh; overflow:auto;
white-space:pre-wrap; overflow-wrap:anywhere; word-break:normal; }
.masked { color:transparent; text-shadow:0 0 0 var(--mask); }
.unmasked { color:inherit; }
.new { background:#e9f7ee; outline:1px dashed #b7e1c3; }
.special { color:var(--muted); }
.meta { color:var(--muted); font-size:12px; margin-bottom:6px; }
.row { display:flex; gap:8px; align-items:center; }
input[type="range"] { width:300px; }
button { padding:4px 10px; }
select { padding:2px 6px; }
label { user-select:none; }
.maskToken { display:inline-block; width:7ch; text-align:center; white-space:nowrap; word-break:keep-all; }
</style>
</head>
<body>
<h1>Unmask Viewer</h1>
<div class="meta" id="meta"></div>
<div class="controls">
<div class="row">
<button id="play">Play</button>
<button id="prev">-1</button>
<input id="step" type="range" min="0" max="0" value="0">
<button id="next">+1</button>
</div>
<div class="row">
<label>Step: <span id="stepNum">0</span>/<span id="stepMax">0</span></label>
<label style="margin-left:12px;">Speed:
<select id="speed">
<option value="1200">0.8×</option>
<option value="800" selected></option>
<option value="500">1.6×</option>
<option value="300">2.6×</option>
</select>
</label>
<label style="margin-left:12px;">
<input id="hideSpecial" type="checkbox"> Hide special tokens
</label>
<label style="margin-left:12px;">
<input id="showMaskedShapes" type="checkbox" checked> Show masked placeholders
</label>
</div>
</div>
<div id="viewer"></div>
<script id="data" type="application/json">{"pieces": ["Re", "in", "forcement", " learning", " is", " a", " type", " of", " machine", " learning", " where", " an", " agent", " learns", " to", " make", " decisions", " by", " interacting", " with", " an", " environment", ".", " The", " agent", " receives", " feedback", " in", " the", " form", " of", " rewards", " or", " punishments", " for", " its", " actions", ",", " and", " uses", " this", " feedback", " to", " adjust", " its", " behavior", " in", " order", " to", " maximize", " its", " total", " reward", " over", " time", ".", " This", " process", " is", " achieved", " through", " trial", " and", " error", ",", " and", " the", " agent", " gradually", " learns", " to", " make", " decisions", " that", " lead", " to", " the", " highest", " possible", " reward", ".", "<|im_end|>", "\n", "<|endoftext|>"], "step_map": [2, 1, 3, 3, 3, 3, 4, 4, 4, 5, 6, 7, 8, 8, 9, 11, 10, 12, 13, 14, 15, 14, 17, 17, 16, 18, 21, 20, 20, 19, 22, 22, 23, 24, 25, 27, 26, 28, 29, 30, 32, 31, 33, 36, 34, 35, 37, 38, 39, 39, 40, 43, 41, 42, 44, 44, 45, 46, 49, 50, 48, 47, 51, 51, 52, 53, 55, 54, 56, 57, 58, 60, 59, 60, 61, 62, 63, 64, 67, 68, 66, 65, 69, 69], "is_special": [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true]}</script>
<script>
const DATA = JSON.parse(document.getElementById('data').textContent);
const pieces = DATA.pieces;
const steps = DATA.step_map;
const isSpec = DATA.is_special;
const maxStep = Math.max(...steps);
const viewer = document.getElementById('viewer');
const stepInput = document.getElementById('step');
const stepNum = document.getElementById('stepNum');
const stepMax = document.getElementById('stepMax');
const playBtn = document.getElementById('play');
const prevBtn = document.getElementById('prev');
const nextBtn = document.getElementById('next');
const speedSel = document.getElementById('speed');
const hideSpecial = document.getElementById('hideSpecial');
const showMaskedShapes = document.getElementById('showMaskedShapes');
const meta = document.getElementById('meta');
stepInput.max = String(maxStep);
stepMax.textContent = String(maxStep);
function render(t) {
stepNum.textContent = String(t);
const frag = document.createDocumentFragment();
let revealed = 0, newly = 0;
for (let i = 0; i < pieces.length; i++) {
if (hideSpecial.checked && isSpec[i]) continue;
const span = document.createElement('span');
const piece = pieces[i];
if (steps[i] <= t) {
span.className = 'unmasked' + (steps[i] === t ? ' new' : '');
span.textContent = piece;
if (steps[i] === t) newly++;
revealed++;
} else {
span.className = 'masked maskToken' + (isSpec[i] ? ' special' : '');
span.textContent = showMaskedShapes.checked ? '|<MASK>|' : '';
}
if (isSpec[i]) span.classList.add('special');
frag.appendChild(span);
}
viewer.innerHTML = '';
viewer.appendChild(frag);
meta.textContent = `Tokens revealed: ${revealed} / ${pieces.length} | Newly at step ${t}: ${newly}`;
}
let timer = null;
function play() {
if (timer) return;
playBtn.textContent = 'Pause';
timer = setInterval(() => {
let v = Number(stepInput.value);
if (v >= maxStep) {
pause();
return;
}
stepInput.value = String(v + 1);
render(v + 1);
}, Number(speedSel.value));
}
function pause() {
if (timer) {
clearInterval(timer);
timer = null;
}
playBtn.textContent = 'Play';
}
stepInput.addEventListener('input', () => render(Number(stepInput.value)));
playBtn.addEventListener('click', () => (timer ? pause() : play()));
prevBtn.addEventListener('click', () => {
const v = Math.max(0, Number(stepInput.value) - 1);
stepInput.value = String(v);
render(v);
});
nextBtn.addEventListener('click', () => {
const v = Math.min(maxStep, Number(stepInput.value) + 1);
stepInput.value = String(v);
render(v);
});
speedSel.addEventListener('change', () => {
if (timer) { pause(); play(); }
});
hideSpecial.addEventListener('change', () => render(Number(stepInput.value)));
showMaskedShapes.addEventListener('change', () => render(Number(stepInput.value)));
render(0);
</script>
</body>
</html>