feat(ml): read suggestions + allowlist from image_prediction (#768 step 2)
Switch every prediction READER off the JSON column onto the normalized
image_prediction table. Parity by construction: each reader loads the same
{raw_name: {category, confidence}} dict it consumed before (via small
_load_predictions helpers), so all downstream threshold/alias/merge/consensus
logic is byte-identical — only the data source changed.
- suggestions.SuggestionService.for_image (and for_selection via it)
- ml.apply_allowlist_tags (iterates images that have prediction rows)
- importer re-import reset deletes the image's prediction rows
The tagger_predictions JSON column is still dual-written (step 1) so it stays
valid during transition; the backfill task's NULL check still works. Removing
the JSON write + DROP column + retiring the #764 prune is the cleanup
follow-up (needs a quiesced-worker window for the DROP lock).
Tests: shared tests/_prediction_helpers.seed_predictions seeds the table;
read-path tests (suggestions, bulk consensus, allowlist apply, API) seed there
instead of ImageRecord.tagger_predictions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
"""#768 test helper: seed image_prediction rows.
|
||||
|
||||
Read-path tests used to seed ImageRecord(tagger_predictions={...}); predictions
|
||||
now live in the normalized image_prediction table, so seed there instead.
|
||||
"""
|
||||
from backend.app.models import ImagePrediction
|
||||
|
||||
|
||||
async def seed_predictions(session, image_id: int, predictions: dict) -> None:
|
||||
"""Insert image_prediction rows from a {raw_name: {category, confidence}}
|
||||
dict (the old JSON shape). Caller commits/flushes as needed; this flushes."""
|
||||
session.add_all([
|
||||
ImagePrediction(
|
||||
image_record_id=image_id,
|
||||
raw_name=name,
|
||||
category=p.get("category", "general"),
|
||||
score=float(p.get("confidence", 0.0)),
|
||||
)
|
||||
for name, p in predictions.items()
|
||||
])
|
||||
await session.flush()
|
||||
Reference in New Issue
Block a user