@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,181 @@
|
|
|
1
|
+
import { Field, InputType, ObjectType, Int, Float } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dataset Labeling Integration Types
|
|
5
|
+
*
|
|
6
|
+
* Types for integrating DataSample with Label Studio tasks and AI predictions
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
@InputType({ description: 'Request to create Label Studio tasks from DataSamples' })
|
|
10
|
+
export class CreateLabelingTasksRequest {
|
|
11
|
+
@Field(type => Int, { description: 'Label Studio project ID' })
|
|
12
|
+
projectId: number
|
|
13
|
+
|
|
14
|
+
@Field({ description: 'DataSet ID to sync' })
|
|
15
|
+
dataSetId: string
|
|
16
|
+
|
|
17
|
+
@Field({ nullable: true, description: 'Image field name in DataSample.data or DataSample.rawData' })
|
|
18
|
+
imageField?: string
|
|
19
|
+
|
|
20
|
+
@Field({ nullable: true, defaultValue: true, description: 'Auto-generate AI predictions for created tasks' })
|
|
21
|
+
autoGeneratePredictions?: boolean
|
|
22
|
+
|
|
23
|
+
@Field(type => Float, { nullable: true, description: 'Confidence threshold for AI predictions' })
|
|
24
|
+
confidenceThreshold?: number
|
|
25
|
+
|
|
26
|
+
@Field({ nullable: true, description: 'AI model ID to use for predictions' })
|
|
27
|
+
modelId?: string
|
|
28
|
+
|
|
29
|
+
@Field({ nullable: true, description: 'Only create tasks for samples after this date' })
|
|
30
|
+
sinceDate?: Date
|
|
31
|
+
|
|
32
|
+
@Field({ nullable: true, description: 'Maximum number of tasks to create' })
|
|
33
|
+
limit?: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@ObjectType({ description: 'Result of task creation from dataset' })
|
|
37
|
+
export class TaskCreationResult {
|
|
38
|
+
@Field(type => Int, { description: 'Total DataSamples processed' })
|
|
39
|
+
totalSamples: number
|
|
40
|
+
|
|
41
|
+
@Field(type => Int, { description: 'Number of tasks successfully created' })
|
|
42
|
+
tasksCreated: number
|
|
43
|
+
|
|
44
|
+
@Field(type => Int, { description: 'Number of tasks that failed to create' })
|
|
45
|
+
tasksFailed: number
|
|
46
|
+
|
|
47
|
+
@Field(type => Int, { description: 'Number of samples skipped (no image, already exists, etc.)' })
|
|
48
|
+
tasksSkipped: number
|
|
49
|
+
|
|
50
|
+
@Field(type => [Int], { description: 'Array of created Label Studio task IDs' })
|
|
51
|
+
taskIds: number[]
|
|
52
|
+
|
|
53
|
+
@Field(type => Int, { nullable: true, description: 'Number of AI predictions generated' })
|
|
54
|
+
predictionsCreated?: number
|
|
55
|
+
|
|
56
|
+
@Field({ nullable: true, description: 'Error message if operation partially failed' })
|
|
57
|
+
error?: string
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@InputType({ description: 'Request to sync Label Studio annotations back to DataSamples' })
|
|
61
|
+
export class SyncAnnotationsRequest {
|
|
62
|
+
@Field(type => Int, { description: 'Label Studio project ID' })
|
|
63
|
+
projectId: number
|
|
64
|
+
|
|
65
|
+
@Field({ description: 'DataSet ID to sync annotations to' })
|
|
66
|
+
dataSetId: string
|
|
67
|
+
|
|
68
|
+
@Field({ nullable: true, defaultValue: false, description: 'Only sync completed annotations' })
|
|
69
|
+
completedOnly?: boolean
|
|
70
|
+
|
|
71
|
+
@Field({ nullable: true, description: 'Only sync annotations updated after this date' })
|
|
72
|
+
sinceDate?: Date
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@ObjectType({ description: 'Result of syncing annotations to dataset' })
|
|
76
|
+
export class SyncAnnotationsResult {
|
|
77
|
+
@Field(type => Int, { description: 'Total annotations processed' })
|
|
78
|
+
totalAnnotations: number
|
|
79
|
+
|
|
80
|
+
@Field(type => Int, { description: 'Number of DataSamples successfully updated' })
|
|
81
|
+
samplesUpdated: number
|
|
82
|
+
|
|
83
|
+
@Field(type => Int, { description: 'Number of updates that failed' })
|
|
84
|
+
updatesFailed: number
|
|
85
|
+
|
|
86
|
+
@Field(type => Int, { description: 'Number of annotations skipped' })
|
|
87
|
+
skipped: number
|
|
88
|
+
|
|
89
|
+
@Field({ nullable: true, description: 'Error message if operation partially failed' })
|
|
90
|
+
error?: string
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@ObjectType({ description: 'Labeling status for a dataset' })
|
|
94
|
+
export class DatasetLabelingStatus {
|
|
95
|
+
@Field({ description: 'DataSet ID' })
|
|
96
|
+
dataSetId: string
|
|
97
|
+
|
|
98
|
+
@Field({ description: 'DataSet name' })
|
|
99
|
+
dataSetName: string
|
|
100
|
+
|
|
101
|
+
@Field(type => Int, { description: 'Total number of DataSamples in the dataset' })
|
|
102
|
+
totalSamples: number
|
|
103
|
+
|
|
104
|
+
@Field(type => Int, { description: 'Number of samples with Label Studio tasks' })
|
|
105
|
+
tasksCreated: number
|
|
106
|
+
|
|
107
|
+
@Field(type => Int, { description: 'Number of samples with AI predictions' })
|
|
108
|
+
withPredictions: number
|
|
109
|
+
|
|
110
|
+
@Field(type => Int, { description: 'Number of samples with human annotations' })
|
|
111
|
+
withAnnotations: number
|
|
112
|
+
|
|
113
|
+
@Field(type => Int, { description: 'Number of samples with completed annotations' })
|
|
114
|
+
annotationsCompleted: number
|
|
115
|
+
|
|
116
|
+
@Field(type => Int, { description: 'Number of samples not yet processed' })
|
|
117
|
+
notProcessed: number
|
|
118
|
+
|
|
119
|
+
@Field(type => Float, { description: 'Labeling completion rate (0-1)' })
|
|
120
|
+
completionRate: number
|
|
121
|
+
|
|
122
|
+
@Field({ nullable: true, description: 'Associated Label Studio project ID' })
|
|
123
|
+
projectId?: number
|
|
124
|
+
|
|
125
|
+
@Field({ nullable: true, description: 'Last sync timestamp' })
|
|
126
|
+
lastSyncedAt?: Date
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@ObjectType({ description: 'Mapping between DataSample and Label Studio task' })
|
|
130
|
+
export class DataSampleTaskMapping {
|
|
131
|
+
@Field({ description: 'DataSample ID' })
|
|
132
|
+
dataSampleId: string
|
|
133
|
+
|
|
134
|
+
@Field({ description: 'DataSample name' })
|
|
135
|
+
dataSampleName: string
|
|
136
|
+
|
|
137
|
+
@Field(type => Int, { description: 'Label Studio task ID' })
|
|
138
|
+
taskId: number
|
|
139
|
+
|
|
140
|
+
@Field({ nullable: true, description: 'Image URL used in the task' })
|
|
141
|
+
imageUrl?: string
|
|
142
|
+
|
|
143
|
+
@Field({ nullable: true, description: 'Task creation timestamp' })
|
|
144
|
+
createdAt?: Date
|
|
145
|
+
|
|
146
|
+
@Field({ nullable: true, description: 'Whether task has AI prediction' })
|
|
147
|
+
hasPrediction?: boolean
|
|
148
|
+
|
|
149
|
+
@Field({ nullable: true, description: 'Whether task has human annotation' })
|
|
150
|
+
hasAnnotation?: boolean
|
|
151
|
+
|
|
152
|
+
@Field({ nullable: true, description: 'Whether annotation is completed' })
|
|
153
|
+
isCompleted?: boolean
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@InputType({ description: 'Request to query dataset labeling status' })
|
|
157
|
+
export class DatasetLabelingStatusRequest {
|
|
158
|
+
@Field({ description: 'DataSet ID' })
|
|
159
|
+
dataSetId: string
|
|
160
|
+
|
|
161
|
+
@Field(type => Int, { nullable: true, description: 'Associated Label Studio project ID' })
|
|
162
|
+
projectId?: number
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@InputType({ description: 'Request to generate predictions for existing tasks' })
|
|
166
|
+
export class GeneratePredictionsForDatasetRequest {
|
|
167
|
+
@Field({ description: 'DataSet ID' })
|
|
168
|
+
dataSetId: string
|
|
169
|
+
|
|
170
|
+
@Field(type => Int, { description: 'Label Studio project ID' })
|
|
171
|
+
projectId: number
|
|
172
|
+
|
|
173
|
+
@Field({ nullable: true, description: 'AI model ID to use' })
|
|
174
|
+
modelId?: string
|
|
175
|
+
|
|
176
|
+
@Field(type => Float, { nullable: true, description: 'Confidence threshold' })
|
|
177
|
+
confidenceThreshold?: number
|
|
178
|
+
|
|
179
|
+
@Field({ nullable: true, defaultValue: false, description: 'Regenerate predictions even if they already exist' })
|
|
180
|
+
forceRegenerate?: boolean
|
|
181
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global type definitions for Things-Factory integration
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Domain } from '@things-factory/shell'
|
|
6
|
+
import { User } from '@things-factory/auth-base'
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
/**
|
|
10
|
+
* GraphQL Resolver Context
|
|
11
|
+
* Available in all @Ctx() decorated parameters
|
|
12
|
+
*/
|
|
13
|
+
interface ResolverContext {
|
|
14
|
+
state: {
|
|
15
|
+
domain: Domain
|
|
16
|
+
user: User
|
|
17
|
+
[key: string]: any
|
|
18
|
+
}
|
|
19
|
+
[key: string]: any
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { Field, ObjectType, InputType, Int, Float } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Project Types
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
@ObjectType({ description: 'Label Studio project information' })
|
|
8
|
+
export class LabelStudioProject {
|
|
9
|
+
@Field(type => Int, { description: 'Project ID' })
|
|
10
|
+
id: number
|
|
11
|
+
|
|
12
|
+
@Field({ description: 'Project title' })
|
|
13
|
+
title: string
|
|
14
|
+
|
|
15
|
+
@Field({ nullable: true, description: 'Project description' })
|
|
16
|
+
description?: string
|
|
17
|
+
|
|
18
|
+
@Field({ description: 'Label configuration XML' })
|
|
19
|
+
labelConfig: string
|
|
20
|
+
|
|
21
|
+
@Field({ nullable: true, description: 'Expert instruction' })
|
|
22
|
+
expertInstruction?: string
|
|
23
|
+
|
|
24
|
+
@Field(type => Int, { description: 'Number of tasks' })
|
|
25
|
+
taskCount: number
|
|
26
|
+
|
|
27
|
+
@Field(type => Int, { description: 'Number of completed tasks' })
|
|
28
|
+
completedTaskCount: number
|
|
29
|
+
|
|
30
|
+
@Field(type => Float, { description: 'Completion rate (0-1)' })
|
|
31
|
+
completionRate: number
|
|
32
|
+
|
|
33
|
+
@Field({ nullable: true, description: 'Created date' })
|
|
34
|
+
createdAt: Date
|
|
35
|
+
|
|
36
|
+
@Field({ nullable: true, description: 'Updated date' })
|
|
37
|
+
updatedAt: Date
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@InputType({ description: 'Input for creating Label Studio project' })
|
|
41
|
+
export class CreateProjectInput {
|
|
42
|
+
@Field({ description: 'Project title' })
|
|
43
|
+
title: string
|
|
44
|
+
|
|
45
|
+
@Field({ nullable: true, description: 'Project description' })
|
|
46
|
+
description?: string
|
|
47
|
+
|
|
48
|
+
@Field({ description: 'Label configuration XML' })
|
|
49
|
+
labelConfig: string
|
|
50
|
+
|
|
51
|
+
@Field({ nullable: true, description: 'Expert instruction' })
|
|
52
|
+
expertInstruction?: string
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@InputType({ description: 'Label config specification for flexible project creation' })
|
|
56
|
+
export class LabelConfigSpecInput {
|
|
57
|
+
@Field({ description: 'Data type (image, text, audio, video, timeseries, html, hypertext)' })
|
|
58
|
+
dataType: string
|
|
59
|
+
|
|
60
|
+
@Field({ nullable: true, description: 'Data name (default: data)' })
|
|
61
|
+
dataName?: string
|
|
62
|
+
|
|
63
|
+
@Field({ description: 'Control specifications as JSON array' })
|
|
64
|
+
controls: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@InputType({ description: 'Input for creating project with flexible config builder' })
|
|
68
|
+
export class CreateProjectWithSpecInput {
|
|
69
|
+
@Field({ description: 'Project title' })
|
|
70
|
+
title: string
|
|
71
|
+
|
|
72
|
+
@Field({ nullable: true, description: 'Project description' })
|
|
73
|
+
description?: string
|
|
74
|
+
|
|
75
|
+
@Field({ description: 'Label config specification' })
|
|
76
|
+
labelConfigSpec: LabelConfigSpecInput
|
|
77
|
+
|
|
78
|
+
@Field({ nullable: true, description: 'Expert instruction' })
|
|
79
|
+
expertInstruction?: string
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@InputType({ description: 'Export annotations input' })
|
|
83
|
+
export class ExportAnnotationsInput {
|
|
84
|
+
@Field({ description: 'Export format (json, jsonl, csv, rank-csv, coco, yolo, ner-json)' })
|
|
85
|
+
format: string
|
|
86
|
+
|
|
87
|
+
@Field({ nullable: true, description: 'Filter by task IDs' })
|
|
88
|
+
taskIds?: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@ObjectType({ description: 'Annotation export result' })
|
|
92
|
+
export class AnnotationExportResult {
|
|
93
|
+
@Field({ description: 'Exported data as JSON string' })
|
|
94
|
+
data: string
|
|
95
|
+
|
|
96
|
+
@Field(type => Int, { description: 'Number of annotations exported' })
|
|
97
|
+
count: number
|
|
98
|
+
|
|
99
|
+
@Field({ description: 'Export format used' })
|
|
100
|
+
format: string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ============================================================================
|
|
104
|
+
// Task Types
|
|
105
|
+
// ============================================================================
|
|
106
|
+
|
|
107
|
+
@ObjectType({ description: 'Label Studio task' })
|
|
108
|
+
export class LabelStudioTask {
|
|
109
|
+
@Field(type => Int, { description: 'Task ID' })
|
|
110
|
+
id: number
|
|
111
|
+
|
|
112
|
+
@Field({ description: 'Task data (JSON)' })
|
|
113
|
+
data: string
|
|
114
|
+
|
|
115
|
+
@Field(type => Int, { description: 'Number of annotations' })
|
|
116
|
+
annotationCount: number
|
|
117
|
+
|
|
118
|
+
@Field({ description: 'Is task completed' })
|
|
119
|
+
isCompleted: boolean
|
|
120
|
+
|
|
121
|
+
@Field({ nullable: true, description: 'Task created date' })
|
|
122
|
+
createdAt?: Date
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@InputType({ description: 'Input for creating tasks' })
|
|
126
|
+
export class TaskDataInput {
|
|
127
|
+
@Field({ description: 'Task data as JSON string' })
|
|
128
|
+
data: string
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@InputType({ description: 'Task transformation rule for flexible data import' })
|
|
132
|
+
export class TaskTransformRuleInput {
|
|
133
|
+
@Field({ description: 'Field mapping as JSON (Label Studio field -> source path)' })
|
|
134
|
+
dataFields: string
|
|
135
|
+
|
|
136
|
+
@Field({ nullable: true, description: 'Prediction configuration as JSON' })
|
|
137
|
+
predictions?: string
|
|
138
|
+
|
|
139
|
+
@Field({ nullable: true, description: 'Metadata mapping as JSON' })
|
|
140
|
+
meta?: string
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@InputType({ description: 'Input for importing tasks with transformation' })
|
|
144
|
+
export class ImportTasksWithTransformInput {
|
|
145
|
+
@Field({ description: 'Source data as JSON array string' })
|
|
146
|
+
sourceData: string
|
|
147
|
+
|
|
148
|
+
@Field({ description: 'Transformation rule' })
|
|
149
|
+
transformRule: TaskTransformRuleInput
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@ObjectType({ description: 'Result of task import operation' })
|
|
153
|
+
export class TaskImportResult {
|
|
154
|
+
@Field(type => Int, { description: 'Number of tasks imported' })
|
|
155
|
+
imported: number
|
|
156
|
+
|
|
157
|
+
@Field(type => Int, { description: 'Number of tasks failed' })
|
|
158
|
+
failed: number
|
|
159
|
+
|
|
160
|
+
@Field(type => [Int], { description: 'IDs of imported tasks' })
|
|
161
|
+
taskIds: number[]
|
|
162
|
+
|
|
163
|
+
@Field(type => [String], { nullable: true, description: 'Error messages' })
|
|
164
|
+
errors?: string[]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Annotation Types
|
|
169
|
+
// ============================================================================
|
|
170
|
+
|
|
171
|
+
@ObjectType({ description: 'Label Studio annotation' })
|
|
172
|
+
export class LabelStudioAnnotation {
|
|
173
|
+
@Field(type => Int, { description: 'Annotation ID' })
|
|
174
|
+
id: number
|
|
175
|
+
|
|
176
|
+
@Field(type => Int, { description: 'Task ID' })
|
|
177
|
+
taskId: number
|
|
178
|
+
|
|
179
|
+
@Field({ description: 'Annotation result (JSON)' })
|
|
180
|
+
result: string
|
|
181
|
+
|
|
182
|
+
@Field({ description: 'Completed by user email' })
|
|
183
|
+
completedBy: string
|
|
184
|
+
|
|
185
|
+
@Field({ description: 'Created date' })
|
|
186
|
+
createdAt: Date
|
|
187
|
+
|
|
188
|
+
@Field({ nullable: true, description: 'Lead time in seconds' })
|
|
189
|
+
leadTime?: number
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ============================================================================
|
|
193
|
+
// Prediction Types
|
|
194
|
+
// ============================================================================
|
|
195
|
+
|
|
196
|
+
@ObjectType({ description: 'Label Studio prediction (AI pre-annotation)' })
|
|
197
|
+
export class LabelStudioPrediction {
|
|
198
|
+
@Field(type => Int, { description: 'Prediction ID' })
|
|
199
|
+
id: number
|
|
200
|
+
|
|
201
|
+
@Field(type => Int, { description: 'Task ID' })
|
|
202
|
+
taskId: number
|
|
203
|
+
|
|
204
|
+
@Field({ description: 'Prediction result (JSON)' })
|
|
205
|
+
result: string
|
|
206
|
+
|
|
207
|
+
@Field(type => Float, { nullable: true, description: 'Prediction confidence score (0-1)' })
|
|
208
|
+
score?: number
|
|
209
|
+
|
|
210
|
+
@Field({ nullable: true, description: 'Model version that generated this prediction' })
|
|
211
|
+
modelVersion?: string
|
|
212
|
+
|
|
213
|
+
@Field({ nullable: true, description: 'Created date' })
|
|
214
|
+
createdAt?: Date
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@InputType({ description: 'Input for creating a prediction' })
|
|
218
|
+
export class PredictionInput {
|
|
219
|
+
@Field(type => Int, { description: 'Task ID to create prediction for' })
|
|
220
|
+
taskId: number
|
|
221
|
+
|
|
222
|
+
@Field({ description: 'Prediction result as JSON string' })
|
|
223
|
+
result: string
|
|
224
|
+
|
|
225
|
+
@Field(type => Float, { nullable: true, description: 'Prediction confidence score (0-1)' })
|
|
226
|
+
score?: number
|
|
227
|
+
|
|
228
|
+
@Field({ nullable: true, description: 'Model version' })
|
|
229
|
+
modelVersion?: string
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@InputType({ description: 'Input for bulk prediction creation' })
|
|
233
|
+
export class BulkPredictionInput {
|
|
234
|
+
@Field(type => Int, { description: 'Task ID' })
|
|
235
|
+
taskId: number
|
|
236
|
+
|
|
237
|
+
@Field({ description: 'Prediction result as JSON string' })
|
|
238
|
+
result: string
|
|
239
|
+
|
|
240
|
+
@Field(type => Float, { nullable: true, description: 'Prediction confidence score (0-1)' })
|
|
241
|
+
score?: number
|
|
242
|
+
|
|
243
|
+
@Field({ nullable: true, description: 'Model version' })
|
|
244
|
+
modelVersion?: string
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@ObjectType({ description: 'Result of prediction import operation' })
|
|
248
|
+
export class PredictionImportResult {
|
|
249
|
+
@Field(type => Int, { description: 'Number of predictions created' })
|
|
250
|
+
created: number
|
|
251
|
+
|
|
252
|
+
@Field(type => Int, { description: 'Number of predictions failed' })
|
|
253
|
+
failed: number
|
|
254
|
+
|
|
255
|
+
@Field(type => [String], { nullable: true, description: 'Error messages' })
|
|
256
|
+
errors?: string[]
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@ObjectType({ description: 'Export result' })
|
|
260
|
+
export class ExportResult {
|
|
261
|
+
@Field({ description: 'Export file path or URL' })
|
|
262
|
+
exportPath: string
|
|
263
|
+
|
|
264
|
+
@Field(type => Int, { description: 'Number of annotations exported' })
|
|
265
|
+
annotationCount: number
|
|
266
|
+
|
|
267
|
+
@Field({ description: 'Export format (JSON, CSV, YOLO, etc.)' })
|
|
268
|
+
format: string
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// ============================================================================
|
|
272
|
+
// Analytics Types
|
|
273
|
+
// ============================================================================
|
|
274
|
+
|
|
275
|
+
@ObjectType({ description: 'Project metrics and statistics' })
|
|
276
|
+
export class ProjectMetrics {
|
|
277
|
+
@Field(type => Int, { description: 'Total number of tasks' })
|
|
278
|
+
totalTasks: number
|
|
279
|
+
|
|
280
|
+
@Field(type => Int, { description: 'Number of completed tasks' })
|
|
281
|
+
completedTasks: number
|
|
282
|
+
|
|
283
|
+
@Field(type => Int, { description: 'Total annotations' })
|
|
284
|
+
totalAnnotations: number
|
|
285
|
+
|
|
286
|
+
@Field(type => Float, { description: 'Average annotations per task' })
|
|
287
|
+
avgAnnotationsPerTask: number
|
|
288
|
+
|
|
289
|
+
@Field(type => Float, { description: 'Completion rate (0-1)' })
|
|
290
|
+
completionRate: number
|
|
291
|
+
|
|
292
|
+
@Field(type => Float, { nullable: true, description: 'Average time per task in seconds' })
|
|
293
|
+
avgTimePerTask?: number
|
|
294
|
+
|
|
295
|
+
@Field(type => [AnnotatorStats], { description: 'Statistics per annotator' })
|
|
296
|
+
annotatorStats: AnnotatorStats[]
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
@ObjectType({ description: 'Annotator statistics' })
|
|
300
|
+
export class AnnotatorStats {
|
|
301
|
+
@Field({ description: 'User email' })
|
|
302
|
+
email: string
|
|
303
|
+
|
|
304
|
+
@Field(type => Int, { description: 'Number of annotations' })
|
|
305
|
+
annotationCount: number
|
|
306
|
+
|
|
307
|
+
@Field(type => Float, { description: 'Average time per annotation in seconds' })
|
|
308
|
+
avgTime: number
|
|
309
|
+
|
|
310
|
+
@Field({ description: 'Last annotation date' })
|
|
311
|
+
lastAnnotationDate: Date
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ============================================================================
|
|
315
|
+
// ML Backend Types
|
|
316
|
+
// ============================================================================
|
|
317
|
+
|
|
318
|
+
@ObjectType({ description: 'ML Backend information' })
|
|
319
|
+
export class MLBackend {
|
|
320
|
+
@Field(type => Int, { description: 'ML Backend ID' })
|
|
321
|
+
id: number
|
|
322
|
+
|
|
323
|
+
@Field({ description: 'ML Backend URL' })
|
|
324
|
+
url: string
|
|
325
|
+
|
|
326
|
+
@Field({ description: 'ML Backend title' })
|
|
327
|
+
title: string
|
|
328
|
+
|
|
329
|
+
@Field({ description: 'Is interactive preannotation enabled' })
|
|
330
|
+
isInteractive: boolean
|
|
331
|
+
|
|
332
|
+
@Field({ description: 'Model version' })
|
|
333
|
+
modelVersion: string
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
@InputType({ description: 'Input for adding ML Backend' })
|
|
337
|
+
export class AddMLBackendInput {
|
|
338
|
+
@Field({ description: 'ML Backend URL' })
|
|
339
|
+
url: string
|
|
340
|
+
|
|
341
|
+
@Field({ description: 'ML Backend title' })
|
|
342
|
+
title: string
|
|
343
|
+
|
|
344
|
+
@Field({ nullable: true, description: 'Is interactive preannotation enabled' })
|
|
345
|
+
isInteractive?: boolean
|
|
346
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Field, ObjectType, InputType, Int, Float } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Label Studio Prediction Generation Types
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Label Studio prediction generation request
|
|
9
|
+
*/
|
|
10
|
+
@InputType({ description: 'Request to generate Label Studio predictions' })
|
|
11
|
+
export class GeneratePredictionRequest {
|
|
12
|
+
@Field(type => Int, { description: 'Label Studio task ID' })
|
|
13
|
+
taskId: number
|
|
14
|
+
|
|
15
|
+
@Field({ description: 'Image URL from task data' })
|
|
16
|
+
imageUrl: string
|
|
17
|
+
|
|
18
|
+
@Field({ nullable: true, description: 'AI model ID to use' })
|
|
19
|
+
modelId?: string
|
|
20
|
+
|
|
21
|
+
@Field(type => Float, { nullable: true, description: 'Confidence threshold (0-1)' })
|
|
22
|
+
confidenceThreshold?: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Batch prediction generation request
|
|
27
|
+
*/
|
|
28
|
+
@InputType({ description: 'Request to generate predictions for multiple tasks' })
|
|
29
|
+
export class BatchGeneratePredictionRequest {
|
|
30
|
+
@Field(type => Int, { description: 'Label Studio project ID' })
|
|
31
|
+
projectId: number
|
|
32
|
+
|
|
33
|
+
@Field(type => [Int], { description: 'Array of task IDs' })
|
|
34
|
+
taskIds: number[]
|
|
35
|
+
|
|
36
|
+
@Field({ nullable: true, description: 'AI model ID to use' })
|
|
37
|
+
modelId?: string
|
|
38
|
+
|
|
39
|
+
@Field(type => Float, { nullable: true, description: 'Confidence threshold (0-1)' })
|
|
40
|
+
confidenceThreshold?: number
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Prediction generation result
|
|
45
|
+
*/
|
|
46
|
+
@ObjectType({ description: 'Prediction generation result' })
|
|
47
|
+
export class PredictionGenerationResult {
|
|
48
|
+
@Field(type => Int, { description: 'Task ID' })
|
|
49
|
+
taskId: number
|
|
50
|
+
|
|
51
|
+
@Field(type => Int, { nullable: true, description: 'Created prediction ID' })
|
|
52
|
+
predictionId?: number
|
|
53
|
+
|
|
54
|
+
@Field({ description: 'Success status' })
|
|
55
|
+
success: boolean
|
|
56
|
+
|
|
57
|
+
@Field({ nullable: true, description: 'Error message if failed' })
|
|
58
|
+
error?: string
|
|
59
|
+
|
|
60
|
+
@Field(type => Int, { description: 'Number of detected objects' })
|
|
61
|
+
objectCount: number
|
|
62
|
+
|
|
63
|
+
@Field(type => Float, { nullable: true, description: 'Average confidence score' })
|
|
64
|
+
avgConfidence?: number
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Batch prediction generation result
|
|
69
|
+
*/
|
|
70
|
+
@ObjectType({ description: 'Batch prediction generation result' })
|
|
71
|
+
export class BatchPredictionResult {
|
|
72
|
+
@Field(type => Int, { description: 'Total tasks processed' })
|
|
73
|
+
total: number
|
|
74
|
+
|
|
75
|
+
@Field(type => Int, { description: 'Number of successful predictions' })
|
|
76
|
+
succeeded: number
|
|
77
|
+
|
|
78
|
+
@Field(type => Int, { description: 'Number of failed predictions' })
|
|
79
|
+
failed: number
|
|
80
|
+
|
|
81
|
+
@Field(type => [PredictionGenerationResult], { description: 'Individual results' })
|
|
82
|
+
results: PredictionGenerationResult[]
|
|
83
|
+
|
|
84
|
+
@Field({ description: 'Model version used' })
|
|
85
|
+
modelVersion: string
|
|
86
|
+
}
|