diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 3f7f5194514..a50edb0c9e3 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -16085,6 +16085,28 @@ "input_cost_per_image_token": 4.7e-07, "source": "https://cohere.com/pricing" }, + "cohere/embed-v5.0-pro": { + "input_cost_per_token": 1.2e-07, + "litellm_provider": "cohere", + "max_input_tokens": 128000, + "max_tokens": 128000, + "mode": "embedding", + "output_cost_per_token": 0.0, + "output_vector_size": 2048, + "supports_embedding_image_input": true, + "source": "https://cohere.com/pricing" + }, + "cohere/embed-v5.0-fast": { + "input_cost_per_token": 8e-08, + "litellm_provider": "cohere", + "max_input_tokens": 128000, + "max_tokens": 128000, + "mode": "embedding", + "output_cost_per_token": 0.0, + "output_vector_size": 2048, + "supports_embedding_image_input": true, + "source": "https://cohere.com/pricing" + }, "cohere/parse-v5.0": { "litellm_provider": "cohere", "mode": "ocr", @@ -61056,6 +61078,9 @@ "input_cost_per_audio_token": 2e-06, "input_cost_per_token": 2e-06, "litellm_provider": "gemini", + "max_input_tokens": 98304, + "max_output_tokens": 32768, + "max_tokens": 32768, "mode": "audio_transcription", "output_cost_per_token": 1.2e-05, "source": "https://ai.google.dev/gemini-api/docs/pricing", @@ -61078,6 +61103,9 @@ "input_cost_per_audio_token": 3.5e-06, "input_cost_per_token": 3.5e-06, "litellm_provider": "gemini", + "max_input_tokens": 131072, + "max_output_tokens": 65536, + "max_tokens": 65536, "mode": "audio_transcription", "output_cost_per_token": 2.1e-05, "source": "https://ai.google.dev/gemini-api/docs/pricing", @@ -64092,6 +64120,23 @@ "video" ] }, + "xai/grok-imagine-video-1.5-lite": { + "input_cost_per_image": 0.01, + "litellm_provider": "xai", + "mode": "video_generation", + "output_cost_per_second": 0.02, + "output_cost_per_second_1080p": 0.14, + "output_cost_per_second_480p": 0.02, + "output_cost_per_second_720p": 0.03, + "source": "https://docs.x.ai/developers/pricing", + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "video" + ] + }, "xai/grok-imagine-video-1.5-2026-05-30": { "input_cost_per_image": 0.01, "litellm_provider": "xai", @@ -75511,6 +75556,42 @@ "supports_vision": true, "supports_web_search": true }, + "openrouter/openai/gpt-image-2": { + "input_cost_per_image_token": 8e-06, + "input_cost_per_token": 5e-06, + "litellm_provider": "openrouter", + "mode": "image_generation", + "output_cost_per_image_token": 3e-05, + "source": "https://openrouter.ai/api/v1/images/models/openai/gpt-image-2/endpoints", + "supported_endpoints": [ + "/v1/images/generations" + ], + "supports_vision": true + }, + "openrouter/openai/gpt-image-2.5-flare": { + "input_cost_per_image_token": 8e-06, + "input_cost_per_token": 5e-06, + "litellm_provider": "openrouter", + "mode": "image_generation", + "output_cost_per_image_token": 3e-05, + "source": "https://openrouter.ai/api/v1/images/models/openai/gpt-image-2.5-flare/endpoints", + "supported_endpoints": [ + "/v1/images/generations" + ], + "supports_vision": true + }, + "openrouter/openai/gpt-image-2.5-sunburst": { + "input_cost_per_image_token": 8e-06, + "input_cost_per_token": 5e-06, + "litellm_provider": "openrouter", + "mode": "image_generation", + "output_cost_per_image_token": 3e-05, + "source": "https://openrouter.ai/api/v1/images/models/openai/gpt-image-2.5-sunburst/endpoints", + "supported_endpoints": [ + "/v1/images/generations" + ], + "supports_vision": true + }, "openrouter/openai/gpt-5.4-mini:batch": { "cache_read_input_token_cost": 3.75e-08, "input_cost_per_token": 3.75e-07, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 3f7f5194514..a50edb0c9e3 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -16085,6 +16085,28 @@ "input_cost_per_image_token": 4.7e-07, "source": "https://cohere.com/pricing" }, + "cohere/embed-v5.0-pro": { + "input_cost_per_token": 1.2e-07, + "litellm_provider": "cohere", + "max_input_tokens": 128000, + "max_tokens": 128000, + "mode": "embedding", + "output_cost_per_token": 0.0, + "output_vector_size": 2048, + "supports_embedding_image_input": true, + "source": "https://cohere.com/pricing" + }, + "cohere/embed-v5.0-fast": { + "input_cost_per_token": 8e-08, + "litellm_provider": "cohere", + "max_input_tokens": 128000, + "max_tokens": 128000, + "mode": "embedding", + "output_cost_per_token": 0.0, + "output_vector_size": 2048, + "supports_embedding_image_input": true, + "source": "https://cohere.com/pricing" + }, "cohere/parse-v5.0": { "litellm_provider": "cohere", "mode": "ocr", @@ -61056,6 +61078,9 @@ "input_cost_per_audio_token": 2e-06, "input_cost_per_token": 2e-06, "litellm_provider": "gemini", + "max_input_tokens": 98304, + "max_output_tokens": 32768, + "max_tokens": 32768, "mode": "audio_transcription", "output_cost_per_token": 1.2e-05, "source": "https://ai.google.dev/gemini-api/docs/pricing", @@ -61078,6 +61103,9 @@ "input_cost_per_audio_token": 3.5e-06, "input_cost_per_token": 3.5e-06, "litellm_provider": "gemini", + "max_input_tokens": 131072, + "max_output_tokens": 65536, + "max_tokens": 65536, "mode": "audio_transcription", "output_cost_per_token": 2.1e-05, "source": "https://ai.google.dev/gemini-api/docs/pricing", @@ -64092,6 +64120,23 @@ "video" ] }, + "xai/grok-imagine-video-1.5-lite": { + "input_cost_per_image": 0.01, + "litellm_provider": "xai", + "mode": "video_generation", + "output_cost_per_second": 0.02, + "output_cost_per_second_1080p": 0.14, + "output_cost_per_second_480p": 0.02, + "output_cost_per_second_720p": 0.03, + "source": "https://docs.x.ai/developers/pricing", + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "video" + ] + }, "xai/grok-imagine-video-1.5-2026-05-30": { "input_cost_per_image": 0.01, "litellm_provider": "xai", @@ -75511,6 +75556,42 @@ "supports_vision": true, "supports_web_search": true }, + "openrouter/openai/gpt-image-2": { + "input_cost_per_image_token": 8e-06, + "input_cost_per_token": 5e-06, + "litellm_provider": "openrouter", + "mode": "image_generation", + "output_cost_per_image_token": 3e-05, + "source": "https://openrouter.ai/api/v1/images/models/openai/gpt-image-2/endpoints", + "supported_endpoints": [ + "/v1/images/generations" + ], + "supports_vision": true + }, + "openrouter/openai/gpt-image-2.5-flare": { + "input_cost_per_image_token": 8e-06, + "input_cost_per_token": 5e-06, + "litellm_provider": "openrouter", + "mode": "image_generation", + "output_cost_per_image_token": 3e-05, + "source": "https://openrouter.ai/api/v1/images/models/openai/gpt-image-2.5-flare/endpoints", + "supported_endpoints": [ + "/v1/images/generations" + ], + "supports_vision": true + }, + "openrouter/openai/gpt-image-2.5-sunburst": { + "input_cost_per_image_token": 8e-06, + "input_cost_per_token": 5e-06, + "litellm_provider": "openrouter", + "mode": "image_generation", + "output_cost_per_image_token": 3e-05, + "source": "https://openrouter.ai/api/v1/images/models/openai/gpt-image-2.5-sunburst/endpoints", + "supported_endpoints": [ + "/v1/images/generations" + ], + "supports_vision": true + }, "openrouter/openai/gpt-5.4-mini:batch": { "cache_read_input_token_cost": 3.75e-08, "input_cost_per_token": 3.75e-07, diff --git a/tests/unit/test_openrouter_gpt_image_model_metadata.py b/tests/unit/test_openrouter_gpt_image_model_metadata.py new file mode 100644 index 00000000000..ee6015a1917 --- /dev/null +++ b/tests/unit/test_openrouter_gpt_image_model_metadata.py @@ -0,0 +1,43 @@ +from pathlib import Path +from typing import Final + +import pytest +from pydantic import TypeAdapter + +from litellm import get_model_info +from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + +REPO_ROOT: Final = Path(__file__).parents[2] +COST_MAP_ADAPTER: Final = TypeAdapter(dict[str, dict[str, object]]) +MODELS: Final = ( + "openrouter/openai/gpt-image-2", + "openrouter/openai/gpt-image-2.5-flare", + "openrouter/openai/gpt-image-2.5-sunburst", +) +PRICE_FIELDS: Final = ("input_cost_per_token", "input_cost_per_image_token", "output_cost_per_image_token") + + +def _cost_map(path: Path) -> dict[str, dict[str, object]]: + return COST_MAP_ADAPTER.validate_json(path.read_bytes()) + + +MAIN_COST_MAP: Final = _cost_map(REPO_ROOT / "model_prices_and_context_window.json") +BACKUP_COST_MAP: Final = _cost_map(REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json") + + +@pytest.mark.parametrize("model", MODELS) +def test_openrouter_gpt_image_row_is_identical_in_main_and_backup(model: str) -> None: + assert model in MAIN_COST_MAP, f"{model} is missing from model_prices_and_context_window.json" + assert BACKUP_COST_MAP.get(model) == MAIN_COST_MAP[model] + + +@pytest.mark.usefixtures("local_model_cost_map") +@pytest.mark.parametrize("model", MODELS) +def test_openrouter_gpt_image_model_info_comes_from_the_openrouter_row(model: str) -> None: + routed_model, provider, _, _ = get_llm_provider(model=model) + assert (routed_model, provider) == (model.removeprefix("openrouter/"), "openrouter") + + info = get_model_info(model=routed_model, custom_llm_provider=provider) + row = MAIN_COST_MAP[model] + assert (info["key"], info["litellm_provider"], info["mode"]) == (model, "openrouter", "image_generation") + assert {field: info[field] for field in PRICE_FIELDS} == {field: row[field] for field in PRICE_FIELDS}