"""This file and its contents are licensed under the Apache License 2.0. Please see the included NOTICE for copyright information and LICENSE for a copy of the license. """ import logging from core.permissions import AllPermissions from data_manager.actions import DataManagerAction from django.utils.timezone import now from tasks.models import Annotation, Prediction, Task from tasks.serializers import TaskSerializerBulk from webhooks.models import WebhookAction from webhooks.utils import emit_webhooks_for_instance all_permissions = AllPermissions() logger = logging.getLogger(__name__) def predictions_to_annotations(project, queryset, **kwargs): request = kwargs['request'] user = request.user model_version = request.data.get('model_version') queryset = queryset.filter(predictions__isnull=False) predictions = Prediction.objects.filter(task__in=queryset, child_annotations__isnull=True) # model version filter if model_version is not None: if isinstance(model_version, list): predictions = predictions.filter(model_version__in=model_version).distinct() else: predictions = predictions.filter(model_version=model_version) predictions_values = list(predictions.values_list('result', 'model_version', 'task_id', 'id')) # prepare annotations annotations = [] tasks_ids = [] for result, model_version, task_id, prediction_id in predictions_values: tasks_ids.append(task_id) body = { 'result': result, 'completed_by_id': user.pk, 'task_id': task_id, 'parent_prediction_id': prediction_id, 'project': project, } body = TaskSerializerBulk.add_annotation_fields(body, user, 'prediction') annotations.append(body) count = len(annotations) logger.debug(f'{count} predictions will be converter to annotations') db_annotations = [Annotation(**annotation) for annotation in annotations] db_annotations = Annotation.objects.bulk_create(db_annotations) Task.objects.filter(id__in=tasks_ids).update(updated_at=now(), updated_by=request.user) if db_annotations: TaskSerializerBulk.post_process_annotations(user, db_annotations, 'prediction') # Execute webhook for created annotations emit_webhooks_for_instance( user.active_organization, project, WebhookAction.ANNOTATIONS_CREATED, db_annotations ) # Update counters for tasks and is_labeled. It should be a single operation as counters affect bulk is_labeled update project.update_tasks_counters_and_is_labeled(Task.objects.filter(id__in=tasks_ids)) try: from stats.functions.stats import recalculate_stats_async_or_sync recalculate_stats_async_or_sync(project, all=False) except (ModuleNotFoundError, ImportError): logger.info('Predictions converted to annotations in LSO, stats recomputation skipped') return {'response_code': 200, 'detail': f'Created {count} annotations'} def predictions_to_annotations_form(user, project): versions = project.get_model_versions() # put the current model version on the top of the list # if it exists first = project.model_version if first: try: versions.remove(first) except ValueError: pass versions = [first] + versions return [ { 'columnCount': 1, 'fields': [ { 'type': 'select', 'name': 'model_version', 'label': 'Choose predictions', 'options': versions, 'value': first, } ], } ] actions: list[DataManagerAction] = [ { 'entry_point': predictions_to_annotations, 'permission': all_permissions.tasks_change, 'title': 'Create Annotations From Predictions', 'order': 91, 'dialog': { 'title': 'Create Annotations From Predictions', 'text': 'Create annotations from predictions using selected predictions set ' 'for each selected task. ' 'Your account will be assigned as an owner to those annotations. ', 'type': 'confirm', 'form': predictions_to_annotations_form, }, } ]