From fddfeb56dc1f4115fea0038e19871b9ac8df1925 Mon Sep 17 00:00:00 2001 From: Shanks0465 Date: Tue, 31 Dec 2024 09:06:19 +0530 Subject: [PATCH 1/4] Added freeze_task to SpeechConversation and updated assign_new_tasks --- .../0047_speechconversation_freeze_task.py | 18 ++++++ backend/dataset/models.py | 7 +++ .../0053_alter_project_project_type.py | 18 ++++++ backend/projects/views.py | 58 ++++++++++++++----- .../migrations/0034_alter_user_is_approved.py | 18 ++++++ 5 files changed, 103 insertions(+), 16 deletions(-) create mode 100644 backend/dataset/migrations/0047_speechconversation_freeze_task.py create mode 100644 backend/projects/migrations/0053_alter_project_project_type.py create mode 100644 backend/users/migrations/0034_alter_user_is_approved.py diff --git a/backend/dataset/migrations/0047_speechconversation_freeze_task.py b/backend/dataset/migrations/0047_speechconversation_freeze_task.py new file mode 100644 index 000000000..488cf352a --- /dev/null +++ b/backend/dataset/migrations/0047_speechconversation_freeze_task.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.14 on 2024-12-31 01:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dataset', '0046_merge_20240416_2233'), + ] + + operations = [ + migrations.AddField( + model_name='speechconversation', + name='freeze_task', + field=models.BooleanField(default=False, help_text='Field to Indicate whether the current task is frozen by the administrator to prevent being annotated.', verbose_name='freeze_task'), + ), + ] diff --git a/backend/dataset/models.py b/backend/dataset/models.py index ec16c9903..12631b7fc 100644 --- a/backend/dataset/models.py +++ b/backend/dataset/models.py @@ -1,6 +1,7 @@ """ Model definitions for Dataset Management """ + from django.db import models from users.models import User, LANG_CHOICES from organizations.models import Organization @@ -485,6 +486,12 @@ class SpeechConversation(DatasetBase): help_text=("Prepopulated prediction for the implemented models"), ) + freeze_task = models.BooleanField( + verbose_name="freeze_task", + default=False, + help_text="Field to Indicate whether the current task is frozen by the administrator to prevent being annotated.", + ) + def __str__(self): return str(self.id) diff --git a/backend/projects/migrations/0053_alter_project_project_type.py b/backend/projects/migrations/0053_alter_project_project_type.py new file mode 100644 index 000000000..e64b768de --- /dev/null +++ b/backend/projects/migrations/0053_alter_project_project_type.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.14 on 2024-12-31 01:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0052_alter_project_project_type'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='project_type', + field=models.CharField(choices=[('MonolingualTranslation', 'MonolingualTranslation'), ('TranslationEditing', 'TranslationEditing'), ('SemanticTextualSimilarity_Scale5', 'SemanticTextualSimilarity_Scale5'), ('ContextualTranslationEditing', 'ContextualTranslationEditing'), ('OCRTranscription', 'OCRTranscription'), ('OCRTextlineSegmentation', 'OCRTextlineSegmentation'), ('OCRTranscriptionEditing', 'OCRTranscriptionEditing'), ('OCRSegmentCategorization', 'OCRSegmentCategorization'), ('OCRSegmentCategorizationEditing', 'OCRSegmentCategorizationEditing'), ('MonolingualCollection', 'MonolingualCollection'), ('SentenceSplitting', 'SentenceSplitting'), ('ContextualSentenceVerification', 'ContextualSentenceVerification'), ('ContextualSentenceVerificationAndDomainClassification', 'ContextualSentenceVerificationAndDomainClassification'), ('ConversationTranslation', 'ConversationTranslation'), ('ConversationTranslationEditing', 'ConversationTranslationEditing'), ('ConversationVerification', 'ConversationVerification'), ('AudioTranscription', 'AudioTranscription'), ('AudioSegmentation', 'AudioSegmentation'), ('AudioTranscriptionEditing', 'AudioTranscriptionEditing'), ('AcousticNormalisedTranscriptionEditing', 'AcousticNormalisedTranscriptionEditing')], help_text='Project Type indicating the annotation task', max_length=100), + ), + ] diff --git a/backend/projects/views.py b/backend/projects/views.py index bce3cbb53..a9bd479a6 100644 --- a/backend/projects/views.py +++ b/backend/projects/views.py @@ -54,6 +54,7 @@ from .models import * from .registry_helper import ProjectRegistry from dataset import models as dataset_models +from django.db.models import Exists, OuterRef from dataset.models import ( DatasetInstance, @@ -658,9 +659,9 @@ def get_supercheck_reports(proj_id, userid, start_date, end_date): result["Rejected Word Count"] = rejected_word_count elif proj_type in get_audio_project_types(): result["Validated Segments Duration"] = validated_audio_duration - result[ - "Validated With Changes Segments Duration" - ] = validated_with_changes_audio_duration + result["Validated With Changes Segments Duration"] = ( + validated_with_changes_audio_duration + ) result["Rejected Segments Duration"] = rejected_audio_duration result["Total Raw Audio Duration"] = total_raw_audio_duration result["Average Word Error Rate R/S"] = round(avg_word_error_rate, 2) @@ -912,9 +913,9 @@ def convert_prediction_json_to_annotation_result( } if proj_type == "AcousticNormalisedTranscriptionEditing": text_dict["from_name"] = "verbatim_transcribed_json" - text_dict_acoustic[ - "from_name" - ] = "acoustic_normalised_transcribed_json" + text_dict_acoustic["from_name"] = ( + "acoustic_normalised_transcribed_json" + ) id = f"shoonya_{idx}s{generate_random_string(13 - len(str(idx)))}" label_dict["id"] = id @@ -2219,9 +2220,9 @@ def create(self, request, *args, **kwargs): if automatic_annotation_creation_mode != None: if proj.metadata_json == None: proj.metadata_json = {} - proj.metadata_json[ - "automatic_annotation_creation_mode" - ] = automatic_annotation_creation_mode + proj.metadata_json["automatic_annotation_creation_mode"] = ( + automatic_annotation_creation_mode + ) if proj.project_type == "AcousticNormalisedTranscriptionEditing": if proj.metadata_json == None: proj.metadata_json = {} @@ -2391,13 +2392,29 @@ def assign_new_tasks(self, request, pk, *args, **kwargs): annotation_status__exact=UNLABELED, completed_by=cur_user ) annotation_tasks = [anno.task.id for anno in proj_annotations] - pending_tasks = ( - Task.objects.filter(project_id=pk) - .filter(annotation_users=cur_user.id) - .filter(task_status__in=[INCOMPLETE, UNLABELED]) - .filter(id__in=annotation_tasks) - .count() - ) + if project.project_type in get_audio_project_types(): + pending_tasks = ( + Task.objects.filter(project_id=pk) + .filter(annotation_users=cur_user.id) + .filter(task_status__in=[INCOMPLETE, UNLABELED]) + .filter(id__in=annotation_tasks) + .filter( + Exists( + SpeechConversation.objects.filter( + id=OuterRef("input_data_id"), freeze_task=False + ) + ) + ) + .count() + ) + else: + pending_tasks = ( + Task.objects.filter(project_id=pk) + .filter(annotation_users=cur_user.id) + .filter(task_status__in=[INCOMPLETE, UNLABELED]) + .filter(id__in=annotation_tasks) + .count() + ) # assigned_tasks_queryset = Task.objects.filter(project_id=pk).filter(annotation_users=cur_user.id) # assigned_tasks = assigned_tasks_queryset.count() # completed_tasks = Annotation_model.objects.filter(task__in=assigned_tasks_queryset).filter(completed_by__exact=cur_user.id).count() @@ -2434,6 +2451,15 @@ def assign_new_tasks(self, request, pk, *args, **kwargs): .exclude(annotation_users=cur_user.id) .annotate(annotator_count=Count("annotation_users")) ) + if project.project_type in get_audio_project_types(): + tasks = tasks.filter( + Exists( + SpeechConversation.objects.filter( + id=OuterRef("input_data_id"), freeze_task=False + ) + ) + ) + tasks = tasks.filter( annotator_count__lt=project.required_annotators_per_task ).distinct() diff --git a/backend/users/migrations/0034_alter_user_is_approved.py b/backend/users/migrations/0034_alter_user_is_approved.py new file mode 100644 index 000000000..00cb50023 --- /dev/null +++ b/backend/users/migrations/0034_alter_user_is_approved.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.14 on 2024-12-31 01:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0033_rename_approved_by_user_invited_by'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='is_approved', + field=models.BooleanField(default=False, help_text='Indicates whether user is approved by the admin or not.', verbose_name='is_approved'), + ), + ] From eae43c2722f6a5dbe2e6fcd19fac46b61fa82e64 Mon Sep 17 00:00:00 2001 From: Shanks0465 Date: Tue, 31 Dec 2024 14:59:34 +0530 Subject: [PATCH 2/4] Added freeze task filter to assign review and supercheck tasks --- backend/projects/views.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/backend/projects/views.py b/backend/projects/views.py index a9bd479a6..0b2faf56e 100644 --- a/backend/projects/views.py +++ b/backend/projects/views.py @@ -2727,6 +2727,7 @@ def assign_new_review_tasks(self, request, pk, *args, **kwargs): except Exception as e: continue # check if the project contains eligible tasks to pull + tasks = ( Task.objects.filter(project_id=pk) .filter(task_status=ANNOTATED) @@ -2734,6 +2735,16 @@ def assign_new_review_tasks(self, request, pk, *args, **kwargs): .exclude(annotation_users=cur_user.id) .distinct() ) + + if project.project_type in get_audio_project_types(): + tasks = tasks.filter( + Exists( + SpeechConversation.objects.filter( + id=OuterRef("input_data_id"), freeze_task=False + ) + ) + ) + if not tasks: project.release_lock(REVIEW_LOCK) return Response( @@ -2936,6 +2947,16 @@ def assign_new_supercheck_tasks(self, request, pk, *args, **kwargs): .exclude(review_user=cur_user.id) .distinct() ) + + if project.project_type in get_audio_project_types(): + tasks = tasks.filter( + Exists( + SpeechConversation.objects.filter( + id=OuterRef("input_data_id"), freeze_task=False + ) + ) + ) + if not tasks: project.release_lock(SUPERCHECK_LOCK) return Response( @@ -2949,12 +2970,26 @@ def assign_new_supercheck_tasks(self, request, pk, *args, **kwargs): sup_exp_rev_tasks_count = ( Task.objects.filter(project_id=pk) .filter(task_status__in=[REVIEWED, EXPORTED, SUPER_CHECKED]) + .filter( + Exists( + SpeechConversation.objects.filter( + id=OuterRef("input_data_id"), freeze_task=False + ) + ) + ) .distinct() .count() ) sup_exp_tasks_count = ( Task.objects.filter(project_id=pk) .filter(task_status__in=[SUPER_CHECKED, EXPORTED]) + .filter( + Exists( + SpeechConversation.objects.filter( + id=OuterRef("input_data_id"), freeze_task=False + ) + ) + ) .distinct() .count() ) From e219314ac3fb741024d7bb2ae27c1dd83d7e891d Mon Sep 17 00:00:00 2001 From: Ishvinder Sethi Date: Fri, 3 Jan 2025 18:54:42 +0530 Subject: [PATCH 3/4] Delete backend/projects/migrations/0053_alter_project_project_type.py --- .../0053_alter_project_project_type.py | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 backend/projects/migrations/0053_alter_project_project_type.py diff --git a/backend/projects/migrations/0053_alter_project_project_type.py b/backend/projects/migrations/0053_alter_project_project_type.py deleted file mode 100644 index e64b768de..000000000 --- a/backend/projects/migrations/0053_alter_project_project_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.14 on 2024-12-31 01:54 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('projects', '0052_alter_project_project_type'), - ] - - operations = [ - migrations.AlterField( - model_name='project', - name='project_type', - field=models.CharField(choices=[('MonolingualTranslation', 'MonolingualTranslation'), ('TranslationEditing', 'TranslationEditing'), ('SemanticTextualSimilarity_Scale5', 'SemanticTextualSimilarity_Scale5'), ('ContextualTranslationEditing', 'ContextualTranslationEditing'), ('OCRTranscription', 'OCRTranscription'), ('OCRTextlineSegmentation', 'OCRTextlineSegmentation'), ('OCRTranscriptionEditing', 'OCRTranscriptionEditing'), ('OCRSegmentCategorization', 'OCRSegmentCategorization'), ('OCRSegmentCategorizationEditing', 'OCRSegmentCategorizationEditing'), ('MonolingualCollection', 'MonolingualCollection'), ('SentenceSplitting', 'SentenceSplitting'), ('ContextualSentenceVerification', 'ContextualSentenceVerification'), ('ContextualSentenceVerificationAndDomainClassification', 'ContextualSentenceVerificationAndDomainClassification'), ('ConversationTranslation', 'ConversationTranslation'), ('ConversationTranslationEditing', 'ConversationTranslationEditing'), ('ConversationVerification', 'ConversationVerification'), ('AudioTranscription', 'AudioTranscription'), ('AudioSegmentation', 'AudioSegmentation'), ('AudioTranscriptionEditing', 'AudioTranscriptionEditing'), ('AcousticNormalisedTranscriptionEditing', 'AcousticNormalisedTranscriptionEditing')], help_text='Project Type indicating the annotation task', max_length=100), - ), - ] From 7bafe1ec26fcc248cb56889167ef8c2483b83249 Mon Sep 17 00:00:00 2001 From: Ishvinder Sethi Date: Fri, 3 Jan 2025 18:54:56 +0530 Subject: [PATCH 4/4] Delete backend/users/migrations/0034_alter_user_is_approved.py --- .../migrations/0034_alter_user_is_approved.py | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 backend/users/migrations/0034_alter_user_is_approved.py diff --git a/backend/users/migrations/0034_alter_user_is_approved.py b/backend/users/migrations/0034_alter_user_is_approved.py deleted file mode 100644 index 00cb50023..000000000 --- a/backend/users/migrations/0034_alter_user_is_approved.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.14 on 2024-12-31 01:54 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0033_rename_approved_by_user_invited_by'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='is_approved', - field=models.BooleanField(default=False, help_text='Indicates whether user is approved by the admin or not.', verbose_name='is_approved'), - ), - ]