This repository has been archived on 2026-05-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
imagerepo/app/tasks/maintenance.py
T
bvandeusen 0f35a0c484 feat: ML tag suggestions, character/fandom integrity, underscores, modal polish
Consolidated merge of feat/tag-suggestions branch. Original 64-commit history
was lost to git-object corruption in a Nextcloud-synced checkout; this single
commit captures the equivalent diff.

Includes:
- pgvector-backed tag suggestion infra (WD14 + SigLIP centroids, ml-worker
  container, Celery tasks, suggestion service, accept/reject endpoints + modal
  UI with green/red chip buttons)
- Character/fandom integrity: title-case normalization on every write path,
  fandom-id backfill, maintenance task + settings button, migrations g26041901
  + h26041901 to canonicalize legacy rows with case-only duplicate merging
- Tag-underscores + modal polish: WD14 name canonicalization at emit + accept
  + add/bulk-add paths, migration i26041901 for legacy-row rename-or-merge
  across character/fandom/NULL kinds, suggestion-accept refresh parity via
  awaited loadTags, persistent chip tint
2026-04-19 19:50:58 -04:00

67 lines
2.0 KiB
Python

"""Maintenance-queue Celery tasks. Lightweight, user-triggered, non-ML."""
import logging
from celery import shared_task
from sqlalchemy import text
from app import db
from app.models import Tag
log = logging.getLogger(__name__)
@shared_task(
name='app.tasks.maintenance.sync_character_fandoms',
soft_time_limit=120,
time_limit=180,
)
def sync_character_fandoms():
"""For every character tag with a non-null fandom_id, attach the fandom
tag to every image tagged with the character but not the fandom.
Additive only — never removes fandom tags.
Returns a summary dict with counts.
"""
chars = (
Tag.query
.filter_by(kind='character')
.filter(Tag.fandom_id.isnot(None))
.all()
)
total_added = 0
failed = 0
for char in chars:
try:
result = db.session.execute(
text("""
INSERT INTO image_tags (image_id, tag_id)
SELECT it.image_id, :fandom_id
FROM image_tags it
WHERE it.tag_id = :char_id
AND NOT EXISTS (
SELECT 1 FROM image_tags it2
WHERE it2.image_id = it.image_id
AND it2.tag_id = :fandom_id
)
"""),
{'char_id': char.id, 'fandom_id': char.fandom_id},
)
total_added += result.rowcount or 0
db.session.commit()
except Exception as e:
db.session.rollback()
failed += 1
log.warning(
"sync_character_fandoms: char tag %s (%s) failed: %s",
char.id, char.name, e,
)
log.info(
"sync_character_fandoms: scanned %d characters, added %d image↔fandom links, %d failed",
len(chars), total_added, failed,
)
return {
'characters_scanned': len(chars),
'links_added': total_added,
'characters_failed': failed,
}