You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
5.7 KiB

6 years ago
3 years ago
3 years ago
6 years ago
3 years ago
3 years ago
  1. import abc
  2. import uuid
  3. from django.contrib.auth.models import User
  4. from django.db import models
  5. from polymorphic.models import PolymorphicModel
  6. from .managers import ExampleManager, ExampleStateManager
  7. DOCUMENT_CLASSIFICATION = 'DocumentClassification'
  8. SEQUENCE_LABELING = 'SequenceLabeling'
  9. SEQ2SEQ = 'Seq2seq'
  10. SPEECH2TEXT = 'Speech2text'
  11. IMAGE_CLASSIFICATION = 'ImageClassification'
  12. INTENT_DETECTION_AND_SLOT_FILLING = 'IntentDetectionAndSlotFilling'
  13. PROJECT_CHOICES = (
  14. (DOCUMENT_CLASSIFICATION, 'document classification'),
  15. (SEQUENCE_LABELING, 'sequence labeling'),
  16. (SEQ2SEQ, 'sequence to sequence'),
  17. (INTENT_DETECTION_AND_SLOT_FILLING, 'intent detection and slot filling'),
  18. (SPEECH2TEXT, 'speech to text'),
  19. (IMAGE_CLASSIFICATION, 'image classification')
  20. )
  21. class Project(PolymorphicModel):
  22. name = models.CharField(max_length=100)
  23. description = models.TextField(default='')
  24. guideline = models.TextField(default='', blank=True)
  25. created_at = models.DateTimeField(auto_now_add=True)
  26. updated_at = models.DateTimeField(auto_now=True)
  27. created_by = models.ForeignKey(
  28. User,
  29. on_delete=models.SET_NULL,
  30. null=True,
  31. )
  32. project_type = models.CharField(max_length=30, choices=PROJECT_CHOICES)
  33. random_order = models.BooleanField(default=False)
  34. collaborative_annotation = models.BooleanField(default=False)
  35. single_class_classification = models.BooleanField(default=False)
  36. @property
  37. @abc.abstractmethod
  38. def is_text_project(self) -> bool:
  39. return False
  40. @property
  41. def can_define_label(self) -> bool:
  42. """Whether or not the project can define label(ignoring the type of label)"""
  43. return False
  44. @property
  45. def can_define_relation(self) -> bool:
  46. """Whether or not the project can define relation."""
  47. return False
  48. @property
  49. def can_define_category(self) -> bool:
  50. """Whether or not the project can define category."""
  51. return False
  52. @property
  53. def can_define_span(self) -> bool:
  54. """Whether or not the project can define span."""
  55. return False
  56. def __str__(self):
  57. return self.name
  58. class TextClassificationProject(Project):
  59. @property
  60. def is_text_project(self) -> bool:
  61. return True
  62. @property
  63. def can_define_label(self) -> bool:
  64. return True
  65. @property
  66. def can_define_category(self) -> bool:
  67. return True
  68. class SequenceLabelingProject(Project):
  69. allow_overlapping = models.BooleanField(default=False)
  70. grapheme_mode = models.BooleanField(default=False)
  71. @property
  72. def is_text_project(self) -> bool:
  73. return True
  74. @property
  75. def can_define_label(self) -> bool:
  76. return True
  77. @property
  78. def can_define_span(self) -> bool:
  79. return True
  80. class Seq2seqProject(Project):
  81. @property
  82. def is_text_project(self) -> bool:
  83. return True
  84. class IntentDetectionAndSlotFillingProject(Project):
  85. @property
  86. def is_text_project(self) -> bool:
  87. return True
  88. @property
  89. def can_define_label(self) -> bool:
  90. return True
  91. @property
  92. def can_define_category(self) -> bool:
  93. return True
  94. @property
  95. def can_define_span(self) -> bool:
  96. return True
  97. class Speech2textProject(Project):
  98. @property
  99. def is_text_project(self) -> bool:
  100. return False
  101. class ImageClassificationProject(Project):
  102. @property
  103. def is_text_project(self) -> bool:
  104. return False
  105. @property
  106. def can_define_label(self) -> bool:
  107. return True
  108. @property
  109. def can_define_category(self) -> bool:
  110. return True
  111. class Example(models.Model):
  112. objects = ExampleManager()
  113. uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True, unique=True)
  114. meta = models.JSONField(default=dict)
  115. filename = models.FileField(default='.', max_length=1024)
  116. project = models.ForeignKey(
  117. to=Project,
  118. on_delete=models.CASCADE,
  119. related_name='examples'
  120. )
  121. annotations_approved_by = models.ForeignKey(
  122. to=User,
  123. on_delete=models.SET_NULL,
  124. null=True,
  125. blank=True
  126. )
  127. text = models.TextField(null=True, blank=True)
  128. created_at = models.DateTimeField(auto_now_add=True, db_index=True)
  129. updated_at = models.DateTimeField(auto_now=True)
  130. @property
  131. def comment_count(self):
  132. return Comment.objects.filter(example=self.id).count()
  133. @property
  134. def data(self):
  135. if self.project.is_text_project:
  136. return self.text
  137. else:
  138. return str(self.filename)
  139. class Meta:
  140. ordering = ['created_at']
  141. class ExampleState(models.Model):
  142. objects = ExampleStateManager()
  143. example = models.ForeignKey(
  144. to=Example,
  145. on_delete=models.CASCADE,
  146. related_name='states'
  147. )
  148. confirmed_by = models.ForeignKey(
  149. to=User,
  150. on_delete=models.CASCADE
  151. )
  152. confirmed_at = models.DateTimeField(auto_now=True)
  153. class Meta:
  154. unique_together = (('example', 'confirmed_by'),)
  155. class Comment(models.Model):
  156. text = models.TextField()
  157. example = models.ForeignKey(
  158. to=Example,
  159. on_delete=models.CASCADE,
  160. related_name='comments'
  161. )
  162. user = models.ForeignKey(
  163. to=User,
  164. on_delete=models.CASCADE,
  165. null=True
  166. )
  167. created_at = models.DateTimeField(auto_now_add=True, db_index=True)
  168. updated_at = models.DateTimeField(auto_now=True)
  169. @property
  170. def username(self):
  171. return self.user.username
  172. class Meta:
  173. ordering = ['created_at']
  174. class Tag(models.Model):
  175. text = models.TextField()
  176. project = models.ForeignKey(
  177. to=Project,
  178. on_delete=models.CASCADE,
  179. related_name='tags'
  180. )
  181. def __str__(self):
  182. return self.text