mirror of
https://github.com/usestrix/strix.git
synced 2026-10-15 04:18:10 +00:00
Merge 2b14448b64 into 87f2d783d6
This commit is contained in:
commit
a2fdcff53b
2 changed files with 68 additions and 1 deletions
|
|
@ -7,7 +7,9 @@ from typing import Any, cast
|
|||
|
||||
|
||||
@lru_cache(maxsize=512)
|
||||
def resolve_litellm_model(model: str) -> str | None:
|
||||
def resolve_litellm_model( # noqa: PLR0911 - each resolution path returns its own name
|
||||
model: str,
|
||||
) -> str | None:
|
||||
"""Return a provider-qualified model name that LiteLLM can price."""
|
||||
try:
|
||||
import litellm
|
||||
|
|
@ -39,6 +41,22 @@ def resolve_litellm_model(model: str) -> str | None:
|
|||
matches = sorted(key for key in model_cost if key.endswith(f"/{name}"))
|
||||
if not matches:
|
||||
continue
|
||||
# Prefer the first-party provider's own listing over an aggregator's
|
||||
# re-listing of the same model. Aggregators (OpenRouter, DeepInfra,
|
||||
# Perplexity, ...) re-key a model under a namespaced path such as
|
||||
# "openrouter/x-ai/grok-4.5"; the native listing is the one whose key
|
||||
# is exactly "<litellm_provider>/<name>" ("xai/grok-4.5"). When that
|
||||
# is unique it is the canonical name, so tie-break on it before
|
||||
# falling back to price consensus (which would otherwise pick the
|
||||
# alphabetically first key, an aggregator).
|
||||
native = [
|
||||
key
|
||||
for key in matches
|
||||
if isinstance(model_cost.get(key), dict)
|
||||
and key == f"{model_cost[key].get('litellm_provider')}/{name}"
|
||||
]
|
||||
if len(native) == 1:
|
||||
return native[0]
|
||||
prices = {
|
||||
(
|
||||
model_cost[key].get("input_cost_per_token"),
|
||||
|
|
|
|||
|
|
@ -127,3 +127,52 @@ def test_resolver_does_not_guess_between_differently_priced_providers() -> None:
|
|||
finally:
|
||||
litellm.model_cost = original
|
||||
resolve_litellm_model.cache_clear()
|
||||
|
||||
|
||||
def test_resolver_prefers_native_provider_over_aggregator() -> None:
|
||||
# The same model re-listed by an aggregator (which sorts first) and by its
|
||||
# first-party provider at the same price. The resolver must return the
|
||||
# native listing, not the alphabetically first aggregator key.
|
||||
original = litellm.model_cost
|
||||
litellm.model_cost = {
|
||||
"openrouter/x-ai/grok-4.5": {
|
||||
"litellm_provider": "openrouter",
|
||||
"input_cost_per_token": 2e-06,
|
||||
"output_cost_per_token": 6e-06,
|
||||
},
|
||||
"xai/grok-4.5": {
|
||||
"litellm_provider": "xai",
|
||||
"input_cost_per_token": 2e-06,
|
||||
"output_cost_per_token": 6e-06,
|
||||
},
|
||||
}
|
||||
try:
|
||||
resolve_litellm_model.cache_clear()
|
||||
assert resolve_litellm_model("grok-4.5") == "xai/grok-4.5"
|
||||
finally:
|
||||
litellm.model_cost = original
|
||||
resolve_litellm_model.cache_clear()
|
||||
|
||||
|
||||
def test_resolver_prefers_unique_native_provider_over_differently_priced_aggregators() -> None:
|
||||
# A unique first-party listing wins even when aggregators price the model
|
||||
# differently, where price consensus alone would give up and return None.
|
||||
original = litellm.model_cost
|
||||
litellm.model_cost = {
|
||||
"deepinfra/x/example-model": {
|
||||
"litellm_provider": "deepinfra",
|
||||
"input_cost_per_token": 1e-06,
|
||||
"output_cost_per_token": 2e-06,
|
||||
},
|
||||
"example/example-model": {
|
||||
"litellm_provider": "example",
|
||||
"input_cost_per_token": 5e-06,
|
||||
"output_cost_per_token": 9e-06,
|
||||
},
|
||||
}
|
||||
try:
|
||||
resolve_litellm_model.cache_clear()
|
||||
assert resolve_litellm_model("example-model") == "example/example-model"
|
||||
finally:
|
||||
litellm.model_cost = original
|
||||
resolve_litellm_model.cache_clear()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue