This commit is contained in:
2026-03-26 06:10:19 -03:00
parent 731964ca10
commit e27cb5bcc3
41 changed files with 2079 additions and 95 deletions

View File

@@ -28,6 +28,25 @@ class ChunkJobStatus(models.TextChoices):
FAILED = "failed", "Failed"
CANCELLED = "cancelled", "Cancelled"
class DetectJobStatus(models.TextChoices):
PENDING = "pending", "Pending"
RUNNING = "running", "Running"
PAUSED = "paused", "Paused"
COMPLETED = "completed", "Completed"
FAILED = "failed", "Failed"
CANCELLED = "cancelled", "Cancelled"
class RunType(models.TextChoices):
INITIAL = "initial", "Initial"
REPLAY = "replay", "Replay"
RETRY = "retry", "Retry"
class BrandSource(models.TextChoices):
OCR = "ocr", "Ocr"
VLM = "local_vlm", "Vlm"
CLOUD = "cloud_llm", "Cloud"
MANUAL = "manual", "Manual"
class MediaAsset(models.Model):
"""A video/audio file registered in the system."""
@@ -148,3 +167,104 @@ class ChunkJob(models.Model):
def __str__(self):
return str(self.id)
class DetectJob(models.Model):
"""A detection pipeline job."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
source_asset_id = models.UUIDField()
video_path = models.CharField(max_length=1000)
profile_name = models.CharField(max_length=255)
parent_job_id = models.UUIDField(null=True, blank=True)
run_type = models.CharField(max_length=20, choices=RunType.choices, default=RunType.INITIAL)
replay_from_stage = models.CharField(max_length=255, null=True, blank=True)
config_overrides = models.JSONField(default=dict, blank=True)
status = models.CharField(max_length=20, choices=DetectJobStatus.choices, default=DetectJobStatus.PENDING)
current_stage = models.CharField(max_length=255, null=True, blank=True)
progress = models.FloatField(default=0.0)
error_message = models.TextField(blank=True, default='')
total_detections = models.IntegerField(default=0)
brands_found = models.IntegerField(default=0)
cloud_llm_calls = models.IntegerField(default=0)
estimated_cost_usd = models.FloatField(default=0.0)
celery_task_id = models.CharField(max_length=255, null=True, blank=True)
priority = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
started_at = models.DateTimeField(null=True, blank=True)
completed_at = models.DateTimeField(null=True, blank=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return str(self.id)
class StageCheckpoint(models.Model):
"""A checkpoint saved after a pipeline stage completes."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
job_id = models.UUIDField()
stage = models.CharField(max_length=255)
stage_index = models.IntegerField()
frames_prefix = models.CharField(max_length=255)
frames_manifest = models.JSONField(default=dict, blank=True)
frames_meta = models.JSONField(default=list, blank=True)
filtered_frame_sequences = models.JSONField(default=list, blank=True)
boxes_by_frame = models.JSONField(default=dict, blank=True)
text_candidates = models.JSONField(default=list, blank=True)
unresolved_candidates = models.JSONField(default=list, blank=True)
detections = models.JSONField(default=list, blank=True)
stats = models.JSONField(default=dict, blank=True)
config_snapshot = models.JSONField(default=dict, blank=True)
config_overrides = models.JSONField(default=dict, blank=True)
video_path = models.CharField(max_length=1000)
profile_name = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return str(self.id)
class KnownBrand(models.Model):
"""A brand discovered or registered in the system."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
canonical_name = models.CharField(max_length=255)
aliases = models.JSONField(default=list, blank=True)
first_source = models.CharField(max_length=20, choices=BrandSource.choices, default=BrandSource.OCR)
total_occurrences = models.IntegerField(default=0)
confirmed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return str(self.id)
class SourceBrandSighting(models.Model):
"""A brand seen in a specific source (video/asset)."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
source_asset_id = models.UUIDField()
brand_id = models.UUIDField()
brand_name = models.CharField(max_length=255)
first_seen_timestamp = models.FloatField(default=0.0)
last_seen_timestamp = models.FloatField(default=0.0)
occurrences = models.IntegerField(default=0)
detection_source = models.CharField(max_length=20, choices=BrandSource.choices, default=BrandSource.OCR)
avg_confidence = models.FloatField(default=0.0)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return str(self.id)