Skip to content

Commit fdcc83a

Browse files
committed
feat(LAB-4125): in consensus labeling step, I export all annotators' latest labeled versions
1 parent 07bf0cc commit fdcc83a

File tree

9 files changed

+487
-24
lines changed

9 files changed

+487
-24
lines changed

pyproject.toml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ dependencies = [
4444
"filelock >= 3.0.0, < 4.0.0",
4545
"pip-system-certs >= 4.0.0, < 5.0.0; platform_system=='Windows'",
4646
"pyrate-limiter >= 3, < 4",
47-
"kili-formats == 1.3.0"
47+
"kili-formats == 1.4.0"
4848
]
4949
urls = { homepage = "https://github.com/kili-technology/kili-python-sdk" }
5050

@@ -63,7 +63,7 @@ dev = [
6363
"pytest-xdist[psutil]",
6464
"pytest-timeout",
6565
# documentation
66-
"mkdocs",
66+
"mkdocs >= 1.0.0, < 2.0.0",
6767
"mkdocs-material",
6868
"mkdocstrings",
6969
"mkdocstrings-python-legacy",
@@ -79,7 +79,7 @@ dev = [
7979
"nbconvert",
8080
"ipykernel",
8181
# optional dependencies
82-
"kili-formats[all] == 1.3.0",
82+
"kili-formats[all] == 1.4.0",
8383
"opencv-python >= 4.0.0, < 5.0.0",
8484
"azure-storage-blob >= 12.0.0, < 13.0.0",
8585
# optional dependencies gis
@@ -90,14 +90,14 @@ dev = [
9090
# optional dependencies - yolo
9191
"pyyaml >= 6.0, < 7.0",
9292
# optional dependencies - image
93-
"Pillow >=9.0.0, <11.0.0"
93+
"Pillow >=10.0.0, <13.0.0"
9494
]
9595
all = [
9696
# aggregate all optional deps without dev
9797
"azure-storage-blob >= 12.0.0, < 13.0.0",
98-
"kili-formats[all] == 1.3.0",
98+
"kili-formats[all] == 1.4.0",
9999
"opencv-python >= 4.0.0, < 5.0.0",
100-
"Pillow >=9.0.0, <11.0.0",
100+
"Pillow >=10.0.0, <13.0.0",
101101
"pyproj == 3.7.1",
102102
"pyyaml >= 6.0, < 7.0",
103103
"shapely >= 1.8, < 3",
@@ -108,20 +108,20 @@ cli = [
108108
"tabulate >= 0.9.0, < 0.10.0"
109109
]
110110
coco = [
111-
"kili-formats[coco] == 1.3.0"
111+
"kili-formats[coco] == 1.4.0"
112112
]
113113
gis = [
114114
"pyproj == 3.7.1",
115115
"shapely >= 1.8, < 3"
116116
]
117117
image = [
118-
"Pillow >=9.0.0, <11.0.0",
119-
"kili-formats[image] == 1.3.0"
118+
"Pillow >=10.0.0, <13.0.0",
119+
"kili-formats[image] == 1.4.0"
120120
]
121121
image-utils = ["opencv-python >= 4.0.0, < 5.0.0"]
122122

123123
video = [
124-
"kili-formats[video] == 1.3.0"
124+
"kili-formats[video] == 1.4.0"
125125
]
126126
yolo = [
127127
"pyyaml >= 6.0, < 7.0"

src/kili/adapters/kili_api_gateway/asset/formatters.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ def load_asset_json_fields(asset: dict, fields: ListOrTuple[str], http_client: H
139139
if "latestLabel.jsonResponse" in fields and asset.get("latestLabel") is not None:
140140
_process_label_json_response(asset["latestLabel"], url_to_label_mapping)
141141

142+
if "latestLabels.jsonResponse" in fields:
143+
for label in asset.get("latestLabels", []):
144+
if label is not None:
145+
_process_label_json_response(label, url_to_label_mapping)
146+
142147
if url_to_label_mapping:
143148
download_json_responses_parallel(url_to_label_mapping, http_client)
144149

src/kili/domain_api/exports.py

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from kili.domain.types import ListOrTuple
1313
from kili.domain_api.base import DomainNamespace
1414
from kili.domain_api.namespace_utils import get_available_methods
15-
from kili.services.export.types import CocoAnnotationModifier, LabelFormat, SplitOption
15+
from kili.services.export.types import CocoAnnotationModifier, ExportType, LabelFormat, SplitOption
1616

1717
if TYPE_CHECKING:
1818
import pandas as pd
@@ -94,6 +94,7 @@ def kili(
9494
include_sent_back_labels: Optional[bool] = None,
9595
label_type_in: Optional[list[LabelType]] = None,
9696
single_file: Optional[bool] = False,
97+
export_type: ExportType = "latest_from_last_step",
9798
):
9899
"""Export project labels in Kili native format.
99100
@@ -114,6 +115,14 @@ def kili(
114115
whose type belongs to that list.
115116
By default, only `DEFAULT` and `REVIEW` labels are exported.
116117
single_file: If True, all labels are exported in a single JSON file.
118+
export_type: Type of export. Options are:
119+
- `"latest_from_last_step"`: exports the latest label from the last workflow step
120+
(uses `latestLabels` field, supports multiple annotators).
121+
- `"latest_from_all_steps"`: exports latest labels from all workflow steps
122+
(useful for consensus projects with multiple annotators).
123+
- `"latest"`: exports the single latest label per asset (uses `latestLabel` field).
124+
- `"normal"`: exports all labels for each asset.
125+
Defaults to `"latest_from_last_step"`.
117126
118127
Returns:
119128
Export information or None if export failed.
@@ -129,6 +138,7 @@ def kili(
129138
normalized_coordinates=True,
130139
fmt="kili",
131140
single_file=bool(single_file),
141+
export_type=export_type,
132142
)
133143

134144
def coco(
@@ -142,6 +152,7 @@ def coco(
142152
include_sent_back_labels: Optional[bool] = None,
143153
label_type_in: Optional[list[LabelType]] = None,
144154
layout: SplitOption = "split",
155+
export_type: ExportType = "latest_from_last_step",
145156
):
146157
"""Export project labels in COCO format.
147158
@@ -165,6 +176,14 @@ def coco(
165176
By default, only `DEFAULT` and `REVIEW` labels are exported.
166177
layout: Layout of the exported files. "split" means there is one folder
167178
per job, "merged" that there is one folder with every labels.
179+
export_type: Type of export. Options are:
180+
- `"latest_from_last_step"`: exports the latest label from the last workflow step
181+
(uses `latestLabels` field, supports multiple annotators).
182+
- `"latest_from_all_steps"`: exports latest labels from all workflow steps
183+
(useful for consensus projects with multiple annotators).
184+
- `"latest"`: exports the single latest label per asset (uses `latestLabel` field).
185+
- `"normal"`: exports all labels for each asset.
186+
Defaults to `"latest_from_last_step"`.
168187
169188
Returns:
170189
Export information or None if export failed.
@@ -180,6 +199,7 @@ def coco(
180199
label_type_in=label_type_in,
181200
layout=layout,
182201
fmt="coco",
202+
export_type=export_type,
183203
)
184204

185205
def yolo_v4(
@@ -192,6 +212,7 @@ def yolo_v4(
192212
filter: Optional[ExportAssetFilter] = None,
193213
include_sent_back_labels: Optional[bool] = None,
194214
label_type_in: Optional[list[LabelType]] = None,
215+
export_type: ExportType = "latest_from_last_step",
195216
):
196217
"""Export project labels in YOLO v4 format.
197218
@@ -214,6 +235,14 @@ def yolo_v4(
214235
By default, only `DEFAULT` and `REVIEW` labels are exported.
215236
include_sent_back_labels: If True, the export will include the labels that
216237
have been sent back.
238+
export_type: Type of export. Options are:
239+
- `"latest_from_last_step"`: exports the latest label from the last workflow step
240+
(uses `latestLabels` field, supports multiple annotators).
241+
- `"latest_from_all_steps"`: exports latest labels from all workflow steps
242+
(useful for consensus projects with multiple annotators).
243+
- `"latest"`: exports the single latest label per asset (uses `latestLabel` field).
244+
- `"normal"`: exports all labels for each asset.
245+
Defaults to `"latest_from_last_step"`.
217246
218247
Returns:
219248
Export information or None if export failed.
@@ -228,6 +257,7 @@ def yolo_v4(
228257
label_type_in=label_type_in,
229258
layout=layout,
230259
fmt="yolo_v4",
260+
export_type=export_type,
231261
)
232262

233263
def yolo_v5(
@@ -240,6 +270,7 @@ def yolo_v5(
240270
filter: Optional[ExportAssetFilter] = None,
241271
include_sent_back_labels: Optional[bool] = None,
242272
label_type_in: Optional[list[LabelType]] = None,
273+
export_type: ExportType = "latest_from_last_step",
243274
):
244275
"""Export project labels in YOLO v5 format.
245276
@@ -262,6 +293,14 @@ def yolo_v5(
262293
By default, only `DEFAULT` and `REVIEW` labels are exported.
263294
include_sent_back_labels: If True, the export will include the labels that
264295
have been sent back.
296+
export_type: Type of export. Options are:
297+
- `"latest_from_last_step"`: exports the latest label from the last workflow step
298+
(uses `latestLabels` field, supports multiple annotators).
299+
- `"latest_from_all_steps"`: exports latest labels from all workflow steps
300+
(useful for consensus projects with multiple annotators).
301+
- `"latest"`: exports the single latest label per asset (uses `latestLabel` field).
302+
- `"normal"`: exports all labels for each asset.
303+
Defaults to `"latest_from_last_step"`.
265304
266305
Returns:
267306
Export information or None if export failed.
@@ -276,6 +315,7 @@ def yolo_v5(
276315
label_type_in=label_type_in,
277316
layout=layout,
278317
fmt="yolo_v5",
318+
export_type=export_type,
279319
)
280320

281321
def yolo_v7(
@@ -288,6 +328,7 @@ def yolo_v7(
288328
filter: Optional[ExportAssetFilter] = None,
289329
include_sent_back_labels: Optional[bool] = None,
290330
label_type_in: Optional[list[LabelType]] = None,
331+
export_type: ExportType = "latest_from_last_step",
291332
):
292333
"""Export project labels in YOLO v7 format.
293334
@@ -310,6 +351,14 @@ def yolo_v7(
310351
By default, only `DEFAULT` and `REVIEW` labels are exported.
311352
include_sent_back_labels: If True, the export will include the labels that
312353
have been sent back.
354+
export_type: Type of export. Options are:
355+
- `"latest_from_last_step"`: exports the latest label from the last workflow step
356+
(uses `latestLabels` field, supports multiple annotators).
357+
- `"latest_from_all_steps"`: exports latest labels from all workflow steps
358+
(useful for consensus projects with multiple annotators).
359+
- `"latest"`: exports the single latest label per asset (uses `latestLabel` field).
360+
- `"normal"`: exports all labels for each asset.
361+
Defaults to `"latest_from_last_step"`.
313362
314363
Returns:
315364
Export information or None if export failed.
@@ -324,6 +373,7 @@ def yolo_v7(
324373
label_type_in=label_type_in,
325374
layout=layout,
326375
fmt="yolo_v7",
376+
export_type=export_type,
327377
)
328378

329379
def yolo_v8(
@@ -336,6 +386,7 @@ def yolo_v8(
336386
filter: Optional[ExportAssetFilter] = None,
337387
include_sent_back_labels: Optional[bool] = None,
338388
label_type_in: Optional[list[LabelType]] = None,
389+
export_type: ExportType = "latest_from_last_step",
339390
):
340391
"""Export project labels in YOLO v8 format.
341392
@@ -358,6 +409,14 @@ def yolo_v8(
358409
By default, only `DEFAULT` and `REVIEW` labels are exported.
359410
include_sent_back_labels: If True, the export will include the labels that
360411
have been sent back.
412+
export_type: Type of export. Options are:
413+
- `"latest_from_last_step"`: exports the latest label from the last workflow step
414+
(uses `latestLabels` field, supports multiple annotators).
415+
- `"latest_from_all_steps"`: exports latest labels from all workflow steps
416+
(useful for consensus projects with multiple annotators).
417+
- `"latest"`: exports the single latest label per asset (uses `latestLabel` field).
418+
- `"normal"`: exports all labels for each asset.
419+
Defaults to `"latest_from_last_step"`.
361420
362421
Returns:
363422
Export information or None if export failed.
@@ -372,6 +431,7 @@ def yolo_v8(
372431
label_type_in=label_type_in,
373432
layout=layout,
374433
fmt="yolo_v8",
434+
export_type=export_type,
375435
)
376436

377437
def pascal_voc(
@@ -383,6 +443,7 @@ def pascal_voc(
383443
filter: Optional[ExportAssetFilter] = None,
384444
include_sent_back_labels: Optional[bool] = None,
385445
label_type_in: Optional[list[LabelType]] = None,
446+
export_type: ExportType = "latest_from_last_step",
386447
):
387448
"""Export project labels in Pascal VOC format.
388449
@@ -403,6 +464,14 @@ def pascal_voc(
403464
By default, only `DEFAULT` and `REVIEW` labels are exported.
404465
include_sent_back_labels: If True, the export will include the labels that
405466
have been sent back.
467+
export_type: Type of export. Options are:
468+
- `"latest_from_last_step"`: exports the latest label from the last workflow step
469+
(uses `latestLabels` field, supports multiple annotators).
470+
- `"latest_from_all_steps"`: exports latest labels from all workflow steps
471+
(useful for consensus projects with multiple annotators).
472+
- `"latest"`: exports the single latest label per asset (uses `latestLabel` field).
473+
- `"normal"`: exports all labels for each asset.
474+
Defaults to `"latest_from_last_step"`.
406475
407476
Returns:
408477
Export information or None if export failed.
@@ -417,6 +486,7 @@ def pascal_voc(
417486
label_type_in=label_type_in,
418487
layout="merged",
419488
fmt="pascal_voc",
489+
export_type=export_type,
420490
)
421491

422492
def geojson(
@@ -428,6 +498,7 @@ def geojson(
428498
filter: Optional[ExportAssetFilter] = None,
429499
include_sent_back_labels: Optional[bool] = None,
430500
label_type_in: Optional[list[LabelType]] = None,
501+
export_type: ExportType = "latest_from_last_step",
431502
):
432503
"""Export project labels in GeoJSON format.
433504
@@ -448,6 +519,14 @@ def geojson(
448519
By default, only `DEFAULT` and `REVIEW` labels are exported.
449520
include_sent_back_labels: If True, the export will include the labels that
450521
have been sent back.
522+
export_type: Type of export. Options are:
523+
- `"latest_from_last_step"`: exports the latest label from the last workflow step
524+
(uses `latestLabels` field, supports multiple annotators).
525+
- `"latest_from_all_steps"`: exports latest labels from all workflow steps
526+
(useful for consensus projects with multiple annotators).
527+
- `"latest"`: exports the single latest label per asset (uses `latestLabel` field).
528+
- `"normal"`: exports all labels for each asset.
529+
Defaults to `"latest_from_last_step"`.
451530
452531
Returns:
453532
Export information or None if export failed.
@@ -462,6 +541,7 @@ def geojson(
462541
label_type_in=label_type_in,
463542
layout="merged",
464543
fmt="geojson",
544+
export_type=export_type,
465545
)
466546

467547
@typechecked
@@ -531,6 +611,7 @@ def _export(
531611
project_id: str,
532612
single_file: bool = False,
533613
with_assets: Optional[bool] = True,
614+
export_type: ExportType = "latest_from_last_step",
534615
) -> Optional[list[dict[str, Union[list[str], str]]]]:
535616
"""Export the project labels with the requested format into the requested output path.
536617
@@ -591,4 +672,5 @@ def _export(
591672
normalized_coordinates=normalized_coordinates,
592673
label_type_in=list(label_type_in) if label_type_in else None,
593674
include_sent_back_labels=include_sent_back_labels,
675+
export_type=export_type,
594676
)

src/kili/presentation/client/label.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
)
4545
from kili.services.export import export_labels
4646
from kili.services.export.exceptions import NoCompatibleJobError
47-
from kili.services.export.types import CocoAnnotationModifier, LabelFormat, SplitOption
47+
from kili.services.export.types import CocoAnnotationModifier, ExportType, LabelFormat, SplitOption
4848
from kili.use_cases.asset.utils import AssetUseCasesUtils
4949
from kili.use_cases.label import LabelUseCases
5050
from kili.use_cases.label.process_shapefiles import get_json_response_from_shapefiles
@@ -1298,6 +1298,7 @@ def export_labels(
12981298
normalized_coordinates: Optional[bool] = None,
12991299
label_type_in: Optional[list[str]] = None,
13001300
include_sent_back_labels: Optional[bool] = None,
1301+
export_type: ExportType = "latest",
13011302
) -> Optional[list[dict[str, Union[list[str], str]]]]:
13021303
# pylint: disable=line-too-long
13031304
"""Export the project labels with the requested format into the requested output path.
@@ -1355,6 +1356,11 @@ def export_labels(
13551356
label_type_in: Optional list of label type. Exported assets should have a label whose type belongs to that list.
13561357
By default, only `DEFAULT` and `REVIEW` labels are exported.
13571358
include_sent_back_labels: If True, the export will include the labels that have been sent back.
1359+
export_type: Type of export. Options are:
1360+
- `"latest"`: Export only the latest label for each asset (deprecated, use `"latest_from_last_step"` instead).
1361+
- `"latest_from_last_step"`: Export the latest label from each annotator for the last step.
1362+
- `"latest_from_all_steps"`: Export the latest label from each annotator for all steps (uses `isLastForStep` filtering).
1363+
- `"normal"`: Export all labels.
13581364
13591365
!!! Info
13601366
The supported formats are:
@@ -1435,7 +1441,7 @@ def is_rectangle(coco_annotation, coco_image, kili_annotation):
14351441
self, # pyright: ignore[reportArgumentType]
14361442
asset_ids=resolved_asset_ids,
14371443
project_id=ProjectId(project_id),
1438-
export_type="latest",
1444+
export_type=export_type,
14391445
label_format=fmt,
14401446
split_option=layout,
14411447
single_file=single_file,

0 commit comments

Comments
 (0)