diff --git a/crowdin_api/api_resources/ai/enums.py b/crowdin_api/api_resources/ai/enums.py index eb0fd85..d9174ec 100644 --- a/crowdin_api/api_resources/ai/enums.py +++ b/crowdin_api/api_resources/ai/enums.py @@ -23,7 +23,7 @@ class EditAIPromptPath(Enum): class AIProviderType(Enum): OPEN_AI = "open_ai" - AZUER_OPEN_AI = "azure_open_ai" + AZURE_OPEN_AI = "azure_open_ai" GOOGLE_GEMINI = "google_gemini" MISTRAL_AI = "mistral_ai" ANTHROPIC = "anthropic" @@ -82,3 +82,8 @@ class ListAiPromptFineTuningJobsOrderBy(Enum): class AiReportFormat(Enum): CSV = "csv" JSON = "json" + + +class ListSupportedAiModelsOrderBy(Enum): + KNOWLEDGE_CUTOFF = "knowledgeCutoff" + RELEASE_DATE = "releaseDate" diff --git a/crowdin_api/api_resources/ai/resource.py b/crowdin_api/api_resources/ai/resource.py index adf325e..38678c2 100644 --- a/crowdin_api/api_resources/ai/resource.py +++ b/crowdin_api/api_resources/ai/resource.py @@ -1,7 +1,7 @@ from typing import Iterable, Optional, Union from crowdin_api.api_resources.abstract.resources import BaseResource -from crowdin_api.api_resources.ai.enums import AIPromptAction, AiPromptFineTuningJobStatus +from crowdin_api.api_resources.ai.enums import AIPromptAction, AiPromptFineTuningJobStatus, AIProviderType from crowdin_api.api_resources.ai.types import ( AddAIPromptRequestScheme, AddAIProviderReqeustScheme, @@ -18,7 +18,7 @@ EditAiSettingsPatch, ) from crowdin_api.sorting import Sorting -from crowdin_api.utils import convert_enum_collection_to_string_if_exists +from crowdin_api.utils import convert_enum_collection_to_string_if_exists, convert_enum_to_string_if_exists class AIResource(BaseResource): @@ -654,6 +654,36 @@ def edit_ai_settings( request_data=patches, ) + def list_supported_ai_provider_models( + self, + user_id: int, + limit: Optional[int] = None, + offset: Optional[int] = None, + provider_type: Optional[AIProviderType] = None, + enabled: Optional[bool] = None, + order_by: Optional[Sorting] = None, + ): + """ + List Supported AI Provider Models + + Link to documentation: + https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.ai.providers.supported-models.crowdin.getMany + """ + + params = { + "limit": limit, + "offset": offset, + "providerType": convert_enum_to_string_if_exists(provider_type), + "enabled": enabled, + "orderBy": str(order_by) if order_by is not None else None, + } + + return self.requester.request( + method="get", + path=f"users/{user_id}/ai/providers/supported-models", + params=params + ) + class EnterpriseAIResource(BaseResource): """ @@ -1256,3 +1286,32 @@ def edit_ai_settings( path="ai/settings", request_data=patches, ) + + def list_supported_ai_provider_models( + self, + limit: Optional[int] = None, + offset: Optional[int] = None, + provider_type: Optional[AIProviderType] = None, + enabled: Optional[bool] = None, + order_by: Optional[Sorting] = None, + ): + """ + List Supported AI Provider Models + + Link to documentation: + https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.providers.supported-models.enterprise.getMany + """ + + params = { + "limit": limit, + "offset": offset, + "providerType": convert_enum_to_string_if_exists(provider_type), + "enabled": enabled, + "orderBy": str(order_by) if order_by is not None else None, + } + + return self.requester.request( + method="get", + path="ai/providers/supported-models", + params=params + ) diff --git a/crowdin_api/api_resources/ai/tests/test_ai_resources.py b/crowdin_api/api_resources/ai/tests/test_ai_resources.py index 567a3dd..4002abd 100644 --- a/crowdin_api/api_resources/ai/tests/test_ai_resources.py +++ b/crowdin_api/api_resources/ai/tests/test_ai_resources.py @@ -12,7 +12,7 @@ EditAiCustomPlaceholderPatchPath, AiToolType, AiReportFormat, - EditAiSettingsPatchPath + EditAiSettingsPatchPath, ListSupportedAiModelsOrderBy ) from crowdin_api.api_resources.ai.resource import AIResource, EnterpriseAIResource from crowdin_api.api_resources.ai.types import ( @@ -1065,6 +1065,44 @@ def test_edit_ai_settings(self, m_request, incoming_data, request_params, base_a request_data=request_params, ) + @pytest.mark.parametrize( + "in_params, request_params", + ( + ( + { + "limit": 25, + "offset": 0, + "provider_type": AIProviderType.OPEN_AI, + "enabled": True, + "order_by": Sorting([ + SortingRule(ListSupportedAiModelsOrderBy.KNOWLEDGE_CUTOFF, SortingOrder.DESC) + ]) + }, + { + "limit": 25, + "offset": 0, + "providerType": "open_ai", + "enabled": True, + "orderBy": "knowledgeCutoff desc", + } + ), + ), + ) + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_list_supported_ai_provider_models(self, m_request, in_params, request_params, base_absolut_url): + m_request.return_value = "response" + + user_id = 1 + + resource = self.get_resource(base_absolut_url) + assert resource.list_supported_ai_provider_models(user_id, **in_params) == "response" + + m_request.assert_called_once_with( + method="get", + path=f"users/{user_id}/ai/providers/supported-models", + params=request_params + ) + class TestEnterpriseAIResources: resource_class = EnterpriseAIResource @@ -2030,3 +2068,39 @@ def test_edit_ai_settings(self, m_request, incoming_data, request_params, base_a path="ai/settings", request_data=request_params, ) + + @pytest.mark.parametrize( + "in_params, request_params", + ( + ( + { + "limit": 25, + "offset": 0, + "provider_type": AIProviderType.OPEN_AI, + "enabled": True, + "order_by": Sorting([ + SortingRule(ListSupportedAiModelsOrderBy.KNOWLEDGE_CUTOFF, SortingOrder.DESC) + ]) + }, + { + "limit": 25, + "offset": 0, + "providerType": "open_ai", + "enabled": True, + "orderBy": "knowledgeCutoff desc", + } + ), + ), + ) + @mock.patch("crowdin_api.requester.APIRequester.request") + def test_list_supported_ai_provider_models(self, m_request, in_params, request_params, base_absolut_url): + m_request.return_value = "response" + + resource = self.get_resource(base_absolut_url) + assert resource.list_supported_ai_provider_models(**in_params) == "response" + + m_request.assert_called_once_with( + method="get", + path="ai/providers/supported-models", + params=request_params + )