feat(maintenance): library-wide apply of auto-accept predictions

Adds a Celery task + Settings button that walks every image and applies
general-category WD14 predictions at or above the auto-accept threshold,
without needing the user to open each modal. Same side effects as the
modal's per-image auto-accept flow (creates kind='user' tag if needed,
attaches to image, writes SuggestionFeedback decision='accepted').

Lazy-imports app.services.tag_suggestions so the maintenance worker
doesn't pay its overhead unless this task fires. Amortizes _config()
and _existing_tag_names() across the loop. Commits per-batch (100
images) to keep transactions short and let later batches see freshly
created Tag rows.

Skips integrity-flagged images (get_suggestions already returns empty
for those). Idempotent — re-running just no-ops on already-applied
images via the existing 'tag not in img.tags' guard.

Trigger: Settings -> Maintenance -> "Apply auto-accepts library-wide"
(confirm-gated since it walks the entire library).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 13:45:34 -04:00
parent 641a52d1ad
commit 6488dfff1a
4 changed files with 130 additions and 1 deletions
+18
View File
@@ -494,6 +494,24 @@
</form>
</section>
<section class="settings-section">
<h3>Apply auto-accepted predictions to all images</h3>
<p class="settings-hint">
Walks every image and applies general-category WD14 predictions
whose confidence is at or above the auto-accept threshold. Same
side-effects as opening each modal individually (creates the
kind='user' tag if needed, attaches it to the image, logs a
SuggestionFeedback rejection-protected record). Idempotent — safe
to re-run. Useful after a fresh ML backfill so high-confidence
tags land without needing to view each image. Skips images flagged
as integrity-corrupt.
</p>
<form action="{{ url_for('main.trigger_apply_auto_accept_predictions') }}" method="post"
onsubmit="return confirm('Apply every above-threshold general-category WD14 prediction to its image? This walks the entire library.');">
<button type="submit" class="btn secondary-btn">Apply auto-accepts library-wide</button>
</form>
</section>
<section class="settings-section">
<h3>Auto-accept threshold (general tags)</h3>
<p class="settings-hint">