Merge pull request #41754 from BerriAI/litellm_qwen3_8_omni_flash

feat(models): add qwen3.8 flash rows, fix Cohere embed v3 context, Bedrock Mantle and OpenRouter pricing
This commit is contained in:
kerry-berri 2026-09-18 13:49:35 -07:00 committed by GitHub
commit 6fa34a299b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 270 additions and 71 deletions

View file

@ -16690,6 +16690,46 @@
"supports_tool_choice": true,
"supports_vision": true
},
"dashscope/qwen3.8-flash": {
"cache_creation_input_token_cost": 2e-07,
"cache_read_input_token_cost": 1.6e-08,
"input_cost_per_token": 1.5e-07,
"litellm_provider": "dashscope",
"max_input_tokens": 991808,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 4.7e-07,
"source": "https://docs.modelstudio.console.alibabacloud.com/en/model-studio/model-pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_video_input": true,
"supports_vision": true,
"supports_web_search": true
},
"dashscope/qwen3.8-omni-flash": {
"cache_read_input_token_cost": 1.6e-08,
"input_cost_per_token": 1.5e-07,
"litellm_provider": "dashscope",
"max_input_tokens": 991808,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 4.7e-07,
"source": "https://docs.modelstudio.console.alibabacloud.com/en/model-studio/model-pricing",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_video_input": true,
"supports_vision": true,
"supports_web_search": true
},
"dashscope/qwq-plus": {
"input_cost_per_token": 8e-07,
"litellm_provider": "dashscope",
@ -18594,6 +18634,46 @@
"supports_tool_choice": true,
"supports_vision": true
},
"qwen_ai_platform/qwen3.8-flash": {
"cache_creation_input_token_cost": 2e-07,
"cache_read_input_token_cost": 1.6e-08,
"input_cost_per_token": 1.5e-07,
"litellm_provider": "qwen_ai_platform",
"max_input_tokens": 991808,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 4.7e-07,
"source": "https://docs.modelstudio.console.alibabacloud.com/en/model-studio/model-pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_video_input": true,
"supports_vision": true,
"supports_web_search": true
},
"qwen_ai_platform/qwen3.8-omni-flash": {
"cache_read_input_token_cost": 1.6e-08,
"input_cost_per_token": 1.5e-07,
"litellm_provider": "qwen_ai_platform",
"max_input_tokens": 991808,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 4.7e-07,
"source": "https://docs.modelstudio.console.alibabacloud.com/en/model-studio/model-pricing",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_video_input": true,
"supports_vision": true,
"supports_web_search": true
},
"qwen_ai_platform/qwq-plus": {
"input_cost_per_token": 8e-07,
"litellm_provider": "qwen_ai_platform",
@ -22090,8 +22170,8 @@
"embed-english-light-v3.0": {
"input_cost_per_token": 1e-07,
"litellm_provider": "cohere",
"max_input_tokens": 1024,
"max_tokens": 1024,
"max_input_tokens": 512,
"max_tokens": 512,
"mode": "embedding",
"output_cost_per_token": 0.0
},
@ -22108,8 +22188,8 @@
"input_cost_per_image": 0.0001,
"input_cost_per_token": 1e-07,
"litellm_provider": "cohere",
"max_input_tokens": 1024,
"max_tokens": 1024,
"max_input_tokens": 512,
"max_tokens": 512,
"metadata": {
"notes": "'supports_image_input' is a deprecated field. Use 'supports_embedding_image_input' instead."
},
@ -22130,8 +22210,8 @@
"embed-multilingual-v3.0": {
"input_cost_per_token": 1e-07,
"litellm_provider": "cohere",
"max_input_tokens": 1024,
"max_tokens": 1024,
"max_input_tokens": 512,
"max_tokens": 512,
"mode": "embedding",
"output_cost_per_token": 0.0,
"supports_embedding_image_input": true
@ -22139,8 +22219,8 @@
"embed-multilingual-light-v3.0": {
"input_cost_per_token": 0.0001,
"litellm_provider": "cohere",
"max_input_tokens": 1024,
"max_tokens": 1024,
"max_input_tokens": 512,
"max_tokens": 512,
"mode": "embedding",
"output_cost_per_token": 0.0,
"supports_embedding_image_input": true
@ -57910,14 +57990,14 @@
"supports_tool_choice": true
},
"bedrock_mantle/openai.gpt-5.6-sol": {
"input_cost_per_token": 5.5e-06,
"input_cost_per_token_above_272k_tokens": 1.1e-05,
"cache_creation_input_token_cost": 6.875e-06,
"cache_creation_input_token_cost_above_272k_tokens": 1.375e-05,
"cache_read_input_token_cost": 5.5e-07,
"cache_read_input_token_cost_above_272k_tokens": 1.1e-06,
"output_cost_per_token": 3.3e-05,
"output_cost_per_token_above_272k_tokens": 4.95e-05,
"input_cost_per_token": 4.4e-06,
"input_cost_per_token_above_272k_tokens": 8.8e-06,
"cache_creation_input_token_cost": 5.5e-06,
"cache_creation_input_token_cost_above_272k_tokens": 1.1e-05,
"cache_read_input_token_cost": 4.4e-07,
"cache_read_input_token_cost_above_272k_tokens": 8.8e-07,
"output_cost_per_token": 2.2e-05,
"output_cost_per_token_above_272k_tokens": 3.3e-05,
"search_context_cost_per_query": {
"search_context_size_high": 0.012,
"search_context_size_low": 0.012,
@ -65816,9 +65896,9 @@
"supports_web_search": false
},
"openrouter/z-ai/glm-5.3": {
"input_cost_per_token": 1.4e-06,
"output_cost_per_token": 4.4e-06,
"cache_read_input_token_cost": 2.6e-07,
"input_cost_per_token": 9.1e-07,
"output_cost_per_token": 2.86e-06,
"cache_read_input_token_cost": 1.69e-07,
"litellm_provider": "openrouter",
"max_input_tokens": 1310720,
"max_output_tokens": 943717,
@ -70539,14 +70619,14 @@
"supports_web_search": false
},
"openrouter/~deepseek/deepseek-flash-latest": {
"cache_read_input_token_cost": 1.5e-08,
"input_cost_per_token": 1.5e-07,
"cache_read_input_token_cost": 4.2e-09,
"input_cost_per_token": 1.4e-07,
"litellm_provider": "openrouter",
"max_input_tokens": 1048576,
"max_output_tokens": 393216,
"max_tokens": 393216,
"mode": "chat",
"output_cost_per_token": 6e-07,
"output_cost_per_token": 4.2e-07,
"source": "https://openrouter.ai/api/v1/models",
"supports_audio_input": false,
"supports_function_calling": true,
@ -70831,14 +70911,14 @@
"supports_web_search": false
},
"openrouter/~z-ai/glm-latest": {
"cache_read_input_token_cost": 1.5e-07,
"cache_read_input_token_cost": 1.46625e-07,
"input_cost_per_token": 9e-07,
"litellm_provider": "openrouter",
"max_input_tokens": 1310720,
"max_output_tokens": 235929,
"max_tokens": 235929,
"mode": "chat",
"output_cost_per_token": 3e-06,
"output_cost_per_token": 2.805e-06,
"source": "https://openrouter.ai/api/v1/models",
"supports_audio_input": false,
"supports_function_calling": true,
@ -73982,14 +74062,14 @@
"supports_web_search": false
},
"openrouter/tencent/hy3": {
"cache_read_input_token_cost": 3.3e-08,
"input_cost_per_token": 1.32e-07,
"cache_read_input_token_cost": 2.0625e-08,
"input_cost_per_token": 8.25e-08,
"litellm_provider": "openrouter",
"max_input_tokens": 262144,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"output_cost_per_token": 5.28e-07,
"output_cost_per_token": 3.3e-07,
"source": "https://openrouter.ai/api/v1/models",
"supports_audio_input": false,
"supports_function_calling": true,

View file

@ -16690,6 +16690,46 @@
"supports_tool_choice": true,
"supports_vision": true
},
"dashscope/qwen3.8-flash": {
"cache_creation_input_token_cost": 2e-07,
"cache_read_input_token_cost": 1.6e-08,
"input_cost_per_token": 1.5e-07,
"litellm_provider": "dashscope",
"max_input_tokens": 991808,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 4.7e-07,
"source": "https://docs.modelstudio.console.alibabacloud.com/en/model-studio/model-pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_video_input": true,
"supports_vision": true,
"supports_web_search": true
},
"dashscope/qwen3.8-omni-flash": {
"cache_read_input_token_cost": 1.6e-08,
"input_cost_per_token": 1.5e-07,
"litellm_provider": "dashscope",
"max_input_tokens": 991808,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 4.7e-07,
"source": "https://docs.modelstudio.console.alibabacloud.com/en/model-studio/model-pricing",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_video_input": true,
"supports_vision": true,
"supports_web_search": true
},
"dashscope/qwq-plus": {
"input_cost_per_token": 8e-07,
"litellm_provider": "dashscope",
@ -18594,6 +18634,46 @@
"supports_tool_choice": true,
"supports_vision": true
},
"qwen_ai_platform/qwen3.8-flash": {
"cache_creation_input_token_cost": 2e-07,
"cache_read_input_token_cost": 1.6e-08,
"input_cost_per_token": 1.5e-07,
"litellm_provider": "qwen_ai_platform",
"max_input_tokens": 991808,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 4.7e-07,
"source": "https://docs.modelstudio.console.alibabacloud.com/en/model-studio/model-pricing",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_video_input": true,
"supports_vision": true,
"supports_web_search": true
},
"qwen_ai_platform/qwen3.8-omni-flash": {
"cache_read_input_token_cost": 1.6e-08,
"input_cost_per_token": 1.5e-07,
"litellm_provider": "qwen_ai_platform",
"max_input_tokens": 991808,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 4.7e-07,
"source": "https://docs.modelstudio.console.alibabacloud.com/en/model-studio/model-pricing",
"supports_audio_input": true,
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"supports_video_input": true,
"supports_vision": true,
"supports_web_search": true
},
"qwen_ai_platform/qwq-plus": {
"input_cost_per_token": 8e-07,
"litellm_provider": "qwen_ai_platform",
@ -22090,8 +22170,8 @@
"embed-english-light-v3.0": {
"input_cost_per_token": 1e-07,
"litellm_provider": "cohere",
"max_input_tokens": 1024,
"max_tokens": 1024,
"max_input_tokens": 512,
"max_tokens": 512,
"mode": "embedding",
"output_cost_per_token": 0.0
},
@ -22108,8 +22188,8 @@
"input_cost_per_image": 0.0001,
"input_cost_per_token": 1e-07,
"litellm_provider": "cohere",
"max_input_tokens": 1024,
"max_tokens": 1024,
"max_input_tokens": 512,
"max_tokens": 512,
"metadata": {
"notes": "'supports_image_input' is a deprecated field. Use 'supports_embedding_image_input' instead."
},
@ -22130,8 +22210,8 @@
"embed-multilingual-v3.0": {
"input_cost_per_token": 1e-07,
"litellm_provider": "cohere",
"max_input_tokens": 1024,
"max_tokens": 1024,
"max_input_tokens": 512,
"max_tokens": 512,
"mode": "embedding",
"output_cost_per_token": 0.0,
"supports_embedding_image_input": true
@ -22139,8 +22219,8 @@
"embed-multilingual-light-v3.0": {
"input_cost_per_token": 0.0001,
"litellm_provider": "cohere",
"max_input_tokens": 1024,
"max_tokens": 1024,
"max_input_tokens": 512,
"max_tokens": 512,
"mode": "embedding",
"output_cost_per_token": 0.0,
"supports_embedding_image_input": true
@ -57910,14 +57990,14 @@
"supports_tool_choice": true
},
"bedrock_mantle/openai.gpt-5.6-sol": {
"input_cost_per_token": 5.5e-06,
"input_cost_per_token_above_272k_tokens": 1.1e-05,
"cache_creation_input_token_cost": 6.875e-06,
"cache_creation_input_token_cost_above_272k_tokens": 1.375e-05,
"cache_read_input_token_cost": 5.5e-07,
"cache_read_input_token_cost_above_272k_tokens": 1.1e-06,
"output_cost_per_token": 3.3e-05,
"output_cost_per_token_above_272k_tokens": 4.95e-05,
"input_cost_per_token": 4.4e-06,
"input_cost_per_token_above_272k_tokens": 8.8e-06,
"cache_creation_input_token_cost": 5.5e-06,
"cache_creation_input_token_cost_above_272k_tokens": 1.1e-05,
"cache_read_input_token_cost": 4.4e-07,
"cache_read_input_token_cost_above_272k_tokens": 8.8e-07,
"output_cost_per_token": 2.2e-05,
"output_cost_per_token_above_272k_tokens": 3.3e-05,
"search_context_cost_per_query": {
"search_context_size_high": 0.012,
"search_context_size_low": 0.012,
@ -65816,9 +65896,9 @@
"supports_web_search": false
},
"openrouter/z-ai/glm-5.3": {
"input_cost_per_token": 1.4e-06,
"output_cost_per_token": 4.4e-06,
"cache_read_input_token_cost": 2.6e-07,
"input_cost_per_token": 9.1e-07,
"output_cost_per_token": 2.86e-06,
"cache_read_input_token_cost": 1.69e-07,
"litellm_provider": "openrouter",
"max_input_tokens": 1310720,
"max_output_tokens": 943717,
@ -70539,14 +70619,14 @@
"supports_web_search": false
},
"openrouter/~deepseek/deepseek-flash-latest": {
"cache_read_input_token_cost": 1.5e-08,
"input_cost_per_token": 1.5e-07,
"cache_read_input_token_cost": 4.2e-09,
"input_cost_per_token": 1.4e-07,
"litellm_provider": "openrouter",
"max_input_tokens": 1048576,
"max_output_tokens": 393216,
"max_tokens": 393216,
"mode": "chat",
"output_cost_per_token": 6e-07,
"output_cost_per_token": 4.2e-07,
"source": "https://openrouter.ai/api/v1/models",
"supports_audio_input": false,
"supports_function_calling": true,
@ -70831,14 +70911,14 @@
"supports_web_search": false
},
"openrouter/~z-ai/glm-latest": {
"cache_read_input_token_cost": 1.5e-07,
"cache_read_input_token_cost": 1.46625e-07,
"input_cost_per_token": 9e-07,
"litellm_provider": "openrouter",
"max_input_tokens": 1310720,
"max_output_tokens": 235929,
"max_tokens": 235929,
"mode": "chat",
"output_cost_per_token": 3e-06,
"output_cost_per_token": 2.805e-06,
"source": "https://openrouter.ai/api/v1/models",
"supports_audio_input": false,
"supports_function_calling": true,
@ -73982,14 +74062,14 @@
"supports_web_search": false
},
"openrouter/tencent/hy3": {
"cache_read_input_token_cost": 3.3e-08,
"input_cost_per_token": 1.32e-07,
"cache_read_input_token_cost": 2.0625e-08,
"input_cost_per_token": 8.25e-08,
"litellm_provider": "openrouter",
"max_input_tokens": 262144,
"max_output_tokens": 128000,
"max_tokens": 128000,
"mode": "chat",
"output_cost_per_token": 5.28e-07,
"output_cost_per_token": 3.3e-07,
"source": "https://openrouter.ai/api/v1/models",
"supports_audio_input": false,
"supports_function_calling": true,

View file

@ -1839,6 +1839,27 @@ class TestBedrockMantleResponsesSigV4:
class TestBedrockMantleResponsesPricing:
@pytest.mark.parametrize(
"model",
["openai.gpt-5.6-sol", "openai.gpt-5.6-terra", "openai.gpt-5.6-luna"],
)
def test_mantle_matches_in_region_converse_pricing(self, local_cost_map, model):
"""bedrock-mantle serves these models In-Region only, and the AWS model
cards price In-Region and Geo CRIS identically -- so every cost field on
the mantle key must equal the `us.` converse key. A price change applied
to one namespace but not the other shows up here.
"""
mantle = litellm.model_cost[f"bedrock_mantle/{model}"]
converse = litellm.model_cost[f"us.{model}"]
cost_fields = [k for k in converse if "cost" in k and k != "search_context_cost_per_query"]
assert cost_fields, "expected cost fields on the converse entry"
for field in cost_fields:
assert mantle.get(field) == pytest.approx(converse[field]), (
f"{model}: {field} is {mantle.get(field)} on bedrock_mantle "
f"but {converse[field]} on us. (bedrock_converse)"
)
def test_models_registered(self, local_cost_map):
assert "bedrock_mantle/openai.gpt-5.5" in litellm.bedrock_mantle_models
assert "bedrock_mantle/openai.gpt-5.4" in litellm.bedrock_mantle_models

View file

@ -7591,25 +7591,35 @@ async def test_deleting_the_stored_pass_through_row_takes_the_route_out_of_servi
deleted. The proxy's own registry of live pass-through routes is what decides whether
a request is routed upstream or falls through to the auth error, so it has to lose the
entry on the reload rather than at the next process restart."""
from litellm.proxy.pass_through_endpoints.pass_through_endpoints import InitPassThroughEndpointHelpers
from litellm.proxy.proxy_server import ProxyConfig
from litellm.proxy.pass_through_endpoints.pass_through_endpoints import (
InitPassThroughEndpointHelpers,
_registered_pass_through_routes,
)
from litellm.proxy.proxy_server import ProxyConfig, app
path: Final = f"/v1/deleted-{uuid.uuid4().hex[:8]}"
db_endpoint: Final = {"id": "db-1", "path": path, "target": "https://example.com/post"}
prior_routes: Final = list(app.routes)
prior_registry: Final = dict(_registered_pass_through_routes)
def live_routes() -> set[str]:
return {route for route in InitPassThroughEndpointHelpers.get_all_registered_pass_through_routes() if path in route}
settings: Final = patch("litellm.proxy.proxy_server.general_settings", {}) # test-quality-ok: the method reads this module global; no injection seam
yaml_endpoints: Final = patch("litellm.proxy.proxy_server.config_passthrough_endpoints", None) # test-quality-ok: module global holding the YAML endpoints; this case has none
with settings, yaml_endpoints:
pc = ProxyConfig()
await pc._update_general_settings(db_general_settings={"pass_through_endpoints": [db_endpoint]})
assert live_routes(), "the stored endpoint should be serving before the row is deleted"
try:
with settings, yaml_endpoints:
pc = ProxyConfig()
await pc._update_general_settings(db_general_settings={"pass_through_endpoints": [db_endpoint]})
assert live_routes(), "the stored endpoint should be serving before the row is deleted"
await pc._update_general_settings(db_general_settings={})
await pc._update_general_settings(db_general_settings={})
assert live_routes() == set()
assert live_routes() == set()
finally:
app.routes[:] = prior_routes
_registered_pass_through_routes.clear()
_registered_pass_through_routes.update(prior_registry)
@pytest.mark.asyncio
@ -7619,15 +7629,18 @@ async def test_a_stored_pass_through_row_never_disturbs_the_config_declared_rout
serving untouched. The stored entry never gets a route of its own."""
from litellm.proxy.pass_through_endpoints.pass_through_endpoints import (
InitPassThroughEndpointHelpers,
_registered_pass_through_routes,
initialize_pass_through_endpoints,
)
from litellm.proxy.proxy_server import ProxyConfig
from litellm.proxy.proxy_server import ProxyConfig, app
marker: Final = uuid.uuid4().hex[:8]
config_path: Final = f"/v1/kept-{marker}"
db_path: Final = f"/v1/ignored-{marker}"
config_endpoint: Final = {"id": f"cfg-{marker}", "path": config_path, "target": "https://example.com/post"}
db_endpoint: Final = {"id": f"db-{marker}", "path": db_path, "target": "https://example.com/post"}
prior_routes: Final = list(app.routes)
prior_registry: Final = dict(_registered_pass_through_routes)
def live_paths() -> set[str]:
registered: Final = InitPassThroughEndpointHelpers.get_all_registered_pass_through_routes()
@ -7635,17 +7648,22 @@ async def test_a_stored_pass_through_row_never_disturbs_the_config_declared_rout
settings: Final = patch("litellm.proxy.proxy_server.general_settings", {"pass_through_endpoints": [config_endpoint]}) # test-quality-ok: the method reads this module global; no injection seam
yaml_endpoints: Final = patch("litellm.proxy.proxy_server.config_passthrough_endpoints", [config_endpoint]) # test-quality-ok: module global holding the YAML endpoints the reload merges in
with settings, yaml_endpoints:
await initialize_pass_through_endpoints(pass_through_endpoints=[config_endpoint])
assert live_paths() == {config_path}
try:
with settings, yaml_endpoints:
await initialize_pass_through_endpoints(pass_through_endpoints=[config_endpoint])
assert live_paths() == {config_path}
pc = ProxyConfig()
await pc._update_general_settings(db_general_settings={"pass_through_endpoints": [db_endpoint]})
assert live_paths() == {config_path}
pc = ProxyConfig()
await pc._update_general_settings(db_general_settings={"pass_through_endpoints": [db_endpoint]})
assert live_paths() == {config_path}
await pc._update_general_settings(db_general_settings={})
await pc._update_general_settings(db_general_settings={})
assert live_paths() == {config_path}
assert live_paths() == {config_path}
finally:
app.routes[:] = prior_routes
_registered_pass_through_routes.clear()
_registered_pass_through_routes.update(prior_registry)
def _fill_user_api_key_cache(cache: DualCache, count: int) -> None: