mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-04 14:39:23 +00:00
fix: re-read Azure env vars in lazy client build
Azure's `_normalize_azure_fields` captures env vars at construction time. When `LLM(model="azure/...")` is instantiated before deployment env vars are set, `self.api_key` / `self.endpoint` freeze as `None` and the lazy client builder then always raises — defeating the point of deferred init for Azure. Re-read `AZURE_API_KEY` / `AZURE_ENDPOINT` (and friends) inside `_make_client_kwargs` when the fields are still unset, matching OpenAI's `_get_client_params` pattern. Runs the endpoint validator on any env-provided value so the same normalization applies. Add a regression test that constructs the LLM with no env vars set, then patches them in afterwards and asserts `_get_sync_client()` successfully builds a client and writes the resolved values back onto the LLM instance.
This commit is contained in:
@@ -155,6 +155,22 @@ class AzureCompletion(BaseLLM):
|
||||
return AsyncChatCompletionsClient(**self._make_client_kwargs())
|
||||
|
||||
def _make_client_kwargs(self) -> dict[str, Any]:
|
||||
# Re-read env vars so that a deferred build can pick up credentials
|
||||
# that weren't set at instantiation time (e.g. LLM constructed at
|
||||
# module import before deployment env vars were injected).
|
||||
if not self.api_key:
|
||||
self.api_key = os.getenv("AZURE_API_KEY")
|
||||
if not self.endpoint:
|
||||
endpoint = (
|
||||
os.getenv("AZURE_ENDPOINT")
|
||||
or os.getenv("AZURE_OPENAI_ENDPOINT")
|
||||
or os.getenv("AZURE_API_BASE")
|
||||
)
|
||||
if endpoint:
|
||||
self.endpoint = AzureCompletion._validate_and_fix_endpoint(
|
||||
endpoint, self.model
|
||||
)
|
||||
|
||||
if not self.api_key:
|
||||
raise ValueError(
|
||||
"Azure API key is required. Set AZURE_API_KEY environment "
|
||||
|
||||
@@ -416,6 +416,32 @@ async def test_azure_aclose_is_noop_when_uninitialized():
|
||||
pass
|
||||
|
||||
|
||||
def test_azure_lazy_build_reads_env_vars_set_after_construction():
|
||||
"""When `LLM(model="azure/...")` is constructed before env vars are set,
|
||||
the lazy client builder must re-read `AZURE_API_KEY` / `AZURE_ENDPOINT`
|
||||
so the LLM actually works once credentials become available."""
|
||||
from crewai.llms.providers.azure.completion import AzureCompletion
|
||||
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
llm = AzureCompletion(model="gpt-4")
|
||||
assert llm.api_key is None
|
||||
assert llm.endpoint is None
|
||||
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"AZURE_API_KEY": "late-key",
|
||||
"AZURE_ENDPOINT": "https://test.openai.azure.com/openai/deployments/gpt-4",
|
||||
},
|
||||
clear=True,
|
||||
):
|
||||
client = llm._get_sync_client()
|
||||
assert client is not None
|
||||
assert llm.api_key == "late-key"
|
||||
assert llm.endpoint is not None
|
||||
assert "test.openai.azure.com" in llm.endpoint
|
||||
|
||||
|
||||
def test_azure_endpoint_configuration():
|
||||
"""
|
||||
Test that Azure endpoint configuration works with multiple environment variable names
|
||||
|
||||
Reference in New Issue
Block a user