From 5afa0ba4bc17a801964cd1190a6d8034e399c0a4 Mon Sep 17 00:00:00 2001 From: Shroominic Date: Sun, 3 Aug 2025 23:57:00 -0300 Subject: [PATCH 1/2] fix context length cost calculation --- router/payment/models.py | 48 ++++++++++++---------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/router/payment/models.py b/router/payment/models.py index ef545c81..0c78cb02 100644 --- a/router/payment/models.py +++ b/router/payment/models.py @@ -89,43 +89,23 @@ async def update_sats_pricing() -> None: model.sats_pricing = Pricing( **{k: v / sats_to_usd for k, v in model.pricing.dict().items()} ) + mspp = model.sats_pricing.prompt + mspc = model.sats_pricing.completion if model.top_provider: - if ( - model.top_provider.context_length - and model.top_provider.max_completion_tokens + if cl := model.top_provider.context_length and ( + mct := model.top_provider.max_completion_tokens ): - max_context_cost = ( - model.top_provider.context_length - * model.sats_pricing.prompt - ) - max_completion_cost = ( - model.top_provider.max_completion_tokens - * model.sats_pricing.completion - ) - model.sats_pricing.max_cost = ( - max_context_cost + max_completion_cost - ) - elif model.top_provider.context_length: - max_context_cost = ( - model.top_provider.context_length - * model.sats_pricing.prompt - ) - max_completion_cost = 32_000 * model.sats_pricing.completion - model.sats_pricing.max_cost = ( - max_context_cost + max_completion_cost - ) - elif model.top_provider.max_completion_tokens: - max_completion_cost = ( - model.top_provider.max_completion_tokens - * model.sats_pricing.completion - ) - max_context_cost = 1_048_576 * model.sats_pricing.prompt - model.sats_pricing.max_cost = max_completion_cost + model.sats_pricing.max_cost = cl - mct * mspp + mct * mspc + elif cl := model.top_provider.context_length: + model.sats_pricing.max_cost = cl * 0.8 * mspp + cl * 0.2 * mspc + elif mct := model.top_provider.max_completion_tokens: + model.sats_pricing.max_cost = mct * 4 * mspp + mct * mspc else: - model.sats_pricing.max_cost = ( - 1_048_576 * model.sats_pricing.prompt - + 32_000 * model.sats_pricing.completion - ) + model.sats_pricing.max_cost = 1_000_000 * mspp + 32_000 * mspc + elif model.context_length: + model.sats_pricing.max_cost = ( + model.sats_pricing.prompt * model.context_length * 0.8 + ) + (model.sats_pricing.completion * model.context_length * 0.2) else: p = model.sats_pricing.prompt * 1_000_000 c = model.sats_pricing.completion * 32_000 From 3845b119513f9566eed752a5beaebd344f606da4 Mon Sep 17 00:00:00 2001 From: Shroominic Date: Mon, 4 Aug 2025 01:21:14 -0300 Subject: [PATCH 2/2] fix tests --- router/payment/models.py | 4 ++-- tests/test_models.py | 30 +++++++++++++++++------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/router/payment/models.py b/router/payment/models.py index 0c78cb02..90766df8 100644 --- a/router/payment/models.py +++ b/router/payment/models.py @@ -92,10 +92,10 @@ async def update_sats_pricing() -> None: mspp = model.sats_pricing.prompt mspc = model.sats_pricing.completion if model.top_provider: - if cl := model.top_provider.context_length and ( + if (cl := model.top_provider.context_length) and ( mct := model.top_provider.max_completion_tokens ): - model.sats_pricing.max_cost = cl - mct * mspp + mct * mspc + model.sats_pricing.max_cost = (cl - mct) * mspp + mct * mspc elif cl := model.top_provider.context_length: model.sats_pricing.max_cost = cl * 0.8 * mspp + cl * 0.2 * mspc elif mct := model.top_provider.max_completion_tokens: diff --git a/tests/test_models.py b/tests/test_models.py index f586fd93..cb101693 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -87,11 +87,18 @@ async def test_update_sats_pricing_calculation(sample_model: Model) -> None: 0.001 / 0.0001 ) # 10 sats - # Verify max_cost calculation for model with top_provider - expected_max_context = 4096 * sample_model.sats_pricing.prompt - expected_max_completion = 2048 * sample_model.sats_pricing.completion + assert sample_model.top_provider is not None + assert sample_model.top_provider.context_length is not None + assert sample_model.top_provider.max_completion_tokens is not None + assert sample_model.sats_pricing.max_cost == pytest.approx( - expected_max_context + expected_max_completion + ( + sample_model.top_provider.context_length + - sample_model.top_provider.max_completion_tokens + ) + * sample_model.sats_pricing.prompt + + sample_model.top_provider.max_completion_tokens + * sample_model.sats_pricing.completion ) # Cancel and await the task @@ -159,16 +166,13 @@ async def test_update_sats_pricing_without_top_provider() -> None: assert model_without_top.sats_pricing is not None # Verify the fallback max_cost calculation - p = model_without_top.sats_pricing.prompt * 1_000_000 - c = model_without_top.sats_pricing.completion * 32_000 - r = model_without_top.sats_pricing.request * 100_000 - i = model_without_top.sats_pricing.image * 100 - w = model_without_top.sats_pricing.web_search * 1000 - ir = model_without_top.sats_pricing.internal_reasoning * 100 - expected_max = p + c + r + i + w + ir - assert model_without_top.sats_pricing.max_cost == pytest.approx( - expected_max + model_without_top.context_length + * 0.8 + * model_without_top.sats_pricing.prompt + + model_without_top.context_length + * 0.2 + * model_without_top.sats_pricing.completion ) # Cancel and await the task