fix(dashboard): compare per-request cost on the same requests (#93) (#124)

The dashboard labeled the average cost of small passthrough requests as what the larger imaged requests would have cost without pxpipe. Compare each paid imaged request with its own cache-aware text counterfactual instead, and explain the same-request calculation in the math drawer.

Fixes #93
This commit is contained in:
Steven
2026-07-18 22:54:01 -04:00
committed by GitHub
parent 69c3a51829
commit c260eae9d8
2 changed files with 38 additions and 24 deletions
+19 -23
View File
@@ -249,24 +249,26 @@ function statTile(
export function renderHeaderFragment(s: StatsPayload, port: number): string {
const pa = s.pricing_assumptions;
// stat strip
const splitReady = s.split_sufficient_sample;
// Compare the same imaged requests on both sides. Passthrough requests are
// generally smaller because the profitability gate selected them, so their
// average is not a valid "without pxpipe" counterfactual.
const cAvg = s.compressed_avg_usd_per_request ?? 0;
const pAvg = s.passthrough_avg_usd_per_request ?? 0;
const costTile = splitReady
const paidImaged = s.compressed_paid_requests ?? 0;
const withoutAvg = paidImaged > 0 ? cAvg + (s.saved_usd ?? 0) / paidImaged : 0;
const costTile = paidImaged > 0
? statTile(
'Cost per request',
`$${cAvg.toFixed(4)}`,
`vs $${pAvg.toFixed(4)} without pxpipe`,
cAvg <= pAvg ? 'pos' : 'neg',
'Average real cost of a request with imaging on vs off (passthrough), measured on your own traffic.',
`vs $${withoutAvg.toFixed(4)} without pxpipe`,
cAvg <= withoutAvg ? 'pos' : 'neg',
'Average cost of paid imaged requests versus the cache-aware text counterfactual for those same requests. Unmeasured requests are assigned zero savings.',
)
: statTile(
'Cost per request',
'collecting…',
`${numFmt(s.compressed_paid_requests)} imaged · ${numFmt(s.passthrough_paid_requests)} passthrough so far`,
'waiting for a paid imaged request',
'muted-val',
`Needs at least ${s.split_min_sample_per_bucket} paid requests on each path before the comparison is trustworthy.`,
'The comparison appears after an imaged request returns provider usage.',
);
const strip =
@@ -306,20 +308,14 @@ export function renderHeaderFragment(s: StatsPayload, port: number): string {
mathRow('saved_usd', `$${(s.saved_usd || 0).toFixed(4)} `, `<span class="op">=</span> saved_tokens × input_rate / 1e6`) +
`<span class="src">source: ${escapeHtml(pa.source || 'docs.anthropic.com pricing')}</span>`;
const splitMath =
`<div><span class="k">formula:</span> <span class="v">bucket_$ = (Σ actual_input + Σ output × ${pa.output_multiplier}) × $${pa.input_per_mtok}/Mtok</span></div>` +
`<div><span class="k">why:</span> <span class="v">partition the paid-rows set by which path actually ran (compressed vs passthrough). Same $/Mtok on both sides so the rate assumption cancels in the delta. Selection bias (the gate routes each turn) does NOT cancel — read with the sample counts.</span></div>` +
const costPerRequestMath =
`<div><span class="k">formula:</span> <span class="v">without_pxpipe = actual_imaged + measured_savings</span></div>` +
`<div><span class="k">why:</span> <span class="v">both averages cover the same paid imaged requests. Passthrough requests are not used because the profitability gate selects a different, generally smaller population.</span></div>` +
`<div class="sp"></div>` +
mathRow(`compressed (n=${s.compressed_paid_requests})`, `$${(s.compressed_actual_usd || 0).toFixed(4)}`, `total · avg $${(s.compressed_avg_usd_per_request || 0).toFixed(4)}/req`) +
mathRow(`passthrough (n=${s.passthrough_paid_requests})`, `$${(s.passthrough_actual_usd || 0).toFixed(4)}`, `total · avg $${(s.passthrough_avg_usd_per_request || 0).toFixed(4)}/req`) +
mathRow(
'compressed passthrough',
`$${(s.compressed_minus_passthrough_avg_usd || 0).toFixed(4)}/req`,
s.split_sufficient_sample
? `(both buckets ≥ ${s.split_min_sample_per_bucket} — delta is meaningful)`
: `(small sample: need ≥ ${s.split_min_sample_per_bucket} per bucket; treat as noisy)`,
) +
`<span class="src">no counterfactual, no probe gate — pure observed $/req on each path</span>`;
mathRow(`actual imaged (n=${paidImaged})`, `$${(s.compressed_actual_usd || 0).toFixed(4)}`, `total · avg $${cAvg.toFixed(4)}/req`) +
mathRow('measured savings', `$${(s.saved_usd || 0).toFixed(4)}`, 'cache-aware input-side total') +
mathRow('without pxpipe', `$${withoutAvg.toFixed(4)}/req`, '<span class="op">=</span> (actual imaged + measured savings) / n') +
`<span class="src">unmeasured imaged rows remain in n and actual cost, with zero assumed savings</span>`;
const pctMath =
`<div><span class="k">formula:</span> <span class="v">share_of_spend = saved / (all_baseline_equivalent + all_output × ${pa.output_multiplier})</span></div>` +
@@ -353,7 +349,7 @@ export function renderHeaderFragment(s: StatsPayload, port: number): string {
`<div class="math-grid">` +
mathBlock('Input tokens saved', savedMath) +
mathBlock('Dollars saved', usdMath) +
mathBlock('Compressed vs passthrough, per request', splitMath) +
mathBlock('Cost per imaged request', costPerRequestMath) +
mathBlock('Share of total spend (diagnostic)', pctMath) +
mathBlock('Token-equivalent (what the weekly cap counts)', tokeqMath) +
`</div></details>`;
+19 -1
View File
@@ -15,7 +15,7 @@ import { getAllowedModelBases, setAllowedModelBases } from '../src/core/applicab
import type { SessionsPaths } from '../src/sessions.js';
import type { TrackEvent } from '../src/core/tracker.js';
import type { StatsPayload, RecentPayload } from '../src/dashboard/types.js';
import { renderPage } from '../src/dashboard/fragments.js';
import { renderHeaderFragment, renderPage } from '../src/dashboard/fragments.js';
function makeTmp(): SessionsPaths {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'pxpipe-dashapi-'));
@@ -332,6 +332,24 @@ describe('dashboard page help UI', () => {
expect(html).toContain('.q:hover::after, .q:focus-visible::after');
expect(html).toContain('content: attr(data-tip)');
});
it('compares imaged requests with their own without-pxpipe counterfactual', () => {
const html = renderHeaderFragment({
compressed_paid_requests: 600,
compressed_actual_usd: 96.42,
compressed_avg_usd_per_request: 0.1607,
passthrough_paid_requests: 36,
passthrough_actual_usd: 2.5992,
passthrough_avg_usd_per_request: 0.0722,
saved_usd: 194.83,
pricing_assumptions: { input_per_mtok: 10, output_multiplier: 5 },
} as StatsPayload, 47821);
expect(html).toContain('$0.1607');
expect(html).toContain('vs $0.4854 without pxpipe');
expect(html).not.toContain('vs $0.0722 without pxpipe');
expect(html).toContain('same paid imaged requests');
});
});
// ---- GPT (OpenAI) savings split ------------------------------------------