modelstudio-sdk 0.0.0.dev0__py3-none-any.whl

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.
@@ -0,0 +1,18 @@
1
+ """Common/shared model types."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class PagedResponse(BaseModel):
11
+ """Generic paged response wrapper matching the API's paginated response."""
12
+
13
+ content: list[dict[str, Any]] = []
14
+ total_elements: int = 0
15
+ total_pages: int = 0
16
+ page: int = 0
17
+ size: int = 0
18
+ facets: dict[str, Any] | None = None
@@ -0,0 +1,55 @@
1
+ """Dataset-related models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from uuid import UUID
7
+
8
+ from pydantic import BaseModel
9
+
10
+ from modelstudio.models.splits import SplitModel
11
+
12
+
13
+ class DatasetModel(BaseModel):
14
+ """Represents a dataset from GET /api/v1/datasets."""
15
+
16
+ id: UUID
17
+ parent_dataset_id: UUID | None = None
18
+ name: str
19
+ dataset_type: str
20
+ format: str
21
+ description: str | None = None
22
+ created_on: datetime | None = None
23
+ locked: bool = False
24
+ uploaded: bool = False
25
+ splits: list[SplitModel] = []
26
+ clone_status: str | None = None
27
+ clone_progress: int = 0
28
+ clone_error: str | None = None
29
+ clone_started_at: datetime | None = None
30
+ clone_finished_at: datetime | None = None
31
+ finalize_status: str | None = None
32
+ finalize_progress: int = 0
33
+ finalize_message: str | None = None
34
+ finalize_started_at: datetime | None = None
35
+ finalize_finished_at: datetime | None = None
36
+
37
+
38
+ class CloneStatusModel(BaseModel):
39
+ """Clone operation status."""
40
+
41
+ clone_status: str | None = None
42
+ clone_progress: int = 0
43
+ clone_error: str | None = None
44
+ clone_started_at: datetime | None = None
45
+ clone_finished_at: datetime | None = None
46
+
47
+
48
+ class FinalizeStatusModel(BaseModel):
49
+ """Finalize operation status."""
50
+
51
+ finalize_status: str | None = None
52
+ finalize_progress: int = 0
53
+ finalize_message: str | None = None
54
+ finalize_started_at: datetime | None = None
55
+ finalize_finished_at: datetime | None = None
@@ -0,0 +1,29 @@
1
+ """Deletion check models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uuid import UUID
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class ExperimentRefModel(BaseModel):
11
+ """An experiment referencing a dataset."""
12
+
13
+ experiment_id: UUID | None = None
14
+ experiment_name: str | None = None
15
+
16
+
17
+ class DatasetRefModel(BaseModel):
18
+ """A child dataset reference."""
19
+
20
+ dataset_id: UUID | None = None
21
+ dataset_name: str | None = None
22
+
23
+
24
+ class DeletionCheckModel(BaseModel):
25
+ """Response from GET /datasets/{id}/can-delete."""
26
+
27
+ can_delete: bool = False
28
+ referencing_experiments: list[ExperimentRefModel] = []
29
+ child_datasets: list[DatasetRefModel] = []
@@ -0,0 +1,32 @@
1
+ """Export-related models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class ExportCocoModel(BaseModel):
11
+ """Response from POST /datasets/{id}/export/coco."""
12
+
13
+ coco_json: dict[str, Any] | None = None
14
+ image_count: int = 0
15
+ annotation_count: int = 0
16
+ category_count: int = 0
17
+ image_id_mapping: dict[str, int] | None = None
18
+ annotation_id_mapping: dict[str, int] | None = None
19
+ category_id_mapping: dict[str, int] | None = None
20
+ reindexed: bool = False
21
+
22
+
23
+ class SegmentationExportModel(BaseModel):
24
+ """Response from POST /datasets/{id}/splits/{sid}/export/segmentation."""
25
+
26
+ split_id: str | None = None
27
+ images_archive_uri: str | None = None
28
+ masks_archive_uri: str | None = None
29
+ categories_uri: str | None = None
30
+ image_count: int = 0
31
+ mask_count: int = 0
32
+ images_without_masks: list[str] = []
@@ -0,0 +1,41 @@
1
+ """Few-shot dataset creation models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+ from uuid import UUID
7
+
8
+ from pydantic import BaseModel
9
+
10
+
11
+ class FewShotRequest(BaseModel):
12
+ """Request for POST /datasets/{id}/few-shot."""
13
+
14
+ num_images: int
15
+ method: str = "RANDOM"
16
+ specific_image_ids: list[UUID] | None = None
17
+ specific_file_names: list[str] | None = None
18
+ new_dataset_name: str | None = None
19
+ new_dataset_description: str | None = None
20
+ seed: int | None = None
21
+
22
+
23
+ class FewShotPreviewModel(BaseModel):
24
+ """Response from POST /datasets/{id}/few-shot/preview."""
25
+
26
+ selected_image_count: int = 0
27
+ total_annotations: int = 0
28
+ selected_images: list[dict[str, Any]] = []
29
+ class_coverage: dict[str, Any] = {}
30
+
31
+
32
+ class FewShotResponseModel(BaseModel):
33
+ """Response from POST /datasets/{id}/few-shot."""
34
+
35
+ success: bool = False
36
+ message: str | None = None
37
+ new_dataset_id: str | None = None
38
+ new_dataset_name: str | None = None
39
+ images_included: int = 0
40
+ annotations_included: int = 0
41
+ categories_included: int = 0
@@ -0,0 +1,81 @@
1
+ """Filter-related models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class CategoryFilter(BaseModel):
11
+ """Category filter options."""
12
+
13
+ keep_categories: list[str] | None = None
14
+ keep_category_ids: list[int] | None = None
15
+ exclude_mode: bool = False
16
+
17
+
18
+ class BboxFilter(BaseModel):
19
+ """Bounding box filter options."""
20
+
21
+ min_width: float | None = None
22
+ max_width: float | None = None
23
+ min_height: float | None = None
24
+ max_height: float | None = None
25
+ min_area: float | None = None
26
+ max_area: float | None = None
27
+ min_aspect_ratio: float | None = None
28
+ max_aspect_ratio: float | None = None
29
+ min_width_meters: float | None = None
30
+ max_width_meters: float | None = None
31
+ min_height_meters: float | None = None
32
+ max_height_meters: float | None = None
33
+ min_area_m2: float | None = None
34
+ max_area_m2: float | None = None
35
+
36
+
37
+ class AnnotationCountFilter(BaseModel):
38
+ """Annotation count filter options."""
39
+
40
+ min_annotations_per_image: int | None = None
41
+ max_annotations_per_image: int | None = None
42
+ count_only_categories: list[str] | None = None
43
+
44
+
45
+ class DatasetFilterRequest(BaseModel):
46
+ """Request for POST /datasets/{id}/filter."""
47
+
48
+ category_filter: CategoryFilter | None = None
49
+ bbox_filter: BboxFilter | None = None
50
+ annotation_count_filter: AnnotationCountFilter | None = None
51
+ consolidate_labels: dict[str, str] | None = None
52
+ output_mode: str | None = None
53
+ new_dataset_name: str | None = None
54
+ new_dataset_description: str | None = None
55
+ dry_run: bool = False
56
+
57
+
58
+ class FilterStatisticsModel(BaseModel):
59
+ """Filter operation statistics."""
60
+
61
+ original_images: int = 0
62
+ original_annotations: int = 0
63
+ original_categories: int = 0
64
+ filtered_images: int = 0
65
+ filtered_annotations: int = 0
66
+ filtered_categories: int = 0
67
+ removed_by_filter: dict[str, int] = {}
68
+ category_distribution: dict[str, Any] = {}
69
+
70
+
71
+ class DatasetFilterResponse(BaseModel):
72
+ """Response from POST /datasets/{id}/filter."""
73
+
74
+ success: bool = False
75
+ message: str | None = None
76
+ mode: str | None = None
77
+ coco_json: dict[str, Any] | None = None
78
+ new_dataset_id: str | None = None
79
+ new_dataset_name: str | None = None
80
+ statistics: FilterStatisticsModel | None = None
81
+ dry_run: bool = False
@@ -0,0 +1,58 @@
1
+ """History and undo/redo models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from uuid import UUID
7
+
8
+ from pydantic import BaseModel
9
+
10
+
11
+ class HistoryEntryModel(BaseModel):
12
+ """A single change in the dataset history."""
13
+
14
+ change_id: UUID | None = None
15
+ sequence_number: int | None = None
16
+ operation_type: str | None = None
17
+ short_description: str | None = None
18
+ detailed_description: str | None = None
19
+ changed_on: datetime | None = None
20
+ changed_by: str | None = None
21
+ is_undone: bool = False
22
+ is_reversible: bool = True
23
+
24
+
25
+ class HistoryModel(BaseModel):
26
+ """Response from GET /datasets/{id}/history."""
27
+
28
+ dataset_id: UUID | None = None
29
+ current_position: int = 0
30
+ total_changes: int = 0
31
+ can_undo: bool = False
32
+ can_redo: bool = False
33
+ changes: list[HistoryEntryModel] = []
34
+
35
+
36
+ class PreviewModel(BaseModel):
37
+ """Response from GET /datasets/{id}/history/preview-undo or preview-redo."""
38
+
39
+ can_perform: bool = False
40
+ description: str | None = None
41
+ operation_type: str | None = None
42
+ changed_on: datetime | None = None
43
+
44
+
45
+ class UndoRedoResponse(BaseModel):
46
+ """Response from POST /datasets/{id}/history/undo or redo."""
47
+
48
+ success: bool = False
49
+ description: str | None = None
50
+ new_position: int = 0
51
+
52
+
53
+ class RewindResponse(BaseModel):
54
+ """Response from POST /datasets/{id}/history/rewind."""
55
+
56
+ success: bool = False
57
+ operations_applied: int = 0
58
+ new_position: int = 0
@@ -0,0 +1,91 @@
1
+ """Image-related models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from uuid import UUID
7
+
8
+ from pydantic import BaseModel
9
+
10
+
11
+ class ImageModel(BaseModel):
12
+ """Core image metadata."""
13
+
14
+ image_id: UUID
15
+ file_name: str | None = None
16
+ hash: str | None = None
17
+ width: int = 0
18
+ height: int = 0
19
+ file_type: str | None = None
20
+ source_info: str | None = None
21
+ path: str | None = None
22
+ uri: str | None = None
23
+ created_on: datetime | None = None
24
+ coco_id: int | None = None
25
+ storage_connection_id: UUID | None = None
26
+ full_tile_id: str | None = None
27
+ tile_spec: str | None = None
28
+ gsd_meters: float | None = None
29
+ is_synthetic: bool | None = None
30
+ mask_uri: str | None = None
31
+ mask_format: str | None = None
32
+ band_count: int | None = None
33
+ band_names: str | None = None
34
+ pixel_data_type: str | None = None
35
+ preview_uri: str | None = None
36
+
37
+
38
+ class DatasetImageModel(BaseModel):
39
+ """Image as part of a dataset split."""
40
+
41
+ dataset_image_id: UUID | None = None
42
+ split_id: UUID | None = None
43
+ image: ImageModel | None = None
44
+ added_on: datetime | None = None
45
+ thumb_url: str | None = None
46
+
47
+
48
+ class SyntheticStatsModel(BaseModel):
49
+ """Response from GET /datasets/{id}/images/synthetic/stats."""
50
+
51
+ total_images: int = 0
52
+ real_images: int = 0
53
+ synthetic_images: int = 0
54
+ synthetic_ratio: float = 0.0
55
+
56
+
57
+ class RemoveEmptyImagesResponse(BaseModel):
58
+ """Response from DELETE /datasets/{id}/images/empty."""
59
+
60
+ success: bool = False
61
+ message: str | None = None
62
+ images_removed: int = 0
63
+ removed_images: list[dict[str, object]] = []
64
+
65
+
66
+ class MarkSyntheticResponse(BaseModel):
67
+ """Response from PUT /datasets/{id}/images/synthetic."""
68
+
69
+ success: bool = False
70
+ message: str | None = None
71
+ images_updated: int = 0
72
+
73
+
74
+ class PaginatedImageModel(BaseModel):
75
+ """An image in the paginated dataset-level image listing."""
76
+
77
+ dataset_image_id: UUID | None = None
78
+ image: ImageModel | None = None
79
+ added_on: datetime | None = None
80
+ thumb_url: str | None = None
81
+ mask_uri: str | None = None
82
+ mask_format: str | None = None
83
+ mask_version: int | None = None
84
+ annotation_count: int = 0
85
+ tags: list[str] = []
86
+ file_size: int | None = None
87
+ cloud_cover: float | None = None
88
+ off_nadir_angle: float | None = None
89
+ sensor_type: str | None = None
90
+ provider: str | None = None
91
+ constellation: str | None = None
@@ -0,0 +1,141 @@
1
+ """Import-related models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from typing import Any
7
+ from uuid import UUID
8
+
9
+ from pydantic import BaseModel
10
+
11
+
12
+ class ImportQueuedModel(BaseModel):
13
+ """Response from POST /datasets/{id}/splits/{sid}/import/{source} (202)."""
14
+
15
+ split_id: UUID | None = None
16
+ status: str | None = None
17
+ progress: int = 0
18
+ source: str | None = None
19
+ poll_url: str | None = None
20
+
21
+
22
+ class ImportStatusModel(BaseModel):
23
+ """Response from GET /datasets/{id}/splits/{sid}/import/status."""
24
+
25
+ split_id: UUID | None = None
26
+ status: str | None = None
27
+ progress: int = 0
28
+ error: str | None = None
29
+ started_at: datetime | None = None
30
+ finished_at: datetime | None = None
31
+
32
+
33
+ class ValidationIssueModel(BaseModel):
34
+ """A single validation issue from pre-import validation."""
35
+
36
+ check: str | None = None
37
+ severity: str | None = None
38
+ message: str | None = None
39
+ entity_type: str | None = None
40
+ entity_id: str | None = None
41
+ details: dict[str, Any] | None = None
42
+
43
+
44
+ class ImportConflictModel(BaseModel):
45
+ """A conflict found during pre-import validation."""
46
+
47
+ type: str | None = None
48
+ severity: str | None = None
49
+ message: str | None = None
50
+ details: dict[str, Any] | None = None
51
+ options: list[str] = []
52
+
53
+
54
+ class PreImportSummaryModel(BaseModel):
55
+ """Summary statistics from pre-import validation."""
56
+
57
+ total_images: int = 0
58
+ total_annotations: int = 0
59
+ total_categories: int = 0
60
+ empty_images: int = 0
61
+ small_annotations: int = 0
62
+ orphan_annotations: int = 0
63
+ duplicate_annotations: int = 0
64
+ unused_categories: int = 0
65
+ invalid_bbox_count: int = 0
66
+ zero_area_bbox_count: int = 0
67
+ fixes_to_apply: list[str] = []
68
+
69
+
70
+ class PreImportValidationModel(BaseModel):
71
+ """Response from GET /datasets/{id}/splits/{sid}/import/validate/{vid}."""
72
+
73
+ validation_id: str | None = None
74
+ status: str | None = None
75
+ progress: int = 0
76
+ can_proceed: bool = False
77
+ error_count: int = 0
78
+ warning_count: int = 0
79
+ conflict_count: int = 0
80
+ issues: list[ValidationIssueModel] = []
81
+ conflicts: list[ImportConflictModel] = []
82
+ summary: PreImportSummaryModel | None = None
83
+ started_at: datetime | None = None
84
+ finished_at: datetime | None = None
85
+ error_message: str | None = None
86
+
87
+
88
+ class ValidationStartedModel(BaseModel):
89
+ """Response from POST /datasets/{id}/splits/{sid}/import/s3/validate (202)."""
90
+
91
+ validation_id: str | None = None
92
+ status: str | None = None
93
+ progress: int = 0
94
+ poll_url: str | None = None
95
+
96
+
97
+ # ── Dataset-level import job models ──────────────────────────────────────
98
+
99
+
100
+ class ImportLogEntryModel(BaseModel):
101
+ """A single log entry from an import job."""
102
+
103
+ ts: datetime | None = None
104
+ level: str | None = None
105
+ message: str | None = None
106
+
107
+
108
+ class ImportJobModel(BaseModel):
109
+ """A dataset-level import job."""
110
+
111
+ job_id: UUID | None = None
112
+ dataset_id: UUID | None = None
113
+ split_id: UUID | None = None
114
+ source: str | None = None
115
+ dataset_type: str | None = None
116
+ status: str | None = None
117
+ progress: int = 0
118
+ error_summary: str | None = None
119
+ import_log: list[ImportLogEntryModel] | None = None
120
+ images_imported: int | None = None
121
+ source_details: dict[str, Any] | None = None
122
+ canceled: bool = False
123
+ created_at: datetime | None = None
124
+ started_at: datetime | None = None
125
+ finished_at: datetime | None = None
126
+
127
+
128
+ class ImportJobListModel(BaseModel):
129
+ """Response from GET /datasets/{id}/imports."""
130
+
131
+ jobs: list[ImportJobModel] = []
132
+
133
+
134
+ class ImportJobQueuedModel(BaseModel):
135
+ """Response from POST /datasets/{id}/imports/{jobId}/retry (202)."""
136
+
137
+ job_id: UUID | None = None
138
+ split_id: UUID | None = None
139
+ status: str | None = None
140
+ source: str | None = None
141
+ poll_url: str | None = None
@@ -0,0 +1,37 @@
1
+ """Media job models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from uuid import UUID
7
+
8
+ from pydantic import BaseModel
9
+
10
+
11
+ class MediaJobErrorModel(BaseModel):
12
+ """A single error from a media processing job."""
13
+
14
+ job_id: UUID | None = None
15
+ image_id: UUID | None = None
16
+ image_name: str | None = None
17
+ error: str | None = None
18
+ updated_at: datetime | None = None
19
+
20
+
21
+ class MediaJobStatusModel(BaseModel):
22
+ """Aggregate status of media processing jobs for a dataset."""
23
+
24
+ total: int = 0
25
+ queued: int = 0
26
+ processing: int = 0
27
+ done: int = 0
28
+ error: int = 0
29
+ recent_errors: list[MediaJobErrorModel] = []
30
+
31
+
32
+ class MediaJobActionModel(BaseModel):
33
+ """Response from a media job action (retry, cancel)."""
34
+
35
+ action: str | None = None
36
+ count: int = 0
37
+ message: str | None = None
@@ -0,0 +1,51 @@
1
+ """Dataset merge models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class MergeDatasetRequest(BaseModel):
11
+ """Request for POST /datasets/merge."""
12
+
13
+ source_dataset_ids: list[str]
14
+ target_name: str
15
+ target_description: str | None = None
16
+ include_categories: list[str] | None = None
17
+ keep_images_with_no_annotations: bool = True
18
+ conflict_strategy: str | None = None
19
+ category_mapping: dict[str, str] | None = None
20
+
21
+
22
+ class MergePreviewModel(BaseModel):
23
+ """Response from POST /datasets/merge/preview."""
24
+
25
+ total_images: int = 0
26
+ total_annotations: int = 0
27
+ total_categories: int = 0
28
+ merged_categories: list[str] = []
29
+ warnings: list[str] = []
30
+ source_contributions: dict[str, Any] = {}
31
+
32
+
33
+ class MergeAnalysisModel(BaseModel):
34
+ """Response from POST /datasets/merge/analyze."""
35
+
36
+ all_categories: list[dict[str, Any]] = []
37
+ conflicts: list[dict[str, Any]] = []
38
+ suggested_mapping: dict[str, str] = {}
39
+ has_conflicts: bool = False
40
+
41
+
42
+ class MergeResponseModel(BaseModel):
43
+ """Response from POST /datasets/merge."""
44
+
45
+ new_dataset_id: str | None = None
46
+ new_dataset_name: str | None = None
47
+ status: str | None = None
48
+ images_created: int = 0
49
+ annotations_created: int = 0
50
+ categories_created: int = 0
51
+ category_id_mapping: dict[str, int] = {}