| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import os
- import logging
- from openai import AzureOpenAI, OpenAI
- logger = logging.getLogger(__name__)
- class LLMError(RuntimeError):
- pass
- class GPTClientFactory:
- def __init__(self):
- self.auth_mode = os.getenv("OPENAI_AUTH_MODE", "entra_id").lower()
- self.base_url = os.getenv("AZURE_OPENAI_ENDPOINT") or os.getenv("OPENAI_BASE_URL")
- self.api_key = os.getenv("OPENAI_API_KEY")
- self.azure_api_version = os.getenv("AZURE_OPENAI_API_VERSION")
- timeout_value = os.getenv("OPENAI_TIMEOUT", "120")
- self.timeout = float(timeout_value) if timeout_value else 120.0
- self.client = None
- def _init_entra_id_client(self) -> None:
- """Initialize client with Entra ID (Azure AD) authentication."""
- try:
- from azure.identity import (
- AzureCliCredential,
- ChainedTokenCredential,
- ManagedIdentityCredential,
- get_bearer_token_provider,
- )
- except ImportError:
- raise LLMError(
- "azure-identity package is required for Entra ID authentication. "
- "Install with: pip install azure-identity"
- )
- if not self.base_url:
- raise LLMError("AZURE_OPENAI_ENDPOINT or OPENAI_BASE_URL is required for Entra ID authentication")
- if not self.azure_api_version:
- raise LLMError("AZURE_OPENAI_API_VERSION is required for Entra ID authentication")
- credential = ChainedTokenCredential(
- AzureCliCredential(),
- ManagedIdentityCredential(),
- )
- token_provider = get_bearer_token_provider(
- credential,
- "https://cognitiveservices.azure.com/.default"
- )
- self.client = AzureOpenAI(
- azure_endpoint=self.base_url,
- azure_ad_token_provider=token_provider,
- api_version=self.azure_api_version,
- timeout=self.timeout,
- )
- logger.debug(f"Initialized Azure OpenAI client with Entra ID authentication (endpoint: {self.base_url})")
- def _init_api_key_client(self) -> None:
- """Initialize client with API Key authentication."""
- if not self.api_key:
- raise LLMError("OPENAI_API_KEY is required for APIKey authentication")
- if self.base_url and ("azure" in self.base_url.lower() or "cognitiveservices" in self.base_url.lower()):
- if not self.azure_api_version:
- raise LLMError("AZURE_OPENAI_API_VERSION is required for Azure OpenAI APIKey authentication")
- self.client = AzureOpenAI(
- azure_endpoint=self.base_url,
- api_key=self.api_key,
- api_version=self.azure_api_version,
- timeout=self.timeout,
- )
- logger.debug(f"Initialized Azure OpenAI client with API Key authentication (endpoint: {self.base_url})")
- else:
- client_kwargs = {
- "api_key": self.api_key,
- "timeout": self.timeout,
- }
- if self.base_url:
- client_kwargs["base_url"] = self.base_url
- self.client = OpenAI(**client_kwargs)
- logger.debug(f"Initialized OpenAI client with API Key authentication (base_url: {self.base_url})")
- def build(self):
- if self.auth_mode in ["entra", "entra_id", "aad", "azure_ad"]:
- self._init_entra_id_client()
- elif self.auth_mode in ["api_key", "apikey", "key"]:
- self._init_api_key_client()
- else:
- raise LLMError(f"Unsupported OPENAI_AUTH_MODE: {self.auth_mode}. Use 'entra_id' or 'api_key'.")
- return self.client
|