Spaces:
Sleeping
Sleeping
| """Serving-economics panel for the Polygen x Qwen2-VL Space. | |
| A self-contained HTML fragment (inline CSS, no JS, no external assets) rendered | |
| into a Gradio gr.HTML block. The requests-per-GPU capacity bars play once whenever | |
| the fragment is (re)rendered; `app.py` re-renders it on each "Run comparison" click | |
| by passing a changing `data-run` nonce, so the animation replays on the user's | |
| action rather than looping on its own. | |
| The figures are measured: NVIDIA H200, Qwen2-VL-7B, vLLM continuous batching. | |
| Source: `tools/runpod_results/results_serving_throughput_7B.json` (throughput, T=2, | |
| cached visual tokens); storage from the SDK tier registry. This panel makes a | |
| throughput and storage claim only -- no per-request latency / wall-clock claim. | |
| """ | |
| # ruff: noqa: E501 (self-contained HTML fragment; inline CSS lines do not wrap) | |
| # `data-run="__NONCE__"` is replaced per render (not str.format, because the | |
| # inline CSS is full of literal braces). A different nonce makes the gr.HTML | |
| # value differ, so Gradio replaces the DOM and the play-once animation restarts. | |
| _PANEL = """<div class="pg-serv" data-run="__NONCE__"> | |
| <style> | |
| /* Datasent 2026 brand palette (matches docs/polygen_theme/custom.css): | |
| Minsk purple primary, bright blue accent, lavender light shades, white page. */ | |
| .pg-serv { --bg:#ffffff; --card:#e6ebfc; --line:#c1cef7; --txt:#222222; | |
| --muted:#4f4f7a; --base:#9aa0ad; --win:#3c3475; --winsoft:#4caaff; | |
| font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; | |
| color: var(--txt); background: var(--bg); padding: 22px 20px; border-radius: 14px; | |
| border: 1px solid var(--line); max-width: 860px; margin: 0 auto; line-height: 1.5; } | |
| .pg-serv h2 { margin: 0 0 2px; font-size: 1.35rem; font-weight: 800; letter-spacing: -0.01em; color: var(--win); } | |
| .pg-serv .sub { color: var(--muted); margin: 0 0 18px; font-size: 0.95rem; } | |
| .pg-serv .race { background: var(--card); border: 1px solid var(--line); | |
| border-radius: 12px; padding: 16px 18px 18px; margin-bottom: 16px; } | |
| .pg-serv .race h3 { margin: 0 0 12px; font-size: 0.82rem; text-transform: uppercase; | |
| letter-spacing: 0.08em; color: var(--muted); font-weight: 600; } | |
| .pg-serv .lane { display: grid; grid-template-columns: 88px 1fr 84px; | |
| align-items: center; gap: 10px; margin: 9px 0; } | |
| .pg-serv .lane .who { font-size: 0.9rem; font-weight: 600; } | |
| .pg-serv .track { position: relative; height: 22px; background: #ffffff; | |
| border: 1px solid var(--line); border-radius: 6px; overflow: hidden; } | |
| .pg-serv .fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 5px; | |
| transform: scaleX(0); transform-origin: left; } | |
| /* Capacity bars, not a time race: both fill over the SAME duration (one shared | |
| per-GPU-second beat); the polygen bar reaches ~3.7x the baseline's width, so | |
| it reads as more throughput per GPU, not an earlier finish. Plays ONCE per | |
| render and holds (animation-fill-mode: forwards); app.py re-renders on each | |
| Run comparison, which replays it. */ | |
| .pg-serv .fill.base { width: 26%; background: linear-gradient(90deg,#d2d5dc,var(--base)); | |
| animation: pg-grow 1.4s ease-out forwards; } | |
| .pg-serv .fill.poly { width: 96%; background: linear-gradient(90deg,var(--winsoft),var(--win)); | |
| animation: pg-grow 1.4s ease-out forwards; } | |
| @keyframes pg-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } } | |
| @media (prefers-reduced-motion: reduce) { | |
| .pg-serv .fill { transform: scaleX(1); animation: none; } } | |
| .pg-serv .ms { font-variant-numeric: tabular-nums; font-size: 0.9rem; text-align: right; } | |
| .pg-serv .ms.win { color: var(--win); font-weight: 700; } | |
| .pg-serv .racecap { color: var(--muted); font-size: 0.84rem; margin: 10px 2px 0; } | |
| .pg-serv .racecap b { color: var(--win); } | |
| .pg-serv .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px,1fr)); | |
| gap: 10px; margin: 4px 0 14px; } | |
| .pg-serv .card { background: var(--card); border: 1px solid var(--line); | |
| border-radius: 11px; padding: 13px 14px; } | |
| .pg-serv .card .big { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; } | |
| .pg-serv .card .big.win { color: var(--win); } | |
| .pg-serv .card .lab { font-size: 0.82rem; color: var(--txt); font-weight: 600; margin-top: 2px; } | |
| .pg-serv .card .basis { font-size: 0.74rem; color: var(--muted); margin-top: 3px; } | |
| .pg-serv .note { background: #f2f5fd; border: 1px solid var(--line); border-left: 3px solid var(--winsoft); | |
| border-radius: 8px; padding: 11px 14px; font-size: 0.85rem; color: var(--muted); } | |
| .pg-serv .note b { color: var(--txt); } | |
| .pg-serv details.more { margin: 0 0 2px; } | |
| .pg-serv details.more > summary { cursor: pointer; font-size: 0.85rem; font-weight: 700; | |
| color: var(--win); padding: 2px 0; } | |
| .pg-serv details.more > summary:hover { color: var(--winsoft); } | |
| .pg-serv details.more .note { margin-top: 8px; } | |
| .pg-serv .tiers { font-size: 0.82rem; color: var(--muted); margin: 0 2px 12px; } | |
| .pg-serv .tiers b { color: var(--txt); } | |
| /* The app's dark theme redefines --body-text-color and applies it via prose | |
| rules that outrank this white-island panel's own colors; re-assert each | |
| under .dark .pg-serv so the panel stays dark-text-on-light in dark mode. */ | |
| .dark .pg-serv { color: var(--txt) !important; } | |
| .dark .pg-serv h2 { color: var(--win) !important; } | |
| .dark .pg-serv .sub, .dark .pg-serv .race h3, .dark .pg-serv .racecap, | |
| .dark .pg-serv .card .basis, .dark .pg-serv .tiers, .dark .pg-serv .note { color: var(--muted) !important; } | |
| .dark .pg-serv .lane .who, .dark .pg-serv .ms, .dark .pg-serv .card .lab, | |
| .dark .pg-serv .card .big, .dark .pg-serv .note b, | |
| .dark .pg-serv .tiers b { color: var(--txt) !important; } | |
| .dark .pg-serv .ms.win, .dark .pg-serv .card .big.win, .dark .pg-serv .racecap b, | |
| .dark .pg-serv details.more > summary { color: var(--win) !important; } | |
| </style> | |
| <h2>Same answer. More requests per GPU.</h2> | |
| <p class="sub">Polygen compresses Qwen2-VL's visual tokens before the language model reads them. | |
| At the T=2 operating point (accuracy <b style="color:var(--win)">+7.4pp above baseline</b>, | |
| a statistical tie with the best tier), the shorter visual sequence is a smaller KV cache and | |
| less attention compute, so one GPU serves more concurrent requests.</p> | |
| <div class="race"> | |
| <h3>Requests per GPU · T=2 · precomputed visual tokens</h3> | |
| <div class="lane"> | |
| <span class="who">Baseline</span> | |
| <span class="track"><span class="fill base"></span></span> | |
| <span class="ms">1x</span> | |
| </div> | |
| <div class="lane"> | |
| <span class="who" style="color:var(--win)">Polygen</span> | |
| <span class="track"><span class="fill poly"></span></span> | |
| <span class="ms win">~3.7x</span> | |
| </div> | |
| <p class="racecap">Per GPU, polygen sustains about <b>3.7x (nearly 4x)</b> the requests per second, | |
| so the same load runs on roughly a quarter of the GPUs. For precomputed / cached visual tokens | |
| (retrieval, repeated queries) -- the pattern the RAG demo shows.</p> | |
| </div> | |
| <div class="grid"> | |
| <div class="card"><div class="big win">~3.7x</div><div class="lab">Requests per GPU</div> | |
| <div class="basis">roughly a quarter the GPUs, T=2, cached</div></div> | |
| <div class="card"><div class="big win">~5x</div><div class="lab">Smaller stored representation</div> | |
| <div class="basis">visual-token cache</div></div> | |
| <div class="card"><div class="big win">+7.4pp</div><div class="lab">Accuracy vs baseline</div> | |
| <div class="basis">ScienceQA, T=2 (above baseline)</div></div> | |
| </div> | |
| <p class="tiers"><b>Tiers, chosen per workload.</b> T=3 is the accuracy peak (+8.4pp on ScienceQA); | |
| T=2, shown here, is the compression peak (+7.4pp, a statistical tie) where the throughput gain is | |
| largest; lower tiers trade accuracy for more compression.</p> | |
| <details class="more"><summary>What this is</summary> | |
| <p class="note">The gain is throughput and storage: a shorter visual sequence is a smaller KV cache | |
| and less attention compute, so a GPU serves more concurrent requests and the cached representation | |
| is smaller. Measured for precomputed / cached visual tokens (retrieval, repeated queries) under | |
| vLLM continuous batching on an NVIDIA H200 with Qwen2-VL-7B.</p> | |
| </details> | |
| </div>""" | |
| def render_serving_story(nonce: str = "0") -> str: | |
| """Return the serving-economics panel HTML fragment. | |
| Args: | |
| nonce: A value that varies per render so a Gradio `gr.HTML` update sees a | |
| different string, replaces the DOM, and restarts the play-once bars. | |
| Returns: | |
| An HTML fragment (no doctype) suitable for a `gr.HTML` block. | |
| """ | |
| return _PANEL.replace("__NONCE__", str(nonce)) | |
| if __name__ == "__main__": | |
| # Regenerate the standalone browser preview from this single source of truth. | |
| with open("serving_story.html", "w", encoding="utf-8") as _fh: | |
| _fh.write('<!doctype html>\n<meta charset="utf-8" />\n') | |
| _fh.write(render_serving_story("preview")) | |
| print("wrote serving_story.html") | |