diff --git a/litellm/llms/gemini/cost_calculator.py b/litellm/llms/gemini/cost_calculator.py index 45850e0d668..5de6eedfbe4 100644 --- a/litellm/llms/gemini/cost_calculator.py +++ b/litellm/llms/gemini/cost_calculator.py @@ -31,11 +31,17 @@ def cost_per_token( def cost_per_web_search_request(usage: "Usage", model_info: "ModelInfo") -> float: """ Calculates the cost per web search request for a given model, prompt tokens, and completion tokens. + + Uses ``search_context_cost_per_query`` from ``model_info`` when available + (keyed by ``search_context_size_medium`` as the default tier). Falls back + to the legacy $0.035 hardcode for models that haven't been updated yet. """ from litellm.types.utils import PromptTokensDetailsWrapper - # cost per web search request - cost_per_web_search_request = 35e-3 + # Resolve per-request cost from model_info, fallback to legacy default + _DEFAULT_COST = 35e-3 + search_costs = model_info.get("search_context_cost_per_query") or {} + _cost = search_costs.get("search_context_size_medium", _DEFAULT_COST) number_of_web_search_requests = 0 # Get number of web search requests @@ -47,10 +53,8 @@ def cost_per_web_search_request(usage: "Usage", model_info: "ModelInfo") -> floa and usage.prompt_tokens_details.web_search_requests is not None ): number_of_web_search_requests = usage.prompt_tokens_details.web_search_requests - else: - number_of_web_search_requests = 0 # Calculate total cost - total_cost = cost_per_web_search_request * number_of_web_search_requests + total_cost = _cost * number_of_web_search_requests return total_cost diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index c53ee943c58..31c1289b0b4 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -13963,7 +13963,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 8000000 + "tpm": 8000000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini-2.5-flash-lite-preview-06-17": { "deprecation_date": "2025-11-18", @@ -14552,7 +14557,12 @@ "supports_vision": true, "supports_web_search": true, "tpm": 250000, - "rpm": 10 + "rpm": 10, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini-2.5-computer-use-preview-10-2025": { "input_cost_per_token": 1.25e-06, @@ -14604,17 +14614,14 @@ "uses_embed_content": true }, "vertex_ai/gemini-embedding-2-preview": { - "input_cost_per_audio_per_second": 0.00016, - "input_cost_per_image": 0.00012, - "input_cost_per_token": 2e-07, - "input_cost_per_video_per_second": 0.00079, + "input_cost_per_token": 1.5e-07, "litellm_provider": "vertex_ai", "max_input_tokens": 8192, "max_tokens": 8192, "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 }, @@ -14631,18 +14638,6 @@ "source": "https://cloud.google.com/vertex-ai/generative-ai/pricing", "uses_embed_content": true }, - "vertex_ai/gemini-embedding-2-preview": { - "input_cost_per_token": 1.5e-07, - "litellm_provider": "vertex_ai", - "max_input_tokens": 8192, - "max_tokens": 8192, - "mode": "embedding", - "output_cost_per_token": 0, - "output_vector_size": 3072, - "source": "https://ai.google.dev/gemini-api/docs/embeddings#multimodal", - "supports_multimodal": true, - "uses_embed_content": true - }, "gemini/gemini-embedding-001": { "input_cost_per_token": 1.5e-07, "litellm_provider": "gemini", @@ -14725,7 +14720,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 10000000 + "tpm": 10000000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.0-flash-001": { "cache_read_input_token_cost": 2.5e-08, @@ -14764,7 +14764,12 @@ "supports_tool_choice": true, "supports_vision": true, "supports_web_search": true, - "tpm": 10000000 + "tpm": 10000000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.0-flash-lite": { "cache_read_input_token_cost": 1.875e-08, @@ -14801,7 +14806,12 @@ "supports_tool_choice": true, "supports_vision": true, "supports_web_search": true, - "tpm": 4000000 + "tpm": 4000000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.5-flash": { "cache_read_input_token_cost": 3e-08, @@ -14848,7 +14858,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 8000000 + "tpm": 8000000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.5-flash-image": { "cache_read_input_token_cost": 3e-08, @@ -14898,7 +14913,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 8000000 + "tpm": 8000000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-3-pro-image-preview": { "input_cost_per_image": 0.0011, @@ -14934,7 +14954,12 @@ "supports_response_schema": true, "supports_system_messages": true, "supports_vision": true, - "supports_web_search": true + "supports_web_search": true, + "search_context_cost_per_query": { + "search_context_size_low": 0.014, + "search_context_size_medium": 0.014, + "search_context_size_high": 0.014 + } }, "gemini/gemini-3.1-flash-image-preview": { "input_cost_per_token": 2.5e-07, @@ -14970,7 +14995,12 @@ "supports_response_schema": true, "supports_system_messages": true, "supports_vision": true, - "supports_web_search": true + "supports_web_search": true, + "search_context_cost_per_query": { + "search_context_size_low": 0.014, + "search_context_size_medium": 0.014, + "search_context_size_high": 0.014 + } }, "gemini/deep-research-pro-preview-12-2025": { "input_cost_per_image": 0.0011, @@ -15006,7 +15036,12 @@ "supports_response_schema": true, "supports_system_messages": true, "supports_vision": true, - "supports_web_search": true + "supports_web_search": true, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.5-flash-lite": { "cache_read_input_token_cost": 1e-08, @@ -15053,7 +15088,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 250000 + "tpm": 250000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.5-flash-lite-preview-09-2025": { "cache_read_input_token_cost": 1e-08, @@ -15100,7 +15140,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 250000 + "tpm": 250000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.5-flash-preview-09-2025": { "cache_read_input_token_cost": 7.5e-08, @@ -15147,7 +15192,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 250000 + "tpm": 250000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-flash-latest": { "cache_read_input_token_cost": 7.5e-08, @@ -15194,7 +15244,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 250000 + "tpm": 250000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-flash-lite-latest": { "cache_read_input_token_cost": 2.5e-08, @@ -15241,7 +15296,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 250000 + "tpm": 250000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.5-flash-lite-preview-06-17": { "deprecation_date": "2025-11-18", @@ -15289,7 +15349,12 @@ "supports_url_context": true, "supports_vision": true, "supports_web_search": true, - "tpm": 250000 + "tpm": 250000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.5-flash-preview-tts": { "input_cost_per_token": 3e-07, @@ -15352,7 +15417,12 @@ "supports_video_input": true, "supports_vision": true, "supports_web_search": true, - "tpm": 800000 + "tpm": 800000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-2.5-computer-use-preview-10-2025": { "input_cost_per_token": 1.25e-06, @@ -15440,7 +15510,12 @@ "output_cost_per_token_above_200k_tokens_priority": 3.24e-05, "cache_read_input_token_cost_priority": 3.6e-07, "cache_read_input_token_cost_above_200k_tokens_priority": 7.2e-07, - "supports_service_tier": true + "supports_service_tier": true, + "search_context_cost_per_query": { + "search_context_size_low": 0.014, + "search_context_size_medium": 0.014, + "search_context_size_high": 0.014 + } }, "gemini/gemini-3.1-flash-lite-preview": { "cache_read_input_token_cost": 2.5e-08, @@ -15493,7 +15568,12 @@ "supports_vision": true, "supports_web_search": true, "supports_native_streaming": true, - "tpm": 250000 + "tpm": 250000, + "search_context_cost_per_query": { + "search_context_size_low": 0.014, + "search_context_size_medium": 0.014, + "search_context_size_high": 0.014 + } }, "gemini/gemini-3-flash-preview": { "cache_read_input_token_cost": 5e-08, @@ -15546,7 +15626,12 @@ "input_cost_per_audio_token_priority": 1.8e-06, "output_cost_per_token_priority": 5.4e-06, "cache_read_input_token_cost_priority": 9e-08, - "supports_service_tier": true + "supports_service_tier": true, + "search_context_cost_per_query": { + "search_context_size_low": 0.014, + "search_context_size_medium": 0.014, + "search_context_size_high": 0.014 + } }, "gemini/gemini-3.1-pro-preview": { "cache_read_input_token_cost": 2e-07, @@ -15604,7 +15689,12 @@ "output_cost_per_token_above_200k_tokens_priority": 3.24e-05, "cache_read_input_token_cost_priority": 3.6e-07, "cache_read_input_token_cost_above_200k_tokens_priority": 7.2e-07, - "supports_service_tier": true + "supports_service_tier": true, + "search_context_cost_per_query": { + "search_context_size_low": 0.014, + "search_context_size_medium": 0.014, + "search_context_size_high": 0.014 + } }, "gemini/gemini-3.1-pro-preview-customtools": { "cache_read_input_token_cost": 2e-07, @@ -15662,7 +15752,12 @@ "output_cost_per_token_above_200k_tokens_priority": 3.24e-05, "cache_read_input_token_cost_priority": 3.6e-07, "cache_read_input_token_cost_above_200k_tokens_priority": 7.2e-07, - "supports_service_tier": true + "supports_service_tier": true, + "search_context_cost_per_query": { + "search_context_size_low": 0.014, + "search_context_size_medium": 0.014, + "search_context_size_high": 0.014 + } }, "gemini-3-flash-preview": { "cache_read_input_token_cost": 5e-08, @@ -15750,7 +15845,12 @@ "supports_tool_choice": true, "supports_vision": true, "supports_web_search": true, - "tpm": 10000000 + "tpm": 10000000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini/gemini-exp-1114": { "input_cost_per_token": 0, @@ -31147,7 +31247,9 @@ "mode": "chat", "output_cost_per_token": 3.2e-06, "source": "https://cloud.google.com/vertex-ai/generative-ai/pricing#glm-models", - "supported_regions": ["global"], + "supported_regions": [ + "global" + ], "supports_function_calling": true, "supports_prompt_caching": true, "supports_reasoning": true, @@ -36756,7 +36858,12 @@ "supports_tool_choice": true, "supports_vision": true, "supports_web_search": true, - "tpm": 4000000 + "tpm": 4000000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini-2.5-flash-native-audio-latest": { "input_cost_per_audio_token": 1e-06, @@ -37102,7 +37209,12 @@ "supports_video_input": true, "supports_vision": true, "supports_web_search": true, - "tpm": 800000 + "tpm": 800000, + "search_context_cost_per_query": { + "search_context_size_low": 0.035, + "search_context_size_medium": 0.035, + "search_context_size_high": 0.035 + } }, "gemini-exp-1206": { "cache_read_input_token_cost": 3e-08, diff --git a/tests/litellm/llms/gemini/__init__.py b/tests/litellm/llms/gemini/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/litellm/llms/gemini/test_cost_calculator.py b/tests/litellm/llms/gemini/test_cost_calculator.py new file mode 100644 index 00000000000..19a7a839688 --- /dev/null +++ b/tests/litellm/llms/gemini/test_cost_calculator.py @@ -0,0 +1,61 @@ +import os +import sys + +import pytest + +sys.path.insert(0, os.path.abspath("../../../..")) + +from litellm.llms.gemini.cost_calculator import cost_per_web_search_request +from litellm.types.utils import PromptTokensDetailsWrapper, Usage + + +def _make_usage(web_search_requests: int) -> Usage: + return Usage( + prompt_tokens=100, + completion_tokens=50, + total_tokens=150, + prompt_tokens_details=PromptTokensDetailsWrapper( + web_search_requests=web_search_requests, + ), + ) + + +def test_web_search_cost_from_model_info(): + """Cost should come from model_info when search_context_cost_per_query is set.""" + model_info = { + "key": "gemini/gemini-3-flash-preview", + "search_context_cost_per_query": { + "search_context_size_low": 0.014, + "search_context_size_medium": 0.014, + "search_context_size_high": 0.014, + }, + } + cost = cost_per_web_search_request(usage=_make_usage(3), model_info=model_info) + assert cost == pytest.approx(0.014 * 3) + + +def test_web_search_cost_legacy_fallback(): + """Without search_context_cost_per_query, should fallback to $0.035.""" + model_info = {"key": "gemini/gemini-2.0-flash"} + cost = cost_per_web_search_request(usage=_make_usage(2), model_info=model_info) + assert cost == pytest.approx(0.035 * 2) + + +def test_web_search_cost_zero_requests(): + """Zero web search requests should return zero cost.""" + model_info = { + "key": "gemini/gemini-3-flash-preview", + "search_context_cost_per_query": { + "search_context_size_medium": 0.014, + }, + } + cost = cost_per_web_search_request(usage=_make_usage(0), model_info=model_info) + assert cost == 0.0 + + +def test_web_search_cost_no_usage_details(): + """Missing prompt_tokens_details should return zero cost.""" + model_info = {"key": "gemini/gemini-3-flash-preview"} + usage = Usage(prompt_tokens=100, completion_tokens=50, total_tokens=150) + cost = cost_per_web_search_request(usage=usage, model_info=model_info) + assert cost == 0.0