Skip to content

feat(inference): distinguish certified vs legacy measured power with quick filter | 推理图表:区分已认证与旧版实测功耗并新增快捷筛选 - #934

Open
edwingao28 wants to merge 5 commits into
masterfrom
feat/measured-power-tiering
Open

feat(inference): distinguish certified vs legacy measured power with quick filter | 推理图表:区分已认证与旧版实测功耗并新增快捷筛选#934
edwingao28 wants to merge 5 commits into
masterfrom
feat/measured-power-tiering

Conversation

@edwingao28

@edwingao28 edwingao28 commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Problem

The nine "Measured Energy" y-axes plot two telemetry populations as one. The transform deliberately admits legacy rows with no producer verdict (power_valid absent) alongside rows aggregate_power.py explicitly validated (power_valid=1), with no visual or filterable distinction. In production the legacy population dominates ~10:1 (~1192 no-verdict rows vs ~130 validated), so the flagship measured-power story silently mixes unvalidated historical measurements with certified ones.

Tier rule

A per-entry power_tier is computed once in rowToAggDataEntry (single source of truth: resolvePowerTier in src/lib/power-tier.ts) and flows to every rendered point — official, overlay, and GPU-comparison — via the existing entry spread:

  • certifiedpower_valid === 1 and whole-deployment energy semantics hold (!disagg || power_metric_schema_version === 2). Non-disagg rows never had a semantics change on the unprefixed joules fields, so a producer verdict alone certifies them; disagg rows additionally need schema v2 — mirroring the field gating the transform already trusts.
  • legacy — measured telemetry renders but predates the validation contract: no verdict at all, or a disagg power_valid=1 row without schema v2.
  • absent — no measured telemetry survives gating (power_valid=0 rows included; the explicit invalid verdict stays authoritative).

Zero change to which values render — the intent is to distinguish, not exclude. Rows lacking power_valid — and the upcoming power_invalid_reasons / power_audit fields from the row-level power provenance change (feat/power-row-provenance in InferenceX, PR queued) and InferenceX-app PR #939 — transform and render unchanged.

Surfaces

  1. Quick filter — new "Measured Power" category (EN/ZH) with Certified/Legacy pills; URL param i_power; identical semantics to the existing categories (empty = no constraint, values OR'd, categories AND'd); pills auto-disable when no matching data exists; wired into every count/clear path (dialog clear, plus the legend "Reset filter" on both the main chart and GPU-comparison graphs).
  2. Dotted ring on power_tier === 'legacy' points only while a Measured Energy axis is selected (official + overlay render paths), modeled on the KV-offload halo but nested outside it (POINT_SIZE + 7, 1 3 dasharray) so both can render on one point; localized footer legend key appears only when ringed points are on screen.
  3. Tooltip tier line — "Power Data: Certified (validated measurement)" / "Legacy (no validation verdict)" (EN/ZH) in all three tooltip generators, gated on measured axes.
  4. Axis explanations — the nine Measured Energy footer entries now state the tier distinction in both locales.

Default: filter OFF

Legacy rows outnumber certified ~10:1 today; defaulting to certified-only would empty most measured charts and vanish historical data. i_power defaults to '' (no constraint) in PARAM_DEFAULTS.

Follow-up (post feat/power-row-provenance producer rollout): once single-node strict-v2 rows land at scale, flip the default by pre-seeding i_power=certified — this must land as a coordinated default change because PARAM_DEFAULTS strips values equal to their default from share links (see the DEFAULT_Y_AXIS_METRIC caveat in url-state.ts).

Note: the public API's powerValid=certified filter (PR #938) deliberately keeps the strict all-rows-v2 rule; the UI-vs-API divergence is documented on both sides and intentional.

Tests

  • bun run test:unit fully green (251 files / 4480 tests), including new coverage: table-driven resolvePowerTier, tier derivation through rowToAggDataEntry / transformBenchmarkRows, quick-filter matching/availability/parsing, MEASURED_ENERGY_METRIC_CONFIG_KEYS lockstep with the registry, per-axis ring rendering in the ScatterGraph harness, EN/ZH tooltip tier lines, and the i_power URL default. tsc --noEmit + oxlint + oxfmt green (lefthook pre-commit on every commit).
  • New e2e spec cypress/e2e/certified-power-filter.cy.ts uses deterministic intercepted fixtures (one certified config, one legacy) to assert the ring, legend key, pills, filtering, clear-filters reset, and i_power=certified share-link restore; registered in timings.json. Verified in CI: E2E chrome shard ran the spec 2/2 passing on this branch (run 33103582116); firefox shards green.
  • Cypress cannot run on the implementing machine (no Node.js runtime or repo-root .env), so the spec's legacy-power-rings / certified-only-filter screenshots are not embedded here — reproduce with cd packages/app && ./node_modules/.bin/cypress run --spec cypress/e2e/certified-power-filter.cy.ts on a node-equipped machine.

Review notes

  • Fixed (aa2cbe9): the main chart legend's quick-filter badge count and "Reset filter" handler in ScatterGraph.tsx — a third copy of the pattern alongside QuickFiltersDialog and GPUGraph — omitted the new power category, so a Certified/Legacy selection was invisible in the legend badge and survived the legend reset. Fixed by mirroring the GPUGraph edit (quickFilters.power.length in the count, setQuickFilterPower([]) in the reset); full unit suite re-run green.
  • Screenshots not attached: the implementing machine has no Node.js runtime and no repo-root .env, the e2e workflow uploads no screenshot artifacts, and GitHub's PR-body image upload has no public API — so the cypress visual evidence cannot be attached from this environment. The spec's assertions (per-point .legacy-power-ring, legend-key visibility, pill filtering, i_power restore) are machine-verified green in CI; a maintainer with a node-equipped machine can run the spec above and drag the two screenshots into this body.

Rollback

Revert this PR. No migrations, no artifact-schema changes; i_power in old links degrades to an ignored param.


Note

Medium Risk
Touches inference filtering, URL share state, and chart rendering for all Measured Energy metrics; behavior is additive (default filter off) but incorrect tier rules could mislabel a large share of power data.

Overview
Inference charts now label and filter measured-power telemetry by certification tier without changing which values are plotted.

Data model: Each point gets a power_tier (certified / legacy / absent) from resolvePowerTier during benchmark transform, based on power_valid, whole-deployment energy semantics, and whether any measured fields survive gating.

UX on Measured Energy y-axes: Legacy points show a dotted ring (official and overlay); a footer legend key appears when any legacy points are visible. Tooltips and axis-metric explanations add a Power Data / tier note in EN and ZH.

Quick Filters: New Measured Power group (Certified / Legacy) with the same OR-within-category / AND-across-categories rules; share links use i_power (default off so legacy data stays visible). Wired through context, dialog, legend badge counts, and clear/reset paths.

Registry: MEASURED_ENERGY_METRIC_CONFIG_KEYS and isMeasuredEnergyConfigKey centralize which axes trigger rings, tooltips, and legend behavior. Cypress component/e2e and unit tests cover tiers, filters, rings, and URL restore.

Reviewed by Cursor Bugbot for commit ac59805. Bugbot is set up for automated code reviews on this repo. Configure here.

…filter | 推理图表:派生实测功耗认证层级并新增快捷筛选

Compute a per-entry power_tier ('certified' | 'legacy') in
rowToAggDataEntry from the producer verdict and whole-deployment energy
semantics, without changing which values render. Add a 'Measured Power'
quick-filter category (Certified/Legacy pills, i_power URL param) wired
through QuickFilters, InferenceContext, the dialog, and GPUGraph.

在 rowToAggDataEntry 中根据生产端验证结论与整体部署能耗语义派生
power_tier(certified/legacy),不改变任何渲染值。新增“实测功耗”
快捷筛选(已认证/旧版,URL 参数 i_power)。
… axes | 推理图表:在实测能耗坐标轴上标记旧版功耗数据点

On the nine Measured Energy y-axes, draw a dotted ring around points
whose telemetry lacks a producer validation verdict (official and
overlay render paths), show a localized footer legend key when such
points are on screen, state the tier in all three tooltip generators
(EN/ZH), and append a tier note to the measured axis explanations.

在九个实测能耗 Y 轴上,为缺少生产端验证结论的数据点绘制虚线圆环
(官方与叠加渲染路径),当此类点可见时在图表底部显示本地化图例,
在三种工具提示中标注认证层级(中英文),并在实测指标说明中补充
层级说明。
…and tooltips | 测试:覆盖实测功耗层级派生、筛选、圆环与工具提示

Table-driven resolvePowerTier cases, tier derivation through
rowToAggDataEntry/transformBenchmarkRows, quick-filter matching and
availability, measured-energy key classification, decoration rendering
per axis, tier tooltip lines (EN/ZH), and the i_power URL default.

覆盖 resolvePowerTier 表驱动用例、转换层层级派生、快捷筛选匹配与
可用性、实测能耗指标判定、按坐标轴的圆环渲染、中英文工具提示层级
行以及 i_power URL 默认值。
…与旧版实测功耗筛选

Deterministic intercepted fixtures (one certified, one legacy config)
drive the measured-axis ring, footer legend key, Certified/Legacy quick
filter pills, clear-filters reset, and i_power share-link restore.

使用确定性的拦截数据(一个已认证、一个旧版配置)验证实测坐标轴
圆环、底部图例、已认证/旧版快捷筛选、清除筛选以及 i_power 分享
链接恢复。
…ick-filter reset | 推理图表:图例快捷筛选计数与重置纳入实测功耗层级

ScatterGraph keeps its own copy of the quick-filter badge count and the
legend "Reset filter" handler; both omitted the new power category, so a
Certified/Legacy selection was invisible in the legend badge and
survived the reset click. Mirror the GPUGraph edit.
@edwingao28
edwingao28 requested a review from adibarra as a code owner August 28, 2026 02:53
@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
inferencemax-app Ready Ready Preview Aug 28, 2026 2:54am

Request Review

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Claude finished @edwingao28's task in 6m 0s —— View job


Review: certified vs legacy measured power (PR #934)

  • Read the diff (git diff origin/master...HEAD)
  • Review core logic (power-tier.ts, transform, quickFilters, url-state)
  • Review UI surfaces (ScatterGraph, GPUGraph, QuickFiltersDialog, legend key, tooltips)
  • Check CI status
  • Runtime verify at localhost with Playwright
  • Check test coverage & Chinese copy
  • Post findings

Solid, well-tested PR. The tier derivation is a clean single source of truth (resolvePowerTier in the transform), hasMeasuredTelemetry correctly covers exactly the 7 source fields behind the 9 Measured Energy axes (no false-negative tiers), and the quick-filter category is wired into every count/clear path. CI: Lint ✅, Unit ✅ (E2E in progress).

Runtime verified on /inference with a Measured Energy axis (Measured J per Token): chart renders 44 points + halos, no console errors, the Quick Filters → Measured Power category appears with Certified enabled and Legacy correctly auto-disabled (this view has no legacy data → no false rings/legend key). Availability gating behaves as intended.

🟡 One finding (inline)

  • GPU-comparison chart advertises the legacy ring but never draws itGPUGraph.tsx. Its tooltip now shows the tier line and ChartDisplay renders <LegacyPowerLegendKey /> from graph.data in isGpuComparison mode, but GPUGraph.onRender only draws the offload halo, never renderLegacyPowerRing. On a GPU/date comparison with a Measured Energy axis + legacy points, the legend key and tooltip promise a dotted ring that isn't drawn, and legacy vs. certified points are visually indistinguishable there. Fix (or suppress the key/tooltip in that mode) suggested inline.

Everything else — transform, resolvePowerTier semantics, quick-filter matching/parsing/availability, URL default (i_power=''), ScatterGraph official + overlay ring paths, tooltip gating, and the EN/ZH copy (axis explanations, dialog, tooltip, legend key) — looks correct and idiomatic. Chinese copy is natural and faithful.
· branch feat/measured-power-tiering

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ac59805. Configure here.

setQuickFilterFrameworks,
setQuickFilterDeployment,
setQuickFilterSpec,
setQuickFilterPower,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GPU comparison omits legacy power rings

Medium Severity

GPU comparison still draws the offload halo in onRender but never calls renderLegacyPowerRing. The shared axis footer still shows LegacyPowerLegendKey whenever graph.data has power_tier === 'legacy' on a Measured Energy axis, so that view advertises a dotted ring that is not on the points. Filters and tooltips still work; only the visual distinction is missing.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ac59805. Configure here.

quickFilters.vendors.length +
quickFilters.frameworks.length +
quickFilters.deployment.length +
quickFilters.power.length +

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 WARNING: The GPU-comparison chart wires the power quick-filter here, but never draws the legacy-power ring — even though it advertises one.

The GPU-comparison chart is a real Measured Energy surface:

  • generateGPUGraphTooltipContent now emits the tier line (tooltipUtils.ts), so a legacy point's tooltip on this chart says "Power Data: Legacy (no validation verdict)".
  • ChartDisplay builds footerPoints from graph.data in isGpuComparison mode (ChartDisplay.tsx:878), so hasLegacyPowerPoints can be true and <LegacyPowerLegendKey /> ("Legacy power data (no validation verdict)") renders under this chart — describing a dotted ring.

But this component's onRender (~line 910) only calls renderOffloadHalo; it never calls renderLegacyPowerRing. So on a GPU/date comparison with a Measured Energy axis and legacy points, the footer legend key and the tooltip both promise a ring that is never drawn on the points — the "distinguish legacy visually" goal of G2 silently fails on this chart, and legacy vs. certified points are indistinguishable there.

Fix: mirror the ScatterGraph decoration pass in onRender — gate on the measured-energy axis and draw the ring alongside the halo:

ctx.layout.zoomGroup
  .selectAll<SVGGElement, InferenceData>('.dot-group')
  .each(function (point) {
    renderOffloadHalo(d3.select(this), point, 'var(--foreground)');
    renderLegacyPowerRing(
      d3.select(this),
      point,
      isMeasuredEnergyConfigKey(selectedYAxisMetric),
      'var(--foreground)',
    );
  });

(add imports for renderLegacyPowerRing and isMeasuredEnergyConfigKey, plus a GPUGraph ring test). Alternatively, if omitting the ring here is intentional, suppress the footer legend key + tooltip tier line when isGpuComparison so the chart doesn't advertise an absent marker. Fix this →

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant