diff --git a/lib/crewai/src/crewai/utilities/internal_instructor.py b/lib/crewai/src/crewai/utilities/internal_instructor.py index 36472482c..074f3a824 100644 --- a/lib/crewai/src/crewai/utilities/internal_instructor.py +++ b/lib/crewai/src/crewai/utilities/internal_instructor.py @@ -105,7 +105,12 @@ class InternalInstructor(Generic[T]): if value is not None: extra_kwargs[attr] = value - return instructor.from_provider(f"{provider}/{model_string}", **extra_kwargs) + qualified_model = ( + model_string + if not provider or model_string.startswith(f"{provider}/") + else f"{provider}/{model_string}" + ) + return instructor.from_provider(qualified_model, **extra_kwargs) def _extract_provider(self) -> str: """Extract provider from LLM model name. diff --git a/lib/crewai/tests/utilities/test_converter.py b/lib/crewai/tests/utilities/test_converter.py index ed6429dac..f46cf8008 100644 --- a/lib/crewai/tests/utilities/test_converter.py +++ b/lib/crewai/tests/utilities/test_converter.py @@ -1004,3 +1004,21 @@ def test_internal_instructor_omits_unset_base_url_and_api_key() -> None: InternalInstructor(content="x", model=SimpleModel, llm=mock_llm) mock_from_provider.assert_called_once_with("openai/gpt-4o") + + +def test_internal_instructor_does_not_double_prefix_qualified_models() -> None: + from crewai.utilities.internal_instructor import InternalInstructor + + mock_llm = Mock() + mock_llm.is_litellm = False + mock_llm.model = "groq/llama-3.3-70b" + mock_llm.provider = "groq" + mock_llm.base_url = None + mock_llm.api_key = None + + with patch("instructor.from_provider") as mock_from_provider: + mock_from_provider.return_value = Mock() + + InternalInstructor(content="x", model=SimpleModel, llm=mock_llm) + + mock_from_provider.assert_called_once_with("groq/llama-3.3-70b")