Skip to content

fix(inference): derive $/M tok and J/token from throughput instead of splining them / 每 token 成本与能耗改为按吞吐量推导而非直接插值 - #726

Merged
Oseltamivir merged 2 commits into
masterfrom
interpolation-cost-identity
Aug 12, 2026
Merged

fix(inference): derive $/M tok and J/token from throughput instead of splining them / 每 token 成本与能耗改为按吞吐量推导而非直接插值#726
Oseltamivir merged 2 commits into
masterfrom
interpolation-cost-identity

Conversation

@Oseltamivir

@Oseltamivir Oseltamivir commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

$/M tok and spec-sheet J/token are defined as a per-chip constant divided by throughput. Previously, the calculator and historical trends independently splined both throughput and the reciprocal metric, so the two interpolated curves could violate:

metric × throughput = constant

This PR now splines throughput and derives the reciprocal metric from it. Measured knots are unchanged; only values between knots can move.

The size and direction of that movement depend on frontier density and change as new benchmark runs land. Earlier snapshot-specific impact figures have therefore been removed rather than presented as permanent results for the live dataset.

Safety

  • recoverReciprocalNumerator applies derivation only when every usable point agrees on the numerator within 0.1%.
  • Metrics with a varying numerator, including measured-energy fields, keep the existing direct-spline fallback.
  • Total, input, and output token costs are validated against one shared provider rate.
  • The Python blog helper now returns null when a reciprocal throughput input is missing, matching TypeScript.
  • Existing unit tests execute the bundled Python helper directly, so TypeScript/Python parity works out of the box without a separate analysis workflow.
  • Official and ?unofficialrun= calculator paths share the same interpolation implementation.

Validation

  • bun run lint
  • bun run fmt
  • bun run typecheck
  • bun run test:unit — 3,821 tests passed across workspaces
  • bun run test:e2e — 88 smoke tests passed
  • Focused reciprocal interpolation suite — 104 tests passed

中文说明

$/M tok 与基于规格功耗计算的 J/token,其定义都是“单芯片常数 ÷ 吞吐量”。此前 TCO Calculator 与 Historical Trends 会分别对吞吐量和倒数指标做样条插值,导致两条插值曲线之间可能不再满足:

指标 × 吞吐量 = 常数

本 PR 改为只对吞吐量做样条插值,再由插值后的吞吐量推导倒数指标。所有实测节点保持不变,只有节点之间的估算值可能变化。

变化幅度和方向取决于 Pareto frontier 的密度,也会随着新 benchmark 结果持续变化。因此,本 PR 已移除旧快照中的影响百分比,避免将其误写成线上数据集长期不变的结论。

安全措施

  • 只有当所有可用数据点的分子在 0.1% 容差内一致时,recoverReciprocalNumerator 才会启用推导逻辑。
  • measured energy 等分子会随数据点变化的指标继续使用原有的直接样条插值回退路径。
  • total、input 与 output token 成本会共同校验同一个 provider rate。
  • Python blog helper 在缺少对应吞吐量输入时会返回 null,与 TypeScript 行为一致。
  • 现有单元测试会直接运行随附的 Python helper,无需额外分析流程即可验证 TypeScript/Python 一致性。
  • 官方数据与 ?unofficialrun= overlay 共用同一套 calculator 插值实现。

验证

  • bun run lint
  • bun run fmt
  • bun run typecheck
  • bun run test:unit — 各 workspace 共 3,821 项测试通过
  • bun run test:e2e — 88 项 smoke test 通过
  • 倒数指标插值专项测试 — 104 项测试通过

Note

High Risk
Changes how cost and energy are interpolated across the calculator, fleet cost-cap lookup, trend charts, and blog helper—published numbers will move, often downward. Guarded by a consistency check with extensive unit coverage, but still user-facing TCO math.

Overview
$/M tok and J/token are now derived from interpolated throughput instead of being splined independently. That preserves metric × throughput = constant between measured knots (previously broken by a median ~72%).

Adds recoverReciprocalNumerator / reciprocalMetricAt and wires them through interpolateForGPU, maxInteractivityAtCost, and interpolateMetricAtInteractivity. A 0.1% consistency guard falls back to the old spline when the numerator is not constant (e.g. measured* energy). Cost rates are recovered across all three token types together so inverse lookups stay on the same curve as the bars.

Syncs iso_interactivity.py with a reciprocal_of option, documents the method in docs/tco-calculator.md, and adds tests that pin the identity, the Python/TS match, and the fallback path.

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

… splining them / 每 token 成本与能耗改为按吞吐量推导而非直接插值

Cost per million tokens and joules per token are a per-chip constant divided by
a throughput. The interpolation splined them directly, which averages
reciprocals; 1/x is convex, so the result diverged from the value implied by the
interpolated throughput.

/inference settles which is right. It plots these metrics only at measured
points (lib/chart-utils.ts:380, roof: false), so its values are the oracle, and
they satisfy `metric x throughput = constant` by construction. Holding out each
interior frontier knot and predicting its real value:

  splined metric            mean err 162.8%   closer on  36 / 144
  derived from throughput   mean err  42.2%   closer on 108 / 144

The splined pair also broke that identity by a median 71.6% and up to 2026% —
reporting operating points no real config could occupy. The two agree exactly at
all 470 measured knots; the divergence is entirely between them, and the splined
read is the higher one 73.6% of the time (max 25.3x on sparsely swept frontiers,
where adjacent knots differ ~100x in throughput).

Changed: interpolateForGPU, maxInteractivityAtCost and
interpolateMetricAtInteractivity now spline the throughput these metrics divide
and re-derive. iso_interactivity.py is synced in this commit per AGENTS.md and
verified to agree to the last digit (0.44517072882391184 on a shared fixture);
that rule now also covers recoverReciprocalNumerator.

recoverReciprocalNumerator returns null unless every usable point agrees on the
constant, and all call sites then fall back to splining. That guard is load
bearing: the measured* energy keys have a numerator measured per point, so they
stay splined, and hand-built points whose cost is unrelated to their throughput
keep their previous values instead of being silently rewritten. The rate is
recovered across all three token types at once — checking one family and falling
back to another recovers a rate from output tokens and applies it to total
throughput, which the existing maxInteractivityAtCost tests caught.

Published numbers move down, since they were the overstated side. Over 555
unclamped reads (dsr1 8k/1k, targets 20-75), two-thirds shift under 10%; the
tail is the sparsely swept disaggregated configs, worst case a 25x drop.

Note for whoever merges second: the Fleet Lifecycle branch documents this as an
open follow-up and derives its break-even to work around it. That prose needs
reconciling once both land — the workaround stays correct, it is just no longer
a workaround.
@Oseltamivir
Oseltamivir requested a review from adibarra as a code owner August 12, 2026 09:39
@vercel

vercel Bot commented Aug 12, 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 12, 2026 11:00am

Request Review

Run the bundled Python helper from the existing unit test, return null for missing reciprocal inputs, and remove snapshot-specific impact claims that do not describe the changing live dataset. Correct the documented consistency tolerance to 0.1%.

中文:对齐倒数指标的插值验证。现有单元测试会直接运行随附的 Python helper;缺少倒数吞吐量输入时返回 null;移除无法代表持续变化的线上数据集的快照影响数字,并将一致性容差文档更正为 0.1%。
@Oseltamivir
Oseltamivir merged commit e3af595 into master Aug 12, 2026
24 checks passed
@Oseltamivir
Oseltamivir deleted the interpolation-cost-identity branch August 12, 2026 11:10
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