fix(suggestions): pill × removal also suppresses re-auto-accept

The previous fix only covered the suggestion-chip ✕ flow (which calls
/suggestions/reject). Removing a tag via the pill × in the Tags section
goes through /tags/remove and wrote no feedback row, so the per-image
rejection filter in get_suggestions had nothing to match on — auto-accept
would re-apply the tag on the next modal load.

/tags/remove now writes SuggestionFeedback(decision='rejected',
suggestion_source='manual_removal', confidence=0) alongside the image_tags
delete. The suggestion_source value distinguishes these rows from
chip-reject rejections in the feedback log without complicating the
get_suggestions filter (it matches on decision alone).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-23 20:11:21 -04:00
parent 2347f5eaa2
commit 4b84076540
+16 -2
View File
@@ -1211,14 +1211,28 @@ def add_tag(image_id):
@main.post("/image/<int:image_id>/tags/remove") @main.post("/image/<int:image_id>/tags/remove")
def remove_tag(image_id): def remove_tag(image_id):
"""Remove a tag from an image.
Also logs a SuggestionFeedback rejection so the auto-suggest + auto-accept
systems treat this as 'the user said no to this tag for this image'.
Without the rejection row, a removed tag whose WD14 prediction still sits
at/above the auto-accept threshold would re-apply itself on the next
modal load.
""" """
Minimal JSON endpoint to remove a tag from an image. from app.models import SuggestionFeedback
"""
name = (request.form.get("name") or "").strip() name = (request.form.get("name") or "").strip()
img = ImageRecord.query.get_or_404(image_id) img = ImageRecord.query.get_or_404(image_id)
tag = Tag.query.filter_by(name=name).first() tag = Tag.query.filter_by(name=name).first()
if tag and tag in img.tags: if tag and tag in img.tags:
img.tags.remove(tag) img.tags.remove(tag)
db.session.add(SuggestionFeedback(
image_id=image_id,
tag_name=name,
suggestion_source='manual_removal',
confidence=0.0,
decision='rejected',
))
db.session.commit() db.session.commit()
return jsonify(ok=True) return jsonify(ok=True)