mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-03 14:09:24 +00:00
fix(instructor): forward base_url and api_key to instructor.from_provider
This commit is contained in:
@@ -98,7 +98,14 @@ class InternalInstructor(Generic[T]):
|
||||
else:
|
||||
provider = "openai" # Default fallback
|
||||
|
||||
return instructor.from_provider(f"{provider}/{model_string}")
|
||||
extra_kwargs: dict[str, Any] = {}
|
||||
if self.llm is not None and not isinstance(self.llm, str):
|
||||
for attr in ("base_url", "api_key"):
|
||||
value = getattr(self.llm, attr, None)
|
||||
if value is not None:
|
||||
extra_kwargs[attr] = value
|
||||
|
||||
return instructor.from_provider(f"{provider}/{model_string}", **extra_kwargs)
|
||||
|
||||
def _extract_provider(self) -> str:
|
||||
"""Extract provider from LLM model name.
|
||||
|
||||
@@ -940,6 +940,8 @@ def test_internal_instructor_real_unsupported_provider() -> None:
|
||||
mock_llm.is_litellm = False
|
||||
mock_llm.model = "unsupported-model"
|
||||
mock_llm.provider = "unsupported"
|
||||
mock_llm.base_url = None
|
||||
mock_llm.api_key = None
|
||||
|
||||
# This should raise a ConfigurationError from the real instructor library
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
@@ -952,3 +954,45 @@ def test_internal_instructor_real_unsupported_provider() -> None:
|
||||
|
||||
# Verify it's a configuration error about unsupported provider
|
||||
assert "Unsupported provider" in str(exc_info.value) or "unsupported" in str(exc_info.value).lower()
|
||||
|
||||
|
||||
def test_internal_instructor_forwards_base_url_and_api_key() -> None:
|
||||
"""base_url and api_key on the LLM must flow into instructor.from_provider."""
|
||||
from crewai.utilities.internal_instructor import InternalInstructor
|
||||
|
||||
mock_llm = Mock()
|
||||
mock_llm.is_litellm = False
|
||||
mock_llm.model = "gpt-4o"
|
||||
mock_llm.provider = "openai"
|
||||
mock_llm.base_url = "https://custom.example.com/v1"
|
||||
mock_llm.api_key = "sk-custom"
|
||||
|
||||
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(
|
||||
"openai/gpt-4o",
|
||||
base_url="https://custom.example.com/v1",
|
||||
api_key="sk-custom",
|
||||
)
|
||||
|
||||
|
||||
def test_internal_instructor_omits_unset_base_url_and_api_key() -> None:
|
||||
"""When base_url/api_key are None, they must not be passed to from_provider."""
|
||||
from crewai.utilities.internal_instructor import InternalInstructor
|
||||
|
||||
mock_llm = Mock()
|
||||
mock_llm.is_litellm = False
|
||||
mock_llm.model = "gpt-4o"
|
||||
mock_llm.provider = "openai"
|
||||
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("openai/gpt-4o")
|
||||
|
||||
Reference in New Issue
Block a user