fix(ml): skip videos in tag_and_embed and backfill

WD14 and SigLIP are image-only. The current backfill enqueues every
ImageRecord row, and tag_and_embed retries 3 times (~3 min) on each
video before giving up, blocking the serialized ml queue. Worse,
videos never get a prediction row, so every subsequent backfill
re-enqueues them.

- tag_and_embed: early return 'unsupported_format' for video
  extensions, no retry.
- backfill: filter the outerjoin query to exclude video extensions
  via VIDEO_EXTS from app.utils.image_importer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-19 22:31:50 -04:00
parent 70957a307c
commit 9a0ac85f8c
+12 -1
View File
@@ -5,7 +5,7 @@ import os
import time
import numpy as np
from sqlalchemy import and_, func
from sqlalchemy import and_, func, or_
from sqlalchemy.dialects.postgresql import insert as pg_insert
from app.celery_app import celery
@@ -47,6 +47,11 @@ def tag_and_embed(self, image_id: int):
log.warning(f"tag_and_embed: file missing at {image.filepath}")
return {'status': 'file_missing'}
# WD14 + SigLIP are image-only; videos bypass inference entirely.
from app.utils.image_importer import VIDEO_EXTS
if image.filepath.lower().endswith(VIDEO_EXTS):
return {'status': 'unsupported_format'}
try:
t0 = time.time()
raw = wd14.infer_filtered(image.filepath, min_any=WD14_STORE_FLOOR)
@@ -102,6 +107,11 @@ def backfill(self, batch_size: int = 50, pause_seconds: float = 0.5):
"""
from app.ml.wd14 import MODEL_VERSION as WD14_VER
from app.ml.siglip import MODEL_VERSION as SIGLIP_VER
from app.utils.image_importer import VIDEO_EXTS
video_filter = ~or_(*[
func.lower(ImageRecord.filepath).like(f'%{ext}') for ext in VIDEO_EXTS
])
enqueued_total = 0
last_id = 0
@@ -123,6 +133,7 @@ def backfill(self, batch_size: int = 50, pause_seconds: float = 0.5):
),
)
.filter(ImageRecord.id > last_id)
.filter(video_filter)
.filter(
(ImageTagPrediction.image_id.is_(None))
| (ImageEmbedding.image_id.is_(None))