Skip to content

Commit bfed07e

Browse files
authored
[PLT-1458] Set tasks_remaining_count to None if labeling has not started (#1817)
1 parent 3998f7f commit bfed07e

File tree

2 files changed

+98
-29
lines changed

2 files changed

+98
-29
lines changed

libs/labelbox/src/labelbox/schema/labeling_service_dashboard.py

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
from labelbox.exceptions import ResourceNotFoundError
66
from labelbox.pagination import PaginatedCollection
7-
from pydantic import BaseModel, root_validator, Field
7+
from pydantic import BaseModel, model_validator, Field
88
from labelbox.schema.search_filters import SearchFilter, build_search_filter
99
from labelbox.utils import _CamelCaseMixin
1010
from .ontology_kind import EditorTaskType
1111
from labelbox.schema.media_type import MediaType
1212
from labelbox.schema.labeling_service_status import LabelingServiceStatus
13-
from labelbox.utils import _CamelCaseMixin, sentence_case
13+
from labelbox.utils import sentence_case
1414

1515
GRAPHQL_QUERY_SELECTIONS = """
1616
id
@@ -58,7 +58,7 @@ class LabelingServiceDashboard(_CamelCaseMixin):
5858
status (LabelingServiceStatus): status of the labeling service
5959
data_rows_count (int): total number of data rows batched in the project
6060
tasks_completed_count (int): number of tasks completed (in the Done queue)
61-
tasks_remaining_count (int): number of tasks remaining (in a queue other then Done)
61+
tasks_remaining_count (int): number of tasks remaining (i.e. tasks in progress), None if labeling has not started
6262
tags (List[LabelingServiceDashboardTags]): tags associated with the project
6363
media_type (MediaType): media type of the project
6464
editor_task_type (EditorTaskType): editor task type of the project
@@ -73,7 +73,7 @@ class LabelingServiceDashboard(_CamelCaseMixin):
7373
status: LabelingServiceStatus = Field(frozen=True, default=None)
7474
data_rows_count: int = Field(frozen=True)
7575
tasks_completed_count: int = Field(frozen=True)
76-
tasks_remaining_count: int = Field(frozen=True)
76+
tasks_remaining_count: Optional[int] = Field(frozen=True, default=None)
7777
media_type: Optional[MediaType] = Field(frozen=True, default=None)
7878
editor_task_type: EditorTaskType = Field(frozen=True, default=None)
7979
tags: List[LabelingServiceDashboardTags] = Field(frozen=True, default=None)
@@ -84,8 +84,7 @@ def __init__(self, **kwargs):
8484
super().__init__(**kwargs)
8585
if not self.client.enable_experimental:
8686
raise RuntimeError(
87-
"Please enable experimental in client to use LabelingService"
88-
)
87+
"Please enable experimental in client to use LabelingService")
8988

9089
@property
9190
def service_type(self):
@@ -98,28 +97,20 @@ def service_type(self):
9897
if self.editor_task_type is None:
9998
return sentence_case(self.media_type.value)
10099

101-
if (
102-
self.editor_task_type == EditorTaskType.OfflineModelChatEvaluation
103-
and self.media_type == MediaType.Conversational
104-
):
100+
if (self.editor_task_type == EditorTaskType.OfflineModelChatEvaluation
101+
and self.media_type == MediaType.Conversational):
105102
return "Offline chat evaluation"
106103

107-
if (
108-
self.editor_task_type == EditorTaskType.ModelChatEvaluation
109-
and self.media_type == MediaType.Conversational
110-
):
104+
if (self.editor_task_type == EditorTaskType.ModelChatEvaluation and
105+
self.media_type == MediaType.Conversational):
111106
return "Live chat evaluation"
112107

113-
if (
114-
self.editor_task_type == EditorTaskType.ResponseCreation
115-
and self.media_type == MediaType.Text
116-
):
108+
if (self.editor_task_type == EditorTaskType.ResponseCreation and
109+
self.media_type == MediaType.Text):
117110
return "Response creation"
118111

119-
if (
120-
self.media_type == MediaType.LLMPromptCreation
121-
or self.media_type == MediaType.LLMPromptResponseCreation
122-
):
112+
if (self.media_type == MediaType.LLMPromptCreation or
113+
self.media_type == MediaType.LLMPromptResponseCreation):
123114
return "Prompt response creation"
124115

125116
return sentence_case(self.media_type.value)
@@ -163,8 +154,7 @@ def get_all(
163154
pageInfo { endCursor }
164155
}
165156
}
166-
"""
167-
)
157+
""")
168158
else:
169159
template = Template(
170160
"""query SearchProjectsPyApi($$first: Int, $$from: String) {
@@ -174,13 +164,11 @@ def get_all(
174164
pageInfo { endCursor }
175165
}
176166
}
177-
"""
178-
)
167+
""")
179168
query_str = template.substitute(
180169
labeling_dashboard_selections=GRAPHQL_QUERY_SELECTIONS,
181170
search_query=build_search_filter(search_query)
182-
if search_query
183-
else None,
171+
if search_query else None,
184172
)
185173
params: Dict[str, Union[str, int]] = {}
186174

@@ -198,7 +186,7 @@ def convert_to_labeling_service_dashboard(client, data):
198186
experimental=True,
199187
)
200188

201-
@root_validator(pre=True)
189+
@model_validator(mode='before')
202190
def convert_boost_data(cls, data):
203191
if "boostStatus" in data:
204192
data["status"] = LabelingServiceStatus(data.pop("boostStatus"))
@@ -212,6 +200,12 @@ def convert_boost_data(cls, data):
212200
if "boostRequestedBy" in data:
213201
data["created_by_id"] = data.pop("boostRequestedBy")
214202

203+
tasks_remaining_count = data.get("tasksRemainingCount", 0)
204+
tasks_total_count = data.get("tasksTotalCount", 0)
205+
# to avoid confusion, setting tasks_completed_count to None if none of tasks has even completed an none are in flight
206+
if tasks_total_count == 0 and tasks_remaining_count == 0:
207+
data.pop("tasksRemainingCount")
208+
215209
return data
216210

217211
def dict(self, *args, **kwargs):
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from unittest.mock import MagicMock
2+
3+
from labelbox.schema.labeling_service_dashboard import LabelingServiceDashboard
4+
5+
6+
def test_no_tasks_remaining_count():
7+
labeling_service_dashboard_data = {
8+
'id': 'cm0eeo4c301lg07061phfhva0',
9+
'name': 'TestStatus',
10+
'boostRequestedAt': '2024-08-28T22:08:07.446Z',
11+
'boostUpdatedAt': '2024-08-28T22:08:07.446Z',
12+
'boostRequestedBy': None,
13+
'boostStatus': 'SET_UP',
14+
'dataRowsCount': 0,
15+
'dataRowsDoneCount': 0,
16+
'dataRowsInReviewCount': 0,
17+
'dataRowsInReworkCount': 0,
18+
'tasksTotalCount': 0,
19+
'tasksCompletedCount': 0,
20+
'tasksRemainingCount': 0,
21+
'mediaType': 'image',
22+
'editorTaskType': None,
23+
'tags': [],
24+
'client': MagicMock()
25+
}
26+
lsd = LabelingServiceDashboard(**labeling_service_dashboard_data)
27+
assert lsd.tasks_remaining_count is None
28+
29+
30+
def test_tasks_remaining_count_exists():
31+
labeling_service_dashboard_data = {
32+
'id': 'cm0eeo4c301lg07061phfhva0',
33+
'name': 'TestStatus',
34+
'boostRequestedAt': '2024-08-28T22:08:07.446Z',
35+
'boostUpdatedAt': '2024-08-28T22:08:07.446Z',
36+
'boostRequestedBy': None,
37+
'boostStatus': 'SET_UP',
38+
'dataRowsCount': 0,
39+
'dataRowsDoneCount': 0,
40+
'dataRowsInReviewCount': 0,
41+
'dataRowsInReworkCount': 0,
42+
'tasksTotalCount': 0,
43+
'tasksCompletedCount': 0,
44+
'tasksRemainingCount': 1,
45+
'mediaType': 'image',
46+
'editorTaskType': None,
47+
'tags': [],
48+
'client': MagicMock()
49+
}
50+
lsd = LabelingServiceDashboard(**labeling_service_dashboard_data)
51+
assert lsd.tasks_remaining_count == 1
52+
53+
54+
def test_tasks_total_no_tasks_remaining_count():
55+
labeling_service_dashboard_data = {
56+
'id': 'cm0eeo4c301lg07061phfhva0',
57+
'name': 'TestStatus',
58+
'boostRequestedAt': '2024-08-28T22:08:07.446Z',
59+
'boostUpdatedAt': '2024-08-28T22:08:07.446Z',
60+
'boostRequestedBy': None,
61+
'boostStatus': 'SET_UP',
62+
'dataRowsCount': 0,
63+
'dataRowsDoneCount': 0,
64+
'dataRowsInReviewCount': 1,
65+
'dataRowsInReworkCount': 0,
66+
'tasksTotalCount': 1,
67+
'tasksCompletedCount': 0,
68+
'tasksRemainingCount': 0,
69+
'mediaType': 'image',
70+
'editorTaskType': None,
71+
'tags': [],
72+
'client': MagicMock()
73+
}
74+
lsd = LabelingServiceDashboard(**labeling_service_dashboard_data)
75+
assert lsd.tasks_remaining_count == 0

0 commit comments

Comments
 (0)