@things-factory/integration-label-studio 9.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +85 -0
- package/EXTERNAL_DATA_SOURCING.md +484 -0
- package/IMPLEMENTATION_GUIDE.md +469 -0
- package/INTEGRATION.md +279 -0
- package/README.md +1014 -0
- package/SETUP_GUIDE.md +577 -0
- package/TEST_GUIDE.md +387 -0
- package/UI_CUSTOMIZATION.md +395 -0
- package/USER_SYNC_GUIDE.md +514 -0
- package/client/bootstrap.ts +1 -0
- package/client/index.ts +1 -0
- package/client/label-studio-label-page.ts +52 -0
- package/client/label-studio-project-create.ts +216 -0
- package/client/label-studio-project-list.ts +214 -0
- package/client/label-studio-wrapper.ts +294 -0
- package/client/route.ts +15 -0
- package/client/tsconfig.json +13 -0
- package/config/config.development.js +124 -0
- package/config/config.production.js +182 -0
- package/dist-client/bootstrap.d.ts +1 -0
- package/dist-client/bootstrap.js +2 -0
- package/dist-client/bootstrap.js.map +1 -0
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +2 -0
- package/dist-client/index.js.map +1 -0
- package/dist-client/label-studio-label-page.d.ts +8 -0
- package/dist-client/label-studio-label-page.js +54 -0
- package/dist-client/label-studio-label-page.js.map +1 -0
- package/dist-client/label-studio-project-create.d.ts +16 -0
- package/dist-client/label-studio-project-create.js +235 -0
- package/dist-client/label-studio-project-create.js.map +1 -0
- package/dist-client/label-studio-project-list.d.ts +16 -0
- package/dist-client/label-studio-project-list.js +222 -0
- package/dist-client/label-studio-project-list.js.map +1 -0
- package/dist-client/label-studio-wrapper.d.ts +57 -0
- package/dist-client/label-studio-wrapper.js +304 -0
- package/dist-client/label-studio-wrapper.js.map +1 -0
- package/dist-client/route.d.ts +1 -0
- package/dist-client/route.js +14 -0
- package/dist-client/route.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-server/controller/label-studio-role-mapper.d.ts +35 -0
- package/dist-server/controller/label-studio-role-mapper.js +65 -0
- package/dist-server/controller/label-studio-role-mapper.js.map +1 -0
- package/dist-server/controller/user-provisioning-service.d.ts +66 -0
- package/dist-server/controller/user-provisioning-service.js +264 -0
- package/dist-server/controller/user-provisioning-service.js.map +1 -0
- package/dist-server/index.d.ts +7 -0
- package/dist-server/index.js +19 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/route/label-studio-sso.d.ts +2 -0
- package/dist-server/route/label-studio-sso.js +156 -0
- package/dist-server/route/label-studio-sso.js.map +1 -0
- package/dist-server/route/webhook.d.ts +65 -0
- package/dist-server/route/webhook.js +248 -0
- package/dist-server/route/webhook.js.map +1 -0
- package/dist-server/route.d.ts +1 -0
- package/dist-server/route.js +21 -0
- package/dist-server/route.js.map +1 -0
- package/dist-server/service/ai-prediction-service.d.ts +27 -0
- package/dist-server/service/ai-prediction-service.js +222 -0
- package/dist-server/service/ai-prediction-service.js.map +1 -0
- package/dist-server/service/dataset-labeling-integration.d.ts +44 -0
- package/dist-server/service/dataset-labeling-integration.js +512 -0
- package/dist-server/service/dataset-labeling-integration.js.map +1 -0
- package/dist-server/service/external-data-source-service.d.ts +78 -0
- package/dist-server/service/external-data-source-service.js +415 -0
- package/dist-server/service/external-data-source-service.js.map +1 -0
- package/dist-server/service/index.d.ts +12 -0
- package/dist-server/service/index.js +27 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/label-studio-sso-service.d.ts +38 -0
- package/dist-server/service/label-studio-sso-service.js +98 -0
- package/dist-server/service/label-studio-sso-service.js.map +1 -0
- package/dist-server/service/ml/ml-backend-service.d.ts +23 -0
- package/dist-server/service/ml/ml-backend-service.js +153 -0
- package/dist-server/service/ml/ml-backend-service.js.map +1 -0
- package/dist-server/service/prediction/prediction-management.d.ts +32 -0
- package/dist-server/service/prediction/prediction-management.js +299 -0
- package/dist-server/service/prediction/prediction-management.js.map +1 -0
- package/dist-server/service/project/project-management.d.ts +36 -0
- package/dist-server/service/project/project-management.js +309 -0
- package/dist-server/service/project/project-management.js.map +1 -0
- package/dist-server/service/task/task-management.d.ts +42 -0
- package/dist-server/service/task/task-management.js +372 -0
- package/dist-server/service/task/task-management.js.map +1 -0
- package/dist-server/service/user-provisioning/user-sync-mutation.d.ts +28 -0
- package/dist-server/service/user-provisioning/user-sync-mutation.js +111 -0
- package/dist-server/service/user-provisioning/user-sync-mutation.js.map +1 -0
- package/dist-server/service/webhook/webhook-management.d.ts +21 -0
- package/dist-server/service/webhook/webhook-management.js +134 -0
- package/dist-server/service/webhook/webhook-management.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/dist-server/types/dataset-labeling-types.d.ts +71 -0
- package/dist-server/types/dataset-labeling-types.js +259 -0
- package/dist-server/types/dataset-labeling-types.js.map +1 -0
- package/dist-server/types/label-studio-types.d.ts +128 -0
- package/dist-server/types/label-studio-types.js +494 -0
- package/dist-server/types/label-studio-types.js.map +1 -0
- package/dist-server/types/prediction-types.d.ts +39 -0
- package/dist-server/types/prediction-types.js +121 -0
- package/dist-server/types/prediction-types.js.map +1 -0
- package/dist-server/utils/annotation-exporter.d.ts +104 -0
- package/dist-server/utils/annotation-exporter.js +261 -0
- package/dist-server/utils/annotation-exporter.js.map +1 -0
- package/dist-server/utils/label-config-builder.d.ts +117 -0
- package/dist-server/utils/label-config-builder.js +286 -0
- package/dist-server/utils/label-config-builder.js.map +1 -0
- package/dist-server/utils/label-studio-api-client.d.ts +180 -0
- package/dist-server/utils/label-studio-api-client.js +401 -0
- package/dist-server/utils/label-studio-api-client.js.map +1 -0
- package/dist-server/utils/media-url-extractor.d.ts +45 -0
- package/dist-server/utils/media-url-extractor.js +152 -0
- package/dist-server/utils/media-url-extractor.js.map +1 -0
- package/dist-server/utils/task-transformer.d.ts +108 -0
- package/dist-server/utils/task-transformer.js +260 -0
- package/dist-server/utils/task-transformer.js.map +1 -0
- package/package.json +47 -0
- package/server/SERVER_STRUCTURE.md +351 -0
- package/server/controller/label-studio-role-mapper.ts +76 -0
- package/server/controller/user-provisioning-service.ts +340 -0
- package/server/index.ts +19 -0
- package/server/route/label-studio-sso.ts +194 -0
- package/server/route/webhook.ts +304 -0
- package/server/route.ts +35 -0
- package/server/service/ai-prediction-service.ts +239 -0
- package/server/service/dataset-labeling-integration.ts +590 -0
- package/server/service/external-data-source-service.ts +438 -0
- package/server/service/index.ts +24 -0
- package/server/service/label-studio-sso-service.ts +108 -0
- package/server/service/labeling-scenario-service.ts.deprecated +566 -0
- package/server/service/ml/ml-backend-service.ts +127 -0
- package/server/service/prediction/prediction-management.ts +281 -0
- package/server/service/project/project-management.ts +284 -0
- package/server/service/task/task-management.ts +363 -0
- package/server/service/user-provisioning/user-sync-mutation.ts +80 -0
- package/server/service/webhook/webhook-management.ts +109 -0
- package/server/tsconfig.json +11 -0
- package/server/types/dataset-labeling-types.ts +181 -0
- package/server/types/global.d.ts +23 -0
- package/server/types/label-studio-types.ts +346 -0
- package/server/types/prediction-types.ts +86 -0
- package/server/types/scenario-types.ts.deprecated +362 -0
- package/server/utils/annotation-exporter.ts +340 -0
- package/server/utils/label-config-builder.ts +340 -0
- package/server/utils/label-studio-api-client.ts +487 -0
- package/server/utils/media-url-extractor.ts +193 -0
- package/server/utils/task-transformer.ts +342 -0
- package/test-ai-prediction.js +268 -0
- package/test-dataset-integration.js +449 -0
- package/test-simple.js +89 -0
- package/things-factory.config.js +12 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LabelStudioSSOService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const axios_1 = tslib_1.__importDefault(require("axios"));
|
|
6
|
+
const env_1 = require("@things-factory/env");
|
|
7
|
+
/**
|
|
8
|
+
* Label Studio SSO Service
|
|
9
|
+
*
|
|
10
|
+
* Handles JWT token acquisition from Label Studio for SSO authentication.
|
|
11
|
+
* The client application requests JWT tokens from Label Studio's token API,
|
|
12
|
+
* then uses cookie-based authentication to automatically log users in.
|
|
13
|
+
*/
|
|
14
|
+
class LabelStudioSSOService {
|
|
15
|
+
/**
|
|
16
|
+
* Get Label Studio SSO configuration
|
|
17
|
+
*/
|
|
18
|
+
static getConfig() {
|
|
19
|
+
const labelStudioConfig = env_1.config.get('labelStudio', {
|
|
20
|
+
serverUrl: 'http://localhost:8080',
|
|
21
|
+
apiToken: ''
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
serverUrl: labelStudioConfig.serverUrl,
|
|
25
|
+
apiToken: labelStudioConfig.apiToken
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Request JWT token from Label Studio for SSO authentication
|
|
30
|
+
*
|
|
31
|
+
* @param email User email address
|
|
32
|
+
* @returns JWT token and expiry time, or null if failed
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const tokenData = await LabelStudioSSOService.getSSOToken('user@example.com')
|
|
37
|
+
* if (tokenData) {
|
|
38
|
+
* console.log('Token:', tokenData.token)
|
|
39
|
+
* console.log('Expires in:', tokenData.expires_in, 'seconds')
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
static async getSSOToken(email) {
|
|
44
|
+
const { serverUrl, apiToken } = this.getConfig();
|
|
45
|
+
if (!apiToken) {
|
|
46
|
+
console.error('[LSS SSO] Label Studio API token not configured');
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
if (!email) {
|
|
50
|
+
console.error('[LSS SSO] Email is required');
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
console.log(`[LSS SSO] Requesting JWT token for: ${email}`);
|
|
55
|
+
const response = await axios_1.default.post(`${serverUrl}/api/sso/token`, { email }, {
|
|
56
|
+
headers: {
|
|
57
|
+
'Authorization': `Token ${apiToken}`,
|
|
58
|
+
'Content-Type': 'application/json'
|
|
59
|
+
},
|
|
60
|
+
timeout: 5000
|
|
61
|
+
});
|
|
62
|
+
const { token, expires_in } = response.data;
|
|
63
|
+
console.log(`[LSS SSO] JWT token acquired for ${email} (expires in ${expires_in}s)`);
|
|
64
|
+
return { token, expires_in };
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (error.response) {
|
|
68
|
+
console.error(`[LSS SSO] Label Studio API error: ${error.response.status}`, error.response.data);
|
|
69
|
+
}
|
|
70
|
+
else if (error.request) {
|
|
71
|
+
console.error('[LSS SSO] No response from Label Studio:', error.message);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.error('[LSS SSO] Request error:', error.message);
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Verify SSO configuration is properly set up
|
|
81
|
+
*
|
|
82
|
+
* @returns True if configuration is valid
|
|
83
|
+
*/
|
|
84
|
+
static verifyConfig() {
|
|
85
|
+
const { serverUrl, apiToken } = this.getConfig();
|
|
86
|
+
if (!serverUrl) {
|
|
87
|
+
console.error('[LSS SSO] Label Studio server URL not configured');
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
if (!apiToken) {
|
|
91
|
+
console.error('[LSS SSO] Label Studio API token not configured');
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.LabelStudioSSOService = LabelStudioSSOService;
|
|
98
|
+
//# sourceMappingURL=label-studio-sso-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label-studio-sso-service.js","sourceRoot":"","sources":["../../server/service/label-studio-sso-service.ts"],"names":[],"mappings":";;;;AAAA,0DAAyB;AACzB,6CAA4C;AAE5C;;;;;;GAMG;AACH,MAAa,qBAAqB;IAChC;;OAEG;IACK,MAAM,CAAC,SAAS;QACtB,MAAM,iBAAiB,GAAG,YAAM,CAAC,GAAG,CAAC,aAAa,EAAE;YAClD,SAAS,EAAE,uBAAuB;YAClC,QAAQ,EAAE,EAAE;SACb,CAAC,CAAA;QAEF,OAAO;YACL,SAAS,EAAE,iBAAiB,CAAC,SAAS;YACtC,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;SACrC,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,KAAa;QACpC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAEhD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAA;YAChE,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;YAC5C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,uCAAuC,KAAK,EAAE,CAAC,CAAA;YAE3D,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAC/B,GAAG,SAAS,gBAAgB,EAC5B,EAAE,KAAK,EAAE,EACT;gBACE,OAAO,EAAE;oBACP,eAAe,EAAE,SAAS,QAAQ,EAAE;oBACpC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,OAAO,EAAE,IAAI;aACd,CACF,CAAA;YAED,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAA;YAE3C,OAAO,CAAC,GAAG,CAAC,oCAAoC,KAAK,gBAAgB,UAAU,IAAI,CAAC,CAAA;YAEpF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;QAC9B,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YAClG,CAAC;iBAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBACzB,OAAO,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;YAC1E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;YAC1D,CAAC;YAED,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,YAAY;QACjB,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAEhD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAA;YACjE,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAA;YAChE,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAjGD,sDAiGC","sourcesContent":["import axios from 'axios'\nimport { config } from '@things-factory/env'\n\n/**\n * Label Studio SSO Service\n *\n * Handles JWT token acquisition from Label Studio for SSO authentication.\n * The client application requests JWT tokens from Label Studio's token API,\n * then uses cookie-based authentication to automatically log users in.\n */\nexport class LabelStudioSSOService {\n /**\n * Get Label Studio SSO configuration\n */\n private static getConfig() {\n const labelStudioConfig = config.get('labelStudio', {\n serverUrl: 'http://localhost:8080',\n apiToken: ''\n })\n\n return {\n serverUrl: labelStudioConfig.serverUrl,\n apiToken: labelStudioConfig.apiToken\n }\n }\n\n /**\n * Request JWT token from Label Studio for SSO authentication\n *\n * @param email User email address\n * @returns JWT token and expiry time, or null if failed\n *\n * @example\n * ```typescript\n * const tokenData = await LabelStudioSSOService.getSSOToken('user@example.com')\n * if (tokenData) {\n * console.log('Token:', tokenData.token)\n * console.log('Expires in:', tokenData.expires_in, 'seconds')\n * }\n * ```\n */\n static async getSSOToken(email: string): Promise<{ token: string; expires_in: number } | null> {\n const { serverUrl, apiToken } = this.getConfig()\n\n if (!apiToken) {\n console.error('[LSS SSO] Label Studio API token not configured')\n return null\n }\n\n if (!email) {\n console.error('[LSS SSO] Email is required')\n return null\n }\n\n try {\n console.log(`[LSS SSO] Requesting JWT token for: ${email}`)\n\n const response = await axios.post(\n `${serverUrl}/api/sso/token`,\n { email },\n {\n headers: {\n 'Authorization': `Token ${apiToken}`,\n 'Content-Type': 'application/json'\n },\n timeout: 5000\n }\n )\n\n const { token, expires_in } = response.data\n\n console.log(`[LSS SSO] JWT token acquired for ${email} (expires in ${expires_in}s)`)\n\n return { token, expires_in }\n } catch (error: any) {\n if (error.response) {\n console.error(`[LSS SSO] Label Studio API error: ${error.response.status}`, error.response.data)\n } else if (error.request) {\n console.error('[LSS SSO] No response from Label Studio:', error.message)\n } else {\n console.error('[LSS SSO] Request error:', error.message)\n }\n\n return null\n }\n }\n\n /**\n * Verify SSO configuration is properly set up\n *\n * @returns True if configuration is valid\n */\n static verifyConfig(): boolean {\n const { serverUrl, apiToken } = this.getConfig()\n\n if (!serverUrl) {\n console.error('[LSS SSO] Label Studio server URL not configured')\n return false\n }\n\n if (!apiToken) {\n console.error('[LSS SSO] Label Studio API token not configured')\n return false\n }\n\n return true\n }\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MLBackend, AddMLBackendInput } from '../../types/label-studio-types.js';
|
|
2
|
+
export declare class MLBackendService {
|
|
3
|
+
/**
|
|
4
|
+
* Get ML backends for a project
|
|
5
|
+
*/
|
|
6
|
+
labelStudioMLBackends(projectId: number, context: ResolverContext): Promise<MLBackend[]>;
|
|
7
|
+
/**
|
|
8
|
+
* Add ML backend to project
|
|
9
|
+
*/
|
|
10
|
+
addMLBackendToProject(projectId: number, input: AddMLBackendInput, context: ResolverContext): Promise<MLBackend>;
|
|
11
|
+
/**
|
|
12
|
+
* Delete ML backend
|
|
13
|
+
*/
|
|
14
|
+
deleteMLBackend(mlBackendId: number, context: ResolverContext): Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Trigger predictions for tasks
|
|
17
|
+
*/
|
|
18
|
+
triggerLabelStudioPredictions(projectId: number, context: ResolverContext, taskIds?: number[]): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* Train ML model
|
|
21
|
+
*/
|
|
22
|
+
trainLabelStudioModel(mlBackendId: number, context: ResolverContext): Promise<boolean>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MLBackendService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const label_studio_api_client_js_1 = require("../../utils/label-studio-api-client.js");
|
|
7
|
+
const label_studio_types_js_1 = require("../../types/label-studio-types.js");
|
|
8
|
+
let MLBackendService = class MLBackendService {
|
|
9
|
+
/**
|
|
10
|
+
* Get ML backends for a project
|
|
11
|
+
*/
|
|
12
|
+
async labelStudioMLBackends(projectId, context) {
|
|
13
|
+
try {
|
|
14
|
+
const backends = await label_studio_api_client_js_1.labelStudioApi.getMLBackends(projectId);
|
|
15
|
+
return backends.map(backend => ({
|
|
16
|
+
id: backend.id,
|
|
17
|
+
url: backend.url,
|
|
18
|
+
title: backend.title,
|
|
19
|
+
isInteractive: backend.is_interactive || false,
|
|
20
|
+
modelVersion: backend.model_version || 'unknown'
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error(`Failed to fetch ML backends for project ${projectId}:`, error);
|
|
25
|
+
throw new Error(`Failed to fetch ML backends: ${error.message}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Add ML backend to project
|
|
30
|
+
*/
|
|
31
|
+
async addMLBackendToProject(projectId, input, context) {
|
|
32
|
+
try {
|
|
33
|
+
const backend = await label_studio_api_client_js_1.labelStudioApi.addMLBackend({
|
|
34
|
+
project: projectId,
|
|
35
|
+
url: input.url,
|
|
36
|
+
title: input.title,
|
|
37
|
+
is_interactive: input.isInteractive || false
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
id: backend.id,
|
|
41
|
+
url: backend.url,
|
|
42
|
+
title: backend.title,
|
|
43
|
+
isInteractive: backend.is_interactive || false,
|
|
44
|
+
modelVersion: backend.model_version || 'unknown'
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error(`Failed to add ML backend to project ${projectId}:`, error);
|
|
49
|
+
throw new Error(`Failed to add ML backend: ${error.message}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Delete ML backend
|
|
54
|
+
*/
|
|
55
|
+
async deleteMLBackend(mlBackendId, context) {
|
|
56
|
+
try {
|
|
57
|
+
await label_studio_api_client_js_1.labelStudioApi.deleteMLBackend(mlBackendId);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error(`Failed to delete ML backend ${mlBackendId}:`, error);
|
|
62
|
+
throw new Error(`Failed to delete ML backend: ${error.message}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Trigger predictions for tasks
|
|
67
|
+
*/
|
|
68
|
+
async triggerLabelStudioPredictions(projectId, context, taskIds) {
|
|
69
|
+
try {
|
|
70
|
+
await label_studio_api_client_js_1.labelStudioApi.triggerPredictions(projectId, taskIds);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error(`Failed to trigger predictions for project ${projectId}:`, error);
|
|
75
|
+
throw new Error(`Failed to trigger predictions: ${error.message}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Train ML model
|
|
80
|
+
*/
|
|
81
|
+
async trainLabelStudioModel(mlBackendId, context) {
|
|
82
|
+
try {
|
|
83
|
+
await label_studio_api_client_js_1.labelStudioApi.trainModel(mlBackendId);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.error(`Failed to train model ${mlBackendId}:`, error);
|
|
88
|
+
throw new Error(`Failed to train model: ${error.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
exports.MLBackendService = MLBackendService;
|
|
93
|
+
tslib_1.__decorate([
|
|
94
|
+
(0, type_graphql_1.Query)(returns => [label_studio_types_js_1.MLBackend], {
|
|
95
|
+
description: 'Get all ML backends connected to a Label Studio project'
|
|
96
|
+
}),
|
|
97
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "query")'),
|
|
98
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
|
|
99
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
100
|
+
tslib_1.__metadata("design:type", Function),
|
|
101
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object]),
|
|
102
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
103
|
+
], MLBackendService.prototype, "labelStudioMLBackends", null);
|
|
104
|
+
tslib_1.__decorate([
|
|
105
|
+
(0, type_graphql_1.Mutation)(returns => label_studio_types_js_1.MLBackend, {
|
|
106
|
+
description: 'Add ML backend to Label Studio project for predictions and training'
|
|
107
|
+
}),
|
|
108
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
|
|
109
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
|
|
110
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('input')),
|
|
111
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
112
|
+
tslib_1.__metadata("design:type", Function),
|
|
113
|
+
tslib_1.__metadata("design:paramtypes", [Number, label_studio_types_js_1.AddMLBackendInput, Object]),
|
|
114
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
115
|
+
], MLBackendService.prototype, "addMLBackendToProject", null);
|
|
116
|
+
tslib_1.__decorate([
|
|
117
|
+
(0, type_graphql_1.Mutation)(returns => Boolean, {
|
|
118
|
+
description: 'Remove ML backend from project'
|
|
119
|
+
}),
|
|
120
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
|
|
121
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('mlBackendId', type => type_graphql_1.Int)),
|
|
122
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
123
|
+
tslib_1.__metadata("design:type", Function),
|
|
124
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object]),
|
|
125
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
126
|
+
], MLBackendService.prototype, "deleteMLBackend", null);
|
|
127
|
+
tslib_1.__decorate([
|
|
128
|
+
(0, type_graphql_1.Mutation)(returns => Boolean, {
|
|
129
|
+
description: 'Trigger ML predictions for tasks in a project'
|
|
130
|
+
}),
|
|
131
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
|
|
132
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
|
|
133
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
134
|
+
tslib_1.__param(2, (0, type_graphql_1.Arg)('taskIds', type => [type_graphql_1.Int], { nullable: true })),
|
|
135
|
+
tslib_1.__metadata("design:type", Function),
|
|
136
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object, Array]),
|
|
137
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
138
|
+
], MLBackendService.prototype, "triggerLabelStudioPredictions", null);
|
|
139
|
+
tslib_1.__decorate([
|
|
140
|
+
(0, type_graphql_1.Mutation)(returns => Boolean, {
|
|
141
|
+
description: 'Trigger ML model training with current annotations'
|
|
142
|
+
}),
|
|
143
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
|
|
144
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('mlBackendId', type => type_graphql_1.Int)),
|
|
145
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
146
|
+
tslib_1.__metadata("design:type", Function),
|
|
147
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object]),
|
|
148
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
149
|
+
], MLBackendService.prototype, "trainLabelStudioModel", null);
|
|
150
|
+
exports.MLBackendService = MLBackendService = tslib_1.__decorate([
|
|
151
|
+
(0, type_graphql_1.Resolver)()
|
|
152
|
+
], MLBackendService);
|
|
153
|
+
//# sourceMappingURL=ml-backend-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ml-backend-service.js","sourceRoot":"","sources":["../../../server/service/ml/ml-backend-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Mutation, Query, Arg, Ctx, Int, Directive } from 'type-graphql'\nimport { labelStudioApi } from '../../utils/label-studio-api-client.js'\nimport { MLBackend, AddMLBackendInput } from '../../types/label-studio-types.js'\n\n@Resolver()\nexport class MLBackendService {\n /**\n * Get ML backends for a project\n */\n @Query(returns => [MLBackend], {\n description: 'Get all ML backends connected to a Label Studio project'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"query\")')\n async labelStudioMLBackends(\n @Arg('projectId', type => Int) projectId: number,\n @Ctx() context: ResolverContext\n ): Promise<MLBackend[]> {\n try {\n const backends = await labelStudioApi.getMLBackends(projectId)\n\n return backends.map(backend => ({\n id: backend.id,\n url: backend.url,\n title: backend.title,\n isInteractive: backend.is_interactive || false,\n modelVersion: backend.model_version || 'unknown'\n }))\n } catch (error) {\n console.error(`Failed to fetch ML backends for project ${projectId}:`, error)\n throw new Error(`Failed to fetch ML backends: ${error.message}`)\n }\n }\n\n /**\n * Add ML backend to project\n */\n @Mutation(returns => MLBackend, {\n description: 'Add ML backend to Label Studio project for predictions and training'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"mutation\")')\n async addMLBackendToProject(\n @Arg('projectId', type => Int) projectId: number,\n @Arg('input') input: AddMLBackendInput,\n @Ctx() context: ResolverContext\n ): Promise<MLBackend> {\n try {\n const backend = await labelStudioApi.addMLBackend({\n project: projectId,\n url: input.url,\n title: input.title,\n is_interactive: input.isInteractive || false\n })\n\n return {\n id: backend.id,\n url: backend.url,\n title: backend.title,\n isInteractive: backend.is_interactive || false,\n modelVersion: backend.model_version || 'unknown'\n }\n } catch (error) {\n console.error(`Failed to add ML backend to project ${projectId}:`, error)\n throw new Error(`Failed to add ML backend: ${error.message}`)\n }\n }\n\n /**\n * Delete ML backend\n */\n @Mutation(returns => Boolean, {\n description: 'Remove ML backend from project'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"mutation\")')\n async deleteMLBackend(\n @Arg('mlBackendId', type => Int) mlBackendId: number,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n try {\n await labelStudioApi.deleteMLBackend(mlBackendId)\n return true\n } catch (error) {\n console.error(`Failed to delete ML backend ${mlBackendId}:`, error)\n throw new Error(`Failed to delete ML backend: ${error.message}`)\n }\n }\n\n /**\n * Trigger predictions for tasks\n */\n @Mutation(returns => Boolean, {\n description: 'Trigger ML predictions for tasks in a project'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"mutation\")')\n async triggerLabelStudioPredictions(\n @Arg('projectId', type => Int) projectId: number,\n @Ctx() context: ResolverContext,\n @Arg('taskIds', type => [Int], { nullable: true }) taskIds?: number[]\n ): Promise<boolean> {\n try {\n await labelStudioApi.triggerPredictions(projectId, taskIds)\n return true\n } catch (error) {\n console.error(`Failed to trigger predictions for project ${projectId}:`, error)\n throw new Error(`Failed to trigger predictions: ${error.message}`)\n }\n }\n\n /**\n * Train ML model\n */\n @Mutation(returns => Boolean, {\n description: 'Trigger ML model training with current annotations'\n })\n @Directive('@privilege(category: \"label-studio\", privilege: \"mutation\")')\n async trainLabelStudioModel(\n @Arg('mlBackendId', type => Int) mlBackendId: number,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n try {\n await labelStudioApi.trainModel(mlBackendId)\n return true\n } catch (error) {\n console.error(`Failed to train model ${mlBackendId}:`, error)\n throw new Error(`Failed to train model: ${error.message}`)\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { LabelStudioPrediction, PredictionInput, PredictionImportResult, BulkPredictionInput } from '../../types/label-studio-types.js';
|
|
2
|
+
export declare class PredictionManagement {
|
|
3
|
+
/**
|
|
4
|
+
* Get predictions for a task
|
|
5
|
+
*/
|
|
6
|
+
labelStudioTaskPredictions(taskId: number, context: ResolverContext): Promise<LabelStudioPrediction[]>;
|
|
7
|
+
/**
|
|
8
|
+
* Get predictions for a project
|
|
9
|
+
*/
|
|
10
|
+
labelStudioProjectPredictions(projectId: number, context: ResolverContext): Promise<LabelStudioPrediction[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Get single prediction by ID
|
|
13
|
+
*/
|
|
14
|
+
labelStudioPrediction(predictionId: number, context: ResolverContext): Promise<LabelStudioPrediction | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Create a prediction for a task
|
|
17
|
+
*/
|
|
18
|
+
createLabelStudioPrediction(input: PredictionInput, context: ResolverContext): Promise<LabelStudioPrediction>;
|
|
19
|
+
/**
|
|
20
|
+
* Create predictions in bulk
|
|
21
|
+
*/
|
|
22
|
+
createBulkPredictions(predictions: BulkPredictionInput[], context: ResolverContext): Promise<PredictionImportResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Import predictions for a project
|
|
25
|
+
* This is the recommended way to bulk import AI model predictions
|
|
26
|
+
*/
|
|
27
|
+
importPredictionsToProject(projectId: number, predictions: BulkPredictionInput[], context: ResolverContext): Promise<PredictionImportResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Delete prediction
|
|
30
|
+
*/
|
|
31
|
+
deleteLabelStudioPrediction(predictionId: number, context: ResolverContext): Promise<boolean>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PredictionManagement = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const label_studio_api_client_js_1 = require("../../utils/label-studio-api-client.js");
|
|
7
|
+
const label_studio_types_js_1 = require("../../types/label-studio-types.js");
|
|
8
|
+
let PredictionManagement = class PredictionManagement {
|
|
9
|
+
/**
|
|
10
|
+
* Get predictions for a task
|
|
11
|
+
*/
|
|
12
|
+
async labelStudioTaskPredictions(taskId, context) {
|
|
13
|
+
try {
|
|
14
|
+
const predictions = await label_studio_api_client_js_1.labelStudioApi.getPredictions(taskId);
|
|
15
|
+
return predictions.map((prediction) => ({
|
|
16
|
+
id: prediction.id,
|
|
17
|
+
taskId: prediction.task || taskId,
|
|
18
|
+
result: JSON.stringify(prediction.result),
|
|
19
|
+
score: prediction.score || undefined,
|
|
20
|
+
modelVersion: prediction.model_version || undefined,
|
|
21
|
+
createdAt: prediction.created_at ? new Date(prediction.created_at) : undefined
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.error(`Failed to fetch predictions for task ${taskId}:`, error);
|
|
26
|
+
throw new Error(`Failed to fetch predictions: ${error.message}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get predictions for a project
|
|
31
|
+
*/
|
|
32
|
+
async labelStudioProjectPredictions(projectId, context) {
|
|
33
|
+
try {
|
|
34
|
+
const predictions = await label_studio_api_client_js_1.labelStudioApi.getProjectPredictions(projectId);
|
|
35
|
+
return predictions.map((prediction) => ({
|
|
36
|
+
id: prediction.id,
|
|
37
|
+
taskId: prediction.task,
|
|
38
|
+
result: JSON.stringify(prediction.result),
|
|
39
|
+
score: prediction.score || undefined,
|
|
40
|
+
modelVersion: prediction.model_version || undefined,
|
|
41
|
+
createdAt: prediction.created_at ? new Date(prediction.created_at) : undefined
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error(`Failed to fetch predictions for project ${projectId}:`, error);
|
|
46
|
+
throw new Error(`Failed to fetch predictions: ${error.message}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get single prediction by ID
|
|
51
|
+
*/
|
|
52
|
+
async labelStudioPrediction(predictionId, context) {
|
|
53
|
+
try {
|
|
54
|
+
const prediction = await label_studio_api_client_js_1.labelStudioApi.getPrediction(predictionId);
|
|
55
|
+
if (!prediction) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
id: prediction.id,
|
|
60
|
+
taskId: prediction.task,
|
|
61
|
+
result: JSON.stringify(prediction.result),
|
|
62
|
+
score: prediction.score || undefined,
|
|
63
|
+
modelVersion: prediction.model_version || undefined,
|
|
64
|
+
createdAt: prediction.created_at ? new Date(prediction.created_at) : undefined
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error(`Failed to fetch prediction ${predictionId}:`, error);
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create a prediction for a task
|
|
74
|
+
*/
|
|
75
|
+
async createLabelStudioPrediction(input, context) {
|
|
76
|
+
try {
|
|
77
|
+
// Parse result JSON
|
|
78
|
+
const result = JSON.parse(input.result);
|
|
79
|
+
// Create prediction
|
|
80
|
+
const prediction = await label_studio_api_client_js_1.labelStudioApi.createPrediction({
|
|
81
|
+
task: input.taskId,
|
|
82
|
+
result,
|
|
83
|
+
score: input.score,
|
|
84
|
+
model_version: input.modelVersion
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
id: prediction.id,
|
|
88
|
+
taskId: prediction.task,
|
|
89
|
+
result: JSON.stringify(prediction.result),
|
|
90
|
+
score: prediction.score || undefined,
|
|
91
|
+
modelVersion: prediction.model_version || undefined,
|
|
92
|
+
createdAt: prediction.created_at ? new Date(prediction.created_at) : undefined
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error(`Failed to create prediction for task ${input.taskId}:`, error);
|
|
97
|
+
throw new Error(`Failed to create prediction: ${error.message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Create predictions in bulk
|
|
102
|
+
*/
|
|
103
|
+
async createBulkPredictions(predictions, context) {
|
|
104
|
+
const errors = [];
|
|
105
|
+
let created = 0;
|
|
106
|
+
let failed = 0;
|
|
107
|
+
try {
|
|
108
|
+
// Parse and validate predictions
|
|
109
|
+
const parsedPredictions = predictions.map((pred, index) => {
|
|
110
|
+
try {
|
|
111
|
+
return {
|
|
112
|
+
task: pred.taskId,
|
|
113
|
+
result: JSON.parse(pred.result),
|
|
114
|
+
score: pred.score,
|
|
115
|
+
model_version: pred.modelVersion
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
failed++;
|
|
120
|
+
errors.push(`Invalid JSON in prediction ${index}: ${pred.result}`);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const validPredictions = parsedPredictions.filter(p => p !== null);
|
|
125
|
+
if (validPredictions.length === 0) {
|
|
126
|
+
return {
|
|
127
|
+
created: 0,
|
|
128
|
+
failed: predictions.length,
|
|
129
|
+
errors
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// Create predictions
|
|
133
|
+
const response = await label_studio_api_client_js_1.labelStudioApi.createPredictions(validPredictions);
|
|
134
|
+
created = response.created || validPredictions.length;
|
|
135
|
+
return {
|
|
136
|
+
created,
|
|
137
|
+
failed,
|
|
138
|
+
errors: errors.length > 0 ? errors : undefined
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error('Failed to create bulk predictions:', error);
|
|
143
|
+
throw new Error(`Failed to create predictions: ${error.message}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Import predictions for a project
|
|
148
|
+
* This is the recommended way to bulk import AI model predictions
|
|
149
|
+
*/
|
|
150
|
+
async importPredictionsToProject(projectId, predictions, context) {
|
|
151
|
+
const errors = [];
|
|
152
|
+
let created = 0;
|
|
153
|
+
let failed = 0;
|
|
154
|
+
try {
|
|
155
|
+
// Parse and validate predictions
|
|
156
|
+
const parsedPredictions = predictions.map((pred, index) => {
|
|
157
|
+
try {
|
|
158
|
+
return {
|
|
159
|
+
task: pred.taskId,
|
|
160
|
+
result: JSON.parse(pred.result),
|
|
161
|
+
score: pred.score,
|
|
162
|
+
model_version: pred.modelVersion
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
failed++;
|
|
167
|
+
errors.push(`Invalid JSON in prediction ${index}: ${pred.result}`);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
const validPredictions = parsedPredictions.filter(p => p !== null);
|
|
172
|
+
if (validPredictions.length === 0) {
|
|
173
|
+
return {
|
|
174
|
+
created: 0,
|
|
175
|
+
failed: predictions.length,
|
|
176
|
+
errors
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// Import predictions using project endpoint
|
|
180
|
+
const response = await label_studio_api_client_js_1.labelStudioApi.importPredictions(projectId, validPredictions);
|
|
181
|
+
// Parse response
|
|
182
|
+
if (response.created !== undefined) {
|
|
183
|
+
created = response.created;
|
|
184
|
+
}
|
|
185
|
+
else if (response.task_count !== undefined) {
|
|
186
|
+
created = response.task_count;
|
|
187
|
+
}
|
|
188
|
+
else if (Array.isArray(response)) {
|
|
189
|
+
created = response.length;
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
created,
|
|
193
|
+
failed,
|
|
194
|
+
errors: errors.length > 0 ? errors : undefined
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
console.error(`Failed to import predictions to project ${projectId}:`, error);
|
|
199
|
+
throw new Error(`Failed to import predictions: ${error.message}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Delete prediction
|
|
204
|
+
*/
|
|
205
|
+
async deleteLabelStudioPrediction(predictionId, context) {
|
|
206
|
+
try {
|
|
207
|
+
await label_studio_api_client_js_1.labelStudioApi.deletePrediction(predictionId);
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error(`Failed to delete prediction ${predictionId}:`, error);
|
|
212
|
+
throw new Error(`Failed to delete prediction: ${error.message}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
exports.PredictionManagement = PredictionManagement;
|
|
217
|
+
tslib_1.__decorate([
|
|
218
|
+
(0, type_graphql_1.Query)(returns => [label_studio_types_js_1.LabelStudioPrediction], {
|
|
219
|
+
description: 'Get all predictions for a Label Studio task'
|
|
220
|
+
}),
|
|
221
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "query")'),
|
|
222
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('taskId', type => type_graphql_1.Int)),
|
|
223
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
224
|
+
tslib_1.__metadata("design:type", Function),
|
|
225
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object]),
|
|
226
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
227
|
+
], PredictionManagement.prototype, "labelStudioTaskPredictions", null);
|
|
228
|
+
tslib_1.__decorate([
|
|
229
|
+
(0, type_graphql_1.Query)(returns => [label_studio_types_js_1.LabelStudioPrediction], {
|
|
230
|
+
description: 'Get all predictions for a Label Studio project'
|
|
231
|
+
}),
|
|
232
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "query")'),
|
|
233
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
|
|
234
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
235
|
+
tslib_1.__metadata("design:type", Function),
|
|
236
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object]),
|
|
237
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
238
|
+
], PredictionManagement.prototype, "labelStudioProjectPredictions", null);
|
|
239
|
+
tslib_1.__decorate([
|
|
240
|
+
(0, type_graphql_1.Query)(returns => label_studio_types_js_1.LabelStudioPrediction, {
|
|
241
|
+
description: 'Get a single prediction by ID',
|
|
242
|
+
nullable: true
|
|
243
|
+
}),
|
|
244
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "query")'),
|
|
245
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('predictionId', type => type_graphql_1.Int)),
|
|
246
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
247
|
+
tslib_1.__metadata("design:type", Function),
|
|
248
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object]),
|
|
249
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
250
|
+
], PredictionManagement.prototype, "labelStudioPrediction", null);
|
|
251
|
+
tslib_1.__decorate([
|
|
252
|
+
(0, type_graphql_1.Mutation)(returns => label_studio_types_js_1.LabelStudioPrediction, {
|
|
253
|
+
description: 'Create a prediction for a Label Studio task'
|
|
254
|
+
}),
|
|
255
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
|
|
256
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('input')),
|
|
257
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
258
|
+
tslib_1.__metadata("design:type", Function),
|
|
259
|
+
tslib_1.__metadata("design:paramtypes", [label_studio_types_js_1.PredictionInput, Object]),
|
|
260
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
261
|
+
], PredictionManagement.prototype, "createLabelStudioPrediction", null);
|
|
262
|
+
tslib_1.__decorate([
|
|
263
|
+
(0, type_graphql_1.Mutation)(returns => label_studio_types_js_1.PredictionImportResult, {
|
|
264
|
+
description: 'Create multiple predictions at once'
|
|
265
|
+
}),
|
|
266
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
|
|
267
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('predictions', type => [label_studio_types_js_1.BulkPredictionInput])),
|
|
268
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
269
|
+
tslib_1.__metadata("design:type", Function),
|
|
270
|
+
tslib_1.__metadata("design:paramtypes", [Array, Object]),
|
|
271
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
272
|
+
], PredictionManagement.prototype, "createBulkPredictions", null);
|
|
273
|
+
tslib_1.__decorate([
|
|
274
|
+
(0, type_graphql_1.Mutation)(returns => label_studio_types_js_1.PredictionImportResult, {
|
|
275
|
+
description: 'Import predictions for a Label Studio project in bulk'
|
|
276
|
+
}),
|
|
277
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
|
|
278
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int)),
|
|
279
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('predictions', type => [label_studio_types_js_1.BulkPredictionInput])),
|
|
280
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
281
|
+
tslib_1.__metadata("design:type", Function),
|
|
282
|
+
tslib_1.__metadata("design:paramtypes", [Number, Array, Object]),
|
|
283
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
284
|
+
], PredictionManagement.prototype, "importPredictionsToProject", null);
|
|
285
|
+
tslib_1.__decorate([
|
|
286
|
+
(0, type_graphql_1.Mutation)(returns => Boolean, {
|
|
287
|
+
description: 'Delete a prediction from Label Studio'
|
|
288
|
+
}),
|
|
289
|
+
(0, type_graphql_1.Directive)('@privilege(category: "label-studio", privilege: "mutation")'),
|
|
290
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('predictionId', type => type_graphql_1.Int)),
|
|
291
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
292
|
+
tslib_1.__metadata("design:type", Function),
|
|
293
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object]),
|
|
294
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
295
|
+
], PredictionManagement.prototype, "deleteLabelStudioPrediction", null);
|
|
296
|
+
exports.PredictionManagement = PredictionManagement = tslib_1.__decorate([
|
|
297
|
+
(0, type_graphql_1.Resolver)()
|
|
298
|
+
], PredictionManagement);
|
|
299
|
+
//# sourceMappingURL=prediction-management.js.map
|