Skip to content

Commit d914a47

Browse files
authored
Merge pull request #31 from hasty-ai/kp-add-automated-labeling
Add automated labeling endpoint support
2 parents ef32000 + 979d210 commit d914a47

3 files changed

Lines changed: 155 additions & 1 deletion

File tree

hasty/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def int_or_str(value):
1919
return value
2020

2121

22-
__version__ = '0.3.5'
22+
__version__ = '0.3.6'
2323
VERSION = tuple(map(int_or_str, __version__.split('.')))
2424

2525
__all__ = [

hasty/automated_labeling.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
from collections import OrderedDict
2+
from time import time
3+
from typing import Optional
4+
5+
from .constants import WAIT_INTERVAL_SEC
6+
from .hasty_object import HastyObject
7+
from .requester import Requester
8+
9+
10+
class AutomatedLabelingJob(HastyObject):
11+
endpoint = '/v1/projects/{project_id}/automated_labeling'
12+
endpoint_job_id = '/v1/projects/{project_id}/automated_labeling/{job_id}'
13+
14+
def __repr__(self):
15+
return self.get__repr__(OrderedDict({"id": self._id,
16+
"status": self._status,
17+
"progress": self._progress}))
18+
19+
@property
20+
def id(self):
21+
"""
22+
:type: string
23+
"""
24+
return self._id
25+
26+
@property
27+
def status(self):
28+
"""
29+
:type: string
30+
"""
31+
return self._status
32+
33+
@property
34+
def project_id(self):
35+
"""
36+
:type: string
37+
"""
38+
return self._project_id
39+
40+
@property
41+
def progress(self):
42+
"""
43+
:type: float
44+
"""
45+
return self._progress
46+
47+
@property
48+
def started_on(self):
49+
"""
50+
:type: string
51+
"""
52+
return self._started_on
53+
54+
@property
55+
def completed_on(self):
56+
"""
57+
:type: string
58+
"""
59+
return self._completed_on
60+
61+
@property
62+
def experiment_id(self):
63+
"""
64+
:type: string
65+
"""
66+
return self._experiment_id
67+
68+
def _init_properties(self):
69+
self._job_id = None
70+
self._status = None
71+
self._project_id = None
72+
self._started_on = None
73+
self._completed_on = None
74+
self._last_check = None
75+
self._experiment_id = None
76+
self._progress = None
77+
78+
def _set_prop_values(self, data):
79+
if "id" in data:
80+
self._id = data["id"]
81+
if "status" in data:
82+
self._status = data["status"]
83+
if "started_on" in data:
84+
self._started_on = data["started_on"]
85+
if "completed_on" in data:
86+
self._completed_on = data["completed_on"]
87+
if "project_id" in data:
88+
self._project_id = data["project_id"]
89+
if "experiment_id" in data:
90+
self._experiment_id = data["experiment_id"]
91+
if "progress" in data:
92+
self._progress = data["progress"]
93+
94+
@staticmethod
95+
def _create(requester: Requester, project_id: str, experiment_id: str, confidence_threshold: float = 0.8,
96+
max_detections_per_image: int = 100, num_images: int = 0, masker_threshold: float = 0.5,
97+
dataset_id: Optional[str] = None):
98+
res = requester.post(AutomatedLabelingJob.endpoint.format(project_id=project_id),
99+
json_data={"experiment_id": experiment_id,
100+
"confidence_threshold": confidence_threshold,
101+
"max_detections_per_image": max_detections_per_image,
102+
"num_images": num_images,
103+
"masker_threshold": masker_threshold,
104+
"dataset_id": dataset_id})
105+
return AutomatedLabelingJob(requester, res, {"project_id": project_id})
106+
107+
def check_status(self):
108+
"""
109+
Returns current status and progress
110+
"""
111+
if self._last_check is None or self._last_check > WAIT_INTERVAL_SEC:
112+
res = self._requester.get(AutomatedLabelingJob.endpoint_job_id.format(project_id=self._project_id,
113+
job_id=self._id))
114+
self._set_prop_values(res)
115+
self._last_check = time()
116+
return {"status": self._status,
117+
"progress": self._progress}

hasty/project.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import List, Union, Optional
33

44
from .attribute import Attribute
5+
from .automated_labeling import AutomatedLabelingJob
56
from .constants import ImageStatus, SemanticFormat, VALID_EXPORT_FORMATS, VALID_SEMANTIC_ORDER, \
67
VALID_SEMANTIC_FORMATS, VALID_STATUSES
78
from .dataset import Dataset
@@ -419,3 +420,39 @@ def get_attributer(self):
419420
d = Attributer(self._requester, {"project_id": self._id})
420421
d.discover_model()
421422
return d
423+
424+
def get_automated_labeling_jobs(self):
425+
"""
426+
Get automated labeling jobs, list of :py:class:`~hasty.AutomatedLabelingJob` objects.
427+
"""
428+
return PaginatedList(AutomatedLabelingJob, self._requester,
429+
AutomatedLabelingJob.endpoint.format(project_id=self._id),
430+
obj_params={"project_id": self.id})
431+
432+
def get_automated_labeling_job(self, job_id: str):
433+
"""
434+
Get automated labeling jobs, list of :py:class:`~hasty.AutomatedLabelingJob` objects.
435+
436+
Args:
437+
job_id (str): Automated labeling job id
438+
"""
439+
res = self._requester.get(AutomatedLabelingJob.endpoint_job_id.format(project_id=self.id, job_id=job_id))
440+
return AutomatedLabelingJob(self._requester, res, {"project_id": self.id})
441+
442+
def create_automated_labeling_job(self, experiment_id: str, confidence_threshold: float = 0.8,
443+
max_detections_per_image: int = 100, num_images: int = 0,
444+
masker_threshold: float = 0.5, dataset_id: Optional[str] = None):
445+
"""
446+
Create automated labeling job, returns :py:class:`~hasty.AutomatedLabelingJob` object.
447+
448+
Args:
449+
experiment_id (str): ID of an experiment, that would be used for automated labeling
450+
confidence_threshold (float, optional): Confidence threshold of the predictions that should be applied
451+
(default 0.8)
452+
max_detections_per_image (int, optional): Max number of labels that should be created, default 100
453+
num_images (int, optional): Total number of images that should be used for automated labeling (default all)
454+
masker_threshold (float, optional): Threshold for mask head (default 0.5)
455+
dataset_id (str, optional): Filter images by dataset
456+
"""
457+
return AutomatedLabelingJob._create(self._requester, self._id, experiment_id, confidence_threshold,
458+
max_detections_per_image, num_images, masker_threshold, dataset_id)

0 commit comments

Comments
 (0)