77from kili .adapters .kili_api_gateway .project .common import get_project
88from kili .core .graphql .graphql_client import GraphQLClient
99from kili .domain .annotation import (
10+ ClassicAnnotation ,
11+ ClassificationAnnotation ,
12+ RankingAnnotation ,
13+ TranscriptionAnnotation ,
1014 Vertice ,
1115 VideoAnnotation ,
1216 VideoClassificationAnnotation ,
@@ -54,11 +58,17 @@ def patch_label_json_response(self, label: Dict, label_id: LabelId) -> None:
5458
5559 Modifies the input label.
5660 """
57- if self ._project_input_type == "VIDEO" :
61+ if self ._project_input_type in { "VIDEO" , "LLM_RLHF" } :
5862 annotations = list_annotations (
5963 graphql_client = self ._graphql_client ,
6064 label_id = label_id ,
6165 annotation_fields = ("__typename" , "id" , "job" , "path" , "labelId" ),
66+ classification_annotation_fields = ("annotationValue.categories" ,),
67+ ranking_annotation_fields = (
68+ "annotationValue.orders.elements" ,
69+ "annotationValue.orders.rank" ,
70+ ),
71+ transcription_annotation_fields = ("annotationValue.text" ,),
6272 video_annotation_fields = (
6373 "frames.start" ,
6474 "frames.end" ,
@@ -79,10 +89,15 @@ def patch_label_json_response(self, label: Dict, label_id: LabelId) -> None:
7989 if not annotations and self ._label_has_json_response_data (label ):
8090 return
8191
82- annotations = cast (List [VideoAnnotation ], annotations )
83- converted_json_resp = _video_label_annotations_to_json_response (
84- annotations = annotations , json_interface = self ._project_json_interface
85- )
92+ if self ._project_input_type == "VIDEO" :
93+ annotations = cast (List [VideoAnnotation ], annotations )
94+ converted_json_resp = _video_annotations_to_json_response (
95+ annotations = annotations , json_interface = self ._project_json_interface
96+ )
97+ else :
98+ annotations = cast (List [ClassicAnnotation ], annotations )
99+ converted_json_resp = _classic_annotations_to_json_response (annotations = annotations )
100+
86101 label ["jsonResponse" ] = converted_json_resp
87102
88103
@@ -105,7 +120,7 @@ def _fill_empty_frames(json_response: Dict) -> None:
105120 json_response .setdefault (str (frame_id ), {})
106121
107122
108- def _video_label_annotations_to_json_response (
123+ def _video_annotations_to_json_response (
109124 annotations : List [VideoAnnotation ], json_interface : Dict
110125) -> Dict [str , Dict [JobName , Dict ]]:
111126 """Convert video label annotations to a video json response."""
@@ -147,14 +162,49 @@ def _video_label_annotations_to_json_response(
147162 json_resp [frame_id ] = {** json_resp [frame_id ], ** frame_json_resp }
148163
149164 else :
150- raise NotImplementedError (f"Cannot convert annotation to json response: { ann } " )
165+ raise NotImplementedError (f"Cannot convert video annotation to json response: { ann } " )
151166
152167 _add_annotation_metadata (annotations , json_resp )
153168 _fill_empty_frames (json_resp )
154169
155170 return dict (sorted (json_resp .items (), key = lambda item : int (item [0 ]))) # sort by frame id
156171
157172
173+ def _classic_annotations_to_json_response (
174+ annotations : List [ClassicAnnotation ],
175+ ) -> Dict [str , Dict [JobName , Dict ]]:
176+ """Convert label annotations to a json response."""
177+ json_resp = defaultdict (dict )
178+
179+ for ann in annotations :
180+ if ann ["__typename" ] == "ClassificationAnnotation" :
181+ ann = cast (ClassificationAnnotation , ann )
182+ ann_json_resp = _classification_annotation_to_json_response (ann )
183+ for job_name , job_resp in ann_json_resp .items ():
184+ json_resp .setdefault (job_name , {}).setdefault ("categories" , []).extend (
185+ job_resp ["categories" ]
186+ )
187+
188+ elif ann ["__typename" ] == "RankingAnnotation" :
189+ ann = cast (RankingAnnotation , ann )
190+ ann_json_resp = _ranking_annotation_to_json_response (ann )
191+ for job_name , job_resp in ann_json_resp .items ():
192+ json_resp .setdefault (job_name , {}).setdefault ("orders" , []).extend (
193+ job_resp ["orders" ]
194+ )
195+
196+ elif ann ["__typename" ] == "TranscriptionAnnotation" :
197+ ann = cast (TranscriptionAnnotation , ann )
198+ ann_json_resp = _transcription_annotation_to_json_response (ann )
199+ for job_name , job_resp in ann_json_resp .items ():
200+ json_resp .setdefault (job_name , {}).setdefault ("text" , job_resp ["text" ])
201+
202+ else :
203+ raise NotImplementedError (f"Cannot convert classic annotation to json response: { ann } " )
204+
205+ return dict (json_resp )
206+
207+
158208@overload
159209def _key_annotations_iterator (
160210 annotation : VideoTranscriptionAnnotation ,
@@ -226,6 +276,40 @@ def _key_annotations_iterator(annotation: VideoAnnotation) -> Generator:
226276 yield key_ann , key_ann_start , key_ann_end , next_key_ann
227277
228278
279+ def _ranking_annotation_to_json_response (
280+ annotation : RankingAnnotation ,
281+ ) -> Dict [JobName , Dict ]:
282+ """Convert ranking annotation to a json response.
283+
284+ Ranking jobs cannot have child jobs.
285+ """
286+ json_resp = {
287+ annotation ["job" ]: {
288+ "orders" : sorted (
289+ annotation ["annotationValue" ]["orders" ], key = lambda item : int (item ["rank" ])
290+ ),
291+ }
292+ }
293+
294+ return json_resp
295+
296+
297+ def _transcription_annotation_to_json_response (
298+ annotation : TranscriptionAnnotation ,
299+ ) -> Dict [JobName , Dict ]:
300+ """Convert transcription annotation to a json response.
301+
302+ Transcription jobs cannot have child jobs.
303+ """
304+ json_resp = {
305+ annotation ["job" ]: {
306+ "text" : annotation ["annotationValue" ]["text" ],
307+ }
308+ }
309+
310+ return json_resp
311+
312+
229313def _video_transcription_annotation_to_json_response (
230314 annotation : VideoTranscriptionAnnotation ,
231315) -> Dict [str , Dict [JobName , Dict ]]:
@@ -286,6 +370,25 @@ def _compute_children_json_resp(
286370 return children_json_resp
287371
288372
373+ def _classification_annotation_to_json_response (
374+ annotation : ClassificationAnnotation ,
375+ ) -> Dict [JobName , Dict ]:
376+ # initialize the json response
377+ json_resp = {
378+ annotation ["job" ]: {
379+ "categories" : [],
380+ }
381+ }
382+
383+ # a frame can have one or multiple categories
384+ categories = annotation ["annotationValue" ]["categories" ]
385+ for category in categories :
386+ category_annotation : Dict = {"name" : category }
387+ json_resp [annotation ["job" ]]["categories" ].append (category_annotation )
388+
389+ return json_resp
390+
391+
289392def _video_classification_annotation_to_json_response (
290393 annotation : VideoClassificationAnnotation ,
291394 other_annotations : List [VideoAnnotation ],
0 commit comments