From e520fef8179edf6cd64b18b8319ecb841bc2ae63 Mon Sep 17 00:00:00 2001 From: Lucas Gomide Date: Thu, 6 Aug 2026 18:16:22 -0300 Subject: [PATCH] fix: avoid double-prefixing instructor model strings With LiteLLM models now carrying a real `provider` while `model` keeps its `provider/name` form, `InternalInstructor` was building `groq/groq/...` for `instructor.from_provider`. Skip the prefix when the model string is already qualified. --- .../crewai/utilities/internal_instructor.py | 7 ++++++- lib/crewai/tests/utilities/test_converter.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) 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")