mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-25 01:02:15 +00:00
Fix Vantage service name fallback
This commit is contained in:
parent
cf9b5e4fa7
commit
3d5192f10f
2 changed files with 64 additions and 1 deletions
|
|
@ -42,6 +42,12 @@ def _build_tags_expr(available_keys: list[str]) -> pl.Expr:
|
|||
)
|
||||
|
||||
|
||||
def _non_blank_string_expr(column_name: str) -> pl.Expr:
|
||||
"""Return a stripped string column, treating null/blank values as null."""
|
||||
value = pl.col(column_name).cast(pl.String).str.strip_chars()
|
||||
return pl.when(value.is_not_null() & (value != "")).then(value).otherwise(None)
|
||||
|
||||
|
||||
class FocusTransformer:
|
||||
"""Transforms LiteLLM DB rows into Focus-compatible schema."""
|
||||
|
||||
|
|
@ -81,6 +87,12 @@ class FocusTransformer:
|
|||
|
||||
none_str = pl.lit(None, dtype=pl.Utf8)
|
||||
none_dec = pl.lit(None, dtype=pl.Decimal(18, 6))
|
||||
service_name = pl.coalesce(
|
||||
_non_blank_string_expr("model_group"),
|
||||
_non_blank_string_expr("model"),
|
||||
_non_blank_string_expr("custom_llm_provider"),
|
||||
pl.lit("litellm-proxy"),
|
||||
)
|
||||
|
||||
return frame.select(
|
||||
dec(pl.col("spend").fill_null(0.0)).alias("BilledCost"),
|
||||
|
|
@ -122,7 +134,7 @@ class FocusTransformer:
|
|||
pl.col("model").cast(pl.String).alias("ResourceType"),
|
||||
pl.lit("AI and Machine Learning").alias("ServiceCategory"),
|
||||
pl.lit("Generative AI").alias("ServiceSubcategory"),
|
||||
pl.col("model_group").cast(pl.String).alias("ServiceName"),
|
||||
service_name.alias("ServiceName"),
|
||||
pl.col("team_id").cast(pl.String).alias("SubAccountId"),
|
||||
pl.col("team_alias").cast(pl.String).alias("SubAccountName"),
|
||||
none_str.alias("SubAccountType"),
|
||||
|
|
|
|||
51
tests/test_litellm/integrations/focus/test_transformer.py
Normal file
51
tests/test_litellm/integrations/focus/test_transformer.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
"""Tests for FocusTransformer normalization."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import polars as pl
|
||||
|
||||
from litellm.integrations.focus.transformer import FocusTransformer
|
||||
|
||||
|
||||
def _usage_frame(rows: list[dict]) -> pl.DataFrame:
|
||||
defaults = {
|
||||
"date": "2026-05-17",
|
||||
"user_id": "user-1",
|
||||
"api_key": "virtual-key-id",
|
||||
"api_key_alias": "test-key",
|
||||
"model": "gpt-4.1",
|
||||
"model_group": "gpt-4.1",
|
||||
"custom_llm_provider": "openai",
|
||||
"spend": 0.1,
|
||||
"team_id": "team-1",
|
||||
"team_alias": "Test Team",
|
||||
"user_email": "user@example.com",
|
||||
}
|
||||
return pl.DataFrame([{**defaults, **row} for row in rows])
|
||||
|
||||
|
||||
def test_should_use_model_group_as_service_name_when_present():
|
||||
result = FocusTransformer().transform(
|
||||
_usage_frame([{"model": "gpt-4.1", "model_group": "production-gpt"}])
|
||||
)
|
||||
|
||||
assert result["ServiceName"].to_list() == ["production-gpt"]
|
||||
|
||||
|
||||
def test_should_fallback_service_name_when_model_group_is_blank():
|
||||
result = FocusTransformer().transform(
|
||||
_usage_frame(
|
||||
[
|
||||
{"model": "mcp-vector-store", "model_group": ""},
|
||||
{"model": "", "model_group": " ", "custom_llm_provider": "proxy"},
|
||||
{"model": None, "model_group": None, "custom_llm_provider": None},
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
assert result["ServiceName"].to_list() == [
|
||||
"mcp-vector-store",
|
||||
"proxy",
|
||||
"litellm-proxy",
|
||||
]
|
||||
assert all(service_name.strip() for service_name in result["ServiceName"])
|
||||
Loading…
Add table
Reference in a new issue