mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-03 22:19:27 +00:00
Fix #5893: Relax model naming prefix filtering for custom-deployed models
- Update _matches_provider_pattern for anthropic to use 'in' (contains) check instead of strict startswith for 'claude' keyword, and accept any model starting with 'anthropic' regardless of separator character - Add pattern-matching fallback to _infer_provider_from_model so custom model names without provider prefix are correctly routed - Update _is_anthropic_model to also detect 'anthropic.' substring - Update ANTHROPIC_PREFIXES constant for consistency - Add regression tests for all affected methods Co-Authored-By: João <joao@crewai.com>
This commit is contained in:
@@ -111,7 +111,7 @@ if LITELLM_AVAILABLE:
|
||||
|
||||
MIN_CONTEXT: Final[int] = 1024
|
||||
MAX_CONTEXT: Final[int] = 2097152 # Current max from gemini-1.5-pro
|
||||
ANTHROPIC_PREFIXES: Final[tuple[str, str, str]] = ("anthropic/", "claude-", "claude/")
|
||||
ANTHROPIC_PREFIXES: Final[tuple[str, ...]] = ("anthropic/", "anthropic.", "claude-", "claude/")
|
||||
|
||||
LLM_CONTEXT_WINDOW_SIZES: Final[dict[str, int]] = {
|
||||
# openai
|
||||
@@ -465,8 +465,9 @@ class LLM(BaseLLM):
|
||||
)
|
||||
|
||||
if provider == "anthropic" or provider == "claude":
|
||||
return any(
|
||||
model_lower.startswith(prefix) for prefix in ["claude-", "anthropic."]
|
||||
return (
|
||||
"claude" in model_lower
|
||||
or model_lower.startswith("anthropic")
|
||||
)
|
||||
|
||||
if provider == "gemini" or provider == "google":
|
||||
@@ -574,6 +575,19 @@ class LLM(BaseLLM):
|
||||
if model in AZURE_MODELS:
|
||||
return "azure"
|
||||
|
||||
# Fallback to pattern matching for models not in constants
|
||||
provider_order = [
|
||||
"bedrock",
|
||||
"openai",
|
||||
"anthropic",
|
||||
"gemini",
|
||||
"deepseek",
|
||||
"dashscope",
|
||||
]
|
||||
for provider in provider_order:
|
||||
if cls._matches_provider_pattern(model, provider):
|
||||
return provider
|
||||
|
||||
return "openai"
|
||||
|
||||
@classmethod
|
||||
@@ -653,8 +667,8 @@ class LLM(BaseLLM):
|
||||
Returns:
|
||||
bool: True if the model is from Anthropic, False otherwise.
|
||||
"""
|
||||
anthropic_prefixes = ("anthropic/", "claude-", "claude/")
|
||||
return any(prefix in model.lower() for prefix in anthropic_prefixes)
|
||||
anthropic_indicators = ("anthropic/", "anthropic.", "claude-", "claude/")
|
||||
return any(indicator in model.lower() for indicator in anthropic_indicators)
|
||||
|
||||
def _prepare_completion_params(
|
||||
self,
|
||||
|
||||
@@ -996,6 +996,81 @@ def test_validate_model_in_constants():
|
||||
is True
|
||||
)
|
||||
|
||||
|
||||
def test_matches_provider_pattern_custom_anthropic_names():
|
||||
"""Test that _matches_provider_pattern handles custom-deployed Anthropic model names.
|
||||
|
||||
Regression test for https://github.com/crewAIInc/crewAI/issues/5893
|
||||
Users with custom-deployed models (e.g. 'anthropic--claude-...') were filtered
|
||||
out because pattern matching only supported ["claude-", "anthropic."] prefixes.
|
||||
"""
|
||||
# Standard patterns still work
|
||||
assert LLM._matches_provider_pattern("claude-3-5-sonnet", "anthropic") is True
|
||||
assert LLM._matches_provider_pattern("anthropic.claude-v2", "anthropic") is True
|
||||
|
||||
# Custom-deployed model names with non-standard separators (issue #5893)
|
||||
assert LLM._matches_provider_pattern("anthropic--claude-3-5-sonnet", "anthropic") is True
|
||||
assert LLM._matches_provider_pattern("anthropic--claude-opus-4", "anthropic") is True
|
||||
|
||||
# Models containing "claude" anywhere in the name
|
||||
assert LLM._matches_provider_pattern("my-claude-model", "anthropic") is True
|
||||
assert LLM._matches_provider_pattern("custom-claude-3-haiku", "anthropic") is True
|
||||
|
||||
# Models starting with "anthropic" regardless of separator
|
||||
assert LLM._matches_provider_pattern("anthropic_custom_model", "anthropic") is True
|
||||
assert LLM._matches_provider_pattern("anthropic-custom", "anthropic") is True
|
||||
|
||||
# Unrelated models should not match
|
||||
assert LLM._matches_provider_pattern("gpt-4o", "anthropic") is False
|
||||
assert LLM._matches_provider_pattern("gemini-2.0-flash", "anthropic") is False
|
||||
assert LLM._matches_provider_pattern("llama-3-70b", "anthropic") is False
|
||||
|
||||
|
||||
def test_validate_model_in_constants_custom_anthropic_names():
|
||||
"""Test that _validate_model_in_constants accepts custom Anthropic model names.
|
||||
|
||||
Regression test for https://github.com/crewAIInc/crewAI/issues/5893
|
||||
"""
|
||||
# Custom naming conventions should be accepted via pattern matching fallback
|
||||
assert LLM._validate_model_in_constants("anthropic--claude-3-5-sonnet", "anthropic") is True
|
||||
assert LLM._validate_model_in_constants("anthropic--claude-3-5-sonnet", "claude") is True
|
||||
assert LLM._validate_model_in_constants("custom-claude-model", "anthropic") is True
|
||||
|
||||
|
||||
def test_infer_provider_custom_anthropic_names():
|
||||
"""Test that _infer_provider_from_model infers anthropic for custom model names.
|
||||
|
||||
Regression test for https://github.com/crewAIInc/crewAI/issues/5893
|
||||
Models like 'anthropic--claude-...' should be inferred as anthropic, not openai.
|
||||
"""
|
||||
assert LLM._infer_provider_from_model("anthropic--claude-3-5-sonnet") == "anthropic"
|
||||
assert LLM._infer_provider_from_model("claude-3-5-sonnet") == "anthropic"
|
||||
|
||||
# Standard models should still be correctly inferred
|
||||
assert LLM._infer_provider_from_model("gpt-4o") == "openai"
|
||||
assert LLM._infer_provider_from_model("gemini-2.0-flash") == "gemini"
|
||||
|
||||
|
||||
def test_is_anthropic_model_custom_names():
|
||||
"""Test that _is_anthropic_model detects custom-deployed Anthropic models.
|
||||
|
||||
Regression test for https://github.com/crewAIInc/crewAI/issues/5893
|
||||
"""
|
||||
# Standard patterns
|
||||
assert LLM._is_anthropic_model("anthropic/claude-3-5-sonnet") is True
|
||||
assert LLM._is_anthropic_model("claude-3-5-sonnet") is True
|
||||
|
||||
# Custom naming with "claude-" substring
|
||||
assert LLM._is_anthropic_model("anthropic--claude-3-5-sonnet") is True
|
||||
|
||||
# Bedrock-style naming with "anthropic."
|
||||
assert LLM._is_anthropic_model("anthropic.claude-v2") is True
|
||||
|
||||
# Non-anthropic models
|
||||
assert LLM._is_anthropic_model("gpt-4o") is False
|
||||
assert LLM._is_anthropic_model("gemini-2.0-flash") is False
|
||||
|
||||
|
||||
@pytest.mark.vcr(record_mode="once",decode_compressed_response=True)
|
||||
def test_usage_info_non_streaming_with_call():
|
||||
llm = LLM(model="gpt-4o-mini", is_litellm=True)
|
||||
|
||||
Reference in New Issue
Block a user