Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions packages/openrouter-realm/model-cost.test.gts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function runTests() {
assert.strictEqual(modelCostTierLabel('0.000003 USD', '0'), undefined);
});

test('maps blended cost across the 1/5/20 tier bounds', function (assert) {
test('maps blended cost across the 1/5/15 tier bounds', function (assert) {
// Encode a target blended $/M as a completion-only per-token price:
// blended = (completion/4)*1e6 => completion = blended*4/1e6. Values are
// kept off the exact bounds so floating-point wobble can't flip a tier.
Expand All @@ -89,17 +89,24 @@ export function runTests() {
assert.strictEqual(byBlended(1.1), '$$', 'just above $1/M');
assert.strictEqual(byBlended(4.9), '$$', 'just below $5/M');
assert.strictEqual(byBlended(5.1), '$$$', 'just above $5/M');
assert.strictEqual(byBlended(19), '$$$', 'just below $20/M');
assert.strictEqual(byBlended(21), '$$$$', 'just above $20/M');
assert.strictEqual(byBlended(200), '$$$$', 'well above $20/M');
assert.strictEqual(byBlended(14), '$$$', 'just below $15/M');
assert.strictEqual(byBlended(16), '$$$$', 'just above $15/M');
assert.strictEqual(byBlended(200), '$$$$', 'well above $15/M');
});

test('bounds are inclusive: exactly 1/5/20 land in the lower tier', function (assert) {
test('bounds are inclusive: exactly 1/5/15 land in the lower tier', function (assert) {
// Completion-only prices whose blended $/M is float-exact at each bound:
// (completion/4)*1e6 with 0.000004 / 0.00002 / 0.00008 => 1 / 5 / 20.
// (completion/4)*1e6 with 0.000004 / 0.00002 / 0.00006 => 1 / 5 / 15.
assert.strictEqual(modelCostTierLabel('0', '0.000004'), '$');
assert.strictEqual(modelCostTierLabel('0', '0.00002'), '$$');
assert.strictEqual(modelCostTierLabel('0', '0.00008'), '$$$');
assert.strictEqual(modelCostTierLabel('0', '0.00006'), '$$$');
});

test('float noise cannot tip an exact-bound price into the tier above', function (assert) {
// gpt-4-turbo: in $10/M out $30/M => blended exactly 15, but the raw
// float math yields 15.000000000000002. The blend rounds that noise
// away, so the price lands on the inclusive bound and stays $$$.
assert.strictEqual(modelCostTierLabel('0.00001', '0.00003'), '$$$');
});

test('classifies representative frontier models (tier + label)', function (assert) {
Expand All @@ -118,6 +125,11 @@ export function runTests() {
tier: 3,
label: '$$$',
});
// claude-fable-5: in $10/M out $50/M => blended 20 => $$$$
assert.deepEqual(modelCostTier('0.00001', '0.00005'), {
tier: 4,
label: '$$$$',
});
// o1: in $15/M out $60/M => blended 26.25 => $$$$
assert.deepEqual(modelCostTier('0.000015', '0.00006'), {
tier: 4,
Expand Down
13 changes: 10 additions & 3 deletions packages/openrouter-realm/model-cost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@

// Upper bounds (inclusive) for the blended $/M cost of each dollar tier. Fixed,
// human-round thresholds — not quantiles — so a model's badge stays stable as
// the catalog churns. Grounded in the live OpenRouter price distribution.
export const COST_TIER_UPPER_BOUNDS = [1, 5, 20] as const; // $, $$, $$$ (>20 => $$$$)
// the catalog churns. Grounded in the live OpenRouter price distribution; the
// top bound sits below premium-priced frontier models (blended $20/M and up)
// so they read as $$$$ rather than sharing $$$ with standard Opus-tier pricing.
export const COST_TIER_UPPER_BOUNDS = [1, 5, 15] as const; // $, $$, $$$ (>15 => $$$$)

const DOLLAR_LABELS = ['$', '$$', '$$$', '$$$$'] as const;

Expand Down Expand Up @@ -59,7 +61,12 @@ export function blendedCostPerMillion(
(3 * (prompt === 'absent' ? 0 : prompt) +
(completion === 'absent' ? 0 : completion)) /
4;
return perToken * 1_000_000;
// Round to a micro-dollar per million tokens. The blend of per-token decimal
// strings picks up binary float noise (e.g. $10/$30 blends to
// 15.000000000000002), which would tip a price sitting exactly on an
// inclusive tier bound into the tier above. No real price distinction lives
// below $0.000001/M, so rounding here only removes representation error.
return Math.round(perToken * 1_000_000 * 1_000_000) / 1_000_000;
}

// Maps OpenRouter pricing to a cost tier, or `undefined` when pricing is
Expand Down