Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions litellm/cost_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,12 @@ def cost_per_token(
)

return dashscope_cost_per_token(model=model, usage=usage_block)
elif custom_llm_provider == "volcengine":
from litellm.llms.volcengine.cost_calculator import (
cost_per_token as volcengine_cost_per_token,
)

return volcengine_cost_per_token(model=model, usage=usage_block)
elif custom_llm_provider == "azure_ai":
return azure_ai_cost_per_token(
model=model,
Expand Down
86 changes: 86 additions & 0 deletions litellm/llms/volcengine/cost_calculator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""
Cost calculator for Volcengine chat models.

Volcengine selects one pricing tier from the request's total input length and
charges every input/output token at that tier. This is not graduated pricing.
"""

from litellm.litellm_core_utils.llm_cost_calc.tiered_pricing import (
select_tier_for_input,
tier_rate,
)
from litellm.types.utils import ModelInfo, Usage
from litellm.utils import get_model_info


def _cached_prompt_tokens(usage: Usage) -> int:
prompt_details = usage.prompt_tokens_details
if prompt_details is None:
return 0
return int(getattr(prompt_details, "cached_tokens", 0) or 0)


def _select_pricing_tier(
tiered_pricing: list[dict] | None, # mutable-ok: shared tier helper accepts JSON-backed lists of dictionaries
prompt_tokens: int,
) -> dict | None: # mutable-ok: returns the JSON-backed tier selected by the shared helper
if not tiered_pricing:
return None

# Output-only synthetic usage blocks have no input length. Use the first
# tier instead of returning zero cost for their completion tokens.
return select_tier_for_input(
tiered_pricing=tiered_pricing,
input_tokens=max(prompt_tokens, 1),
)


def _output_rate(
tier: dict, # mutable-ok: tier_rate accepts a JSON-backed dictionary
completion_tokens: int,
) -> float:
"""Read the output rate, including Seed 1.8's short-output discount."""
if completion_tokens > 200 and tier.get("output_cost_per_token_above_200_tokens") is not None:
return tier_rate(tier, "output_cost_per_token_above_200_tokens")
return tier_rate(tier, "output_cost_per_token")


def cost_per_token(model: str, usage: Usage) -> tuple[float, float]:
"""
Return ``(prompt_cost_usd, completion_cost_usd)`` for a Volcengine request.

Tier selection is based on total prompt tokens. Cached prompt tokens still
count toward the tier boundary, but use the cache-read rate when one is
declared by the model.
"""
model_info: ModelInfo = get_model_info(
model=model,
custom_llm_provider="volcengine",
)

prompt_tokens = int(usage.prompt_tokens or 0)
completion_tokens = int(usage.completion_tokens or 0)
cached_tokens = min(_cached_prompt_tokens(usage), prompt_tokens)
uncached_tokens = prompt_tokens - cached_tokens

raw_tiered_pricing = model_info.get("tiered_pricing")
tiered_pricing = raw_tiered_pricing if isinstance(raw_tiered_pricing, list) else None
tier = _select_pricing_tier(
tiered_pricing=tiered_pricing,
prompt_tokens=prompt_tokens,
)

if tier is not None:
input_rate = tier_rate(tier, "input_cost_per_token")
output_rate = _output_rate(tier=tier, completion_tokens=completion_tokens)
cache_rate_value = model_info.get("cache_read_input_token_cost")
cache_rate = float(cache_rate_value) if cache_rate_value is not None else input_rate
else:
input_rate = float(model_info.get("input_cost_per_token") or 0.0)
output_rate = float(model_info.get("output_cost_per_token") or 0.0)
cache_rate_value = model_info.get("cache_read_input_token_cost")
cache_rate = float(cache_rate_value) if cache_rate_value is not None else input_rate

prompt_cost = (uncached_tokens * input_rate) + (cached_tokens * cache_rate)
completion_cost = completion_tokens * output_rate
return prompt_cost, completion_cost
41 changes: 41 additions & 0 deletions litellm/model_prices_and_context_window_backup.json
Original file line number Diff line number Diff line change
Expand Up @@ -45281,6 +45281,47 @@
"supports_vision": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"volcengine/doubao-seed-1-8-251228": {
"cache_read_input_token_cost": 2.2e-08,
"litellm_provider": "volcengine",
"max_input_tokens": 256000,
"max_output_tokens": 64000,
"max_tokens": 64000,
"mode": "chat",
"source": "https://www.volcengine.com/docs/82379/1330310",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_tool_choice": false,
"supports_vision": true,
"tiered_pricing": [
{
"input_cost_per_token": 1.1e-07,
"output_cost_per_token": 2.8e-07,
"output_cost_per_token_above_200_tokens": 1.1e-06,
"range": [
0,
32000.0
]
},
{
"input_cost_per_token": 1.7e-07,
"output_cost_per_token": 2.2e-06,
"range": [
32000.0,
128000.0
]
},
{
"input_cost_per_token": 3.3e-07,
"output_cost_per_token": 3.3e-06,
"range": [
128000.0,
256000.0
]
}
]
},
"volcengine/doubao-seed-2-0-pro-260215": {
"litellm_provider": "volcengine",
"max_input_tokens": 256000,
Expand Down
41 changes: 41 additions & 0 deletions model_prices_and_context_window.json
Original file line number Diff line number Diff line change
Expand Up @@ -45402,6 +45402,47 @@
"supports_vision": true,
"source": "https://aws.amazon.com/bedrock/pricing/"
},
"volcengine/doubao-seed-1-8-251228": {
"cache_read_input_token_cost": 2.2e-08,
"litellm_provider": "volcengine",
"max_input_tokens": 256000,
"max_output_tokens": 64000,
"max_tokens": 64000,
"mode": "chat",
"source": "https://www.volcengine.com/docs/82379/1330310",
"supports_function_calling": true,
"supports_prompt_caching": true,
"supports_reasoning": true,
"supports_tool_choice": false,
"supports_vision": true,
"tiered_pricing": [
{
"input_cost_per_token": 1.1e-07,
"output_cost_per_token": 2.8e-07,
"output_cost_per_token_above_200_tokens": 1.1e-06,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Low: Higher output rate bypasses the pre-call budget bound

An authenticated user can request more than 200 output tokens while near their budget limit because _max_cost_for_cost_info() only considers output_cost_per_token and output_cost_per_reasoning_token. For this tier it reserves at 2.8e-07, while post-call accounting charges the entire output at 1.1e-06; concurrent requests can therefore incur substantially more provider spend than the atomic budget gate permits. Update the budget reservation calculation to include this conditional rate when estimating maximum output cost.

"range": [
0,
32000.0
]
},
{
"input_cost_per_token": 1.7e-07,
"output_cost_per_token": 2.2e-06,
"range": [
32000.0,
128000.0
]
},
{
"input_cost_per_token": 3.3e-07,
"output_cost_per_token": 3.3e-06,
"range": [
128000.0,
256000.0
]
}
]
},
"volcengine/doubao-seed-2-0-pro-260215": {
"litellm_provider": "volcengine",
"max_input_tokens": 256000,
Expand Down
Loading
Loading