From 3050c8c8bd49fac8f7354322ecf8a6b214b6fe1c Mon Sep 17 00:00:00 2001 From: Yuge Zhang Date: Wed, 17 Sep 2025 15:56:11 +0800 Subject: [PATCH] Python: Add base_url support to OpenAI settings and improve initialization (#788) Co-authored-by: Chris <66376200+crickman@users.noreply.github.com> --- .../main/agent_framework/openai/_chat_client.py | 7 +++++-- .../main/agent_framework/openai/_shared.py | 3 +++ .../main/tests/openai/test_openai_chat_client.py | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/python/packages/main/agent_framework/openai/_chat_client.py b/python/packages/main/agent_framework/openai/_chat_client.py index aa98257804..450323504a 100644 --- a/python/packages/main/agent_framework/openai/_chat_client.py +++ b/python/packages/main/agent_framework/openai/_chat_client.py @@ -427,7 +427,9 @@ class OpenAIChatClient(OpenAIConfigMixin, OpenAIBaseChatClient): async_client: An existing client to use. (Optional) instruction_role: The role to use for 'instruction' messages, for example, "system" or "developer". If not provided, the default is "system". - base_url: The optional base URL to use. If provided will override the standard value for a OpenAI connector. + base_url: The optional base URL to use. If provided will override + the standard value for a OpenAI connector, + the env vars or .env file value. env_file_path: Use the environment settings file as a fallback to environment variables. (Optional) env_file_encoding: The encoding of the environment settings file. (Optional) @@ -435,6 +437,7 @@ class OpenAIChatClient(OpenAIConfigMixin, OpenAIBaseChatClient): try: openai_settings = OpenAISettings( api_key=SecretStr(api_key) if api_key else None, + base_url=base_url, org_id=org_id, chat_model_id=ai_model_id, env_file_path=env_file_path, @@ -456,11 +459,11 @@ class OpenAIChatClient(OpenAIConfigMixin, OpenAIBaseChatClient): super().__init__( ai_model_id=openai_settings.chat_model_id, api_key=openai_settings.api_key.get_secret_value() if openai_settings.api_key else None, + base_url=openai_settings.base_url if openai_settings.base_url else None, org_id=openai_settings.org_id, default_headers=default_headers, client=async_client, instruction_role=instruction_role, - base_url=base_url, ) @classmethod diff --git a/python/packages/main/agent_framework/openai/_shared.py b/python/packages/main/agent_framework/openai/_shared.py index de8ada2ca4..9d5ab7e52f 100644 --- a/python/packages/main/agent_framework/openai/_shared.py +++ b/python/packages/main/agent_framework/openai/_shared.py @@ -78,6 +78,8 @@ class OpenAISettings(AFBaseSettings): Attributes: api_key: OpenAI API key, see https://platform.openai.com/account/api-keys (Env var OPENAI_API_KEY) + base_url: The base URL for the OpenAI API. + (Env var OPENAI_BASE_URL) org_id: This is usually optional unless your account belongs to multiple organizations. (Env var OPENAI_ORG_ID) chat_model_id: The OpenAI chat model ID to use, for example, gpt-3.5-turbo or gpt-4. @@ -106,6 +108,7 @@ class OpenAISettings(AFBaseSettings): env_prefix: ClassVar[str] = "OPENAI_" api_key: SecretStr | None = None + base_url: str | None = None org_id: str | None = None chat_model_id: str | None = None responses_model_id: str | None = None diff --git a/python/packages/main/tests/openai/test_openai_chat_client.py b/python/packages/main/tests/openai/test_openai_chat_client.py index f57af48207..62c7bbf948 100644 --- a/python/packages/main/tests/openai/test_openai_chat_client.py +++ b/python/packages/main/tests/openai/test_openai_chat_client.py @@ -80,6 +80,22 @@ def test_init_base_url(openai_unit_test_env: dict[str, str]) -> None: assert str(open_ai_chat_completion.client.base_url) == "http://localhost:1234/v1/" +def test_init_base_url_from_settings_env() -> None: + """Test that base_url from OpenAISettings environment variable is properly used.""" + # Set environment variable for base_url + with patch.dict( + os.environ, + { + "OPENAI_API_KEY": "dummy", + "OPENAI_CHAT_MODEL_ID": "gpt-5", + "OPENAI_BASE_URL": "https://custom-openai-endpoint.com/v1", + }, + ): + client = OpenAIChatClient() + assert client.ai_model_id == "gpt-5" + assert str(client.client.base_url) == "https://custom-openai-endpoint.com/v1/" + + @pytest.mark.parametrize("exclude_list", [["OPENAI_CHAT_MODEL_ID"]], indirect=True) def test_init_with_empty_model_id(openai_unit_test_env: dict[str, str]) -> None: with pytest.raises(ServiceInitializationError):