Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ci_cd/generate_model_prices_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@
"description": "Output modalities the model can produce.",
"items": {"type": "string", "enum": ["text", "image", "audio", "video", "code"]},
},
"reasoning_effort_levels": {
"type": "array",
"description": "Exact reasoning_effort levels this deployment accepts; wins over supports_* flags.",
"items": {"type": "string", "enum": ["none", "minimal", "low", "medium", "high", "xhigh", "max"]},
},
"supported_regions": {
"type": "array",
"description": "Cloud regions the model is available in ('global' or region ids).",
Expand Down
29 changes: 29 additions & 0 deletions litellm/llms/anthropic/experimental_pass_through/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import os
from collections.abc import Mapping
from types import MappingProxyType
from typing import Final

import litellm
Expand All @@ -23,6 +25,29 @@ def is_reasoning_auto_summary_enabled() -> bool:
return litellm.reasoning_auto_summary or os.getenv("LITELLM_REASONING_AUTO_SUMMARY", "false").lower() == "true"


_DECLARED_DEGRADATION_CHAINS: Final[Mapping[str, tuple[str, ...]]] = MappingProxyType(
{"max": ("max", "xhigh", "high"), "xhigh": ("xhigh", "high"), "minimal": ("minimal", "low")}
)


def _effort_from_declaration(model_info: ModelInfo, effort: str) -> str | None:
"""A declared level set is the WHOLE answer for this gate, so a level it omits degrades even
where a per-level flag would have allowed it. Honoring both would let /model_group/info and
this path disagree about the same entry. None means the entry declares nothing, and the flag
chain below decides as before.

A declaration that omits every level in a chain still lands on that chain's terminal, which can
itself be undeclared. Picking a nearer declared level instead would need a strength ordering,
and the advertisement order is presentation only by design, so the terminal stays the answer."""
from litellm.router_utils.reasoning_effort_capability import declared_reasoning_efforts

declared: Final = declared_reasoning_efforts(model_info)
if declared is None:
return None
chain: Final = _DECLARED_DEGRADATION_CHAINS[effort]
return next((level for level in chain if level in declared), chain[-1])


def normalize_reasoning_effort_value(
effort: str,
model: str,
Expand All @@ -48,6 +73,10 @@ def normalize_reasoning_effort_value(
except Exception:
model_info = None

declared_effort: Final = _effort_from_declaration(model_info, effort) if model_info is not None else None
if declared_effort is not None:
return declared_effort

if effort == "max":
if model_info and model_info.get("supports_max_reasoning_effort"):
return "max"
Expand Down
53 changes: 53 additions & 0 deletions litellm/model_prices_and_context_window_backup.json
Original file line number Diff line number Diff line change
Expand Up @@ -9315,6 +9315,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.65e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/introducing-kimi-k3-through-fireworks-ai-on-microsoft-foundry/4540187",
"supported_modalities": [
"text",
Expand Down Expand Up @@ -31632,6 +31637,11 @@
"max_tokens": 1048576,
"mode": "chat",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://platform.kimi.ai/docs/pricing/chat-k3",
"supports_function_calling": true,
"supports_reasoning": true,
Expand Down Expand Up @@ -36240,6 +36250,14 @@
"litellm_provider": "perplexity",
"mode": "responses",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"minimal",
"low",
"medium",
"high",
"xhigh",
"max"
],
"source": "https://docs.perplexity.ai/docs/agent-api/models",
"supports_web_search": true,
"supports_reasoning": true,
Expand Down Expand Up @@ -38698,6 +38716,11 @@
"max_tokens": 1048576,
"mode": "chat",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.together.ai/docs/serverless-models",
"supports_function_calling": true,
"supports_parallel_function_calling": true,
Expand Down Expand Up @@ -51487,6 +51510,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand Down Expand Up @@ -51551,6 +51579,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand All @@ -51567,6 +51600,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2.25e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand All @@ -51583,6 +51621,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.65e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand Down Expand Up @@ -51755,6 +51798,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2.25e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand All @@ -51771,6 +51819,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.65e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand Down
32 changes: 27 additions & 5 deletions litellm/router_utils/reasoning_effort_capability.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""Resolve which reasoning_effort values a deployment, and by intersection a model group, accepts.

The model map's supports_*_reasoning_effort flags are the only signal, and each level's polarity
mirrors how a request path reads that same flag. medium and high are unconditional for a reasoning
model. minimal and low are opt-out: openai/chat/gpt_5_transformation.py refuses them only when the
map says false. xhigh and max are opt-in. none is opt-out everywhere except the azure gpt-5 family,
whose config raises UnsupportedParamsError without an explicit true.
An entry that states its levels outright in reasoning_effort_levels is read first and wins
whole, for a model whose set the per-level flags cannot express: Kimi K3 takes low, high and max,
and no flag can drop medium because medium has none. Every other entry answers through the
supports_*_reasoning_effort flags below, whose polarity mirrors how a request path reads that same
flag. medium and high are unconditional for a reasoning model. minimal and low are opt-out:
openai/chat/gpt_5_transformation.py refuses them only when the map says false. xhigh and max are
opt-in. none is opt-out everywhere except the azure gpt-5 family, whose config raises
UnsupportedParamsError without an explicit true.

xhigh is gated on the request path by the openai and azure gpt-5 configs. max is not gated there at
all: every entry carrying supports_max_reasoning_effort is Claude-family, and
Expand Down Expand Up @@ -41,6 +44,7 @@
("xhigh", "supports_xhigh_reasoning_effort"),
("max", "supports_max_reasoning_effort"),
)
_DECLARED_EFFORTS_KEY: Final = "reasoning_effort_levels"
_OPT_OUT_EFFORTS: Final = ("minimal", "low")
_OPT_IN_EFFORTS: Final = ("xhigh", "max")
_UNCONDITIONAL_EFFORTS: Final = frozenset(("medium", "high"))
Expand Down Expand Up @@ -69,6 +73,20 @@ def _declared_effort_flags(model_info: Mapping[str, object]) -> Mapping[str, obj
)


def declared_reasoning_efforts(model_info: Mapping[str, object]) -> tuple[str, ...] | None:
"""The entry's own answer, read through the same bare twin as the flags so both spellings of one
model agree. Present-and-a-list IS the answer, so a declared [] correctly empties the group and
an unknown level is dropped rather than raised: the bundled map is enum-validated by
validate-model-prices-json, but an operator can put this key on a config.yaml model_info block
where that schema never runs, and one mistyped level must not fail every sibling on the proxy."""
own: Final = model_info.get(_DECLARED_EFFORTS_KEY)
raw: Final = own if own is not None else _bare_model_entry(model_info).get(_DECLARED_EFFORTS_KEY)
if not isinstance(raw, Sequence) or isinstance(raw, (str, bytes)):
return None
declared: Final = frozenset(effort for effort in raw if isinstance(effort, str))
return tuple(effort for effort in REASONING_EFFORT_ADVERTISEMENT_ORDER if effort in declared)


def _supports_none_reasoning_effort(model_info: Mapping[str, object], flag: object) -> bool:
"""Opt-in only where a request path refuses the level. AzureOpenAIGPT5Config raises
UnsupportedParamsError on reasoning_effort='none' without an explicit true, and it is selected
Expand Down Expand Up @@ -119,6 +137,10 @@ def resolve_supported_reasoning_efforts(
if supports_reasoning is not True:
return () if supports_reasoning is False or deployment_is_mapped else None

declared: Final = declared_reasoning_efforts(model_info)
if declared is not None:
return declared

flags: Final = _declared_effort_flags(model_info)
if all(value is None for value in flags.values()):
return None
Expand Down
1 change: 1 addition & 0 deletions litellm/types/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ class ProviderSpecificModelInfo(TypedDict, total=False):
supports_low_reasoning_effort: bool | None
supports_xhigh_reasoning_effort: bool | None
supports_max_reasoning_effort: bool | None
reasoning_effort_levels: ReadOnly[Sequence[str] | None]
supports_output_config: bool | None
supports_image_size: bool | None
bedrock_output_config_effort_ceiling: Literal["low", "medium", "high", "max", "xhigh"] | None
Expand Down
1 change: 1 addition & 0 deletions litellm/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5876,6 +5876,7 @@ def _get_model_info_helper(
supports_low_reasoning_effort=_model_info.get("supports_low_reasoning_effort", None),
supports_xhigh_reasoning_effort=_model_info.get("supports_xhigh_reasoning_effort", None),
supports_max_reasoning_effort=_model_info.get("supports_max_reasoning_effort", None),
reasoning_effort_levels=_model_info.get("reasoning_effort_levels", None),
bedrock_output_config_effort_ceiling=_model_info.get("bedrock_output_config_effort_ceiling", None),
bedrock_converse_supports_strict_tools=_model_info.get("bedrock_converse_supports_strict_tools", None),
supports_computer_use=_model_info.get("supports_computer_use", None),
Expand Down
53 changes: 53 additions & 0 deletions model_prices_and_context_window.json
Original file line number Diff line number Diff line change
Expand Up @@ -9315,6 +9315,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.65e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://techcommunity.microsoft.com/blog/azure-ai-foundry-blog/introducing-kimi-k3-through-fireworks-ai-on-microsoft-foundry/4540187",
"supported_modalities": [
"text",
Expand Down Expand Up @@ -31632,6 +31637,11 @@
"max_tokens": 1048576,
"mode": "chat",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://platform.kimi.ai/docs/pricing/chat-k3",
"supports_function_calling": true,
"supports_reasoning": true,
Expand Down Expand Up @@ -36240,6 +36250,14 @@
"litellm_provider": "perplexity",
"mode": "responses",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"minimal",
"low",
"medium",
"high",
"xhigh",
"max"
],
"source": "https://docs.perplexity.ai/docs/agent-api/models",
"supports_web_search": true,
"supports_reasoning": true,
Expand Down Expand Up @@ -38698,6 +38716,11 @@
"max_tokens": 1048576,
"mode": "chat",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.together.ai/docs/serverless-models",
"supports_function_calling": true,
"supports_parallel_function_calling": true,
Expand Down Expand Up @@ -51487,6 +51510,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand Down Expand Up @@ -51551,6 +51579,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.5e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand All @@ -51567,6 +51600,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2.25e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand All @@ -51583,6 +51621,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.65e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand Down Expand Up @@ -51755,6 +51798,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2.25e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand All @@ -51771,6 +51819,11 @@
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 1.65e-05,
"reasoning_effort_levels": [
"low",
"high",
"max"
],
"source": "https://docs.fireworks.ai/serverless/pricing",
"supports_function_calling": true,
"supports_reasoning": true,
Expand Down
Loading
Loading