| |
| |
| |
|
|
| const DEMO_DEVICE_LABELS = { |
| orin_nano_super: "Jetson Orin Nano Super", |
| agx_orin: "Jetson AGX Orin", |
| agx_thor: "Jetson AGX Thor", |
| }; |
|
|
| const DEMO_DEFAULT_DEVICE = "agx_orin"; |
| const DEMO_TOKENS_PER_WORD = 1.33; |
|
|
| |
|
|
| function demoParseCsv(text) { |
| const lines = text.replace(/\r/g, "").trim().split("\n"); |
| const headers = lines[0].split(","); |
| return lines.slice(1).map(line => { |
| const vals = line.split(","); |
| const row = {}; |
| headers.forEach((h, i) => { row[h] = (vals[i] || "").trim(); }); |
| return row; |
| }); |
| } |
|
|
| |
|
|
| function demoLookupTps(csvRows, modelName, device, matchCriteria) { |
| const row = csvRows.find(r => |
| r.model === modelName && |
| r.device === device && |
| Object.entries(matchCriteria).every(([col, val]) => r[col] === val) |
| ); |
| if (row) { |
| if (!row.tps || row.tps.toUpperCase() === "OOM") return { found: true, tps: null }; |
| return { found: true, tps: parseFloat(row.tps) }; |
| } |
| const oomRow = csvRows.find(r => |
| r.model === modelName && |
| r.device === device && |
| r.tps && r.tps.toUpperCase() === "OOM" |
| ); |
| if (oomRow) return { found: true, tps: null }; |
| return { found: false, tps: null }; |
| } |
|
|
| |
|
|
| function demoAvailableDevices(csvRows, models, matchCriteria) { |
| const deviceSet = new Set(); |
| csvRows.forEach(r => { |
| if (!models.includes(r.model)) return; |
| if (!Object.entries(matchCriteria).every(([col, val]) => r[col] === val)) return; |
| if (r.tps && r.tps.toUpperCase() !== "OOM") deviceSet.add(r.device); |
| }); |
| return Object.keys(DEMO_DEVICE_LABELS).filter(d => deviceSet.has(d)); |
| } |
|
|
| |
|
|
| function demoStreamText(element, fullText, tps) { |
| const handle = { _tid: null, cancel() { clearTimeout(this._tid); } }; |
| element.textContent = ""; |
| if (!tps || tps <= 0) { |
| element.textContent = fullText; |
| return handle; |
| } |
| const words = fullText.split(/(\s+)/); |
| const delayMs = 1000 / (tps / DEMO_TOKENS_PER_WORD); |
| let idx = 0; |
|
|
| function tick() { |
| if (idx < words.length) { |
| element.textContent += words[idx]; |
| idx++; |
| handle._tid = setTimeout(tick, delayMs); |
| } |
| } |
| tick(); |
| return handle; |
| } |
|
|
| |
|
|
| function demoPreCalcHeight(box, textEl, fullText) { |
| textEl.textContent = fullText; |
| const h = box.offsetHeight; |
| box.style.minHeight = h + "px"; |
| textEl.textContent = ""; |
| } |
|
|
| |
|
|
| async function renderDemo(data, container, optimizedOrg, dataFile, modelColors) { |
| if (!data) return; |
|
|
| |
| let clips = data.clips; |
| if (!clips) { |
| clips = [{ |
| video: data.video, |
| label: data.title, |
| prompt: data.prompt, |
| inference_setup: data.inference_setup, |
| citation: data.citation, |
| citation_url: data.citation_url, |
| outputs: data.outputs, |
| }]; |
| } |
| if (!clips.length) return; |
|
|
| const matchCriteria = data.benchmark_match || {}; |
|
|
| |
| const allModelNames = [...new Set(clips.flatMap(c => (c.outputs || []).map(o => o.model)))]; |
|
|
| |
| let csvRows = []; |
| if (dataFile) { |
| try { |
| const csvResp = await fetch(dataFile); |
| if (csvResp.ok) csvRows = demoParseCsv(await csvResp.text()); |
| } catch { } |
| } |
|
|
| const devices = csvRows.length |
| ? demoAvailableDevices(csvRows, allModelNames, matchCriteria) |
| : []; |
|
|
| let selectedDevice = devices.includes(DEMO_DEFAULT_DEVICE) |
| ? DEMO_DEFAULT_DEVICE |
| : (devices[0] || DEMO_DEFAULT_DEVICE); |
|
|
| let currentClipIdx = 0; |
| let activeStreams = []; |
|
|
| |
|
|
| const section = document.createElement("div"); |
| section.className = "demo-section"; |
|
|
| |
| const toggle = document.createElement("button"); |
| toggle.className = "demo-toggle"; |
| toggle.innerHTML = '<span class="demo-toggle-arrow">▶</span> Show Demo'; |
|
|
| |
| const content = document.createElement("div"); |
| content.className = "demo-content"; |
| const inner = document.createElement("div"); |
| inner.className = "demo-content-inner"; |
|
|
| const card = document.createElement("div"); |
| card.className = "demo-card"; |
|
|
| |
| const titleRow = document.createElement("div"); |
| titleRow.className = "demo-title-row"; |
|
|
| const titleLeft = document.createElement("div"); |
| titleLeft.className = "demo-title-left"; |
|
|
| const h3 = document.createElement("h3"); |
| titleLeft.appendChild(h3); |
|
|
| const clipSetup = document.createElement("span"); |
| clipSetup.className = "demo-clip-setup"; |
| titleLeft.appendChild(clipSetup); |
|
|
| titleRow.appendChild(titleLeft); |
|
|
| const deviceSelector = document.createElement("div"); |
| deviceSelector.className = "demo-device-selector"; |
|
|
| if (devices.length > 1) { |
| const deviceGroup = document.createElement("div"); |
| deviceGroup.className = "btn-group"; |
|
|
| function renderDeviceButtons() { |
| deviceGroup.innerHTML = ""; |
| devices.forEach(dev => { |
| const btn = document.createElement("button"); |
| btn.className = "btn" + (dev === selectedDevice ? " active" : ""); |
| btn.dataset.value = dev; |
| btn.textContent = DEMO_DEVICE_LABELS[dev] || dev; |
| deviceGroup.appendChild(btn); |
| }); |
| } |
| renderDeviceButtons(); |
|
|
| deviceGroup.addEventListener("click", e => { |
| const btn = e.target.closest(".btn"); |
| if (!btn) return; |
| const newDevice = btn.dataset.value; |
| if (newDevice === selectedDevice) return; |
| selectedDevice = newDevice; |
| renderDeviceButtons(); |
| renderOutputs(); |
| }); |
|
|
| deviceSelector.appendChild(deviceGroup); |
| } |
|
|
| card.appendChild(titleRow); |
|
|
| |
| const videoWrap = document.createElement("div"); |
| videoWrap.className = "demo-video-wrap"; |
|
|
| |
| const clipVideos = clips.map(clip => { |
| if (!clip.video) return null; |
| const v = document.createElement("video"); |
| v.loop = true; |
| v.muted = true; |
| v.playsInline = true; |
| v.preload = "auto"; |
| v.className = "demo-video"; |
| v.style.opacity = "0"; |
| v.src = clip.video; |
| videoWrap.appendChild(v); |
| return v; |
| }); |
|
|
| let activeVideoIdx = -1; |
|
|
| const arrowLeft = document.createElement("button"); |
| arrowLeft.className = "demo-arrow demo-arrow-left"; |
| arrowLeft.innerHTML = "◀"; |
| arrowLeft.setAttribute("aria-label", "Previous clip"); |
|
|
| const arrowRight = document.createElement("button"); |
| arrowRight.className = "demo-arrow demo-arrow-right"; |
| arrowRight.innerHTML = "▶"; |
| arrowRight.setAttribute("aria-label", "Next clip"); |
|
|
| videoWrap.appendChild(arrowLeft); |
| videoWrap.appendChild(arrowRight); |
| card.appendChild(videoWrap); |
|
|
| |
| card.appendChild(deviceSelector); |
|
|
| |
| const promptEl = document.createElement("div"); |
| promptEl.className = "demo-prompt"; |
| card.appendChild(promptEl); |
|
|
| |
| const grid = document.createElement("div"); |
| grid.className = "demo-outputs"; |
| card.appendChild(grid); |
|
|
| |
| const citeEl = document.createElement("p"); |
| citeEl.className = "demo-citation"; |
| card.appendChild(citeEl); |
|
|
| |
|
|
| function updateArrows() { |
| const showArrows = clips.length > 1; |
| arrowLeft.style.display = showArrows ? "" : "none"; |
| arrowRight.style.display = showArrows ? "" : "none"; |
| arrowLeft.disabled = false; |
| arrowRight.disabled = false; |
| } |
|
|
| arrowLeft.addEventListener("click", () => { |
| currentClipIdx = (currentClipIdx - 1 + clips.length) % clips.length; |
| renderClip(); |
| }); |
| arrowRight.addEventListener("click", () => { |
| currentClipIdx = (currentClipIdx + 1) % clips.length; |
| renderClip(); |
| }); |
|
|
| |
|
|
| function cancelStreams() { |
| activeStreams.forEach(s => s.cancel()); |
| activeStreams = []; |
| } |
|
|
| function renderOutputs() { |
| cancelStreams(); |
| grid.innerHTML = ""; |
| const clip = clips[currentClipIdx]; |
| const outputs = clip.outputs || []; |
|
|
| outputs.forEach(out => { |
| const color = modelColors && modelColors[out.model]; |
| const borderColor = color ? color.border : null; |
| const box = document.createElement("div"); |
| box.className = "demo-output"; |
| if (borderColor) box.style.borderColor = borderColor; |
|
|
| const modelEl = document.createElement("span"); |
| modelEl.className = "demo-output-model"; |
| modelEl.textContent = out.model; |
| if (borderColor) modelEl.style.color = borderColor; |
| box.appendChild(modelEl); |
|
|
| const tpsEl = document.createElement("span"); |
| tpsEl.className = "demo-output-tps"; |
| if (borderColor) tpsEl.style.color = borderColor; |
| box.appendChild(tpsEl); |
|
|
| const textEl = document.createElement("span"); |
| textEl.className = "demo-output-text"; |
| box.appendChild(textEl); |
|
|
| grid.appendChild(box); |
|
|
| |
| let tps = null; |
| if (csvRows.length) { |
| const lookup = demoLookupTps(csvRows, out.model, selectedDevice, matchCriteria); |
| tps = lookup.found ? lookup.tps : (out.tps || null); |
| } else { |
| tps = out.tps || null; |
| } |
|
|
| if (tps != null) { |
| tpsEl.textContent = tps.toFixed(2) + " Tokens / sec"; |
| tpsEl.classList.remove("oom"); |
| textEl.style.display = ""; |
| demoPreCalcHeight(box, textEl, out.text); |
| const handle = demoStreamText(textEl, out.text, tps); |
| activeStreams.push(handle); |
| } else { |
| tpsEl.textContent = "OOM"; |
| tpsEl.classList.add("oom"); |
| tpsEl.style.color = ""; |
| textEl.style.display = "none"; |
| box.style.minHeight = ""; |
| } |
| }); |
| } |
|
|
| function renderClip() { |
| const clip = clips[currentClipIdx]; |
|
|
| |
| h3.textContent = clip.label || data.title || "Output Examples"; |
| clipSetup.textContent = clip.inference_setup || ""; |
| clipSetup.style.display = clip.inference_setup ? "" : "none"; |
|
|
| |
| const newVideo = clipVideos[currentClipIdx]; |
| if (newVideo) { |
| videoWrap.style.display = ""; |
| const oldVideo = activeVideoIdx >= 0 ? clipVideos[activeVideoIdx] : null; |
|
|
| const showNew = () => { |
| newVideo.style.opacity = "1"; |
| newVideo.play(); |
| if (oldVideo && oldVideo !== newVideo) { |
| oldVideo.style.opacity = "0"; |
| oldVideo.pause(); |
| oldVideo.currentTime = 0; |
| } |
| activeVideoIdx = currentClipIdx; |
| }; |
|
|
| |
| if (newVideo.readyState >= 3) { |
| showNew(); |
| } else { |
| newVideo.addEventListener("canplay", showNew, { once: true }); |
| } |
| } else { |
| videoWrap.style.display = "none"; |
| if (activeVideoIdx >= 0 && clipVideos[activeVideoIdx]) { |
| clipVideos[activeVideoIdx].style.opacity = "0"; |
| clipVideos[activeVideoIdx].pause(); |
| } |
| activeVideoIdx = -1; |
| } |
|
|
| |
| if (clip.prompt) { |
| promptEl.innerHTML = "<strong>Prompt:</strong> " + clip.prompt.replace(/\n/g, "<br>"); |
| promptEl.style.display = ""; |
| } else { |
| promptEl.style.display = "none"; |
| } |
|
|
| |
| if (clip.citation) { |
| if (clip.citation_url) { |
| citeEl.innerHTML = clip.citation.replace( |
| /Autonomous Vehicle Domain Adaptation Gallery/, |
| `<a href="${clip.citation_url}" target="_blank" rel="noopener">Autonomous Vehicle Domain Adaptation Gallery</a>` |
| ); |
| } else { |
| citeEl.textContent = clip.citation; |
| } |
| citeEl.style.display = ""; |
| } else { |
| citeEl.style.display = "none"; |
| } |
|
|
| |
| renderOutputs(); |
|
|
| updateArrows(); |
|
|
| } |
|
|
| |
|
|
| toggle.addEventListener("click", () => { |
| const isOpen = content.classList.toggle("open"); |
| toggle.classList.toggle("active", isOpen); |
| toggle.innerHTML = isOpen |
| ? '<span class="demo-toggle-arrow">▶</span> Hide Demo' |
| : '<span class="demo-toggle-arrow">▶</span> Show Demo'; |
|
|
| if (isOpen) { |
| renderClip(); |
| } else { |
| cancelStreams(); |
| } |
| }); |
|
|
| inner.appendChild(card); |
| content.appendChild(inner); |
| section.appendChild(toggle); |
| section.appendChild(content); |
| container.appendChild(section); |
| } |
|
|