diff --git a/assets/language_model_utils.py b/assets/language_model_utils.py new file mode 100644 index 000000000..754ab412d --- /dev/null +++ b/assets/language_model_utils.py @@ -0,0 +1,134 @@ +# Copyright 2024 Palantir Technologies, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from typing import Optional + +from foundry_sdk._core.config import Config +from foundry_sdk._core.context_and_environment_vars import HOSTNAME_VAR +from foundry_sdk._core.context_and_environment_vars import TOKEN_VAR +from foundry_sdk._core.http_client import HttpClient + + +def _get_api_gateway_base_url(*, preview: bool = False) -> str: + """Get the Foundry hostname from the current execution context. + + Args: + preview: Must be set to True to use this beta feature. + + Returns: + The Foundry API gateway base URL. + + Raises: + ValueError: If preview is not set to True. + RuntimeError: If the Foundry API gateway base URL is not available in the current context. + """ + if not preview: + raise ValueError( + "get_api_gateway_base_url() is in beta. " + "Please set the preview parameter to True to use it." + ) + hostname = HOSTNAME_VAR.get() + if hostname is None: + raise RuntimeError("Foundry API gateway base URL is not available in the current context.") + return hostname + + +def get_foundry_token(*, preview: bool = False) -> str: + """Get the Foundry token from the current execution context. + + Args: + preview: Must be set to True to use this beta feature. + + Returns: + The Foundry token. + + Raises: + ValueError: If preview is not set to True. + RuntimeError: If the Foundry token is not available in the current context. + """ + if not preview: + raise ValueError( + "get_foundry_token() is in beta. " "Please set the preview parameter to True to use it." + ) + token = TOKEN_VAR.get() + if token is None: + raise RuntimeError("Foundry token is not available in the current context.") + return token + + +def get_openai_base_url(*, preview: bool = False) -> str: + """Get the OpenAI proxy base URL for the current Foundry environment. + + Args: + preview: Must be set to True to use this beta feature. + + Returns: + The OpenAI proxy base URL. + + Raises: + ValueError: If preview is not set to True. + RuntimeError: If the Foundry API gateway base URL is not available in the current context. + """ + if not preview: + raise ValueError( + "get_openai_base_url() is in beta. " + "Please set the preview parameter to True to use it." + ) + hostname = _get_api_gateway_base_url(preview=True) + return f"https://{hostname}/api/v1/models/openai" + + +def get_anthropic_base_url(*, preview: bool = False) -> str: + """Get the Anthropic proxy base URL for the current Foundry environment. + + Args: + preview: Must be set to True to use this beta feature. + + Returns: + The Anthropic proxy base URL. + + Raises: + ValueError: If preview is not set to True. + RuntimeError: If the Foundry API gateway base URL is not available in the current context. + """ + if not preview: + raise ValueError( + "get_anthropic_base_url() is in beta. " + "Please set the preview parameter to True to use it." + ) + hostname = _get_api_gateway_base_url(preview=True) + return f"https://{hostname}/api/v1/models/anthropic" + + +def get_http_client(*, preview: bool = False, config: Optional[Config] = None) -> HttpClient: + """Get an HTTP client configured for the current Foundry environment. + + Args: + preview: Must be set to True to use this beta feature. + config: Optional configuration for the HTTP client. + + Returns: + An HttpClient instance configured with the Foundry hostname. + + Raises: + ValueError: If preview is not set to True. + RuntimeError: If the Foundry API gateway base URL is not available in the current context. + """ + if not preview: + raise ValueError( + "get_http_client() is in beta. " "Please set the preview parameter to True to use it." + ) + hostname = _get_api_gateway_base_url(preview=True) + return HttpClient(hostname=hostname, config=config) diff --git a/assets/test_language_model_utils.py b/assets/test_language_model_utils.py new file mode 100644 index 000000000..404fc6435 --- /dev/null +++ b/assets/test_language_model_utils.py @@ -0,0 +1,131 @@ +# Copyright 2024 Palantir Technologies, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import pytest + +from foundry_sdk._core.context_and_environment_vars import HOSTNAME_VAR +from foundry_sdk._core.context_and_environment_vars import TOKEN_VAR +from foundry_sdk._core.http_client import HttpClient +from foundry_sdk.v2.language_models import ( + get_anthropic_base_url, + get_foundry_token, + get_http_client, + get_openai_base_url, +) +from foundry_sdk.v2.language_models.utils import _get_api_gateway_base_url + + +class TestPreviewParameter: + """Test that all functions require preview=True.""" + + def test__get_api_gateway_base_url_requires_preview(self): + with pytest.raises(ValueError, match="preview parameter"): + _get_api_gateway_base_url() + + def test_get_foundry_token_requires_preview(self): + with pytest.raises(ValueError, match="preview parameter"): + get_foundry_token() + + def test_get_openai_base_url_requires_preview(self): + with pytest.raises(ValueError, match="preview parameter"): + get_openai_base_url() + + def test_get_anthropic_base_url_requires_preview(self): + with pytest.raises(ValueError, match="preview parameter"): + get_anthropic_base_url() + + def test_get_http_client_requires_preview(self): + with pytest.raises(ValueError, match="preview parameter"): + get_http_client() + + +class TestGetApiGatewayBaseUrl: + """Test _get_api_gateway_base_url function.""" + + def test_returns_hostname_from_context(self): + token = HOSTNAME_VAR.set("test.palantirfoundry.com") + try: + result = _get_api_gateway_base_url(preview=True) + assert result == "test.palantirfoundry.com" + finally: + HOSTNAME_VAR.reset(token) + + def test_raises_runtime_error_when_not_in_context(self): + with pytest.raises(RuntimeError, match="not available"): + _get_api_gateway_base_url(preview=True) + + +class TestGetFoundryToken: + """Test get_foundry_token function.""" + + def test_returns_token_from_context(self): + token = TOKEN_VAR.set("test-token-12345") + try: + result = get_foundry_token(preview=True) + assert result == "test-token-12345" + finally: + TOKEN_VAR.reset(token) + + def test_raises_runtime_error_when_not_in_context(self): + with pytest.raises(RuntimeError, match="not available"): + get_foundry_token(preview=True) + + +class TestGetOpenaiBaseUrl: + """Test get_openai_base_url function.""" + + def test_returns_correct_url(self): + token = HOSTNAME_VAR.set("test.palantirfoundry.com") + try: + result = get_openai_base_url(preview=True) + assert result == "https://test.palantirfoundry.com/api/v1/models/openai" + finally: + HOSTNAME_VAR.reset(token) + + def test_raises_runtime_error_when_not_in_context(self): + with pytest.raises(RuntimeError, match="not available"): + get_openai_base_url(preview=True) + + +class TestGetAnthropicBaseUrl: + """Test get_anthropic_base_url function.""" + + def test_returns_correct_url(self): + token = HOSTNAME_VAR.set("test.palantirfoundry.com") + try: + result = get_anthropic_base_url(preview=True) + assert result == "https://test.palantirfoundry.com/api/v1/models/anthropic" + finally: + HOSTNAME_VAR.reset(token) + + def test_raises_runtime_error_when_not_in_context(self): + with pytest.raises(RuntimeError, match="not available"): + get_anthropic_base_url(preview=True) + + +class TestGetHttpClient: + """Test get_http_client function.""" + + def test_returns_http_client(self): + token = HOSTNAME_VAR.set("test.palantirfoundry.com") + try: + result = get_http_client(preview=True) + assert isinstance(result, HttpClient) + finally: + HOSTNAME_VAR.reset(token) + + def test_raises_runtime_error_when_not_in_context(self): + with pytest.raises(RuntimeError, match="not available"): + get_http_client(preview=True) diff --git a/config.json b/config.json index 7feda2d1f..6efb9f75b 100644 --- a/config.json +++ b/config.json @@ -8,6 +8,10 @@ "description": "The official Python library for the Foundry API", "autoreleaseUrl": "https://autorelease.general.dmz.palantir.tech/palantir/foundry-platform-python", "promotedMajorVersion": "v2", + "additionalFiles": [ + ["assets/language_model_utils.py", "foundry_sdk/v2/language_models/utils.py"], + ["assets/test_language_model_utils.py", "tests/language_models/test_utils.py"] + ], "documentationBaseUrl": "https://palantir.com", "extraDocsDir": "assets/docs_examples", "exampleOperation": { @@ -173,7 +177,15 @@ "Functions": true, "Gaia": false, "Geo": true, - "LanguageModels": true, + "LanguageModels": { + "exclude": [], + "additionalExports": [ + "from foundry_sdk.v2.language_models.utils import get_foundry_token", + "from foundry_sdk.v2.language_models.utils import get_openai_base_url", + "from foundry_sdk.v2.language_models.utils import get_anthropic_base_url", + "from foundry_sdk.v2.language_models.utils import get_http_client" + ] + }, "MapRendering": false, "MediaSets": true, "Models": true,