"""Live e2e: a deployment's custom per-token pricing is loaded, billed, and isolated. Each test registers the deployment(s) it needs through /model/new (deleted on teardown) instead of relying on a statically configured model, so the check is self-contained and never inherits pricing another suite or a stale config left on the shared proxy. custom-priced-flash sets input/output rates deliberately far above the canonical gemini price; the isolation sibling shares the same gemini/gemini-2.5-flash backend but sets no override. Three behaviors are checked independently: - billing: a real call's logged cost breakdown charges input and output tokens at the custom rates, each component checked separately (a base-rate bill lands ~100x lower; a swapped input/output rate passes a total-only check but not this) - reporting: /model/info surfaces those rates for the deployment - isolation: the sibling keeps its own price; an override that leaks into the shared backend cost map (LIT-3897) misprices it, making the sibling's rate match the custom one and failing the isolation check """ import time import pytest from pydantic import BaseModel, RootModel from e2e_config import unique_marker from proxy_client import ProxyClient from e2e_http import Success, unwrap from endpoints_client import EndpointsClient from lifecycle import ResourceManager from models import ( ChatBody, ChatMessage, LiteLLMParamsBody, ModelInfoEntry, SpendLogsParams, ) pytestmark = pytest.mark.e2e BACKEND_MODEL = "gemini/gemini-2.5-flash" GEMINI_API_KEY = "os.environ/GEMINI_API_KEY" # Deliberately ~100x above canonical gemini-2.5-flash (input 3e-7 / output 2.5e-6) # so an override that is ignored or under-applied bills at the base rate and fails. CUSTOM_INPUT_RATE = 5e-05 CUSTOM_OUTPUT_RATE = 1e-04 class _CostBreakdown(BaseModel): input_cost: float | None = None output_cost: float | None = None class _RowMetadata(BaseModel): cost_breakdown: _CostBreakdown | None = None class _SpendRow(BaseModel): request_id: str | None = None prompt_tokens: int | None = None completion_tokens: int | None = None metadata: _RowMetadata | None = None class _SpendRows(RootModel[list[_SpendRow]]): pass def _approx_equal(actual: float, expected: float) -> bool: """Within 1% or 1e-9 absolute - spend math, not exact float identity.""" return abs(actual - expected) <= max(1e-9, abs(expected) * 1e-2) def _provision( endpoints_client: EndpointsClient, resources: ResourceManager, prefix: str, *, input_cost_per_token: float | None, output_cost_per_token: float | None, ) -> str: """Register a fresh gemini/gemini-2.5-flash deployment (deleted on teardown) and return its model name. With the cost fields set the deployment carries a custom pricing override; with them None it is a plain sibling on the same backend. The marker keeps the name unique so concurrent runs on the shared proxy never collide.""" model_name = f"{prefix}-{unique_marker()}" model_id = endpoints_client.create_model( model_name, LiteLLMParamsBody( model=BACKEND_MODEL, api_key=GEMINI_API_KEY, input_cost_per_token=input_cost_per_token, output_cost_per_token=output_cost_per_token, ), ) resources.defer(lambda: endpoints_client.delete_model(model_id)) return model_name def _provision_custom_priced( endpoints_client: EndpointsClient, resources: ResourceManager ) -> str: return _provision( endpoints_client, resources, "custom-priced-flash", input_cost_per_token=CUSTOM_INPUT_RATE, output_cost_per_token=CUSTOM_OUTPUT_RATE, ) def _model_info_entry(entries: list[ModelInfoEntry], model_name: str) -> ModelInfoEntry: for entry in entries: if entry.model_name == model_name: return entry pytest.fail(f"{model_name} absent from /model/info; the override did not load") def _poll_breakdown_row(proxy: ProxyClient, key: str, response_id: str | None) -> _SpendRow: """Poll /spend/logs until the call's row lands with a cost breakdown (rows flush ~60s behind the call via proxy_batch_write_at).""" deadline = time.monotonic() + proxy.poll_timeout while time.monotonic() < deadline: result = proxy.transport.get( "/spend/logs", headers=proxy.transport.master, params=SpendLogsParams(api_key=key), response_type=_SpendRows, ) match result: case Success(data=data): rows = data.root case _: rows = [] priced = [ row for row in rows if row.metadata and row.metadata.cost_breakdown and row.metadata.cost_breakdown.input_cost is not None ] for row in priced: if response_id and row.request_id == response_id: return row if priced and response_id is None: return priced[0] time.sleep(proxy.poll_interval) pytest.fail("no spend row with a cost breakdown landed before the deadline") class TestCustomPricing: def test_custom_pricing_is_billed_at_configured_rate( self, endpoints_client: EndpointsClient, resources: ResourceManager, scoped_key: str, ) -> None: model = _provision_custom_priced(endpoints_client, resources) chat = unwrap( endpoints_client.proxy.chat( scoped_key, ChatBody( model=model, messages=[ ChatMessage( role="user", content=f"reply with one word {unique_marker()}" ) ], max_tokens=16, ), ) ) row = _poll_breakdown_row(endpoints_client.proxy, scoped_key, chat.id) assert row.metadata and row.metadata.cost_breakdown # guaranteed by the poll breakdown = row.metadata.cost_breakdown prompt = row.prompt_tokens or 0 completion = row.completion_tokens or 0 assert prompt > 0 and completion > 0, f"call tokens not logged on the row: {row}" input_cost = breakdown.input_cost output_cost = breakdown.output_cost assert input_cost is not None and output_cost is not None, ( f"row cost breakdown missing input/output cost: {breakdown}" ) assert _approx_equal(input_cost, prompt * CUSTOM_INPUT_RATE), ( f"input_cost {input_cost} != {prompt} tokens * {CUSTOM_INPUT_RATE} " f"= {prompt * CUSTOM_INPUT_RATE}" ) assert _approx_equal(output_cost, completion * CUSTOM_OUTPUT_RATE), ( f"output_cost {output_cost} != {completion} tokens * {CUSTOM_OUTPUT_RATE} " f"= {completion * CUSTOM_OUTPUT_RATE}" ) def test_model_info_reports_custom_pricing( self, endpoints_client: EndpointsClient, resources: ResourceManager ) -> None: model = _provision_custom_priced(endpoints_client, resources) entry = _model_info_entry(endpoints_client.proxy.model_info(), model) assert entry.litellm_params.input_cost_per_token == CUSTOM_INPUT_RATE, ( f"/model/info litellm_params input rate " f"{entry.litellm_params.input_cost_per_token} != configured {CUSTOM_INPUT_RATE}" ) assert entry.litellm_params.output_cost_per_token == CUSTOM_OUTPUT_RATE, ( f"/model/info litellm_params output rate " f"{entry.litellm_params.output_cost_per_token} != configured {CUSTOM_OUTPUT_RATE}" ) def test_custom_pricing_is_isolated_from_sibling_deployment( self, endpoints_client: EndpointsClient, resources: ResourceManager ) -> None: # Register the override first so its rate is in the backend cost map before # the sibling resolves; a leak (LIT-3897) would then poison the sibling. custom = _provision_custom_priced(endpoints_client, resources) sibling = _provision( endpoints_client, resources, "base-flash", input_cost_per_token=None, output_cost_per_token=None, ) entries = {entry.model_name: entry for entry in endpoints_client.proxy.model_info()} custom_entry = entries.get(custom) sibling_entry = entries.get(sibling) assert custom_entry is not None, f"{custom} absent from /model/info" assert sibling_entry is not None, f"{sibling} absent from /model/info" # custom-priced-flash overrides pricing; the sibling shares the same # gemini/gemini-2.5-flash backend but sets no override, so it must keep its # own price. Equal rates mean the override leaked into the shared cost map. assert ( sibling_entry.model_info.input_cost_per_token != custom_entry.model_info.input_cost_per_token ), ( f"{sibling} input rate {sibling_entry.model_info.input_cost_per_token} matches " f"{custom}'s override {custom_entry.model_info.input_cost_per_token}; " f"per-deployment custom pricing is not isolated" )