diff --git a/lib/crewai/src/crewai/llms/providers/bedrock/completion.py b/lib/crewai/src/crewai/llms/providers/bedrock/completion.py index d10fc2ba8f..c8655bc7af 100644 --- a/lib/crewai/src/crewai/llms/providers/bedrock/completion.py +++ b/lib/crewai/src/crewai/llms/providers/bedrock/completion.py @@ -2090,6 +2090,20 @@ def supports_stop_words(self) -> bool: """Check if the model supports stop words.""" return True + @staticmethod + def _strip_inference_profile_prefix(model_id: str) -> str: + """Strip geographic cross-region inference profile prefixes. + + AWS Bedrock inference profile ids look like + ``us.anthropic.claude-sonnet-4-...`` / ``eu.`` / ``apac.`` / ``us-gov.``. + Context-window tables are keyed on the bare foundation-model id. + """ + model_id = model_id.removeprefix("bedrock/") + for geo in ("us-gov.", "apac.", "us.", "eu.", "jp.", "au.", "ca."): + if model_id.startswith(geo): + return model_id[len(geo) :] + return model_id + def get_context_window_size(self) -> int: """Get the context window size for the model.""" from crewai.llm import CONTEXT_WINDOW_USAGE_RATIO @@ -2114,8 +2128,12 @@ def get_context_window_size(self) -> int: "deepseek.r1": 32768, } - for model_prefix, size in context_windows.items(): - if self.model.startswith(model_prefix): + model_id = self._strip_inference_profile_prefix(self.model) + # Longest prefix first so claude-3-5-sonnet wins over claude-3 + for model_prefix, size in sorted( + context_windows.items(), key=lambda item: len(item[0]), reverse=True + ): + if model_id.startswith(model_prefix): return int(size * CONTEXT_WINDOW_USAGE_RATIO) return int(8192 * CONTEXT_WINDOW_USAGE_RATIO) diff --git a/lib/crewai/tests/llms/bedrock/test_bedrock.py b/lib/crewai/tests/llms/bedrock/test_bedrock.py index d48334d310..1770e2a8b0 100644 --- a/lib/crewai/tests/llms/bedrock/test_bedrock.py +++ b/lib/crewai/tests/llms/bedrock/test_bedrock.py @@ -530,6 +530,21 @@ def test_bedrock_context_window_size(): assert context_size_titan > 5000 +def test_bedrock_cross_region_inference_profile_context_window(): + """Cross-region inference profile ids (us./eu./apac./us-gov.) must map to the bare model window.""" + from crewai.llm import CONTEXT_WINDOW_USAGE_RATIO + + expected = int(200000 * CONTEXT_WINDOW_USAGE_RATIO) + for model in ( + "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", + "bedrock/eu.anthropic.claude-sonnet-4-20250514-v1:0", + "bedrock/apac.anthropic.claude-3-5-sonnet-20241022-v2:0", + "us.anthropic.claude-sonnet-4-20250514-v1:0", + ): + llm = LLM(model=model) + assert llm.get_context_window_size() == expected, model + + def test_bedrock_message_formatting(): """ Test that messages are properly formatted for Bedrock Converse API