refactor(gemini): use web_search_billing_unit field instead of hardcoded model name check
Replace _is_gemini_3_model() substring check with a web_search_billing_unit field in model_prices JSON: - "per_query": each search query billed individually (Gemini 3.x) - "per_prompt" (default): flat fee per grounded API call (Gemini 2.x) Add web_search_billing_unit to 23 Gemini 3.x model entries. Update docs and tests accordingly.
This commit is contained in:
parent
a0d1d22bcf
commit
e82d3f6d2e
@ -613,11 +613,15 @@ LiteLLM tracks web search costs automatically based on provider-specific billing
|
||||
|
||||
### Pricing configuration
|
||||
|
||||
Web search costs are defined in `model_prices_and_context_window.json` using the `search_context_cost_per_query` field:
|
||||
Web search costs are defined in `model_prices_and_context_window.json` using two fields:
|
||||
|
||||
- **`search_context_cost_per_query`**: the cost per billable unit (per search context size tier).
|
||||
- **`web_search_billing_unit`**: `"per_query"` (each search query is billed individually) or `"per_prompt"` (default — flat fee per API call that uses search).
|
||||
|
||||
```json
|
||||
{
|
||||
"gemini/gemini-3-flash-preview": {
|
||||
"web_search_billing_unit": "per_query",
|
||||
"search_context_cost_per_query": {
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
@ -634,7 +638,11 @@ Web search costs are defined in `model_prices_and_context_window.json` using the
|
||||
}
|
||||
```
|
||||
|
||||
You can override these costs in your proxy config using `model_info`:
|
||||
:::info
|
||||
Models without `web_search_billing_unit` default to `"per_prompt"` — one flat charge per API call that uses web search, regardless of how many internal queries the model executes.
|
||||
:::
|
||||
|
||||
You can override these in your proxy config using `model_info`:
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
@ -642,6 +650,7 @@ model_list:
|
||||
litellm_params:
|
||||
model: gemini/gemini-3-flash-preview
|
||||
model_info:
|
||||
web_search_billing_unit: per_query
|
||||
search_context_cost_per_query:
|
||||
search_context_size_low: 0.014
|
||||
search_context_size_medium: 0.014
|
||||
|
||||
@ -28,19 +28,13 @@ def cost_per_token(
|
||||
)
|
||||
|
||||
|
||||
def _is_gemini_3_model(model_info: "ModelInfo") -> bool:
|
||||
"""Check if the model is a Gemini 3.x variant based on its key."""
|
||||
key = model_info.get("key", "")
|
||||
return "gemini-3" in key
|
||||
|
||||
|
||||
def cost_per_web_search_request(usage: "Usage", model_info: "ModelInfo") -> float:
|
||||
"""
|
||||
Calculates the cost of web search (grounding with Google Search).
|
||||
|
||||
Billing differs by model family:
|
||||
- Gemini 3.x: charged per individual search query ($0.014 default).
|
||||
- Gemini 2.x and older: charged per grounded prompt ($0.035 default),
|
||||
Billing mode is determined by ``web_search_billing_unit`` in model_info:
|
||||
- ``"per_query"``: charged per individual search query (Gemini 3.x).
|
||||
- ``"per_prompt"`` (default): charged per grounded prompt (Gemini 2.x),
|
||||
regardless of how many queries were executed internally.
|
||||
|
||||
Reads the per-request cost from ``search_context_cost_per_query`` in
|
||||
@ -63,8 +57,9 @@ def cost_per_web_search_request(usage: "Usage", model_info: "ModelInfo") -> floa
|
||||
):
|
||||
number_of_web_search_requests = usage.prompt_tokens_details.web_search_requests
|
||||
|
||||
# Gemini 2.x charges per grounded prompt (flat 1), not per query
|
||||
if number_of_web_search_requests > 0 and not _is_gemini_3_model(model_info):
|
||||
# per_prompt billing: clamp to 1 (flat fee per grounded API call)
|
||||
billing_mode = model_info.get("web_search_billing_unit", "per_prompt")
|
||||
if number_of_web_search_requests > 0 and billing_mode == "per_prompt":
|
||||
number_of_web_search_requests = 1
|
||||
|
||||
return _cost * number_of_web_search_requests
|
||||
|
||||
@ -13651,7 +13651,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3.1-flash-image-preview": {
|
||||
"input_cost_per_image": 0.00056,
|
||||
@ -13688,7 +13689,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3.1-flash-lite-preview": {
|
||||
"cache_read_input_token_cost": 2.5e-08,
|
||||
@ -13744,7 +13746,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"deep-research-pro-preview-12-2025": {
|
||||
"input_cost_per_image": 0.0011,
|
||||
@ -14191,7 +14194,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3.1-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14254,7 +14258,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3.1-pro-preview-customtools": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14310,7 +14315,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/gemini-3-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14371,7 +14377,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/gemini-3-flash-preview": {
|
||||
"cache_read_input_token_cost": 5e-08,
|
||||
@ -14425,7 +14432,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/gemini-3.1-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14488,7 +14496,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/gemini-3.1-pro-preview-customtools": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14551,7 +14560,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-2.5-pro-preview-tts": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
@ -15069,7 +15079,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3.1-flash-image-preview": {
|
||||
"input_cost_per_token": 2.5e-07,
|
||||
@ -15110,7 +15121,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/deep-research-pro-preview-12-2025": {
|
||||
"input_cost_per_image": 0.0011,
|
||||
@ -15625,7 +15637,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3.1-flash-lite-preview": {
|
||||
"cache_read_input_token_cost": 2.5e-08,
|
||||
@ -15683,7 +15696,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3-flash-preview": {
|
||||
"cache_read_input_token_cost": 5e-08,
|
||||
@ -15741,7 +15755,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3.1-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -15804,7 +15819,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3.1-pro-preview-customtools": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -15867,7 +15883,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3-flash-preview": {
|
||||
"cache_read_input_token_cost": 5e-08,
|
||||
@ -15923,7 +15940,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-2.5-pro-preview-tts": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
@ -24692,7 +24710,8 @@
|
||||
"supports_tool_choice": true,
|
||||
"supports_video_input": true,
|
||||
"supports_vision": true,
|
||||
"supports_web_search": true
|
||||
"supports_web_search": true,
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"openrouter/google/gemini-3-flash-preview": {
|
||||
"cache_read_input_token_cost": 5e-08,
|
||||
@ -24739,7 +24758,8 @@
|
||||
"supports_url_context": true,
|
||||
"supports_vision": true,
|
||||
"supports_web_search": true,
|
||||
"tpm": 800000
|
||||
"tpm": 800000,
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"openrouter/google/gemini-3.1-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -26286,14 +26306,16 @@
|
||||
"mode": "responses",
|
||||
"supports_web_search": true,
|
||||
"supports_reasoning": false,
|
||||
"supports_function_calling": true
|
||||
"supports_function_calling": true,
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"perplexity/google/gemini-3-flash-preview": {
|
||||
"litellm_provider": "perplexity",
|
||||
"mode": "responses",
|
||||
"supports_web_search": true,
|
||||
"supports_reasoning": false,
|
||||
"supports_function_calling": true
|
||||
"supports_function_calling": true,
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"perplexity/google/gemini-2.5-pro": {
|
||||
"litellm_provider": "perplexity",
|
||||
@ -31029,7 +31051,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/deep-research-pro-preview-12-2025": {
|
||||
"input_cost_per_image": 0.0011,
|
||||
|
||||
@ -13651,7 +13651,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3.1-flash-image-preview": {
|
||||
"input_cost_per_image": 0.00056,
|
||||
@ -13688,7 +13689,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3.1-flash-lite-preview": {
|
||||
"cache_read_input_token_cost": 2.5e-08,
|
||||
@ -13744,7 +13746,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"deep-research-pro-preview-12-2025": {
|
||||
"input_cost_per_image": 0.0011,
|
||||
@ -14191,7 +14194,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3.1-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14254,7 +14258,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3.1-pro-preview-customtools": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14310,7 +14315,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/gemini-3-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14371,7 +14377,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/gemini-3-flash-preview": {
|
||||
"cache_read_input_token_cost": 5e-08,
|
||||
@ -14425,7 +14432,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/gemini-3.1-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14488,7 +14496,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/gemini-3.1-pro-preview-customtools": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -14551,7 +14560,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-2.5-pro-preview-tts": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
@ -15069,7 +15079,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3.1-flash-image-preview": {
|
||||
"input_cost_per_token": 2.5e-07,
|
||||
@ -15110,7 +15121,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/deep-research-pro-preview-12-2025": {
|
||||
"input_cost_per_image": 0.0011,
|
||||
@ -15625,7 +15637,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3.1-flash-lite-preview": {
|
||||
"cache_read_input_token_cost": 2.5e-08,
|
||||
@ -15683,7 +15696,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3-flash-preview": {
|
||||
"cache_read_input_token_cost": 5e-08,
|
||||
@ -15741,7 +15755,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3.1-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -15804,7 +15819,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-3.1-pro-preview-customtools": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -15867,7 +15883,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini-3-flash-preview": {
|
||||
"cache_read_input_token_cost": 5e-08,
|
||||
@ -15923,7 +15940,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"gemini/gemini-2.5-pro-preview-tts": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
@ -24692,7 +24710,8 @@
|
||||
"supports_tool_choice": true,
|
||||
"supports_video_input": true,
|
||||
"supports_vision": true,
|
||||
"supports_web_search": true
|
||||
"supports_web_search": true,
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"openrouter/google/gemini-3-flash-preview": {
|
||||
"cache_read_input_token_cost": 5e-08,
|
||||
@ -24739,7 +24758,8 @@
|
||||
"supports_url_context": true,
|
||||
"supports_vision": true,
|
||||
"supports_web_search": true,
|
||||
"tpm": 800000
|
||||
"tpm": 800000,
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"openrouter/google/gemini-3.1-pro-preview": {
|
||||
"cache_read_input_token_cost": 2e-07,
|
||||
@ -26286,14 +26306,16 @@
|
||||
"mode": "responses",
|
||||
"supports_web_search": true,
|
||||
"supports_reasoning": false,
|
||||
"supports_function_calling": true
|
||||
"supports_function_calling": true,
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"perplexity/google/gemini-3-flash-preview": {
|
||||
"litellm_provider": "perplexity",
|
||||
"mode": "responses",
|
||||
"supports_web_search": true,
|
||||
"supports_reasoning": false,
|
||||
"supports_function_calling": true
|
||||
"supports_function_calling": true,
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"perplexity/google/gemini-2.5-pro": {
|
||||
"litellm_provider": "perplexity",
|
||||
@ -31029,7 +31051,8 @@
|
||||
"search_context_size_low": 0.014,
|
||||
"search_context_size_medium": 0.014,
|
||||
"search_context_size_high": 0.014
|
||||
}
|
||||
},
|
||||
"web_search_billing_unit": "per_query"
|
||||
},
|
||||
"vertex_ai/deep-research-pro-preview-12-2025": {
|
||||
"input_cost_per_image": 0.0011,
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from litellm.llms.gemini.cost_calculator import (
|
||||
_is_gemini_3_model,
|
||||
cost_per_web_search_request,
|
||||
)
|
||||
from litellm.llms.gemini.cost_calculator import cost_per_web_search_request
|
||||
from litellm.types.utils import PromptTokensDetailsWrapper, Usage
|
||||
|
||||
|
||||
@ -18,22 +15,21 @@ def _make_usage(web_search_requests: int) -> Usage:
|
||||
)
|
||||
|
||||
|
||||
def test_gemini3_charged_per_query():
|
||||
"""Gemini 3.x should charge per search query at $0.014."""
|
||||
def test_per_query_billing():
|
||||
"""web_search_billing_unit=per_query charges per search query."""
|
||||
model_info = {
|
||||
"key": "gemini/gemini-3-flash-preview",
|
||||
"web_search_billing_unit": "per_query",
|
||||
"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_gemini2_charged_per_prompt():
|
||||
"""Gemini 2.x should charge 1 grounded prompt regardless of query count."""
|
||||
def test_per_prompt_billing():
|
||||
"""web_search_billing_unit=per_prompt (default) clamps to 1."""
|
||||
model_info = {
|
||||
"key": "gemini/gemini-2.5-flash",
|
||||
"search_context_cost_per_query": {
|
||||
@ -44,8 +40,8 @@ def test_gemini2_charged_per_prompt():
|
||||
assert cost == pytest.approx(0.035 * 1)
|
||||
|
||||
|
||||
def test_legacy_fallback():
|
||||
"""Without search_context_cost_per_query, should fallback to $0.035 × 1."""
|
||||
def test_default_billing_unit_is_per_prompt():
|
||||
"""Without web_search_billing_unit, defaults to per_prompt (clamp to 1)."""
|
||||
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 * 1)
|
||||
@ -53,7 +49,10 @@ def test_legacy_fallback():
|
||||
|
||||
def test_zero_requests():
|
||||
"""Zero web search requests should return zero cost."""
|
||||
model_info = {"key": "gemini/gemini-3-flash-preview"}
|
||||
model_info = {
|
||||
"key": "gemini/gemini-3-flash-preview",
|
||||
"web_search_billing_unit": "per_query",
|
||||
}
|
||||
cost = cost_per_web_search_request(usage=_make_usage(0), model_info=model_info)
|
||||
assert cost == 0.0
|
||||
|
||||
@ -64,10 +63,3 @@ def test_no_usage_details():
|
||||
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
|
||||
|
||||
|
||||
def test_is_gemini_3_model():
|
||||
assert _is_gemini_3_model({"key": "gemini/gemini-3-flash-preview"})
|
||||
assert _is_gemini_3_model({"key": "gemini/gemini-3.1-pro-preview"})
|
||||
assert not _is_gemini_3_model({"key": "gemini/gemini-2.5-flash"})
|
||||
assert not _is_gemini_3_model({"key": "gemini/gemini-2.0-flash"})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user