Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/main/java/com/crowdin/client/ai/AIApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,32 @@ public ResponseObject<Map<String, Object>> createProxyChatCompletion(final Long
return ResponseObject.of(response.getData());
}

/**
* @param userId user identifier
* @param limit maximum numbers of items to retrieve (default 25)
* @param offset starting offset in the collection (default 0)
* @param providerType provider (e.g. open_ai)
* @param enabled filter by enabled providers
* @param orderBy
* @return List of supported AI models for a specific AI provider
* @see <ul>
* <li><a href="https://developer.crowdin.com/api/v2/#tag/AI/operation/api.ai.providers.supported-models.crowdin.getMany" target="_blank"><b>API Documentation</b></a></li>
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#tag/AI/operation/api.ai.providers.supported-models.enterprise.getMany" target="_blank"><b>Enterprise API Documentation</b></a></li>
* </ul>
*/
public ResponseList<AiSupportedModel> listSupportedAiProviderModels(Long userId, Integer limit, Integer offset, String providerType, Boolean enabled, String orderBy) throws HttpException, HttpBadRequestException {
Map<String, Optional<Object>> queryParams = HttpRequestConfig.buildUrlParams(
"limit", Optional.ofNullable(limit),
"offset", Optional.ofNullable(offset),
"providerType", Optional.ofNullable(providerType),
"enabled", Optional.ofNullable(enabled),
"orderBy", Optional.ofNullable(orderBy)
);
String url = getAIPath(userId, "ai/providers/supported-models");
AiSupportedModelResponseList responseList = this.httpClient.get(url, new HttpRequestConfig(queryParams), AiSupportedModelResponseList.class);
return AiSupportedModelResponseList.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
50 changes: 50 additions & 0 deletions src/main/java/com/crowdin/client/ai/model/AiSupportedModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.crowdin.client.ai.model;

import lombok.Data;

import java.util.Date;

@Data
public class AiSupportedModel {
private Long providerId;
private String providerType;
private String providerName;
private String id;
private String displayName;
private Boolean supportReasoning;
private Integer intelligence;
private Integer speed;
private Price price;
private Modality modalities;
private Integer contextWindow;
private Integer maxOutputTokens;
private Date knowledgeCutoff;
private Date releaseDate;
private Feature features;

@Data
public static class Price {
private Double input;
private Double output;
}

@Data
public static class Modality {
private ModalityConfig input;
private ModalityConfig output;

@Data
public static class ModalityConfig {
private Boolean text;
private Boolean image;
private Boolean audio;
}
}

@Data
public static class Feature {
private Boolean streaming;
private Boolean structuredOutput;
private Boolean functionCalling;
}
}
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 AiSupportedModelResponseList {
private List<AiSupportedModelResponseObject> data;
private Pagination pagination;

public static ResponseList<AiSupportedModel> to(AiSupportedModelResponseList responseList) {
return ResponseList.of(
responseList.data.stream()
.map(AiSupportedModelResponseObject::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 AiSupportedModelResponseObject {
private AiSupportedModel data;
}
18 changes: 17 additions & 1 deletion src/test/java/com/crowdin/client/ai/AIApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class AIApiTest extends TestClient {
private static final long userId = 2L;
private static final long customPlaceholderId = 2L;
private static final long aiPromptId = 3L;
private static final long providerId = 0L;
private static final long progress = 100L;
private static final int year = 119;
private static final int month = Calendar.SEPTEMBER;
Expand Down Expand Up @@ -64,6 +65,7 @@ public class AIApiTest extends TestClient {
private static final String AI_PROMPT_COMPLETION = "%s/users/%d/ai/prompts/%d/completions/%s";
private static final String AI_PROMPT_COMPLETION_DOWNLOAD = "%s/users/%d/ai/prompts/%d/completions/%s/download";
private static final String PROXY_CHAT = "%s/users/%d/ai/providers/%d/chat/completions";
private static final String LIST_SUPPORTED_AI_PROVIDER_MODELS = "%s/users/%d/ai/providers/supported-models";

@Override
public List<RequestMock> getMocks() {
Expand Down Expand Up @@ -103,7 +105,8 @@ public List<RequestMock> getMocks() {
RequestMock.build(String.format(AI_PROMPT, this.url, userId, aiPromptId), HttpGet.METHOD_NAME, "api/ai/promptResponse.json"),
RequestMock.build(String.format(AI_PROMPT, this.url, userId, aiPromptId), HttpDelete.METHOD_NAME),
RequestMock.build(String.format(AI_PROMPT, this.url, userId, aiPromptId), HttpPatch.METHOD_NAME, "api/ai/editPromptRequest.json", "api/ai/promptResponse.json"),
RequestMock.build(String.format(PROXY_CHAT, this.url, userId, aiPromptId), HttpPost.METHOD_NAME, "api/ai/proxyChatCompletionRequest.json", "api/ai/proxyChatCompletionResponse.json")
RequestMock.build(String.format(PROXY_CHAT, this.url, userId, aiPromptId), HttpPost.METHOD_NAME, "api/ai/proxyChatCompletionRequest.json", "api/ai/proxyChatCompletionResponse.json"),
RequestMock.build(String.format(LIST_SUPPORTED_AI_PROVIDER_MODELS, this.url, userId), HttpGet.METHOD_NAME, "api/ai/listSupportedAiProviderModels.json")
);
}

Expand Down Expand Up @@ -515,4 +518,17 @@ public void createProxyChatCompletionTest() {

assertEquals(proxyChatCompletion.getData().size(), 0);
}

@Test
public void listSupportedAiProviderModelsTest() {
ResponseList<AiSupportedModel> response = this.getAiApi().listSupportedAiProviderModels(userId, null, null, null, null, null);

assertEquals(1, response.getData().size());
assertEquals(providerId, response.getData().get(0).getData().getProviderId());
assertTrue(response.getData().get(0).getData().getFeatures().getStreaming());
assertEquals(new Date(year, Calendar.AUGUST, 24, 14, 15, 22), response.getData().get(0).getData().getKnowledgeCutoff());
assertTrue(response.getData().get(0).getData().getModalities().getInput().getText());
assertTrue(response.getData().get(0).getData().getModalities().getOutput().getImage());
assertEquals(0.1, response.getData().get(0).getData().getPrice().getInput());
}
}
41 changes: 41 additions & 0 deletions src/test/resources/api/ai/listSupportedAiProviderModels.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"data": [
{
"data": {
"providerId": 0,
"providerType": "string",
"providerName": "string",
"id": "string",
"displayName": "string",
"supportReasoning": true,
"intelligence": 0,
"speed": 0,
"price": {
"input": 0.1,
"output": 0.1
},
"modalities": {
"input": {
"text": true,
"image": true,
"audio": true
},
"output": {
"text": true,
"image": true,
"audio": true
}
},
"contextWindow": 0,
"maxOutputTokens": 0,
"knowledgeCutoff": "2019-08-24T14:15:22Z",
"releaseDate": "2019-08-24T14:15:22Z",
"features": {
"streaming": true,
"structuredOutput": true,
"functionCalling": true
}
}
}
]
}