From 0c7373675f7a4f0ff2a27f1c352ab99e6f931388 Mon Sep 17 00:00:00 2001 From: 9qeklajc Date: Sat, 27 Jun 2026 22:53:35 +0200 Subject: [PATCH] solidify logic --- routstr/payment/models.py | 8 +++++- tests/unit/test_cache_pricing.py | 42 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/routstr/payment/models.py b/routstr/payment/models.py index db477b93..e6ea643d 100644 --- a/routstr/payment/models.py +++ b/routstr/payment/models.py @@ -243,7 +243,13 @@ def _row_to_model( # without this, ``_row_to_model`` bills cache reads at the full input rate — # the ``_apply_provider_fee_to_model`` path backfills, but the override path # used for admin-configured providers did not. - parsed_pricing = backfill_cache_pricing(row.id, parsed_pricing) + # + # Key on ``forwarded_model_id`` (the actual upstream model name litellm + # prices) when set: an alias row (id="local-alias", + # forwarded_model_id="deepseek-v4-flash") would otherwise look up the alias + # and miss the cache rate. + pricing_model_id = getattr(row, "forwarded_model_id", None) or row.id + parsed_pricing = backfill_cache_pricing(pricing_model_id, parsed_pricing) if apply_provider_fee: parsed_pricing = Pricing.parse_obj( diff --git a/tests/unit/test_cache_pricing.py b/tests/unit/test_cache_pricing.py index 14bb884c..cfb7e9a6 100644 --- a/tests/unit/test_cache_pricing.py +++ b/tests/unit/test_cache_pricing.py @@ -196,6 +196,48 @@ def test_row_to_model_backfills_cache_rate() -> None: assert model.sats_pricing.input_cache_read > 0 +def test_row_to_model_backfills_via_forwarded_model_id() -> None: + """An alias row (id != forwarded_model_id) must backfill cache rates from + the *forwarded* model name — the real upstream model litellm prices — + not the alias id, which litellm doesn't know.""" + import json + + from routstr.core.db import ModelRow + from routstr.payment.models import _row_to_model + + row = ModelRow( + id="local-alias", # litellm has no such key + name="local-alias", + created=0, + description="", + context_length=1000000, + architecture=json.dumps( + { + "modality": "text", + "input_modalities": ["text"], + "output_modalities": ["text"], + "tokenizer": "unknown", + "instruct_type": None, + } + ), + pricing=json.dumps({"prompt": 1.4e-07, "completion": 2.8e-07}), + enabled=True, + upstream_provider_id=1, + forwarded_model_id="deepseek-v4-flash", + ) + + with patch( + "routstr.payment.models.sats_usd_price", return_value=5.0e-5 + ): + model = _row_to_model(row, apply_provider_fee=True, provider_fee=1.0) + + litellm_read = litellm.model_cost["deepseek-v4-flash"][ + "cache_read_input_token_cost" + ] + assert model.pricing.input_cache_read == pytest.approx(litellm_read) + assert model.pricing.input_cache_read < model.pricing.prompt + + # ============================================================================ # calculate_cost — cached tokens billed at cache rates # ============================================================================