From 028481cd212a025c26625fb04dc4a429a2329453 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 19 Jun 2026 01:17:03 -0400 Subject: [PATCH 1/3] fix: apply 10% surcharge for bedrock cross-region inference profiles --- litellm/llms/bedrock/cost_calculation.py | 57 +++++++++++++++++++----- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/litellm/llms/bedrock/cost_calculation.py b/litellm/llms/bedrock/cost_calculation.py index ac99d4e36e7..829c9df411c 100644 --- a/litellm/llms/bedrock/cost_calculation.py +++ b/litellm/llms/bedrock/cost_calculation.py @@ -8,20 +8,53 @@ from typing import TYPE_CHECKING, Optional, Tuple from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_token if TYPE_CHECKING: - from litellm.types.utils import Usage + from litellm.types.utils import Usage + +# AWS charges a ~10% surcharge for cross-region inference profiles (us./eu./ap. prefixes) +_CROSS_REGION_INFERENCE_SURCHARGE = 1.1 + + +def _is_cross_region_inference_model(model: str) -> bool: + """Return True if *model* uses a Bedrock cross-region inference prefix. + + Cross-region inference profile IDs begin with a geographic abbreviation + followed by a dot, e.g. ``us.anthropic.claude-sonnet-4-6``. AWS bills + these at a ~10 % premium over the equivalent base-model price. + """ + from litellm.llms.bedrock.common_utils import ( + get_bedrock_cross_region_inference_regions, + ) + + stripped = model + for prefix in ("bedrock/", "converse/"): + if stripped.startswith(prefix): + stripped = stripped[len(prefix):] + break + + potential_region = stripped.split(".", 1)[0] + return potential_region in get_bedrock_cross_region_inference_regions() def cost_per_token( - model: str, usage: "Usage", service_tier: Optional[str] = None + model: str, usage: "Usage", service_tier: Optional[str] = None ) -> Tuple[float, float]: - """ - Calculates the cost per token for a given model, prompt tokens, and completion tokens. + """ + Calculates the cost per token for a given model, prompt tokens, and completion tokens. - Follows the same logic as Anthropic's cost per token calculation. - """ - return generic_cost_per_token( - model=model, - usage=usage, - custom_llm_provider="bedrock", - service_tier=service_tier, - ) + Follows the same logic as Anthropic's cost per token calculation. + + For cross-region inference profiles (us./eu./ap. prefixes), applies the AWS + 10 % surcharge on top of the base-model token prices. + """ + prompt_cost, completion_cost = generic_cost_per_token( + model=model, + usage=usage, + custom_llm_provider="bedrock", + service_tier=service_tier, + ) + + if _is_cross_region_inference_model(model): + prompt_cost *= _CROSS_REGION_INFERENCE_SURCHARGE + completion_cost *= _CROSS_REGION_INFERENCE_SURCHARGE + + return prompt_cost, completion_cost From 4a6ebaf183c91e4c470391e52c90f80d0a79639a Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 19 Jun 2026 23:56:25 -0400 Subject: [PATCH 2/3] style: fix Black formatting and indentation in cost_calculation.py --- litellm/llms/bedrock/cost_calculation.py | 54 ++++++++++++------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/litellm/llms/bedrock/cost_calculation.py b/litellm/llms/bedrock/cost_calculation.py index 829c9df411c..2705462b87c 100644 --- a/litellm/llms/bedrock/cost_calculation.py +++ b/litellm/llms/bedrock/cost_calculation.py @@ -8,53 +8,53 @@ from typing import TYPE_CHECKING, Optional, Tuple from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_token if TYPE_CHECKING: - from litellm.types.utils import Usage + from litellm.types.utils import Usage # AWS charges a ~10% surcharge for cross-region inference profiles (us./eu./ap. prefixes) _CROSS_REGION_INFERENCE_SURCHARGE = 1.1 def _is_cross_region_inference_model(model: str) -> bool: - """Return True if *model* uses a Bedrock cross-region inference prefix. + """Return True if *model* uses a Bedrock cross-region inference prefix. - Cross-region inference profile IDs begin with a geographic abbreviation - followed by a dot, e.g. ``us.anthropic.claude-sonnet-4-6``. AWS bills - these at a ~10 % premium over the equivalent base-model price. - """ - from litellm.llms.bedrock.common_utils import ( - get_bedrock_cross_region_inference_regions, + Cross-region inference profile IDs begin with a geographic abbreviation + followed by a dot, e.g. ``us.anthropic.claude-sonnet-4-6``. AWS bills + these at a ~10% premium over the equivalent base-model price. + """ + from litellm.llms.bedrock.common_utils import ( + get_bedrock_cross_region_inference_regions, ) stripped = model for prefix in ("bedrock/", "converse/"): - if stripped.startswith(prefix): - stripped = stripped[len(prefix):] - break + if stripped.startswith(prefix): + stripped = stripped[len(prefix) :] + break - potential_region = stripped.split(".", 1)[0] + potential_region = stripped.split(".", 1)[0] return potential_region in get_bedrock_cross_region_inference_regions() def cost_per_token( - model: str, usage: "Usage", service_tier: Optional[str] = None + model: str, usage: "Usage", service_tier: Optional[str] = None ) -> Tuple[float, float]: - """ - Calculates the cost per token for a given model, prompt tokens, and completion tokens. + """ + Calculates the cost per token for a given model, prompt tokens, and completion tokens. - Follows the same logic as Anthropic's cost per token calculation. + Follows the same logic as Anthropic's cost per token calculation. - For cross-region inference profiles (us./eu./ap. prefixes), applies the AWS - 10 % surcharge on top of the base-model token prices. - """ - prompt_cost, completion_cost = generic_cost_per_token( - model=model, - usage=usage, - custom_llm_provider="bedrock", - service_tier=service_tier, - ) + For cross-region inference profiles (us./eu./ap. prefixes), applies the AWS + 10% surcharge on top of the base-model token prices. + """ + prompt_cost, completion_cost = generic_cost_per_token( + model=model, + usage=usage, + custom_llm_provider="bedrock", + service_tier=service_tier, + ) if _is_cross_region_inference_model(model): - prompt_cost *= _CROSS_REGION_INFERENCE_SURCHARGE - completion_cost *= _CROSS_REGION_INFERENCE_SURCHARGE + prompt_cost *= _CROSS_REGION_INFERENCE_SURCHARGE + completion_cost *= _CROSS_REGION_INFERENCE_SURCHARGE return prompt_cost, completion_cost From a02a9eb5310374bbb9463da42c9c7e61d72b1cd9 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Sat, 20 Jun 2026 10:11:41 -0400 Subject: [PATCH 3/3] fix: replace double-count multiplier with routing-prefix stripping Refactor cost calculation logic to remove cross-region surcharge handling and strip Bedrock routing prefixes. --- litellm/llms/bedrock/cost_calculation.py | 50 ++++++++++-------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/litellm/llms/bedrock/cost_calculation.py b/litellm/llms/bedrock/cost_calculation.py index 2705462b87c..7c87a734d13 100644 --- a/litellm/llms/bedrock/cost_calculation.py +++ b/litellm/llms/bedrock/cost_calculation.py @@ -10,29 +10,24 @@ from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_toke if TYPE_CHECKING: from litellm.types.utils import Usage -# AWS charges a ~10% surcharge for cross-region inference profiles (us./eu./ap. prefixes) -_CROSS_REGION_INFERENCE_SURCHARGE = 1.1 +# Routing prefixes stripped before model-info lookup, ordered longest-first so +# that "bedrock/converse/" is matched before the shorter "bedrock/" prefix. +_BEDROCK_ROUTING_PREFIXES = ("bedrock/converse/", "bedrock/", "converse/") -def _is_cross_region_inference_model(model: str) -> bool: - """Return True if *model* uses a Bedrock cross-region inference prefix. +def _strip_bedrock_routing_prefix(model: str) -> str: + """Return *model* with any leading Bedrock routing prefix removed. - Cross-region inference profile IDs begin with a geographic abbreviation - followed by a dot, e.g. ``us.anthropic.claude-sonnet-4-6``. AWS bills - these at a ~10% premium over the equivalent base-model price. + litellm may pass model strings that still carry provider or converse routing + prefixes (e.g. ``bedrock/converse/us.anthropic.claude-sonnet-4-6``). + ``get_model_info`` looks up the canonical key without these prefixes, so + stripping them first ensures the correct price entry — including cross-region + keys such as ``us.*`` — is found and used. """ - from litellm.llms.bedrock.common_utils import ( - get_bedrock_cross_region_inference_regions, - ) - - stripped = model - for prefix in ("bedrock/", "converse/"): - if stripped.startswith(prefix): - stripped = stripped[len(prefix) :] - break - - potential_region = stripped.split(".", 1)[0] - return potential_region in get_bedrock_cross_region_inference_regions() + for prefix in _BEDROCK_ROUTING_PREFIXES: + if model.startswith(prefix): + return model[len(prefix):] + return model def cost_per_token( @@ -43,18 +38,15 @@ def cost_per_token( Follows the same logic as Anthropic's cost per token calculation. - For cross-region inference profiles (us./eu./ap. prefixes), applies the AWS - 10% surcharge on top of the base-model token prices. + Cross-region inference model prices (``us.*``, ``eu.*``, ``ap.*``) are + already encoded in ``model_prices_and_context_window.json`` with the correct + surcharge applied — no additional multiplier is needed here. The prefix + stripping ensures that callers using ``bedrock/converse/us.*`` style strings + still resolve to the correct cross-region price entry. """ - prompt_cost, completion_cost = generic_cost_per_token( - model=model, + return generic_cost_per_token( + model=_strip_bedrock_routing_prefix(model), usage=usage, custom_llm_provider="bedrock", service_tier=service_tier, ) - - if _is_cross_region_inference_model(model): - prompt_cost *= _CROSS_REGION_INFERENCE_SURCHARGE - completion_cost *= _CROSS_REGION_INFERENCE_SURCHARGE - - return prompt_cost, completion_cost