Skip to content

Commit

Permalink
feat: Adding APIs for AI Providers
Browse files Browse the repository at this point in the history
Support for #270
  • Loading branch information
vedantnd111 committed Oct 21, 2024
1 parent b818b6a commit 653ed98
Show file tree
Hide file tree
Showing 16 changed files with 421 additions and 1 deletion.
100 changes: 100 additions & 0 deletions src/main/java/com/crowdin/client/ai/AIApi.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package com.crowdin.client.ai;

import com.crowdin.client.ai.model.AiProvider;
import com.crowdin.client.ai.model.AiProviderModel;
import com.crowdin.client.ai.model.AiProviderModelResponseList;
import com.crowdin.client.ai.model.AiProviderResponseList;
import com.crowdin.client.ai.model.AiProviderRequest;
import com.crowdin.client.ai.model.AiProviderResponseObject;
import com.crowdin.client.ai.model.AiSettingResponse;
import com.crowdin.client.ai.model.AiSetting;
import com.crowdin.client.ai.model.FineTuningDatasetDownload;
Expand Down Expand Up @@ -183,6 +189,100 @@ public ResponseObject<AiSetting> editAiSetting(Long userId, List<PatchRequest> r
return ResponseObject.of(aiSettingResponse.getData());
}

/**
* @param userId user identifier
* @param limit limit
* @param offset offset
* @return List of AI Providers
* @see <ul>
* <li><a href="https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.ai.providers.getMany" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.providers.getMany" target="_blank"><b>Enterprise API Documentation</b></li>
* </ul>
*/
public ResponseList<AiProvider> listAiProviders(final Long userId, final Integer limit, final Integer offset) {
Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"limit", Optional.ofNullable(limit),
"offset", Optional.ofNullable(offset)
);
String url = getAIPath(userId, "ai/providers");
AiProviderResponseList responseList = this.httpClient.get(url, new HttpRequestConfig(queryParams), AiProviderResponseList.class);
return AiProviderResponseList.to(responseList);
}

/**
* @param userId user identifier
* @param request AiProviderJobRequest
* @return AiProvider
* @see <ul>
* <li><a href="https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.providers.post" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.providers.post" target="_blank"><b>Enterprise API Documentation</b></li>
* </ul>
*/
public ResponseObject<AiProvider> addAiProviders(final Long userId, final AiProviderRequest request) {
String url = getAIPath(userId, "ai/providers");
AiProviderResponseObject response = this.httpClient.post(url, request, new HttpRequestConfig(), AiProviderResponseObject.class);
return ResponseObject.of(response.getData());
}

/**
* @param userId user identifier
* @param aiProviderId id of AiProvider
* @return AiProvider
* @see <ul>
* <li><a href="https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.providers.get" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.providers.get" target="_blank"><b>Enterprise API Documentation</b></li>
* </ul>
*/
public ResponseObject<AiProvider> getAiProvider(final Long userId, final Integer aiProviderId) {
String url = getAIPath(userId, "ai/providers/" + aiProviderId);
AiProviderResponseObject response = this.httpClient.get(url, new HttpRequestConfig(), AiProviderResponseObject.class);
return ResponseObject.of(response.getData());
}

/**
* @param userId user identifier
* @param aiProviderId id of AiProvider
* @see <ul>
* <li><a href="https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.providers.delete" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.providers.delete" target="_blank"><b>Enterprise API Documentation</b></li>
* </ul>
*/
public void deleteAiProvider(final Long userId, final Integer aiProviderId) {
String url = getAIPath(userId, "ai/providers/" + aiProviderId);
this.httpClient.delete(url, new HttpRequestConfig(), Void.class);
}

/**
* @param userId user identifier
* @param aiProviderId id of AiProvider
* @param requests list of PatchRequest
* @return updated AiProvider
* @see <ul>
* <li><a href="https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.users.ai.providers.patch" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.providers.patch" target="_blank"><b>Enterprise API Documentation</b></li>
* </ul>
*/
public ResponseObject<AiProvider> editAiProvider(final Long userId, final Integer aiProviderId, List<PatchRequest> requests) {
String url = getAIPath(userId, "ai/providers/" + aiProviderId);
AiProviderResponseObject response = this.httpClient.patch(url, requests, new HttpRequestConfig(), AiProviderResponseObject.class);
return ResponseObject.of(response.getData());
}

/**
* @param userId user identifier
* @param aiProviderId id of AiProvider
* @return list of AiProviderModel
* @see <ul>
* <li><a href="https://support.crowdin.com/developer/api/v2/#tag/AI/operation/api.ai.providers.models.getMany" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://support.crowdin.com/developer/enterprise/api/v2/#tag/AI/operation/api.ai.providers.models.getMany" target="_blank"><b>Enterprise API Documntation</b></li>
* </ul>
*/
public ResponseList<AiProviderModel> listAiProviderModels(final Long userId, final Integer aiProviderId) {
String url = getAIPath(userId, "ai/providers/" + aiProviderId + "/models");
AiProviderModelResponseList responseList = this.httpClient.get(url, new HttpRequestConfig(), AiProviderModelResponseList.class);
return AiProviderModelResponseList.to(responseList);
}

private String getAIPath(Long userId, String path) {
return userId != null ? String.format("%s/users/%d/%s", this.url, userId, path) : String.format("%s/%s", this.url, path);
}
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/com/crowdin/client/ai/model/AiProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.crowdin.client.ai.model;

import lombok.Data;

import java.util.Date;

@Data
public class AiProvider {
private Date createdAt;
private Integer promptsCount;
private Credentials credentials;
private Boolean isEnabled;
private String name;
private Integer id;
private String type;
private Config config;
private Boolean useSystemCredentials;
private Date updatedAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.crowdin.client.ai.model;

import lombok.Data;

@Data
public class AiProviderModel {
private String id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.crowdin.client.ai.model;

import com.crowdin.client.core.model.Pagination;
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;
import lombok.Data;

import java.util.List;
import java.util.stream.Collectors;

@Data
public class AiProviderModelResponseList {
private List<AiProviderModelResponseObject> data;
private Pagination pagination;

public static ResponseList<AiProviderModel> to(AiProviderModelResponseList responseList) {
return ResponseList.of(
responseList.data.stream()
.map(AiProviderModelResponseObject::getData)
.map(ResponseObject::of)
.collect(Collectors.toList()),
responseList.getPagination()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.crowdin.client.ai.model;

import lombok.Data;

@Data
public class AiProviderModelResponseObject {
private AiProviderModel data;
}
14 changes: 14 additions & 0 deletions src/main/java/com/crowdin/client/ai/model/AiProviderRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.crowdin.client.ai.model;

import lombok.Data;

@Data
public class AiProviderRequest {

private String name;
private String type;
private Credentials credentials;
private Config config;
private Boolean isEnabled;
private Boolean useSystemCredentials;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.crowdin.client.ai.model;

import com.crowdin.client.core.model.Pagination;
import com.crowdin.client.core.model.ResponseList;
import com.crowdin.client.core.model.ResponseObject;
import lombok.Data;

import java.util.List;
import java.util.stream.Collectors;

@Data
public class AiProviderResponseList {
private List<AiProviderResponseObject> data;
private Pagination pagination;

public static ResponseList<AiProvider> to(AiProviderResponseList responseList) {
return ResponseList.of(
responseList.data.stream()
.map(AiProviderResponseObject::getData)
.map(ResponseObject::of)
.collect(Collectors.toList()),
responseList.pagination
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.crowdin.client.ai.model;

import lombok.Data;

@Data
public class AiProviderResponseObject {
private AiProvider data;
}
16 changes: 16 additions & 0 deletions src/main/java/com/crowdin/client/ai/model/Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.crowdin.client.ai.model;

import lombok.Data;

import java.util.List;

@Data
public class Config {
private List<ActionRulesItem> actionRules;

@Data
public static class ActionRulesItem {
private List<String> availableAiModelIds;
private String action;
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/crowdin/client/ai/model/Credentials.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.crowdin.client.ai.model;

import lombok.Data;

@Data
public class Credentials {
private String apiKey;
}
109 changes: 108 additions & 1 deletion src/test/java/com/crowdin/client/ai/AIApiTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.crowdin.client.ai;

import com.crowdin.client.ai.model.AiProvider;
import com.crowdin.client.ai.model.AiProviderRequest;
import com.crowdin.client.ai.model.Credentials;
import com.crowdin.client.ai.model.AiProviderModel;
import com.crowdin.client.ai.model.AiSetting;
import com.crowdin.client.ai.model.FineTuningDatasetDownload;
import com.crowdin.client.ai.model.FineTuningDatasetRequest;
Expand All @@ -16,12 +20,14 @@
import com.crowdin.client.framework.RequestMock;
import com.crowdin.client.framework.TestClient;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
Expand Down Expand Up @@ -58,6 +64,9 @@ public class AIApiTest extends TestClient {
private static final String GET_FINE_TUNING_JOB_STATUS_PATH = "%s/users/%d/ai/prompts/%d/fine-tuning/jobs/%s";
private static final String FINE_TUNING_DATASET_DOWNLOAD_PATH = "%s/users/%d/ai/prompts/%d/fine-tuning/datasets/%s/download";
private static final String GET_SETTINGS = "%s/users/%d/ai/settings";
private static final String LIST_AI_PROVIDERS = "%s/users/%d/ai/providers";
private static final String GET_AI_PROVIDER = "%s/users/%d/ai/providers/%d";
private static final String LIST_AI_MODELS = "%s/users/%d/ai/providers/%d/models";

private Date getDateTime(int year, int month, int date, int hour, int minute, int second) {
calendar.set(year, month, date, hour, minute, second);
Expand All @@ -75,7 +84,14 @@ public List<RequestMock> getMocks() {
RequestMock.build(String.format(GET_FINE_TUNING_JOB_STATUS_PATH, this.url, userId, aiPromptId, jobIdentifier), HttpGet.METHOD_NAME, "api/ai/fineTuningJobStatusResponse.json"),
RequestMock.build(String.format(FINE_TUNING_DATASET_DOWNLOAD_PATH, this.url, userId, aiPromptId, jobIdentifier), HttpGet.METHOD_NAME, "api/ai/downloadFineTuningDataset.json"),
RequestMock.build(String.format(GET_SETTINGS, this.url, userId), HttpGet.METHOD_NAME, "api/ai/getAiSettingResponse.json"),
RequestMock.build(String.format(GET_SETTINGS, this.url, userId), HttpPatch.METHOD_NAME, "api/ai/editAiSettingRequest.json", "api/ai/getAiSettingResponse.json")
RequestMock.build(String.format(GET_SETTINGS, this.url, userId), HttpPatch.METHOD_NAME, "api/ai/editAiSettingRequest.json", "api/ai/getAiSettingResponse.json"),
RequestMock.build(String.format(FINE_TUNING_DATASET_DOWNLOAD_PATH, this.url, userId, aiPromptId, jobIdentifier), HttpGet.METHOD_NAME, "api/ai/downloadFineTuningDataset.json"),
RequestMock.build(String.format(LIST_AI_PROVIDERS, this.url, userId), HttpGet.METHOD_NAME, "api/ai/listAiProviderResponse.json"),
RequestMock.build(String.format(LIST_AI_PROVIDERS, this.url, userId), HttpPost.METHOD_NAME, "api/ai/addAiProviderRequestObject.json", "api/ai/aiProvidersResponseObject.json"),
RequestMock.build(String.format(GET_AI_PROVIDER, this.url, userId, 1), HttpGet.METHOD_NAME, "api/ai/aiProvidersResponseObject.json"),
RequestMock.build(String.format(GET_AI_PROVIDER, this.url, userId, 1), HttpPatch.METHOD_NAME, "api/ai/editAiProviderRequest.json", "api/ai/aiProvidersResponseObject.json"),
RequestMock.build(String.format(LIST_AI_MODELS, this.url, userId, 1), HttpGet.METHOD_NAME, "api/ai/listAiProviderModels.json"),
RequestMock.build(String.format(GET_AI_PROVIDER, this.url, userId, 1), HttpDelete.METHOD_NAME)
);
}

Expand Down Expand Up @@ -203,4 +219,95 @@ public void editAiSettingTest() {
assertEquals(aiSettingResponseObject.getData().getAssistActionAiPromptId(), 2);
assertEquals(aiSettingResponseObject.getData().getEditorSuggestionAiPromptId(), 5);
}

@Test
public void listAiProvidersTest() {
ResponseList<AiProvider> response = this.getAiApi().listAiProviders(userId, null, null);
Pagination pagination = response.getPagination();
AiProvider aiProvider = response.getData().get(0).getData();
assertNotNull(response);
assertEquals(pagination.getOffset(), 0);
assertEquals(pagination.getLimit(), 25);
assertEquals(aiProvider.getName(), "OpenAI");
assertEquals(aiProvider.getType(), "open_ai");
assertEquals(aiProvider.getCredentials().getApiKey(), "string");
assertEquals(aiProvider.getIsEnabled(), true);
assertEquals(aiProvider.getUseSystemCredentials(), false);
assertEquals(aiProvider.getConfig().getActionRules().get(0).getAction(), "pre_translate");
assertEquals(aiProvider.getConfig().getActionRules().get(0).getAvailableAiModelIds().get(0), "gpt-3.5-turbo-instruct");
}

@Test
public void addAiProvidersListTest() {
AiProviderRequest request = new AiProviderRequest();
final Date dateCreated = getDateTime(year, month, date, hour, minutes, seconds);
Credentials credentials = new Credentials();
credentials.setApiKey("string");
request.setName("OpenAI");
request.setType("open_ai");
request.setCredentials(credentials);
request.setIsEnabled(true);
request.setUseSystemCredentials(false);
ResponseObject<AiProvider> response = this.getAiApi().addAiProviders(userId, request);
assertNotNull(response);
assertEquals(response.getData().getId(), 2);
assertEquals(response.getData().getName(), "OpenAI");
assertEquals(response.getData().getType(), "open_ai");
assertEquals(response.getData().getCredentials().getApiKey(), "string");
assertEquals(response.getData().getIsEnabled(), true);
assertEquals(response.getData().getUseSystemCredentials(), false);
assertEquals(response.getData().getPromptsCount(), 42);
assertEquals(response.getData().getCreatedAt(), dateCreated);
assertEquals(response.getData().getUpdatedAt(), dateCreated);
}

@Test
public void getAiProviderTest() {
ResponseObject<AiProvider> response = this.getAiApi().getAiProvider(userId, 1);
final Date dateCreated = getDateTime(year, month, date, hour, minutes, seconds);
assertNotNull(response);
assertEquals(response.getData().getId(), 2);
assertEquals(response.getData().getName(), "OpenAI");
assertEquals(response.getData().getType(), "open_ai");
assertEquals(response.getData().getCredentials().getApiKey(), "string");
assertEquals(response.getData().getIsEnabled(), true);
assertEquals(response.getData().getUseSystemCredentials(), false);
assertEquals(response.getData().getPromptsCount(), 42);
assertEquals(response.getData().getCreatedAt(), dateCreated);
assertEquals(response.getData().getUpdatedAt(), dateCreated);
}

@Test
public void editAiProviderTest() {
PatchRequest request = new PatchRequest();
request.setOp(PatchOperation.REPLACE);
request.setPath("/name");
List<PatchRequest> patchRequests = new ArrayList<>();
patchRequests.add(request);
ResponseObject<AiProvider> response = this.getAiApi().editAiProvider(userId, 1, patchRequests);
final Date dateCreated = getDateTime(year, month, date, hour, minutes, seconds);
assertNotNull(response);
assertEquals(response.getData().getId(), 2);
assertEquals(response.getData().getName(), "OpenAI");
assertEquals(response.getData().getType(), "open_ai");
assertEquals(response.getData().getCredentials().getApiKey(), "string");
assertEquals(response.getData().getIsEnabled(), true);
assertEquals(response.getData().getUseSystemCredentials(), false);
assertEquals(response.getData().getPromptsCount(), 42);
assertEquals(response.getData().getCreatedAt(), dateCreated);
assertEquals(response.getData().getUpdatedAt(), dateCreated);
}

@Test
public void deleteAiProviderTest() {
this.getAiApi().deleteAiProvider(userId, 1);
}

@Test
public void listAiProviderModelsTest() {
ResponseList<AiProviderModel> response = this.getAiApi().listAiProviderModels(userId, 1);
AiProviderModel aiProviderModel = response.getData().get(0).getData();
assertNotNull(aiProviderModel);
assertEquals(aiProviderModel.getId(), "gpt-3.5-turbo-instruct");
}
}
Loading

0 comments on commit 653ed98

Please sign in to comment.