Skip to content

Commit

Permalink
Auto extraction entry
Browse files Browse the repository at this point in the history
mock data added draftentry
  • Loading branch information
sudan45 committed Nov 23, 2023
1 parent a940ef5 commit e682efc
Show file tree
Hide file tree
Showing 19 changed files with 1,224 additions and 8 deletions.
31 changes: 31 additions & 0 deletions apps/assisted_tagging/admin.py
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
# Register your models here.
from django.contrib import admin

from assisted_tagging.models import AssistedTaggingModelPredictionTag, AssistedTaggingPrediction, DraftEntry
from deep.admin import VersionAdmin


@admin.register(DraftEntry)
class DraftEntryAdmin(VersionAdmin):
list_display = [
'lead',
'prediction_status',
'excerpt',
]


@admin.register(AssistedTaggingPrediction)
class AssistedTaggingPredictionAdmin(VersionAdmin):
list_display = [
"data_type",
"draft_entry",
"value"
]


@admin.register(AssistedTaggingModelPredictionTag)
class AssistedTaggingModelPredictionTagAdmin(VersionAdmin):
list_display = [
'name',
'is_category',
'tag_id',
]
9 changes: 9 additions & 0 deletions apps/assisted_tagging/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,26 @@
DraftEntry,
AssistedTaggingPrediction,
)
from lead.models import Lead

DraftEntryPredictionStatusEnum = convert_enum_to_graphene_enum(
DraftEntry.PredictionStatus, name='DraftEntryPredictionStatusEnum')
AssistedTaggingPredictionDataTypeEnum = convert_enum_to_graphene_enum(
AssistedTaggingPrediction.DataType, name='AssistedTaggingPredictionDataTypeEnum')
DraftEntryTypeEnum = convert_enum_to_graphene_enum(
DraftEntry.DraftEntryType, name="DraftEntryTypeEnum"
)
AutoEntryExtractionTypeEnum = convert_enum_to_graphene_enum(
Lead.AutoExtractionStatus, name="AutoEntryExtractionTypeEnum"
)

enum_map = {
get_enum_name_from_django_field(field): enum
for field, enum in (
(DraftEntry.prediction_status, DraftEntryPredictionStatusEnum),
(AssistedTaggingPrediction.data_type, AssistedTaggingPredictionDataTypeEnum),
(DraftEntry.draft_entry_type, DraftEntryTypeEnum),
(Lead.auto_entry_extraction_status, AutoEntryExtractionTypeEnum),
)
}

Expand Down
32 changes: 31 additions & 1 deletion apps/assisted_tagging/filters.py
Original file line number Diff line number Diff line change
@@ -1 +1,31 @@
#
import django_filters

from deep.filter_set import generate_type_for_filter_set
from .models import DraftEntry
from utils.graphene.filters import IDListFilter, MultipleInputFilter
from .enums import (
DraftEntryTypeEnum
)


class DraftEntryFilterSet(django_filters.FilterSet):
lead = IDListFilter()
draft_entry_type = MultipleInputFilter(DraftEntryTypeEnum)

class Meta:
model = DraftEntry
fields = ()

def filter_lead(self, qs, _, value):
return qs if value is None else qs.filter(lead=value)

def filter_draft_entry_type(self, qs, _, value):
return qs if value is None else qs.filter(draft_entry_type=value)


DraftEntryFilterDataType, DraftEntryFilterDataInputType = generate_type_for_filter_set(
DraftEntryFilterSet,
"project.schema.ProjectListType",
"DraftEntryFilterDataType",
"DraftEntryFilterDataInputType",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.17 on 2023-11-06 10:06

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('assisted_tagging', '0010_draftentry_related_geoareas'),
]

operations = [
migrations.AddField(
model_name='draftentry',
name='draft_entry_type',
field=models.SmallIntegerField(choices=[(0, 'Auto Extraction'), (1, 'Manual Extraction')], default=1),
),
]
5 changes: 5 additions & 0 deletions apps/assisted_tagging/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ class PredictionStatus(models.IntegerChoices):
DONE = 2, 'Done'
SEND_FAILED = 3, 'Send Failed'

class DraftEntryType(models.IntegerChoices):
AUTO = 0, 'Auto Extraction' # NLP defiend extraction text
MANUAL = 1, 'Manual Extraction' # manaul defiend extraction text

project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='+')
lead = models.ForeignKey(Lead, on_delete=models.CASCADE, related_name='+')
excerpt = models.TextField()
Expand All @@ -98,6 +102,7 @@ class PredictionStatus(models.IntegerChoices):
prediction_received_at = models.DateTimeField(null=True, blank=True)
# Additional attribues
related_geoareas = models.ManyToManyField(GeoArea, blank=True)
draft_entry_type = models.SmallIntegerField(choices=DraftEntryType.choices, default=DraftEntryType.MANUAL)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down
18 changes: 18 additions & 0 deletions apps/assisted_tagging/mutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
DraftEntryGqlSerializer,
WrongPredictionReviewGqlSerializer,
MissingPredictionReviewGqlSerializer,
AutoDraftEntryGqlSerializer
)


Expand All @@ -39,6 +40,11 @@
serializer_class=MissingPredictionReviewGqlSerializer,
)

AutoDraftEntryInputType = generate_input_type_for_serializer(
"AutoDraftEntryInputType",
serializer_class=AutoDraftEntryGqlSerializer
)


class CreateDraftEntry(PsGrapheneMutation):
class Arguments:
Expand Down Expand Up @@ -96,10 +102,22 @@ def filter_queryset(cls, qs, info):
created_by=info.context.user,
)

# auto draft_entry_create


class CreateAutoDraftEntry(PsGrapheneMutation):
class Arguments:
data = AutoDraftEntryInputType(required=True)
model = DraftEntry
serializer_class = AutoDraftEntryGqlSerializer
result = graphene.Field(DraftEntryType)
permissions = [PP.Permission.CREATE_ENTRY]


class AssistedTaggingMutationType(graphene.ObjectType):
draft_entry_create = CreateDraftEntry.Field()
missing_prediction_review_create = CreateMissingPredictionReview.Field()
wrong_prediction_review_create = CreateWrongPredictionReview.Field()
missing_prediction_review_delete = DeleteMissingPredictionReview.Field()
wrong_prediction_review_delete = DeleteWrongPredictionReview.Field()
auto_draft_entry_create = CreateAutoDraftEntry.Field()
79 changes: 78 additions & 1 deletion apps/assisted_tagging/schema.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import graphene
from graphene_django import DjangoObjectType
from graphene_django import DjangoObjectType, DjangoListField
from graphene_django_extras import DjangoObjectField
from django.db.models import Prefetch
from assisted_tagging.filters import DraftEntryFilterDataInputType, DraftEntryFilterSet

from utils.graphene.enums import EnumDescription
from user_resource.schema import UserResourceMixin
Expand All @@ -20,9 +21,11 @@
MissingPredictionReview,
WrongPredictionReview,
)
from lead.models import Lead
from .enums import (
DraftEntryPredictionStatusEnum,
AssistedTaggingPredictionDataTypeEnum,
AutoEntryExtractionTypeEnum
)


Expand Down Expand Up @@ -103,6 +106,13 @@ def get_draft_entry_qs(info):
return qs.none()


def get_draft_entry_with_filter_qs(info, filters):
qs = DraftEntry.objects.filter(project=info.context.active_project)
if PP.check_permission(info, PP.Permission.VIEW_ENTRY):
return DraftEntryFilterSet(queryset=qs, data=filters).qs
return qs.none()


class WrongPredictionReviewType(UserResourceMixin, DjangoObjectType):
prediction = graphene.ID(source='prediction_id', required=True)

Expand Down Expand Up @@ -208,6 +218,73 @@ def resolve_related_geoareas(root, info, **kwargs):
return root.related_geoareas.all() # NOTE: Prefetched by DraftEntry


class DraftEntryByLeadType(DjangoObjectType):
prediction_status = graphene.Field(DraftEntryPredictionStatusEnum, required=True)
prediction_status_display = EnumDescription(source='get_prediction_status_display', required=True)
predictions = graphene.List(
graphene.NonNull(AssistedTaggingPredictionType)
)
missing_prediction_reviews = graphene.List(
graphene.NonNull(MissingPredictionReviewType),
)
related_geoareas = graphene.List(
graphene.NonNull(ProjectGeoAreaType)
)

class Meta:
model = DraftEntry
only_fields = (
'id',
'excerpt',
'prediction_received_at',
)

@staticmethod
def custom_queryset(queryset, info, _filter, **kwargs):
return get_draft_entry_with_filter_qs(info, _filter).prefetch_related(
Prefetch(
'predictions',
queryset=AssistedTaggingPrediction.objects.order_by('id'),
),
Prefetch(
'related_geoareas',
queryset=get_geo_area_queryset_for_project_geo_area_type().order_by('id'),
),
'predictions__model_version',
'predictions__model_version__model',
'predictions__wrong_prediction_reviews',
'missing_prediction_reviews',
'related_geoareas',
)

@staticmethod
def resolve_predictions(root, info, **kwargs):
return root.predictions.filter(is_selected=True) # NOTE: Prefetched by DraftEntry

@staticmethod
def resolve_missing_prediction_reviews(root, info, **kwargs):
return root.missing_prediction_reviews.all() # NOTE: Prefetched by DraftEntry

@staticmethod
def resolve_related_geoareas(root, info, **kwargs):
return root.related_geoareas.all()


class AutoextractionStatusType(DjangoObjectType):
auto_entry_extraction_status = graphene.Field(AutoEntryExtractionTypeEnum, required=True)

class Meta:
model = Lead
only_fiels = (
'id'
)
# This is attached to project type.


class AssistedTaggingQueryType(graphene.ObjectType):
draft_entry = DjangoObjectField(DraftEntryType)
draft_entry_by_leads = DjangoListField(DraftEntryByLeadType, filter=DraftEntryFilterDataInputType())
extraction_status_by_lead = DjangoObjectField(AutoextractionStatusType)

def resolve_draft_entry_by_leads(root, info, filter):
return DraftEntryByLeadType.custom_queryset(root, info, filter)
44 changes: 42 additions & 2 deletions apps/assisted_tagging/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from django.db import transaction
from rest_framework import serializers

from user_resource.serializers import UserResourceSerializer, UserResourceCreatedMixin
from deep.serializers import ProjectPropertySerializerMixin, TempClientIdMixin
from analysis_framework.models import Widget
Expand All @@ -11,7 +10,8 @@
PredictionTagAnalysisFrameworkWidgetMapping,
WrongPredictionReview,
)
from .tasks import trigger_request_for_draft_entry_task
from lead.models import LeadPreview
from .tasks import trigger_request_for_draft_entry_task, trigger_request_for_mock_entry_task


# ---------- Graphql ---------------------------
Expand Down Expand Up @@ -127,3 +127,43 @@ def validate(self, data):
association='Association is required for this widget.'
))
return data


class AutoDraftEntryGqlSerializer(ProjectPropertySerializerMixin, UserResourceCreatedMixin, serializers.ModelSerializer):
class Meta:
model = DraftEntry
fields = (
'lead',
)

def validate_lead(self, lead):
if lead.project != self.project:
raise serializers.ValidationError('Only lead from current project are allowed.')
af = lead.project.analysis_framework
if af is None or not af.assisted_tagging_enabled:
raise serializers.ValidationError('Assisted tagging is disabled for the Framework used by this project.')
return lead

def validate(self, data):
if self.instance and self.instance.created_by != self.context['request'].user:
raise serializers.ValidationError('Only reviewer can edit this review')
data['project'] = self.project
if self.project.is_private:
raise serializers.ValidationError('Assisted tagging is not available for private projects.')
return data

def create(self, data):
text = LeadPreview.objects.filter(lead=self.data['lead']).first()
if text.text_extract == '' or None:
raise serializers.DjangoValidationError('Simplifed Text is empty')
# Use already existing draft entry if found
data['draft_entry_type'] = 0 # auto extraction
# Create new one and send trigger to deepl
transaction.on_commit(
lambda: trigger_request_for_mock_entry_task.delay(self.data['lead'])
)

return True

def update(self, *_):
raise Exception('Update not allowed')
10 changes: 9 additions & 1 deletion apps/assisted_tagging/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import requests

from celery import shared_task
from lead.models import Lead

from utils.common import redis_lock
from deep.deepl import DeeplServiceEndpoint
from deepl_integration.handlers import AssistedTaggingDraftEntryHandler
from deepl_integration.handlers import AssistedTaggingDraftEntryHandler, AutoAssistedTaggingDraftEntryHandler

from .models import (
DraftEntry,
Expand Down Expand Up @@ -92,6 +93,13 @@ def trigger_request_for_draft_entry_task(draft_entry_id):
return AssistedTaggingDraftEntryHandler.send_trigger_request_to_extractor(draft_entry)


@shared_task
@redis_lock('trigger_request_for_mock_entry_task_{0}', 60 * 60 * 0.5)
def trigger_request_for_mock_entry_task(lead):
lead = Lead.objects.get(id=lead)
return AutoAssistedTaggingDraftEntryHandler.auto_trigger_request_to_extractor(lead)


@shared_task
@redis_lock('sync_tags_with_deepl_task', 60 * 60 * 0.5)
def sync_tags_with_deepl_task():
Expand Down
Loading

0 comments on commit e682efc

Please sign in to comment.