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>
66 lines
2.3 KiB
Python
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"
|
|
)
|