Merge pull request #41423 from BerriAI/litellm_strip_dated_snapshot_cost_lookup

fix(cost): resolve dated openai/azure snapshots to their undated cost map entry
This commit is contained in:
Mateo Wang 2026-09-19 05:51:46 -07:00 committed by GitHub
commit aa0ffee00f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 51 additions and 1 deletions

View file

@ -5342,6 +5342,13 @@ def _strip_stable_vertex_version(model_name) -> str:
return re.sub(r"-\d+$", "", model_name)
_DATED_SNAPSHOT_SUFFIX: Final = re.compile(r"-\d{4}-\d{2}-\d{2}$")
def _strip_dated_snapshot_suffix(model_name: str) -> str:
return _DATED_SNAPSHOT_SUFFIX.sub("", model_name)
def _get_base_bedrock_model(model_name) -> str:
"""
Get the base model from the given model name.
@ -5389,7 +5396,7 @@ def _strip_model_name(model: str, custom_llm_provider: str | None) -> str:
strip_finetune: Final = _strip_openai_finetune_model_name(model_name=model)
return strip_finetune
else:
return model
return _strip_dated_snapshot_suffix(model_name=model)
# Global case-insensitive lookup map for model_cost (built eagerly at module import)

View file

@ -21,7 +21,9 @@ from litellm.types.llms.openai import OpenAIRealtimeStreamList, ResponseAPIUsage
from litellm.types.rerank import RerankResponse
from litellm.types.utils import (
CallTypes,
Choices,
LiteLLMRealtimeStreamLoggingObject,
Message,
ModelInfo,
ModelResponse,
PromptTokensDetailsWrapper,
@ -109,6 +111,28 @@ def test_completion_cost_uses_response_model_for_dynamic_routing(_local_model_co
assert cost > 0, "Cost should be calculated using response model"
def test_completion_cost_strips_dated_azure_snapshot_model(_local_model_cost_map: None) -> None:
dated_response = ModelResponse(
model="gpt-5.6-luna-2026-07-09",
choices=[Choices(index=0, message=Message(role="assistant", content="hi"), finish_reason="stop")],
usage=Usage(prompt_tokens=100, completion_tokens=50, total_tokens=150),
)
dated_response._hidden_params = {"custom_llm_provider": "azure"}
undated_response = ModelResponse(
model="gpt-5.6-luna",
choices=[Choices(index=0, message=Message(role="assistant", content="hi"), finish_reason="stop")],
usage=Usage(prompt_tokens=100, completion_tokens=50, total_tokens=150),
)
undated_response._hidden_params = {"custom_llm_provider": "azure"}
dated_cost = litellm.completion_cost(completion_response=dated_response)
undated_cost = litellm.completion_cost(completion_response=undated_response)
assert dated_cost == undated_cost
assert dated_cost > 0
def test_cost_calculator_with_response_cost_in_additional_headers():
class MockResponse(BaseModel):
_hidden_params = {"additional_headers": {"llm_provider-x-litellm-response-cost": 1000}}

View file

@ -183,6 +183,25 @@ def test_get_model_info_strips_openai_finetune_ids_without_a_custom_suffix(local
assert info["key"] == "ft:gpt-4o-2024-08-06"
@pytest.mark.parametrize(
("model", "custom_llm_provider", "expected_key"),
[
("gpt-5.6-luna-2026-07-09", "openai", "gpt-5.6-luna"),
("gpt-5.6-luna-2026-07-09", "azure", "azure/gpt-5.6-luna"),
],
)
def test_get_model_info_falls_back_from_dated_snapshot_to_undated_entry(
local_model_cost_map, model, custom_llm_provider, expected_key
):
info = litellm.get_model_info(model=model, custom_llm_provider=custom_llm_provider)
assert info["key"] == expected_key
def test_get_model_info_prefers_exact_dated_key_over_stripped(local_model_cost_map):
info = litellm.get_model_info(model="gpt-4o-2024-08-06", custom_llm_provider="openai")
assert info["key"] == "gpt-4o-2024-08-06"
def test_check_provider_match_azure_ai_allows_openai_and_azure():
"""
Test that azure_ai provider can match openai and azure models.