fix(anthropic,bedrock,databricks): four reasoning_effort follow-ups

- claude-sonnet-4-6 + reasoning_effort=max no longer 400s. Renamed
  _is_opus_4_6_model to _is_claude_4_6_model at three sites and added
  supports_max_reasoning_effort: true to 12 model entries in the JSON
  cost map (10 sonnet 4.6 ids + OpenRouter opus 4.6/4.7).
- _map_reasoning_effort now raises BadRequestError(400) directly with
  llm_provider, instead of letting Databricks (and similar callers)
  surface its raw ValueError as a 500.
- output_config.effort on Opus 4.5 over Bedrock no longer 400s for
  missing effort-2025-11-24 beta. Flipped JSON to "effort-2025-11-24"
  for bedrock + bedrock_converse and added an auto-attach branch in
  _process_tools_and_beta for non-adaptive Anthropic + output_config
  on Converse.
- reasoning_effort=xhigh / =max on legacy budget-mode models
  (Haiku 4.5, Sonnet 4.5, Opus 4.5) now map to thinking.budget_tokens
  8192 / 16384 instead of returning 400. Added two constants in
  litellm/constants.py.

Tests updated for all four flips. Validated end-to-end via 306-cell
live proxy matrix (6 model families x 3 routes x 17 effort cases),
all pass.
This commit is contained in:
mateo-berri 2026-05-03 10:03:53 -07:00
parent 36f1f13925
commit 108b87fb24
11 changed files with 559 additions and 204 deletions

View file

@ -72,7 +72,7 @@
"computer-use-2025-11-24": "computer-use-2025-11-24",
"context-1m-2025-08-07": "context-1m-2025-08-07",
"context-management-2025-06-27": null,
"effort-2025-11-24": null,
"effort-2025-11-24": "effort-2025-11-24",
"fast-mode-2026-02-01": null,
"files-api-2025-04-14": null,
"fine-grained-tool-streaming-2025-05-14": null,
@ -103,7 +103,7 @@
"computer-use-2025-11-24": "computer-use-2025-11-24",
"context-1m-2025-08-07": "context-1m-2025-08-07",
"context-management-2025-06-27": null,
"effort-2025-11-24": null,
"effort-2025-11-24": "effort-2025-11-24",
"fast-mode-2026-02-01": null,
"files-api-2025-04-14": null,
"fine-grained-tool-streaming-2025-05-14": null,

View file

@ -202,6 +202,23 @@ DEFAULT_REASONING_EFFORT_MEDIUM_THINKING_BUDGET = int(
DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET = int(
os.getenv("DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET", 4096)
)
# ``xhigh`` / ``max`` budget extrapolation for legacy ``thinking.budget_tokens``
# models (Claude 4.5 series + haiku). Continues the 2× progression
# 1024 → 2048 → 4096 from the existing low/medium/high tiers. These tiers
# also exist as adaptive ``output_config.effort`` enum values on Claude 4.6+
# / 4.7; this constant only governs the budget-tokens fallback for models
# that aren't on the adaptive path. Per
# https://platform.claude.com/docs/en/build-with-claude/effort the ``effort``
# enum is gated by model, but the legacy ``budget_tokens`` knob accepts any
# integer up to the model's max_tokens — adopting #27051's mapping here lets
# ``reasoning_effort=xhigh|max`` Just Work as a unified OpenAI-format knob
# regardless of which Anthropic API surface implements it.
DEFAULT_REASONING_EFFORT_XHIGH_THINKING_BUDGET = int(
os.getenv("DEFAULT_REASONING_EFFORT_XHIGH_THINKING_BUDGET", 8192)
)
DEFAULT_REASONING_EFFORT_MAX_THINKING_BUDGET = int(
os.getenv("DEFAULT_REASONING_EFFORT_MAX_THINKING_BUDGET", 16384)
)
MAX_TOKEN_TRIMMING_ATTEMPTS = int(
os.getenv("MAX_TOKEN_TRIMMING_ATTEMPTS", 10)
) # Maximum number of attempts to trim the message

View file

@ -21,8 +21,10 @@ from litellm.constants import (
DEFAULT_ANTHROPIC_CHAT_MAX_TOKENS,
DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET,
DEFAULT_REASONING_EFFORT_LOW_THINKING_BUDGET,
DEFAULT_REASONING_EFFORT_MAX_THINKING_BUDGET,
DEFAULT_REASONING_EFFORT_MEDIUM_THINKING_BUDGET,
DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET,
DEFAULT_REASONING_EFFORT_XHIGH_THINKING_BUDGET,
RESPONSE_FORMAT_TOOL_NAME,
)
from litellm.litellm_core_utils.core_helpers import map_finish_reason
@ -869,7 +871,18 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
def _map_reasoning_effort(
reasoning_effort: Optional[Union[REASONING_EFFORT, str]],
model: str,
llm_provider: str = "anthropic",
) -> Optional[AnthropicThinkingParam]:
"""Map an OpenAI-format ``reasoning_effort`` string to Anthropic's
``thinking`` payload.
Raises ``BadRequestError`` (clean 400) instead of ``ValueError`` (500)
on unmapped efforts so every caller Anthropic native, Bedrock
Invoke/Converse, Databricks, Vertex Anthropic, Azure AI Anthropic,
and the experimental ``/v1/messages`` pass-through surfaces a
consistent error to the user. Pass ``llm_provider`` so the
``BadRequestError`` carries the right provider name in logs.
"""
if reasoning_effort is None or reasoning_effort == "none":
return None
if AnthropicConfig._is_claude_4_6_model(
@ -893,6 +906,28 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
type="enabled",
budget_tokens=DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET,
)
elif reasoning_effort == "xhigh":
# Continues the 2× progression of low/medium/high (1024/2048/4096).
# On adaptive models (Claude 4.6/4.7) the ``xhigh`` tier is
# already routed via ``output_config.effort=xhigh`` above; this
# branch only applies to budget-mode models (Claude 4.5 series +
# haiku) where the OpenAI-format ``reasoning_effort`` knob would
# otherwise 400 with ``Unmapped reasoning effort``. Keeps the
# cross-model UX uniform — ``reasoning_effort=xhigh`` Just Works
# regardless of which Anthropic API surface implements it.
return AnthropicThinkingParam(
type="enabled",
budget_tokens=DEFAULT_REASONING_EFFORT_XHIGH_THINKING_BUDGET,
)
elif reasoning_effort == "max":
# Same rationale as ``xhigh`` above — ``max`` is the adaptive
# enum's top tier on Claude 4.6/4.7, but for budget-mode models
# we extend the 2× progression (8192 → 16384) so the OpenAI-
# format alias is usable on every Claude model.
return AnthropicThinkingParam(
type="enabled",
budget_tokens=DEFAULT_REASONING_EFFORT_MAX_THINKING_BUDGET,
)
elif reasoning_effort == "minimal":
# Anthropic Messages API rejects ``budget_tokens < 1024`` with a
# 400. Floor at the provider minimum so ``minimal`` is a usable
@ -906,7 +941,15 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
),
)
else:
raise ValueError(f"Unmapped reasoning effort: {reasoning_effort}")
raise litellm.exceptions.BadRequestError(
message=(
f"Unmapped reasoning effort: {reasoning_effort!r}. "
f"Must be one of: 'minimal', 'low', 'medium', 'high', "
f"'xhigh', 'max', 'none'."
),
model=model,
llm_provider=llm_provider,
)
def _extract_json_schema_from_response_format(
self, value: Optional[dict]
@ -1170,21 +1213,15 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
elif param == "thinking":
optional_params["thinking"] = value
elif param == "reasoning_effort" and isinstance(value, str):
# Wrap the ``ValueError`` ``_map_reasoning_effort`` raises on
# unmapped efforts (``disabled`` / ``invalid`` / ``""`` /
# ``xhigh``/``max`` on budget-mode Claude 4.5) into a clean
# 400 ``BadRequestError`` instead of letting it surface as
# 500.
try:
mapped_thinking = AnthropicConfig._map_reasoning_effort(
reasoning_effort=value, model=model
)
except ValueError as e:
raise litellm.exceptions.BadRequestError(
message=str(e),
model=model,
llm_provider=self.custom_llm_provider or "anthropic",
)
# ``_map_reasoning_effort`` raises ``BadRequestError`` (400)
# directly on unmapped efforts (``disabled`` / ``invalid`` /
# ``""`` / ``xhigh``/``max`` on budget-mode Claude 4.5) so
# we no longer need to wrap a ``ValueError`` here.
mapped_thinking = AnthropicConfig._map_reasoning_effort(
reasoning_effort=value,
model=model,
llm_provider=self.custom_llm_provider or "anthropic",
)
if mapped_thinking is None:
optional_params.pop("thinking", None)
optional_params.pop("output_config", None)
@ -1673,15 +1710,18 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
model=model,
llm_provider=self.custom_llm_provider or "anthropic",
)
# ``max`` is for Opus 4.6+ output effort (not Sonnet 4.6, not Opus 4.5).
# Accept known Opus 4.6/4.7 id patterns and/or ``supports_max_reasoning_effort``
# in the model map (same pattern as ``xhigh`` below). The hardcoded
# patterns cover OpenRouter/GitHub Copilot/Vercel variants that don't
# carry the model-map flag yet — keep both checks until those provider
# entries are fully populated.
# ``max`` is supported on Claude 4.6 (Opus + Sonnet) and Claude 4.7
# adaptive-thinking models (per
# https://platform.claude.com/docs/en/build-with-claude/effort).
# Prefer the data-driven ``supports_max_reasoning_effort`` flag in
# ``model_prices_and_context_window.json`` so new variants only
# require a model-map update. Family-level ``_is_claude_4_6_model``
# / ``_is_claude_4_7_model`` checks remain as a fallback for
# OpenRouter/GitHub Copilot/Vercel/Bedrock variants whose entries
# don't yet carry the flag.
if effort == "max" and not (
self._is_opus_4_6_model(model)
or self._is_opus_4_7_model(model)
self._is_claude_4_6_model(model)
or self._is_claude_4_7_model(model)
or self._supports_effort_level(model, "max")
):
raise litellm.exceptions.BadRequestError(

View file

@ -201,12 +201,18 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
if not isinstance(reasoning_effort, str):
return
# ``_map_reasoning_effort`` raises ``BadRequestError`` (400) directly
# on unmapped efforts. The /v1/messages pass-through surfaces errors
# as ``AnthropicError``; convert here so callers see a provider-shaped
# 400 rather than the LiteLLM-shaped one.
from litellm.exceptions import BadRequestError as _BadRequestError
try:
mapped_thinking = AnthropicConfig._map_reasoning_effort(
reasoning_effort=reasoning_effort, model=model
)
except ValueError as e:
raise AnthropicError(message=str(e), status_code=400)
except _BadRequestError as e:
raise AnthropicError(message=str(e.message), status_code=400)
if mapped_thinking is None:
optional_params.pop("thinking", None)
@ -238,9 +244,15 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
# The chat completion path enforces this via
# ``_apply_output_config``; mirror it here so /v1/messages
# callers see a clean 400 instead of a provider-side error.
# ``max`` is supported on Claude 4.6 (Opus + Sonnet) and Claude
# 4.7 adaptive-thinking models. Prefer the data-driven
# ``supports_max_reasoning_effort`` flag in
# ``model_prices_and_context_window.json``; family-level checks
# are a fallback for variants whose entries don't yet carry the
# flag.
if mapped_effort == "max" and not (
AnthropicConfig._is_opus_4_6_model(model)
or AnthropicConfig._is_opus_4_7_model(model)
AnthropicConfig._is_claude_4_6_model(model)
or AnthropicConfig._is_claude_4_7_model(model)
or AnthropicConfig._supports_effort_level(model, "max")
):
raise AnthropicError(

View file

@ -463,20 +463,16 @@ class AmazonConverseConfig(BaseConfig):
optional_params.update(reasoning_config)
else:
# Anthropic and other models: convert to thinking parameter.
# Wrap the ``ValueError`` ``_map_reasoning_effort`` raises on
# unmapped efforts (``disabled`` / ``invalid`` / ``""`` /
# ``xhigh``/``max`` on budget-mode Claude 4.5) into a clean 400
# ``BadRequestError`` instead of letting it surface as 500.
try:
mapped_thinking = AnthropicConfig._map_reasoning_effort(
reasoning_effort=reasoning_effort, model=model
)
except ValueError as e:
raise litellm.exceptions.BadRequestError(
message=str(e),
model=model,
llm_provider="bedrock_converse",
)
# ``_map_reasoning_effort`` raises ``BadRequestError`` (400)
# directly on unmapped efforts (``disabled`` / ``invalid`` /
# ``""`` / ``xhigh``/``max`` on budget-mode Claude 4.5); pass
# ``llm_provider="bedrock_converse"`` so the error carries the
# right provider name.
mapped_thinking = AnthropicConfig._map_reasoning_effort(
reasoning_effort=reasoning_effort,
model=model,
llm_provider="bedrock_converse",
)
if mapped_thinking is None:
optional_params.pop("thinking", None)
optional_params.pop("output_config", None)
@ -555,9 +551,15 @@ class AmazonConverseConfig(BaseConfig):
model=model,
llm_provider="bedrock_converse",
)
# ``max`` is supported on Claude 4.6 (Opus + Sonnet) and Claude 4.7
# adaptive-thinking models. Prefer the data-driven
# ``supports_max_reasoning_effort`` flag in
# ``model_prices_and_context_window.json`` so new variants only
# require a model-map update; family-level checks remain a fallback
# for Bedrock model ids whose entries don't yet carry the flag.
if effort == "max" and not (
AnthropicConfig._is_opus_4_6_model(model)
or AnthropicConfig._is_opus_4_7_model(model)
AnthropicConfig._is_claude_4_6_model(model)
or AnthropicConfig._is_claude_4_7_model(model)
or AmazonConverseConfig._supports_effort_level_on_bedrock(model, "max")
):
raise litellm.exceptions.BadRequestError(
@ -1535,9 +1537,29 @@ class AmazonConverseConfig(BaseConfig):
# Append pre-formatted tools (systemTool etc.) after transformation
bedrock_tools.extend(pre_formatted_tools)
# Auto-attach the effort beta header for non-adaptive Anthropic
# models on Bedrock Converse (i.e. Opus 4.5). Claude 4.6/4.7 accept
# ``output_config.effort`` as a stable, GA feature with no beta
# header; Opus 4.5 still gates it behind ``effort-2025-11-24``. The
# check mirrors ``AnthropicModelInfo.is_effort_used`` (which returns
# False for adaptive models) so we don't double-flag adaptive routes.
base_model = BedrockModelInfo.get_base_model(model)
if base_model.startswith("anthropic"):
output_config = additional_request_params.get("output_config")
if (
isinstance(output_config, dict)
and output_config.get("effort") is not None
and not AnthropicConfig._is_adaptive_thinking_model(model)
):
from litellm.types.llms.anthropic import (
ANTHROPIC_EFFORT_BETA_HEADER,
)
if ANTHROPIC_EFFORT_BETA_HEADER not in anthropic_beta_list:
anthropic_beta_list.append(ANTHROPIC_EFFORT_BETA_HEADER)
# Set anthropic_beta in additional_request_params if we have any beta features
# ONLY apply to Anthropic/Claude models - other models (e.g., Qwen, Llama) don't support this field
base_model = BedrockModelInfo.get_base_model(model)
if anthropic_beta_list and base_model.startswith("anthropic"):
additional_request_params["anthropic_beta"] = anthropic_beta_list

View file

@ -330,8 +330,15 @@ class DatabricksConfig(DatabricksBase, OpenAILikeChatConfig, AnthropicConfig):
) # unsupported for claude models - if json_schema -> convert to tool call
if "reasoning_effort" in non_default_params and "claude" in model:
# ``_map_reasoning_effort`` raises ``BadRequestError`` (400)
# directly on unmapped efforts; pass ``llm_provider="databricks"``
# so the surfaced error carries the correct provider name (the
# default is ``"anthropic"``, which would mislead users routing
# via Databricks Foundation Model APIs).
optional_params["thinking"] = AnthropicConfig._map_reasoning_effort(
reasoning_effort=non_default_params.get("reasoning_effort"), model=model
reasoning_effort=non_default_params.get("reasoning_effort"),
model=model,
llm_provider="databricks",
)
optional_params.pop("reasoning_effort", None)
## handle thinking tokens

View file

@ -984,21 +984,6 @@
"tool_use_system_prompt_tokens": 159,
"supports_native_structured_output": true
},
"anthropic.claude-mythos-preview": {
"input_cost_per_token": 0,
"output_cost_per_token": 0,
"litellm_provider": "bedrock",
"max_input_tokens": 1000000,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"supports_function_calling": true,
"supports_vision": true,
"supports_prompt_caching": false,
"supports_reasoning": true,
"supports_minimal_reasoning_effort": true,
"supports_tool_choice": true
},
"anthropic.claude-opus-4-6-v1": {
"cache_creation_input_token_cost": 6.25e-06,
"cache_creation_input_token_cost_above_1hr": 1e-05,
@ -1178,6 +1163,21 @@
"supports_max_reasoning_effort": true,
"supports_minimal_reasoning_effort": true
},
"anthropic.claude-mythos-preview": {
"input_cost_per_token": 0,
"output_cost_per_token": 0,
"litellm_provider": "bedrock",
"max_input_tokens": 1000000,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"supports_function_calling": true,
"supports_vision": true,
"supports_prompt_caching": false,
"supports_reasoning": true,
"supports_minimal_reasoning_effort": true,
"supports_tool_choice": true
},
"global.anthropic.claude-opus-4-7": {
"cache_creation_input_token_cost": 6.25e-06,
"cache_creation_input_token_cost_above_1hr": 1e-05,
@ -1323,6 +1323,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -1352,6 +1353,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -1381,6 +1383,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -1409,6 +1412,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -1437,6 +1441,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -2055,6 +2060,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -9229,6 +9235,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -9496,7 +9503,6 @@
"us": 1.1,
"fast": 6.0
},
"supports_max_reasoning_effort": true,
"supports_minimal_reasoning_effort": true
},
"claude-opus-4-7-20260416": {
@ -9531,7 +9537,6 @@
"us": 1.1,
"fast": 6.0
},
"supports_max_reasoning_effort": true,
"supports_minimal_reasoning_effort": true
},
"claude-sonnet-4-20250514": {
@ -15568,7 +15573,7 @@
"mode": "embedding",
"output_cost_per_token": 0,
"output_vector_size": 3072,
"source": "https://cloud.google.com/vertex-ai/generative-ai/pricing",
"source": "https://ai.google.dev/gemini-api/docs/embeddings#multimodal",
"supports_multimodal": true,
"uses_embed_content": true
},
@ -21164,7 +21169,7 @@
},
"gradient_ai/alibaba-qwen3-32b": {
"litellm_provider": "gradient_ai",
"max_tokens": 2048,
"max_tokens": 40960,
"mode": "chat",
"supported_endpoints": [
"/v1/chat/completions"
@ -21172,7 +21177,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 131072,
"max_output_tokens": 40960
},
"gradient_ai/anthropic-claude-3-opus": {
"input_cost_per_token": 1.5e-05,
@ -21186,7 +21193,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 200000,
"max_output_tokens": 1024
},
"gradient_ai/anthropic-claude-3.5-haiku": {
"input_cost_per_token": 8e-07,
@ -21200,7 +21209,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 200000,
"max_output_tokens": 1024
},
"gradient_ai/anthropic-claude-3.5-sonnet": {
"input_cost_per_token": 3e-06,
@ -21214,7 +21225,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 200000,
"max_output_tokens": 1024
},
"gradient_ai/anthropic-claude-3.7-sonnet": {
"input_cost_per_token": 3e-06,
@ -21228,7 +21241,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 200000,
"max_output_tokens": 1024
},
"gradient_ai/deepseek-r1-distill-llama-70b": {
"input_cost_per_token": 9.9e-07,
@ -21242,7 +21257,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 32768,
"max_output_tokens": 8000
},
"gradient_ai/llama3-8b-instruct": {
"input_cost_per_token": 2e-07,
@ -21256,7 +21273,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 8192,
"max_output_tokens": 512
},
"gradient_ai/llama3.3-70b-instruct": {
"input_cost_per_token": 6.5e-07,
@ -21270,7 +21289,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 128000,
"max_output_tokens": 2048
},
"gradient_ai/mistral-nemo-instruct-2407": {
"input_cost_per_token": 3e-07,
@ -21284,7 +21305,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 128000,
"max_output_tokens": 512
},
"gradient_ai/openai-gpt-4o": {
"litellm_provider": "gradient_ai",
@ -21296,7 +21319,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 128000,
"max_output_tokens": 16384
},
"gradient_ai/openai-gpt-4o-mini": {
"litellm_provider": "gradient_ai",
@ -21308,7 +21333,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 128000,
"max_output_tokens": 16384
},
"gradient_ai/openai-o3": {
"input_cost_per_token": 2e-06,
@ -21322,7 +21349,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 200000,
"max_output_tokens": 100000
},
"gradient_ai/openai-o3-mini": {
"input_cost_per_token": 1.1e-06,
@ -21336,7 +21365,9 @@
"supported_modalities": [
"text"
],
"supports_tool_choice": false
"supports_tool_choice": false,
"max_input_tokens": 200000,
"max_output_tokens": 100000
},
"lemonade/Qwen3-Coder-30B-A3B-Instruct-GGUF": {
"input_cost_per_token": 0,
@ -21636,11 +21667,13 @@
},
"heroku/claude-3-5-haiku": {
"litellm_provider": "heroku",
"max_tokens": 4096,
"max_tokens": 8192,
"mode": "chat",
"supports_function_calling": true,
"supports_system_messages": true,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 200000,
"max_output_tokens": 8192
},
"heroku/claude-3-5-sonnet-latest": {
"litellm_provider": "heroku",
@ -21648,7 +21681,9 @@
"mode": "chat",
"supports_function_calling": true,
"supports_system_messages": true,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 200000,
"max_output_tokens": 8192
},
"heroku/claude-3-7-sonnet": {
"litellm_provider": "heroku",
@ -21656,7 +21691,9 @@
"mode": "chat",
"supports_function_calling": true,
"supports_system_messages": true,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 200000,
"max_output_tokens": 8192
},
"heroku/claude-4-sonnet": {
"litellm_provider": "heroku",
@ -21664,7 +21701,9 @@
"mode": "chat",
"supports_function_calling": true,
"supports_system_messages": true,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 200000,
"max_output_tokens": 8192
},
"high/1024-x-1024/gpt-image-1": {
"input_cost_per_image": 0.167,
@ -22472,48 +22511,6 @@
"/v1/images/generations"
]
},
"luminous-base": {
"input_cost_per_token": 3e-05,
"litellm_provider": "aleph_alpha",
"max_tokens": 2048,
"mode": "completion",
"output_cost_per_token": 3.3e-05
},
"luminous-base-control": {
"input_cost_per_token": 3.75e-05,
"litellm_provider": "aleph_alpha",
"max_tokens": 2048,
"mode": "chat",
"output_cost_per_token": 4.125e-05
},
"luminous-extended": {
"input_cost_per_token": 4.5e-05,
"litellm_provider": "aleph_alpha",
"max_tokens": 2048,
"mode": "completion",
"output_cost_per_token": 4.95e-05
},
"luminous-extended-control": {
"input_cost_per_token": 5.625e-05,
"litellm_provider": "aleph_alpha",
"max_tokens": 2048,
"mode": "chat",
"output_cost_per_token": 6.1875e-05
},
"luminous-supreme": {
"input_cost_per_token": 0.000175,
"litellm_provider": "aleph_alpha",
"max_tokens": 2048,
"mode": "completion",
"output_cost_per_token": 0.0001925
},
"luminous-supreme-control": {
"input_cost_per_token": 0.00021875,
"litellm_provider": "aleph_alpha",
"max_tokens": 2048,
"mode": "chat",
"output_cost_per_token": 0.000240625
},
"max-x-max/50-steps/stability.stable-diffusion-xl-v0": {
"litellm_provider": "bedrock",
"max_input_tokens": 77,
@ -25985,12 +25982,14 @@
"input_cost_per_image": 0.0004,
"input_cost_per_token": 2.5e-07,
"litellm_provider": "openrouter",
"max_tokens": 200000,
"max_tokens": 4096,
"mode": "chat",
"output_cost_per_token": 1.25e-06,
"supports_function_calling": true,
"supports_tool_choice": true,
"supports_vision": true
"supports_vision": true,
"max_input_tokens": 200000,
"max_output_tokens": 4096
},
"openrouter/anthropic/claude-3.5-sonnet": {
"input_cost_per_token": 3e-06,
@ -26109,6 +26108,7 @@
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 159,
@ -26149,6 +26149,7 @@
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -26197,6 +26198,29 @@
"supports_vision": true,
"tool_use_system_prompt_tokens": 346
},
"openrouter/anthropic/claude-opus-4.7": {
"cache_creation_input_token_cost": 6.25e-06,
"cache_read_input_token_cost": 5e-07,
"input_cost_per_token": 5e-06,
"litellm_provider": "openrouter",
"max_input_tokens": 1000000,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"output_cost_per_token": 2.5e-05,
"supports_assistant_prefill": false,
"supports_computer_use": true,
"supports_function_calling": true,
"supports_pdf_input": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
"tool_use_system_prompt_tokens": 346
},
"openrouter/bytedance/ui-tars-1.5-7b": {
"input_cost_per_token": 1e-07,
"litellm_provider": "openrouter",
@ -26562,18 +26586,22 @@
"openrouter/mancer/weaver": {
"input_cost_per_token": 5.625e-06,
"litellm_provider": "openrouter",
"max_tokens": 8000,
"max_tokens": 2000,
"mode": "chat",
"output_cost_per_token": 5.625e-06,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 8000,
"max_output_tokens": 2000
},
"openrouter/meta-llama/llama-3-70b-instruct": {
"input_cost_per_token": 5.9e-07,
"litellm_provider": "openrouter",
"max_tokens": 8192,
"max_tokens": 8000,
"mode": "chat",
"output_cost_per_token": 7.9e-07,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 8192,
"max_output_tokens": 8000
},
"openrouter/minimax/minimax-m2": {
"input_cost_per_token": 2.55e-07,
@ -26661,34 +26689,42 @@
"openrouter/mistralai/mistral-7b-instruct": {
"input_cost_per_token": 1.3e-07,
"litellm_provider": "openrouter",
"max_tokens": 8192,
"max_tokens": 8191,
"mode": "chat",
"output_cost_per_token": 1.3e-07,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 32768,
"max_output_tokens": 8191
},
"openrouter/mistralai/mistral-large": {
"input_cost_per_token": 8e-06,
"litellm_provider": "openrouter",
"max_tokens": 32000,
"max_tokens": 8191,
"mode": "chat",
"output_cost_per_token": 2.4e-05,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 128000,
"max_output_tokens": 8191
},
"openrouter/mistralai/mistral-small-3.1-24b-instruct": {
"input_cost_per_token": 1e-07,
"litellm_provider": "openrouter",
"max_tokens": 32000,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 3e-07,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 131072,
"max_output_tokens": 131072
},
"openrouter/mistralai/mistral-small-3.2-24b-instruct": {
"input_cost_per_token": 1e-07,
"litellm_provider": "openrouter",
"max_tokens": 32000,
"max_tokens": 128000,
"mode": "chat",
"output_cost_per_token": 3e-07,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 128000,
"max_output_tokens": 128000
},
"openrouter/mistralai/mixtral-8x22b-instruct": {
"input_cost_per_token": 6.5e-07,
@ -26696,7 +26732,9 @@
"max_tokens": 65536,
"mode": "chat",
"output_cost_per_token": 6.5e-07,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 65536,
"max_output_tokens": 65536
},
"openrouter/moonshotai/kimi-k2.5": {
"cache_read_input_token_cost": 1e-07,
@ -26716,26 +26754,32 @@
"openrouter/openai/gpt-3.5-turbo": {
"input_cost_per_token": 1.5e-06,
"litellm_provider": "openrouter",
"max_tokens": 4095,
"max_tokens": 4096,
"mode": "chat",
"output_cost_per_token": 2e-06,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 16385,
"max_output_tokens": 4096
},
"openrouter/openai/gpt-3.5-turbo-16k": {
"input_cost_per_token": 3e-06,
"litellm_provider": "openrouter",
"max_tokens": 16383,
"max_tokens": 4096,
"mode": "chat",
"output_cost_per_token": 4e-06,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 16385,
"max_output_tokens": 4096
},
"openrouter/openai/gpt-4": {
"input_cost_per_token": 3e-05,
"litellm_provider": "openrouter",
"max_tokens": 8192,
"max_tokens": 4096,
"mode": "chat",
"output_cost_per_token": 6e-05,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 8191,
"max_output_tokens": 4096
},
"openrouter/openai/gpt-4.1": {
"cache_read_input_token_cost": 5e-07,
@ -27243,10 +27287,12 @@
"openrouter/undi95/remm-slerp-l2-13b": {
"input_cost_per_token": 1.875e-06,
"litellm_provider": "openrouter",
"max_tokens": 6144,
"max_tokens": 4096,
"mode": "chat",
"output_cost_per_token": 1.875e-06,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 6144,
"max_output_tokens": 4096
},
"openrouter/x-ai/grok-4": {
"input_cost_per_token": 3e-06,
@ -29868,14 +29914,16 @@
"together_ai/deepseek-ai/DeepSeek-V3.1": {
"input_cost_per_token": 6e-07,
"litellm_provider": "together_ai",
"max_tokens": 128000,
"max_tokens": 16384,
"mode": "chat",
"output_cost_per_token": 1.7e-06,
"source": "https://www.together.ai/models/deepseek-v3-1",
"supports_function_calling": true,
"supports_parallel_function_calling": true,
"supports_reasoning": true,
"supports_tool_choice": true
"supports_tool_choice": true,
"max_input_tokens": 128000,
"max_output_tokens": 16384
},
"together_ai/meta-llama/Llama-3.2-3B-Instruct-Turbo": {
"litellm_provider": "together_ai",
@ -32552,6 +32600,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -34456,6 +34505,7 @@
"output_cost_per_token": 1.5e-05,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_response_schema": false,
"supports_tool_choice": true,
"supports_web_search": true
@ -34471,6 +34521,7 @@
"output_cost_per_token": 1.5e-05,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_response_schema": false,
"supports_tool_choice": true,
"supports_web_search": true
@ -34486,6 +34537,7 @@
"output_cost_per_token": 2.5e-05,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_response_schema": false,
"supports_tool_choice": true,
"supports_web_search": true
@ -34501,6 +34553,7 @@
"output_cost_per_token": 2.5e-05,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_response_schema": false,
"supports_tool_choice": true,
"supports_web_search": true
@ -34516,6 +34569,7 @@
"output_cost_per_token": 1.5e-05,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_response_schema": false,
"supports_tool_choice": true,
"supports_web_search": true
@ -34532,6 +34586,7 @@
"output_cost_per_token": 5e-07,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": true,
@ -34549,6 +34604,7 @@
"output_cost_per_token": 5e-07,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": true,
@ -34565,6 +34621,7 @@
"output_cost_per_token": 4e-06,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": true,
@ -34581,6 +34638,7 @@
"output_cost_per_token": 4e-06,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": true,
@ -34597,6 +34655,7 @@
"output_cost_per_token": 4e-06,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": true,
@ -34613,6 +34672,7 @@
"output_cost_per_token": 5e-07,
"source": "https://x.ai/api#pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": false,
"supports_tool_choice": true,
@ -34628,38 +34688,41 @@
"output_cost_per_token": 1.5e-05,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_tool_choice": true,
"supports_web_search": true
},
"xai/grok-4-fast-reasoning": {
"cache_read_input_token_cost": 5e-08,
"input_cost_per_token": 2e-07,
"input_cost_per_token_above_128k_tokens": 4e-07,
"litellm_provider": "xai",
"max_input_tokens": 2000000.0,
"max_output_tokens": 2000000.0,
"max_tokens": 2000000.0,
"mode": "chat",
"input_cost_per_token": 2e-07,
"input_cost_per_token_above_128k_tokens": 4e-07,
"output_cost_per_token": 5e-07,
"output_cost_per_token_above_128k_tokens": 1e-06,
"cache_read_input_token_cost": 5e-08,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_tool_choice": true,
"supports_web_search": true
},
"xai/grok-4-fast-non-reasoning": {
"cache_read_input_token_cost": 5e-08,
"input_cost_per_token": 2e-07,
"input_cost_per_token_above_128k_tokens": 4e-07,
"litellm_provider": "xai",
"max_input_tokens": 2000000.0,
"max_output_tokens": 2000000.0,
"cache_read_input_token_cost": 5e-08,
"max_tokens": 2000000.0,
"mode": "chat",
"input_cost_per_token": 2e-07,
"input_cost_per_token_above_128k_tokens": 4e-07,
"output_cost_per_token": 5e-07,
"output_cost_per_token_above_128k_tokens": 1e-06,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_tool_choice": true,
"supports_web_search": true
},
@ -34675,6 +34738,7 @@
"output_cost_per_token_above_128k_tokens": 3e-05,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_tool_choice": true,
"supports_web_search": true
},
@ -34690,6 +34754,7 @@
"output_cost_per_token_above_128k_tokens": 3e-05,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_tool_choice": true,
"supports_web_search": true
},
@ -34707,6 +34772,7 @@
"source": "https://docs.x.ai/docs/models/grok-4-1-fast-reasoning",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
@ -34727,6 +34793,7 @@
"source": "https://docs.x.ai/docs/models/grok-4-1-fast-reasoning",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
@ -34747,6 +34814,7 @@
"source": "https://docs.x.ai/docs/models/grok-4-1-fast-reasoning",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
@ -34767,6 +34835,7 @@
"source": "https://docs.x.ai/docs/models/grok-4-1-fast-non-reasoning",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": true,
@ -34786,6 +34855,7 @@
"source": "https://docs.x.ai/docs/models/grok-4-1-fast-non-reasoning",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_vision": true,
@ -34802,6 +34872,7 @@
"output_cost_per_token": 6e-06,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_tool_choice": true,
"supports_vision": true,
@ -34818,6 +34889,7 @@
"output_cost_per_token": 6e-06,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_tool_choice": true,
"supports_vision": true,
@ -34850,6 +34922,7 @@
"output_cost_per_token": 6e-06,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_tool_choice": true,
"supports_vision": true,
"supports_web_search": true
@ -34878,6 +34951,7 @@
"output_cost_per_token": 1.5e-06,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_tool_choice": true
},
@ -34892,6 +34966,7 @@
"output_cost_per_token": 1.5e-06,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_tool_choice": true
},
@ -34906,6 +34981,7 @@
"output_cost_per_token": 1.5e-06,
"source": "https://docs.x.ai/docs/models",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_tool_choice": true
},
@ -34937,6 +35013,20 @@
"supports_tool_choice": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"zai.glm-5": {
"input_cost_per_token": 1e-06,
"litellm_provider": "bedrock_converse",
"max_input_tokens": 200000,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"output_cost_per_token": 3.2e-06,
"supports_function_calling": true,
"supports_reasoning": true,
"supports_system_messages": true,
"supports_tool_choice": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"zai.glm-4.7-flash": {
"input_cost_per_token": 7e-08,
"litellm_provider": "bedrock_converse",
@ -39522,6 +39612,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -39746,6 +39837,87 @@
}
]
},
"zai.glm-5": {
"input_cost_per_token": 1e-06,
"output_cost_per_token": 3.2e-06,
"litellm_provider": "bedrock_converse",
"max_input_tokens": 200000,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_system_messages": true,
"supports_tool_choice": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"bedrock/us-east-1/zai.glm-5": {
"input_cost_per_token": 1e-06,
"output_cost_per_token": 3.2e-06,
"litellm_provider": "bedrock",
"max_input_tokens": 200000,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_system_messages": true,
"supports_tool_choice": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"bedrock/us-west-2/zai.glm-5": {
"input_cost_per_token": 1e-06,
"output_cost_per_token": 3.2e-06,
"litellm_provider": "bedrock",
"max_input_tokens": 200000,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_system_messages": true,
"supports_tool_choice": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"minimax.minimax-m2.5": {
"input_cost_per_token": 3e-07,
"output_cost_per_token": 1.2e-06,
"litellm_provider": "bedrock_converse",
"max_input_tokens": 1000000,
"max_output_tokens": 8192,
"max_tokens": 8192,
"mode": "chat",
"supports_function_calling": true,
"supports_system_messages": true,
"supports_tool_choice": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"bedrock/us-east-1/minimax.minimax-m2.5": {
"input_cost_per_token": 3e-07,
"output_cost_per_token": 1.2e-06,
"litellm_provider": "bedrock",
"max_input_tokens": 1000000,
"max_output_tokens": 8192,
"max_tokens": 8192,
"mode": "chat",
"supports_function_calling": true,
"supports_system_messages": true,
"supports_tool_choice": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"bedrock/us-west-2/minimax.minimax-m2.5": {
"input_cost_per_token": 3e-07,
"output_cost_per_token": 1.2e-06,
"litellm_provider": "bedrock",
"max_input_tokens": 1000000,
"max_output_tokens": 8192,
"max_tokens": 8192,
"mode": "chat",
"supports_function_calling": true,
"supports_system_messages": true,
"supports_tool_choice": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"bedrock/us-gov-east-1/anthropic.claude-haiku-4-5-20251001-v1:0": {
"cache_creation_input_token_cost": 1.5e-06,
"cache_read_input_token_cost": 1.2e-07,

View file

@ -1323,6 +1323,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -1352,6 +1353,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -1381,6 +1383,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -1409,6 +1412,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -1437,6 +1441,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -2055,6 +2060,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -9229,6 +9235,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -26101,6 +26108,7 @@
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 159,
@ -26141,6 +26149,7 @@
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -26206,6 +26215,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"supports_xhigh_reasoning_effort": true,
@ -32590,6 +32600,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,
@ -39601,6 +39612,7 @@
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_max_reasoning_effort": true,
"supports_tool_choice": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 346,

View file

@ -2078,13 +2078,17 @@ def test_get_config_does_not_leak_module_constants():
("claude-opus-4-7", "xhigh", True),
("claude-opus-4-6", "max", True),
("claude-opus-4-6", "xhigh", False),
("claude-sonnet-4-6", "max", False),
# ``max`` is documented as supported on Sonnet 4.6 (Claude 4.6 family).
# The model-map JSON now carries ``supports_max_reasoning_effort: true``
# for every Sonnet 4.6 entry; ``_supports_effort_level`` should report
# ``True`` on every route prefix (anthropic, bedrock, vertex, azure).
("claude-sonnet-4-6", "max", True),
("claude-sonnet-4-6", "xhigh", False),
("bedrock/invoke/us.anthropic.claude-opus-4-7", "max", True),
("bedrock/invoke/us.anthropic.claude-opus-4-7", "xhigh", True),
("bedrock/invoke/us.anthropic.claude-opus-4-6-v1", "max", True),
("bedrock/invoke/us.anthropic.claude-opus-4-6-v1", "xhigh", False),
("bedrock/invoke/us.anthropic.claude-sonnet-4-6", "max", False),
("bedrock/invoke/us.anthropic.claude-sonnet-4-6", "max", True),
("vertex_ai/claude-opus-4-7", "xhigh", True),
("azure_ai/claude-opus-4-7", "xhigh", True),
],
@ -2393,25 +2397,40 @@ def test_reasoning_effort_does_not_set_output_config_for_older_models():
), f"output_config should not be set for {model}"
def test_max_effort_rejected_for_sonnet_46():
"""Test that effort='max' is rejected for Sonnet 4.6 (Opus-only effort level).
@pytest.mark.parametrize(
"model",
[
"claude-sonnet-4-6",
"claude-sonnet-4-6-20260219",
"us.anthropic.claude-sonnet-4-6",
"bedrock/converse/us.anthropic.claude-sonnet-4-6",
"vertex_ai/claude-sonnet-4-6",
"openrouter/anthropic/claude-sonnet-4.6",
],
)
def test_max_effort_accepted_for_sonnet_46_variants(model):
"""``effort='max'`` is documented as supported on Claude 4.6 (Opus + Sonnet)
and Claude 4.7 (https://platform.claude.com/docs/en/build-with-claude/effort).
Surfaces as a clean 400 BadRequestError, not a 500 ValueError.
Earlier versions of this test asserted a 400 for Sonnet 4.6, mirroring an
Opus-only allow-list in ``_apply_output_config``. That gate has since been
widened to ``_is_claude_4_6_model`` (Opus + Sonnet) and the
``supports_max_reasoning_effort`` JSON flag, matching Anthropic's published
matrix. Verify the param actually flows through every Sonnet 4.6 id
variant our routing layer might see.
"""
config = AnthropicConfig()
messages = [{"role": "user", "content": "Test"}]
with pytest.raises(
litellm.exceptions.BadRequestError,
match="effort='max' is not supported by this model",
):
config.transform_request(
model="claude-sonnet-4-6-20260219",
messages=messages,
optional_params={"output_config": {"effort": "max"}},
litellm_params={},
headers={},
)
result = config.transform_request(
model=model,
messages=messages,
optional_params={"output_config": {"effort": "max"}},
litellm_params={},
headers={},
)
assert result["output_config"]["effort"] == "max"
def test_max_effort_accepted_for_opus_46():
@ -2510,24 +2529,37 @@ def test_reasoning_effort_garbage_raises_bad_request(effort):
@pytest.mark.parametrize(
"effort",
["xhigh", "max"],
"effort,expected_budget",
[("xhigh", 8192), ("max", 16384)],
)
def test_reasoning_effort_unsupported_tier_on_budget_model_raises_bad_request(
effort,
def test_reasoning_effort_xhigh_max_maps_to_budget_on_budget_model(
effort, expected_budget
):
"""``xhigh`` / ``max`` aren't defined for budget-mode (4.5) Claude models;
surface as a clean 400 instead of 500.
"""``xhigh`` / ``max`` extend the legacy ``thinking.budget_tokens``
progression (low=1024 / medium=2048 / high=4096 xhigh=8192 / max=16384)
on budget-mode Claude models (haiku / 4.5 series).
Adopted from #27051. Keeps the OpenAI-format ``reasoning_effort`` knob
usable across the full Claude lineup adaptive models (4.6/4.7) route
these tiers via ``output_config.effort``; budget-mode models use the
extended budget. Anthropic's "max only on Mythos / Opus 4.7 / Opus 4.6 /
Sonnet 4.6" gating applies to the *adaptive enum*, not to the legacy
``budget_tokens`` knob, which accepts any integer up to ``max_tokens``.
"""
config = AnthropicConfig()
with pytest.raises(litellm.exceptions.BadRequestError):
config.map_openai_params(
non_default_params={"reasoning_effort": effort},
optional_params={},
model="claude-sonnet-4-5-20250929",
drop_params=False,
)
result = config.map_openai_params(
non_default_params={"reasoning_effort": effort},
optional_params={},
model="claude-sonnet-4-5-20250929",
drop_params=False,
)
assert result["thinking"]["type"] == "enabled"
assert result["thinking"]["budget_tokens"] == expected_budget
# Budget-mode models must NOT carry an ``output_config`` payload — that
# path is exclusively for adaptive (4.6+) models.
assert "output_config" not in result
def test_output_config_effort_empty_string_raises_bad_request():

View file

@ -132,11 +132,11 @@ def test_invalid_reasoning_effort_raises_400(bad_effort):
@pytest.mark.parametrize(
"model,bad_effort",
[
# ``xhigh`` is Opus-4.7-only on the public Anthropic effort matrix,
# so Opus 4.6 / Sonnet 4.6 must still 400 on it.
("claude-opus-4-6", "xhigh"),
("bedrock/invoke/us.anthropic.claude-opus-4-6-v1", "xhigh"),
("claude-sonnet-4-6", "xhigh"),
("claude-sonnet-4-6", "max"),
("bedrock/invoke/us.anthropic.claude-sonnet-4-6", "max"),
],
)
def test_reasoning_effort_unsupported_tier_raises_400_messages(model, bad_effort):
@ -160,6 +160,32 @@ def test_reasoning_effort_unsupported_tier_raises_400_messages(model, bad_effort
assert "not supported by this model" in str(exc_info.value)
@pytest.mark.parametrize(
"model",
[
# ``max`` is documented as supported on Claude 4.6 (Opus + Sonnet)
# and Claude 4.7. Verify the /v1/messages route accepts it for
# Sonnet 4.6 variants instead of 400-ing client-side.
"claude-sonnet-4-6",
"bedrock/invoke/us.anthropic.claude-sonnet-4-6",
],
)
def test_reasoning_effort_max_accepted_on_sonnet_46_messages(model):
config = AnthropicMessagesConfig()
optional_params = {"max_tokens": 1024, "reasoning_effort": "max"}
result = config.transform_anthropic_messages_request(
model=model,
messages=[{"role": "user", "content": "Hello"}],
anthropic_messages_optional_request_params=optional_params,
litellm_params={},
headers={},
)
output_config = result.get("output_config")
assert isinstance(output_config, dict) and output_config.get("effort") == "max"
def test_explicit_output_config_wins_over_reasoning_effort():
"""
Explicit native ``output_config.effort`` is never overridden by the

View file

@ -395,24 +395,39 @@ def test_reasoning_effort_garbage_raises_bad_request_converse(effort):
)
def test_output_config_effort_unsupported_max_on_sonnet_46_raises_bad_request():
"""``effort='max'`` is Opus-only. On Sonnet 4.6 the explicit-output_config
path must surface a 400 (matching the chat-completion validation), not
silently forward an unsupported tier to Bedrock."""
@pytest.mark.parametrize(
"model",
[
"bedrock/converse/us.anthropic.claude-sonnet-4-6",
"bedrock/converse/global.anthropic.claude-sonnet-4-6",
"bedrock/converse/eu.anthropic.claude-sonnet-4-6",
"bedrock/converse/au.anthropic.claude-sonnet-4-6",
],
)
def test_output_config_effort_max_passes_through_on_sonnet_46_variants(model):
"""``effort='max'`` is supported on Claude 4.6 (Opus + Sonnet) per
https://platform.claude.com/docs/en/build-with-claude/effort. The earlier
Opus-only allow-list in ``_validate_anthropic_adaptive_effort`` has been
widened to ``_is_claude_4_6_model`` (Opus + Sonnet) plus the
``supports_max_reasoning_effort`` JSON flag. Verify the param actually
flows through to ``additionalModelRequestFields.output_config.effort``
for every Bedrock Converse Sonnet 4.6 id variant."""
config = AmazonConverseConfig()
messages = [{"role": "user", "content": "hi"}]
with pytest.raises(litellm.exceptions.BadRequestError):
config._transform_request(
model="bedrock/converse/us.anthropic.claude-sonnet-4-6",
messages=messages,
optional_params={
"maxTokens": 256,
"output_config": {"effort": "max"},
},
litellm_params={},
headers={},
)
result = config._transform_request(
model=model,
messages=messages,
optional_params={
"maxTokens": 256,
"output_config": {"effort": "max"},
},
litellm_params={},
headers={},
)
additional = result.get("additionalModelRequestFields", {})
assert additional.get("output_config") == {"effort": "max"}
def test_get_supported_openai_params():