feat(app): role-local measured energy axes + per-worker power drilldown | 前端:新增角色级实测能耗坐标轴与每 worker 功耗下钻 - #935
Conversation
…rilldown | 推理图表:新增角色级实测能耗坐标轴与每 worker 功耗下钻 Add y_measuredPrefillJPerInputToken and y_measuredDecodeJPerOutputToken to the Measured Energy group (bilingual labels, lower polarity, explanations), map prefill_joules_per_input_token / decode_joules_per_output_token into chart fields, and render a pinned-only per-worker power table (role, chips, watts, optional temp/util/mem/hosts, 8-row cap, HTML-escaped JSONB strings) in all three tooltip generators. 在“实测能耗”分组新增每输入 token 实测 Prefill 能耗与每输出 token 实测 Decode 能耗两个 Y 轴(双语标签、越低越好、附说明),将角色级能耗字段映射 为图表字段,并在三种工具提示中新增仅固定时显示的每 worker 功耗表 (角色、芯片数、功耗,可选温度/利用率/显存/主机,上限 8 行,HTML 转义)。
…worker drilldown | 测试:覆盖 AgentX 实测功耗、角色级能耗坐标轴与 worker 下钻 Agentic-traces transform pass-through and power_valid=0 scrub (including workers), role-energy chart-field emission/absence/zero-preservation, Pareto corners and bilingual labels for the two new axes, input/output token classification and share-link round-trip, and the pinned worker table across all three tooltip generators (cap, ZH, HTML escaping). 覆盖 agentic_traces 变换透传与 power_valid=0 清除(含 workers)、角色级 能耗图表字段的生成/缺省/零值保留、两个新坐标轴的帕累托方向与双语标签、 输入/输出 token 分类与分享链接解析回环,以及三种工具提示中固定状态下 的 worker 表(行数上限、中文、HTML 转义)。
…使用合成 worker 数据的 AgentX 实测功耗 Spec-scoped intercepts inject a disagg agentic series (role energy + workers[]) and an aggregate series (whole-run metrics, workers: null): the two role-energy axes render under Measured Energy, the aggregate series coverage-filters off while the legend stays intact, the pinned tooltip shows the worker table, and a workers-less point stays clean. 通过 spec 级拦截注入分离式 agentic 序列(角色级能耗 + workers[])与 聚合序列(全程指标、workers 为 null):两个角色级能耗坐标轴显示在 “实测能耗”分组下,聚合序列因无该指标从图中过滤但图例保持完整, 固定的工具提示显示 worker 表,无 workers 的点保持正常。
…n-destructive axis switch | 端到端测试修复:断言覆盖过滤会移出图例,并验证坐标轴切换可无损恢复 The rendered legend is metric-aware (hwTypesWithData), so a series without the selected role-energy metric drops out of the legend too — the previous assertion expected it to stay and failed deterministically. Re-selecting a whole-run measured axis now proves the selection universe survives the switch. Also documents the MiB reading of avg_mem_used_mb in the worker tooltip. 图例渲染依据所选指标(hwTypesWithData),缺少角色级能耗指标的系列会同时从图例中 移除,原断言必然失败。现改为断言其不在图例中,并通过重新选择全局实测坐标轴验证 选择集在切换后无损恢复。同时为 worker 工具提示中 avg_mem_used_mb 的 MiB 语义 补充说明。
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @edwingao28's task in 3m 5s —— View job Review: PR #935 — role-local measured energy axes + per-worker power drilldown
🟢 LGTM — no blocking issues foundStatic review + runtime verification both clean. This is a tight, well-scoped, well-tested addition. What I verified statically
Runtime (Playwright, real read-only DB)
Tests — comprehensive: transform pass-through + scrub, chart-field emission/absence/zero-preservation, Pareto corners + bilingual labels, token-type classification + share-link round-trip, tooltip table across all three generators (pinned/unpinned, empty/absent, 8-row cap, ZH, HTML escaping), and a new AgentX e2e spec covering both axes, non-destructive coverage filtering, the worker drilldown, and graceful absence. Note: stacked PR — base is |
Important
STACKED PR — base branch is
feat/measured-power-tiering(#934). That PR must merge first; this diff contains only this PR's deltas on top of it. Do not squash-merge this PR intomasterbefore #934 lands.What
Three connected issues left measured-power data invisible or untested in the app frontend:
workers[]was plumbed end-to-end but nothing rendered it. The type, transform (benchmark-transform.ts), and API docs all carry per-worker power, yet no tooltip/dialog/page consumed it.prefill_joules_per_input_token/decode_joules_per_output_tokenare populated wheneverpower_valid !== 0, but users could only plot whole-deployment J/tok and role watts — not the role energy efficiency that separates prefill-bound from decode-bound disagg deployments.single_turn; both power cypress specs were fixed-seq only.Changes
Two new registry axes (Measured Energy group)
y_measuredPrefillJPerInputToken— Measured Prefill Joules per Input Token / 每输入 token 实测 Prefill 能耗y_measuredDecodeJPerOutputToken— Measured Decode Joules per Output Token / 每输出 token 实测 Decode 能耗polarity: 'lower'(Paretolower_righton interactivity /lower_lefton e2e derives automatically), bilingual labels/titles, entries inMETRIC_EXPLANATIONSwith the certification-tier note, and membership inMEASURED_ENERGY_METRIC_CONFIG_KEYS— so the tier ring / tooltip tier line / footer key from feat(inference): distinguish certified vs legacy measured power with quick filter | 推理图表:区分已认证与旧版实测功耗并新增快捷筛选 #934 apply to them too.buildMeasuredPowerChartFieldsmaps the two role scalars into{y, roof}chart fields;tokenMetricTypeForConfigKeyclassifies theminput/outputby substring (asserted in tests).hwTypesWithData). The switch is non-destructive: the selection universe (selectableHwTypes) never intersects metric coverage, so switching back to an axis both series carry restores the series with no legend re-selection (asserted in the e2e spec).WorkerPower drilldown in the pinned chart tooltip
generateWorkerPowerHTML(d, isPinned, locale)intooltipUtils.ts, rendered by all three generators (official, overlay, GPU-compare) only when pinned andworkersis non-empty.role[worker_idx] · N chips · W, plus temp (avg/peak°C), util %, mem GiB, and hosts when present. Capped at 8 rows with a bilingual+N more workersline.roleandhostsare HTML-escaped (they arrive from artifact JSONB).avg_mem_used_mbis read as MiB (nvidia-smi convention) →/1024GiB; commented in code, to be confirmed against the producer in the AgentX power artifacts change (feat/agentx-power-artifactsin InferenceX, PR queued).Tests
benchmark_type='agentic_traces'with the full measured-power payload (pass-through incl.workers) and thepower_valid: 0scrub mirror.chart-utils.test.ts: emission / absence / zero-preservation for the two new chart fields.measured-power-direction.test.ts: Pareto corners + bilingual labels for both new config keys.metric-registry.test.ts: token-type classification + share-link round-trip; the pre-existing registry⇄groups parity test enforces group membership.tooltip-utils.test.ts: worker table across all three generators — pinned/unpinned, empty/absent, 8-row cap, ZH strings, HTML escaping.cypress/e2e/agentic-measured-power.cy.ts(spec-scoped intercepts, synthetic fixtures via newmeasuredPowerMetrics()/syntheticWorkers()helpers inagentic-fixtures.ts): both axes visible under Measured Energy, aggregate series coverage-filtered off chart and legend with a non-destructive switch back, worker table on a pinned agentic point, graceful absence on a workers-less point. Registered intimings.jsonfor cypress-split.Data caveat
Production
workers[]is currently empty for AgentX runs — producer-side emission lands withfeat/agentx-power-artifacts(InferenceX). The UI renders gracefully withworkersabsent/empty (verified by unit tests and the e2e spec's aggregate series); the synthetic cypress fixtures verify the drilldown ahead of real data. Fixed-seq multinode disagg points already carry realworkerstoday.Backward compatibility
workers, no role energy, nopower_valid) render exactly as before — the untouched pre-existing transform/chart/tooltip tests stay green.resolveMetricConfigKey(fall back to the default axis); old links are unaffected.Review notes
Findings from review of the initial push, with resolutions:
703aaae0: the e2e spec's first test asserted the legend still containsB300after selecting the prefill-energy axis, but the rendered legend is metric-aware (hwTypesWithData,InferenceContext.tsx) and intentionally drops coverage-filtered series — the assertion failed deterministically. Fixed to assertnot.contain.text('B300'), and the test now also proves the switch is non-destructive by re-selecting Measured Joules per Output Token and asserting the b300 dots and legend entry return.E2E_FIXTURES=1dev server): 3/3 passing, plus adjacent regression specsmeasured-power-overlay/yaxis-metrics-render/ttft-x-axis-toggle/certified-power-filter— 69/69 passing.packages/app(dev-server byproducts, regenerated on everynext dev) removed from the worktree; never part of this diff.avg_mem_used_mb→ GiB/1024conversion assumes MiB semantics (nvidia-smi convention); noted in code for re-check when thefeat/agentx-power-artifactsproducer lands.have.length, 3) is stricter than sibling specs'at.least. Kept: the fixture injects exactly 3 disagg rows, hidden points are hidden via opacity (not DOM removal), and the assertion passed locally on the first attempt; relax only if CI proves it flaky.Validation
bun run typecheck✅bun run lint✅bun run fmt✅packages/appfull unit suite: 251 files / 4499 tests passed ✅ (targeted power/registry/tooltip suites: 456 tests ✅)packages/db(596 tests) andpackages/constants(47 tests) ✅ (packages/mcpsrc/server.test.tsfails identically on the base branch — pre-existing environment issue, untouched here)E2E_FIXTURES=1): newagentic-measured-power.cy.ts3/3 ✅; adjacentmeasured-power-overlay+yaxis-metrics-render+ttft-x-axis-toggle+certified-power-filter69/69 ✅. CI re-verifies viatests-e2e.yml(specPattern+ cypress-split,timings.jsonentry added).Note
Low Risk
Frontend-only inference chart and tooltip changes with broad test coverage; tooltip HTML escapes JSONB worker fields to limit XSS risk.
Overview
Adds Measured Prefill/Decode J per token y-axes so disaggregated runs can plot role-local energy efficiency, not only whole-deployment J/tok and role watts. The metrics join the Measured Energy group (tier ring, tooltip tier line, Pareto lower-is-better) and map from
prefill_joules_per_input_token/decode_joules_per_output_tokeninbuildMeasuredPowerChartFields; series without those fields drop from the chart and legend until you pick an axis both carry.Pinned chart tooltips now show a Measured Worker Power table when
workers[]is present (role, chips, W, optional temp/util/mem/hosts), with HTML escaping, an 8-row cap, and EN/ZH strings across official, overlay, and GPU-compare tooltips; hover and emptyworkersstay unchanged.Coverage includes Cypress agentic-measured-power (intercepted agentic benchmarks + fixtures), plus unit tests for transform, chart-utils, registry, tooltip drilldown, and Pareto direction.
Reviewed by Cursor Bugbot for commit ce14eec. Bugbot is set up for automated code reviews on this repo. Configure here.