From 73805f5f5e4fcdcbea45abed0feff328c2352c16 Mon Sep 17 00:00:00 2001 From: blublinsky Date: Thu, 25 Sep 2025 09:49:41 +0100 Subject: [PATCH 01/11] fixed Azure client creation --- ols/src/llms/providers/azure_openai.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ols/src/llms/providers/azure_openai.py b/ols/src/llms/providers/azure_openai.py index ab4ec7866..e7d741370 100644 --- a/ols/src/llms/providers/azure_openai.py +++ b/ols/src/llms/providers/azure_openai.py @@ -73,8 +73,8 @@ def default_params(self) -> dict[str, Any]: "cache": None, "max_tokens": 512, "verbose": False, - "http_client": self._construct_httpx_client(False, False), - "http_async_client": self._construct_httpx_client(False, True), + "http_client": self._construct_httpx_client(True, False), + "http_async_client": self._construct_httpx_client(True, True), } # gpt-5 and o-series models don't support certain parameters From c0db0cc7b1554b5de142fc7dd64be4b725cae96a Mon Sep 17 00:00:00 2001 From: blublinsky Date: Fri, 26 Sep 2025 08:54:43 +0100 Subject: [PATCH 02/11] Add more logging --- ols/app/models/config.py | 1 + ols/src/llms/llm_loader.py | 1 + ols/src/llms/providers/azure_openai.py | 3 ++- ols/src/llms/providers/provider.py | 3 +++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ols/app/models/config.py b/ols/app/models/config.py index 70894b2f7..17e1b00b9 100644 --- a/ols/app/models/config.py +++ b/ols/app/models/config.py @@ -449,6 +449,7 @@ def set_provider_specific_configuration(self, data: dict) -> None: # noqa: C901 raise_on_error=False, ) self.read_api_key(azure_config) + print(f"Azure config {azure_config}") self.azure_config = AzureOpenAIConfig(**azure_config) case constants.PROVIDER_OPENAI: openai_config = data.get("openai_config") diff --git a/ols/src/llms/llm_loader.py b/ols/src/llms/llm_loader.py index 9bf41c023..9b5052709 100644 --- a/ols/src/llms/llm_loader.py +++ b/ols/src/llms/llm_loader.py @@ -49,6 +49,7 @@ def resolve_provider_config( f"Valid models are: {list(provider_config.models.keys())}" ) + print(f"provider config {provider_config}") return provider_config diff --git a/ols/src/llms/providers/azure_openai.py b/ols/src/llms/providers/azure_openai.py index e7d741370..37a10a264 100644 --- a/ols/src/llms/providers/azure_openai.py +++ b/ols/src/llms/providers/azure_openai.py @@ -57,7 +57,7 @@ def default_params(self) -> dict[str, Any]: deployment_name = self.provider_config.deployment_name azure_config = self.provider_config.azure_config - # provider-specific configuration has precendence over regular configuration + # provider-specific configuration has precedence over regular configuration if azure_config is not None: self.url = str(azure_config.url) deployment_name = azure_config.deployment_name @@ -92,6 +92,7 @@ def default_params(self) -> dict[str, Any]: # client_id and client_secret) access_token = self.resolve_access_token(azure_config) default_parameters["azure_ad_token"] = access_token + logger.info(f"Created Azure default parameters {default_parameters}") return default_parameters def load(self) -> BaseChatModel: diff --git a/ols/src/llms/providers/provider.py b/ols/src/llms/providers/provider.py index 56ace8acd..c364b2aab 100644 --- a/ols/src/llms/providers/provider.py +++ b/ols/src/llms/providers/provider.py @@ -370,6 +370,7 @@ def _construct_httpx_client( # noqa: C901 } sec_profile = self.provider_config.tls_security_profile + logger.info(f"security profile {sec_profile}") # if security profile is not set, use httpx client as is if sec_profile is None or sec_profile.profile_type is None: @@ -385,6 +386,7 @@ def _construct_httpx_client( # noqa: C901 cafile=self.provider_config.certificates_store ) verify = custom_context + logger.info(f"No security profiles. creating httpx.Client with verify {verify}") if use_async: return httpx.AsyncClient(verify=verify, proxies=proxy, mounts=mounts) return httpx.Client(verify=verify, proxies=proxy, mounts=mounts) @@ -411,6 +413,7 @@ def _construct_httpx_client( # noqa: C901 if use_custom_certificate_store: context.load_verify_locations(self.provider_config.certificates_store) + logger.info(f"with security profile, creating httpx.Client with verify {context}") if use_async: return httpx.AsyncClient(verify=context, proxies=proxy) return httpx.Client(verify=context, proxies=proxy) From 5c5443fd3bb313e24a9473e96a528bb73221fd3f Mon Sep 17 00:00:00 2001 From: blublinsky Date: Fri, 26 Sep 2025 10:46:35 +0100 Subject: [PATCH 03/11] Add more logging --- ols/app/models/config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ols/app/models/config.py b/ols/app/models/config.py index 17e1b00b9..0edf85155 100644 --- a/ols/app/models/config.py +++ b/ols/app/models/config.py @@ -365,6 +365,7 @@ def __init__( constants.PROVIDER_RHOAI_VLLM, constants.PROVIDER_RHELAI_VLLM, constants.PROVIDER_OPENAI, + constants.PROVIDER_AZURE_OPENAI, ): self.certificates_store = os.path.join( certificate_directory, constants.CERTIFICATE_STORAGE_FILENAME From 3ae0ecf8c451afa5ba63f8c083a8f8072aa5dfd7 Mon Sep 17 00:00:00 2001 From: blublinsky Date: Fri, 26 Sep 2025 12:04:54 +0100 Subject: [PATCH 04/11] Add more logging --- ols/app/models/config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ols/app/models/config.py b/ols/app/models/config.py index 0edf85155..0c1b166d3 100644 --- a/ols/app/models/config.py +++ b/ols/app/models/config.py @@ -450,7 +450,6 @@ def set_provider_specific_configuration(self, data: dict) -> None: # noqa: C901 raise_on_error=False, ) self.read_api_key(azure_config) - print(f"Azure config {azure_config}") self.azure_config = AzureOpenAIConfig(**azure_config) case constants.PROVIDER_OPENAI: openai_config = data.get("openai_config") From 15293562e176e6101a00252210be8dad78e3e51a Mon Sep 17 00:00:00 2001 From: blublinsky Date: Fri, 26 Sep 2025 12:17:22 +0100 Subject: [PATCH 05/11] removed prints --- ols/src/llms/llm_loader.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ols/src/llms/llm_loader.py b/ols/src/llms/llm_loader.py index 9b5052709..9bf41c023 100644 --- a/ols/src/llms/llm_loader.py +++ b/ols/src/llms/llm_loader.py @@ -49,7 +49,6 @@ def resolve_provider_config( f"Valid models are: {list(provider_config.models.keys())}" ) - print(f"provider config {provider_config}") return provider_config From 82237049ebca846622389d6bff07a59e65f9b63c Mon Sep 17 00:00:00 2001 From: blublinsky Date: Wed, 1 Oct 2025 12:54:08 +0100 Subject: [PATCH 06/11] fixed formatting --- ols/src/llms/providers/azure_openai.py | 2 +- ols/src/llms/providers/provider.py | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ols/src/llms/providers/azure_openai.py b/ols/src/llms/providers/azure_openai.py index 37a10a264..cff639dee 100644 --- a/ols/src/llms/providers/azure_openai.py +++ b/ols/src/llms/providers/azure_openai.py @@ -92,7 +92,7 @@ def default_params(self) -> dict[str, Any]: # client_id and client_secret) access_token = self.resolve_access_token(azure_config) default_parameters["azure_ad_token"] = access_token - logger.info(f"Created Azure default parameters {default_parameters}") + logger.info("Created Azure default parameters %s", default_parameters) return default_parameters def load(self) -> BaseChatModel: diff --git a/ols/src/llms/providers/provider.py b/ols/src/llms/providers/provider.py index c364b2aab..11250c49d 100644 --- a/ols/src/llms/providers/provider.py +++ b/ols/src/llms/providers/provider.py @@ -370,7 +370,7 @@ def _construct_httpx_client( # noqa: C901 } sec_profile = self.provider_config.tls_security_profile - logger.info(f"security profile {sec_profile}") + logger.info("Security profile %s", sec_profile) # if security profile is not set, use httpx client as is if sec_profile is None or sec_profile.profile_type is None: @@ -386,7 +386,9 @@ def _construct_httpx_client( # noqa: C901 cafile=self.provider_config.certificates_store ) verify = custom_context - logger.info(f"No security profiles. creating httpx.Client with verify {verify}") + logger.info( + "No security profiles. creating httpx.Client with verify %s", verify + ) if use_async: return httpx.AsyncClient(verify=verify, proxies=proxy, mounts=mounts) return httpx.Client(verify=verify, proxies=proxy, mounts=mounts) @@ -413,7 +415,9 @@ def _construct_httpx_client( # noqa: C901 if use_custom_certificate_store: context.load_verify_locations(self.provider_config.certificates_store) - logger.info(f"with security profile, creating httpx.Client with verify {context}") + logger.info( + "With security profile, creating httpx.Client with verify %s", context + ) if use_async: return httpx.AsyncClient(verify=context, proxies=proxy) return httpx.Client(verify=context, proxies=proxy) From d40ab7fb1c1372c0f0a7efec2953e5dbb335df1c Mon Sep 17 00:00:00 2001 From: blublinsky Date: Wed, 1 Oct 2025 15:22:58 +0100 Subject: [PATCH 07/11] fixed test_azure_openai --- .../unit/llms/providers/test_azure_openai.py | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/tests/unit/llms/providers/test_azure_openai.py b/tests/unit/llms/providers/test_azure_openai.py index 53bfe4d97..c7b983258 100644 --- a/tests/unit/llms/providers/test_azure_openai.py +++ b/tests/unit/llms/providers/test_azure_openai.py @@ -1,10 +1,12 @@ """Unit tests for Azure OpenAI provider.""" import time +import os from unittest.mock import patch import httpx import pytest +from ols import constants from azure.core.credentials import AccessToken from langchain_openai import AzureChatOpenAI from pydantic import AnyHttpUrl @@ -17,6 +19,21 @@ ) +cert_in_certificates_store_path = "tests/unit/extra_certs/sample_cert_1.crt" + + +@pytest.fixture +def fake_certifi_store(tmpdir): + """Create a fake certifi store.""" + cert_store_path = os.path.join( + constants.DEFAULT_CERTIFICATE_DIRECTORY, constants.CERTIFICATE_STORAGE_FILENAME + ) + with open(cert_store_path, "wb") as cert_store: + with open(cert_in_certificates_store_path, "rb") as cert_file: + cert_store.write(cert_file.read()) + return cert_store_path + + @pytest.fixture def provider_config(): """Fixture with provider configuration for Azure OpenAI.""" @@ -189,7 +206,7 @@ def provider_config_access_token_related_parameters(): ) -def test_basic_interface(provider_config): +def test_basic_interface(provider_config, fake_certifi_store): """Test basic interface.""" azure_openai = AzureOpenAI( model="uber-model", params={}, provider_config=provider_config @@ -236,7 +253,8 @@ def test_credentials_in_directory_handling(provider_config_credentials_directory assert azure_openai.default_params["api_key"] == "secret_key" -def test_loading_provider_specific_parameters(provider_config_with_specific_parameters): +def test_loading_provider_specific_parameters( + provider_config_with_specific_parameters, fake_certifi_store): """Test if provider-specific parameters are loaded too.""" azure_openai = AzureOpenAI( model="uber-model", @@ -268,7 +286,7 @@ def test_loading_provider_specific_parameters(provider_config_with_specific_para assert azure_openai.credentials == "secret_key_2" -def test_params_handling(provider_config): +def test_params_handling(provider_config, fake_certifi_store): """Test that not allowed parameters are removed before model init.""" # first three parameters should be removed before model init # rest need to stay From 7a6d57ecea0b8d278507614d066956cdafa6d827 Mon Sep 17 00:00:00 2001 From: blublinsky Date: Wed, 1 Oct 2025 16:02:39 +0100 Subject: [PATCH 08/11] fixed formatting --- pdm.lock | 2 +- tests/unit/llms/providers/test_azure_openai.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pdm.lock b/pdm.lock index 6c0127ba1..01db7084b 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev", "evaluation"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:ce8969ef24388dae7b8205727984c23b4e3036d514b43c259a0202e20667b436" +content_hash = "sha256:f52973e650c7b62620102963425c2e51eca278cbb08ac7b396d1ad534db99e3e" [[metadata.targets]] requires_python = ">=3.11.1,<=3.12.10" diff --git a/tests/unit/llms/providers/test_azure_openai.py b/tests/unit/llms/providers/test_azure_openai.py index c7b983258..39be22336 100644 --- a/tests/unit/llms/providers/test_azure_openai.py +++ b/tests/unit/llms/providers/test_azure_openai.py @@ -1,16 +1,16 @@ """Unit tests for Azure OpenAI provider.""" -import time import os +import time from unittest.mock import patch import httpx import pytest -from ols import constants from azure.core.credentials import AccessToken from langchain_openai import AzureChatOpenAI from pydantic import AnyHttpUrl +from ols import constants from ols.app.models.config import AzureOpenAIConfig, ProviderConfig from ols.src.llms.providers.azure_openai import ( TOKEN_EXPIRATION_LEEWAY, @@ -18,7 +18,6 @@ TokenCache, ) - cert_in_certificates_store_path = "tests/unit/extra_certs/sample_cert_1.crt" @@ -254,7 +253,8 @@ def test_credentials_in_directory_handling(provider_config_credentials_directory def test_loading_provider_specific_parameters( - provider_config_with_specific_parameters, fake_certifi_store): + provider_config_with_specific_parameters, fake_certifi_store +): """Test if provider-specific parameters are loaded too.""" azure_openai = AzureOpenAI( model="uber-model", From fed8aae2125f0806171081c67094a1acd4faf112 Mon Sep 17 00:00:00 2001 From: blublinsky Date: Wed, 1 Oct 2025 20:49:42 +0100 Subject: [PATCH 09/11] removed pdm.lock --- pdm.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdm.lock b/pdm.lock index 01db7084b..095995646 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev", "evaluation"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:f52973e650c7b62620102963425c2e51eca278cbb08ac7b396d1ad534db99e3e" +content_hash = "sha256:ce8969ef24388dae7b8205727984c23b4e3036d514b43c259a0202e20667b436" [[metadata.targets]] requires_python = ">=3.11.1,<=3.12.10" @@ -5034,4 +5034,4 @@ files = [ {file = "zstandard-0.23.0-cp312-cp312-win32.whl", hash = "sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d"}, {file = "zstandard-0.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b"}, {file = "zstandard-0.23.0.tar.gz", hash = "sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09"}, -] +] \ No newline at end of file From e5888eeaca63e88ab1ef903f477602780d7b476f Mon Sep 17 00:00:00 2001 From: blublinsky Date: Wed, 1 Oct 2025 20:53:23 +0100 Subject: [PATCH 10/11] removed pdm.lock --- pdm.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdm.lock b/pdm.lock index 095995646..01db7084b 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev", "evaluation"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:ce8969ef24388dae7b8205727984c23b4e3036d514b43c259a0202e20667b436" +content_hash = "sha256:f52973e650c7b62620102963425c2e51eca278cbb08ac7b396d1ad534db99e3e" [[metadata.targets]] requires_python = ">=3.11.1,<=3.12.10" @@ -5034,4 +5034,4 @@ files = [ {file = "zstandard-0.23.0-cp312-cp312-win32.whl", hash = "sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d"}, {file = "zstandard-0.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b"}, {file = "zstandard-0.23.0.tar.gz", hash = "sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09"}, -] \ No newline at end of file +] From 2537ac47f030c647edf062b99f94e3a8b99e812b Mon Sep 17 00:00:00 2001 From: blublinsky Date: Fri, 3 Oct 2025 20:37:06 +0100 Subject: [PATCH 11/11] removed pdm.lock --- pdm.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdm.lock b/pdm.lock index 01db7084b..6c0127ba1 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev", "evaluation"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:f52973e650c7b62620102963425c2e51eca278cbb08ac7b396d1ad534db99e3e" +content_hash = "sha256:ce8969ef24388dae7b8205727984c23b4e3036d514b43c259a0202e20667b436" [[metadata.targets]] requires_python = ">=3.11.1,<=3.12.10"