Files
mule-image/backend/alembic/versions/0012_strip_ai_pipeline.py
dtoro 574d71371f refactor: strip AI pipeline to binary photo/other classifier
Drops face recognition, OCR, object detection, and semantic embeddings.
The sole remaining vision task is a CLIP-based binary classifier
(photography vs other); photos in "other" get needs_review=true so
screenshots, documents, memes and scans can be triaged from a new
filter pill in the UI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:27:17 +02:00

66 lines
2.3 KiB
Python

"""Strip AI pipeline to binary classifier only
Revision ID: 0012_strip_ai
Revises: 0011_sharing
Create Date: 2026-04-14
Removes face recognition, OCR, object detection, and semantic embeddings.
The remaining AI is a single binary 'photography' vs 'other' classifier
whose output feeds Tag(kind='content_type') and a new Photo.needs_review
flag.
Drops: embeddings, face_embeddings, ocr_text tables.
Drops: photo_tags rows produced by 'vision:yolov8n' and 'vision:sface'.
Drops: tags with kind IN ('object','scene','face_cluster').
Drops: tags.representative_photo_id column.
Adds: photos.needs_review (bool, default false) + partial index.
"""
from typing import Sequence, Union
from alembic import op
revision: str = "0012_strip_ai"
down_revision: Union[str, None] = "0011_sharing"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# Drop dropped-AI tables. CASCADE clears any lingering FKs/indices.
op.execute("DROP TABLE IF EXISTS embeddings CASCADE")
op.execute("DROP TABLE IF EXISTS face_embeddings CASCADE")
op.execute("DROP TABLE IF EXISTS ocr_text CASCADE")
# Clear ML-produced photo_tags rows and their parent tags.
op.execute(
"DELETE FROM photo_tags WHERE source IN ('vision:yolov8n','vision:sface')"
)
op.execute(
"DELETE FROM tags WHERE kind IN ('object','scene','face_cluster')"
)
# Drop the face-cluster representative column.
op.execute("ALTER TABLE tags DROP COLUMN IF EXISTS representative_photo_id")
# Add the needs_review flag.
op.execute(
"ALTER TABLE photos ADD COLUMN IF NOT EXISTS needs_review "
"BOOLEAN NOT NULL DEFAULT false"
)
op.execute(
"CREATE INDEX IF NOT EXISTS ix_photos_needs_review "
"ON photos(needs_review) WHERE needs_review"
)
def downgrade() -> None:
# Data is not recoverable on downgrade — only the schema stubs are
# put back so a future reinstall of the old pipeline can re-populate.
op.execute("DROP INDEX IF EXISTS ix_photos_needs_review")
op.execute("ALTER TABLE photos DROP COLUMN IF EXISTS needs_review")
op.execute(
"ALTER TABLE tags ADD COLUMN IF NOT EXISTS representative_photo_id "
"VARCHAR REFERENCES photos(id) ON DELETE SET NULL"
)