Skip to content

Commit fd15c77

Browse files
committed
feat: add AI report methods
1 parent a333c8c commit fd15c77

12 files changed

+237
-3
lines changed

src/main/java/com/crowdin/client/ai/AIApi.java

+52
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import com.crowdin.client.ai.model.AiProviderResponseList;
77
import com.crowdin.client.ai.model.AiProviderRequest;
88
import com.crowdin.client.ai.model.AiProviderResponseObject;
9+
import com.crowdin.client.ai.model.AiReportGenerate;
10+
import com.crowdin.client.ai.model.AiReportGenerateResponse;
911
import com.crowdin.client.ai.model.AiSettingResponse;
1012
import com.crowdin.client.ai.model.AiSetting;
1113
import com.crowdin.client.ai.model.FineTuningDatasetDownload;
@@ -19,10 +21,15 @@
1921
import com.crowdin.client.ai.model.FineTuningJobRequest;
2022
import com.crowdin.client.ai.model.FineTuningJobResponseList;
2123
import com.crowdin.client.ai.model.FineTuningJobResponseObject;
24+
import com.crowdin.client.ai.model.GenerateAiReportRequest;
2225
import com.crowdin.client.core.CrowdinApi;
2326
import com.crowdin.client.core.http.HttpRequestConfig;
27+
import com.crowdin.client.core.http.exceptions.HttpBadRequestException;
28+
import com.crowdin.client.core.http.exceptions.HttpException;
2429
import com.crowdin.client.core.model.ClientConfig;
2530
import com.crowdin.client.core.model.Credentials;
31+
import com.crowdin.client.core.model.DownloadLink;
32+
import com.crowdin.client.core.model.DownloadLinkResponseObject;
2633
import com.crowdin.client.core.model.PatchRequest;
2734
import com.crowdin.client.core.model.ResponseList;
2835
import com.crowdin.client.core.model.ResponseObject;
@@ -161,6 +168,51 @@ public ResponseObject<FineTuningDatasetDownload> downloadFineTuningDataset(final
161168
return ResponseObject.of(response.getData());
162169
}
163170

171+
/**
172+
* @param userId user identifier
173+
* @param request request object
174+
* @return AI report generation status
175+
* @see <ul>
176+
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.reports.post" target="_blank"><b>API Documentation</b></a></li>
177+
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.ai.reports.post" target="_blank"><b>Enterprise API Documentation</b></a></li>
178+
* </ul>
179+
*/
180+
public ResponseObject<AiReportGenerate> generateAiReport(final Long userId, final GenerateAiReportRequest request) throws HttpException, HttpBadRequestException {
181+
String url = getAIPath(userId, "ai/reports");
182+
AiReportGenerateResponse response = this.httpClient.post(url, request, new HttpRequestConfig(), AiReportGenerateResponse.class);
183+
return ResponseObject.of(response.getData());
184+
}
185+
186+
/**
187+
* @param userId user identifier
188+
* @param aiReportId AI report identifier, consists of 36 characters
189+
* @return AI report generation status
190+
* @see <ul>
191+
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.reports.get" target="_blank"><b>API Documentation</b></a></li>
192+
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.ai.reports.get" target="_blank"><b>Enterprise API Documentation</b></a></li>
193+
* </ul>
194+
*/
195+
public ResponseObject<AiReportGenerate> checkAiReportGenerationStatus(final Long userId, final String aiReportId) throws HttpException, HttpBadRequestException {
196+
String url = getAIPath(userId, String.format("ai/reports/%s", aiReportId));
197+
AiReportGenerateResponse response = this.httpClient.get(url, new HttpRequestConfig(), AiReportGenerateResponse.class);
198+
return ResponseObject.of(response.getData());
199+
}
200+
201+
/**
202+
* @param userId user identifier
203+
* @param reportId AI report identifier, consists of 36 characters
204+
* @return AI report download URL
205+
* @see <ul>
206+
* <li><a href="https://developer.crowdin.com/api/v2/#operation/api.users.ai.reports.download.download" target="_blank"><b>API Documentation</b></a></li>
207+
* <li><a href="https://developer.crowdin.com/enterprise/api/v2/#operation/api.ai.reports.download.download" target="_blank"><b>Enterprise API Documentation</b></a></li>
208+
* </ul>
209+
*/
210+
public ResponseObject<DownloadLink> downloadAiReport(final Long userId, final String reportId) throws HttpException, HttpBadRequestException {
211+
String url = getAIPath(userId, String.format("ai/reports/%s/download", reportId));
212+
DownloadLinkResponseObject response = this.httpClient.get(url, new HttpRequestConfig(), DownloadLinkResponseObject.class);
213+
return ResponseObject.of(response.getData());
214+
}
215+
164216
/**
165217
* @param userId user identifier
166218
* @return AI settings
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.crowdin.client.ai.model;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class AiReportAttributes {
7+
private AiReportFormat format;
8+
private String reportType;
9+
private Object schema;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.crowdin.client.ai.model;
2+
3+
import com.crowdin.client.core.model.EnumConverter;
4+
5+
public enum AiReportFormat implements EnumConverter<AiReportFormat> {
6+
JSON, CSV;
7+
8+
public static AiReportFormat from(String value) {
9+
return AiReportFormat.valueOf(value.toUpperCase());
10+
}
11+
12+
@Override
13+
public Object to(AiReportFormat v) {
14+
return v.name().toLowerCase();
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.crowdin.client.ai.model;
2+
3+
import lombok.Data;
4+
5+
import java.util.Date;
6+
7+
@Data
8+
public class AiReportGenerate {
9+
private String identifier;
10+
private String status;
11+
private int progress;
12+
private AiReportAttributes attributes;
13+
private Date createdAt;
14+
private Date updatedAt;
15+
private Date startedAt;
16+
private Date finishedAt;
17+
private String eta;
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.crowdin.client.ai.model;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class AiReportGenerateResponse {
7+
private AiReportGenerate data;
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.crowdin.client.ai.model;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class GenerateAiReportRequest {
7+
private String type;
8+
private GenerateAiReportRequestSchema schema;
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.crowdin.client.ai.model;
2+
3+
import lombok.Data;
4+
5+
import java.util.Date;
6+
import java.util.List;
7+
8+
@Data
9+
public class GenerateAiReportRequestSchema {
10+
private Date dateFrom;
11+
private Date dateTo;
12+
private AiReportFormat format;
13+
private List<Long> projectIds;
14+
private List<Long> promptIds;
15+
private List<Long> userIds;
16+
}

src/test/java/com/crowdin/client/ai/AIApiTest.java

+51-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.crowdin.client.ai.model.AiProvider;
44
import com.crowdin.client.ai.model.AiProviderRequest;
5+
import com.crowdin.client.ai.model.AiReportGenerate;
6+
import com.crowdin.client.ai.model.AiReportFormat;
57
import com.crowdin.client.ai.model.Credentials;
68
import com.crowdin.client.ai.model.AiProviderModel;
79
import com.crowdin.client.ai.model.AiSetting;
@@ -12,6 +14,9 @@
1214
import com.crowdin.client.ai.model.FineTuningJob;
1315
import com.crowdin.client.ai.model.FineTuningJobRequest;
1416
import com.crowdin.client.ai.model.FineTuningJobRequest.Hyperparameters;
17+
import com.crowdin.client.ai.model.GenerateAiReportRequest;
18+
import com.crowdin.client.ai.model.GenerateAiReportRequestSchema;
19+
import com.crowdin.client.core.model.DownloadLink;
1520
import com.crowdin.client.core.model.Pagination;
1621
import com.crowdin.client.core.model.PatchRequest;
1722
import com.crowdin.client.core.model.PatchOperation;
@@ -33,7 +38,6 @@
3338
import org.apache.http.client.methods.HttpPost;
3439
import org.junit.jupiter.api.Test;
3540

36-
3741
import static org.junit.jupiter.api.Assertions.assertEquals;
3842
import static org.junit.jupiter.api.Assertions.assertNotNull;
3943

@@ -52,17 +56,20 @@ public class AIApiTest extends TestClient {
5256
private static final long size = 1L;
5357
private static final String status = "finished";
5458
private static final String jobIdentifier = "50fb3506-4127-4ba8-8296-f97dc7e3e0c3";
59+
private static final String aiReportId = "50fb3506-4127-4ba8-8296-f97dc7e3e0c3";
5560
private static final TimeZone tz = TimeZone.getTimeZone("GMT");
5661
private final Calendar calendar = GregorianCalendar.getInstance(tz);
5762

58-
5963
private static final String FINE_TUNING_DATASET_GENERATION_STATUS_PATH = "%s/users/%d/ai/prompts/%d/fine-tuning/datasets/%s";
6064
private static final String GENERATE_FINE_TUNING_DATASET_PATH = "%s/users/%d/ai/prompts/%d/fine-tuning/datasets";
6165
private static final String GET_FINE_TUNING_EVENT_LIST_PATH = "%s/users/%d/ai/prompts/%d/fine-tuning/jobs/%s/events";
6266
private static final String GET_FINE_TUNING_JOB_LIST_PATH = "%s/users/%d/ai/prompts/fine-tuning/jobs";
6367
private static final String CREATE_FINE_TUNING_JOB_PATH = "%s/users/%d/ai/prompts/%d/fine-tuning/jobs";
6468
private static final String GET_FINE_TUNING_JOB_STATUS_PATH = "%s/users/%d/ai/prompts/%d/fine-tuning/jobs/%s";
6569
private static final String FINE_TUNING_DATASET_DOWNLOAD_PATH = "%s/users/%d/ai/prompts/%d/fine-tuning/datasets/%s/download";
70+
private static final String GENERATE_AI_REPORT_PATH = "%s/users/%d/ai/reports";
71+
private static final String CHECK_AI_REPORT_GENERATION_PATH = "%s/users/%d/ai/reports/%s";
72+
private static final String DOWNLOAD_AI_REPORT_PATH = "%s/users/%d/ai/reports/%s/download";
6673
private static final String GET_SETTINGS = "%s/users/%d/ai/settings";
6774
private static final String LIST_AI_PROVIDERS = "%s/users/%d/ai/providers";
6875
private static final String GET_AI_PROVIDER = "%s/users/%d/ai/providers/%d";
@@ -73,6 +80,7 @@ private Date getDateTime(int year, int month, int date, int hour, int minute, in
7380
calendar.set(Calendar.MILLISECOND, 0);
7481
return calendar.getTime();
7582
}
83+
7684
@Override
7785
public List<RequestMock> getMocks() {
7886
return Arrays.asList(
@@ -83,6 +91,10 @@ public List<RequestMock> getMocks() {
8391
RequestMock.build(String.format(CREATE_FINE_TUNING_JOB_PATH, this.url, userId, aiPromptId), HttpPost.METHOD_NAME, "api/ai/fineTuningJobRequest.json", "api/ai/fineTuningJobResponse.json"),
8492
RequestMock.build(String.format(GET_FINE_TUNING_JOB_STATUS_PATH, this.url, userId, aiPromptId, jobIdentifier), HttpGet.METHOD_NAME, "api/ai/fineTuningJobStatusResponse.json"),
8593
RequestMock.build(String.format(FINE_TUNING_DATASET_DOWNLOAD_PATH, this.url, userId, aiPromptId, jobIdentifier), HttpGet.METHOD_NAME, "api/ai/downloadFineTuningDataset.json"),
94+
RequestMock.build(String.format(GENERATE_AI_REPORT_PATH, this.url, userId), HttpPost.METHOD_NAME, "api/ai/generateAiReportRequest.json", "api/ai/generateAiReportResponse.json"),
95+
RequestMock.build(String.format(CHECK_AI_REPORT_GENERATION_PATH, this.url, userId, aiReportId), HttpGet.METHOD_NAME, "api/ai/checkAiReportGenerationStatusResponse.json"),
96+
RequestMock.build(String.format(DOWNLOAD_AI_REPORT_PATH, this.url, userId, aiReportId), HttpGet.METHOD_NAME, "api/ai/downloadAiReportResponse.json"),
97+
RequestMock.build(String.format(FINE_TUNING_DATASET_DOWNLOAD_PATH, this.url, userId, aiPromptId, jobIdentifier), HttpGet.METHOD_NAME, "api/ai/downloadFineTuningDataset.json"),
8698
RequestMock.build(String.format(GET_SETTINGS, this.url, userId), HttpGet.METHOD_NAME, "api/ai/getAiSettingResponse.json"),
8799
RequestMock.build(String.format(GET_SETTINGS, this.url, userId), HttpPatch.METHOD_NAME, "api/ai/editAiSettingRequest.json", "api/ai/getAiSettingResponse.json"),
88100
RequestMock.build(String.format(FINE_TUNING_DATASET_DOWNLOAD_PATH, this.url, userId, aiPromptId, jobIdentifier), HttpGet.METHOD_NAME, "api/ai/downloadFineTuningDataset.json"),
@@ -95,7 +107,6 @@ public List<RequestMock> getMocks() {
95107
);
96108
}
97109

98-
99110
@Test
100111
public void datasetGenerationStatusTest() {
101112
Date dateCreated = getDateTime(year, month, date, hour, minutes, seconds);
@@ -199,6 +210,43 @@ public void downloadFineTuningDatasetTest() {
199210
assertNotNull(responseObject.getData().getUrl());
200211
}
201212

213+
@Test
214+
public void generateAiReportTest() {
215+
final Date dateFrom = getDateTime(year, month, date, hour, minutes, seconds);
216+
final Date dateTo = getDateTime(year, month, date, hour, minutes, seconds);
217+
218+
GenerateAiReportRequestSchema schema = new GenerateAiReportRequestSchema();
219+
schema.setDateFrom(dateFrom);
220+
schema.setDateTo(dateTo);
221+
schema.setFormat(AiReportFormat.JSON);
222+
schema.setProjectIds(Collections.singletonList(0L));
223+
schema.setPromptIds(Collections.singletonList(0L));
224+
schema.setUserIds(Collections.singletonList(userId));
225+
226+
GenerateAiReportRequest request = new GenerateAiReportRequest();
227+
request.setType("tokens-usage-raw-data");
228+
request.setSchema(schema);
229+
230+
ResponseObject<AiReportGenerate> responseObject = this.getAiApi().generateAiReport(userId, request);
231+
assertNotNull(responseObject.getData());
232+
assertEquals(responseObject.getData().getAttributes().getReportType(), request.getType());
233+
}
234+
235+
@Test
236+
public void checkAiReportGenerationStatusTest() {
237+
final Date dateCreated = getDateTime(year, month, date, hour, minutes, seconds);
238+
ResponseObject<AiReportGenerate> responseObject = this.getAiApi().checkAiReportGenerationStatus(userId, aiReportId);
239+
assertNotNull(responseObject.getData());
240+
assertEquals(responseObject.getData().getCreatedAt(), dateCreated);
241+
}
242+
243+
@Test
244+
public void downloadAiReportTest() {
245+
ResponseObject<DownloadLink> responseObject = this.getAiApi().downloadAiReport(userId, aiReportId);
246+
assertNotNull(responseObject.getData());
247+
assertNotNull(responseObject.getData().getUrl());
248+
}
249+
202250
@Test
203251
public void getAiSettingTest() {
204252
AiSetting aiSetting = this.getAiApi().getAiSetting(userId).getData();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"data": {
3+
"identifier": "50fb3506-4127-4ba8-8296-f97dc7e3e0c3",
4+
"status": "finished",
5+
"progress": 100,
6+
"attributes": {
7+
"format": "json",
8+
"reportType": "tokens-usage-raw-data",
9+
"schema": {}
10+
},
11+
"createdAt": "2019-09-23T11:26:54+00:00",
12+
"updatedAt": "2019-09-23T11:26:54+00:00",
13+
"startedAt": "2019-09-23T11:26:54+00:00",
14+
"finishedAt": "2019-09-23T11:26:54+00:00",
15+
"eta": "1 second"
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"data": {
3+
"url": "https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62",
4+
"expireIn": "2019-09-23T11:26:54+00:00"
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"type": "tokens-usage-raw-data",
3+
"schema": {
4+
"dateFrom": "2019-09-23T11:26:54+00:00",
5+
"dateTo": "2019-09-23T11:26:54+00:00",
6+
"format": "json",
7+
"projectIds": [
8+
0
9+
],
10+
"promptIds": [
11+
0
12+
],
13+
"userIds": [
14+
2
15+
]
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"data": {
3+
"identifier": "50fb3506-4127-4ba8-8296-f97dc7e3e0c3",
4+
"status": "finished",
5+
"progress": 100,
6+
"attributes": {
7+
"format": "json",
8+
"reportType": "tokens-usage-raw-data",
9+
"schema": {}
10+
},
11+
"createdAt": "2019-09-23T11:26:54+00:00",
12+
"updatedAt": "2019-09-23T11:26:54+00:00",
13+
"startedAt": "2019-09-23T11:26:54+00:00",
14+
"finishedAt": "2019-09-23T11:26:54+00:00",
15+
"eta": "1 second"
16+
}
17+
}

0 commit comments

Comments
 (0)