feat(suggestions): tag-input dropdown searches the full prediction set
The typed dropdown sourced the threshold-filtered panel list (>= 0.70 general), so low-confidence actions/features the model DID predict never appeared — forcing hand-typed custom tags instead of accepting the model's canonical formatting. Add a threshold override: SuggestionService.for_image(threshold_override=) and GET /images/<id>/suggestions?min=<f> surface EVERY stored prediction (down to the 0.05 store floor), alias-resolved and normalized, still excluding applied/rejected and unsurfaced categories. The suggestions store gains allByCategory + loadAll (min=0); the dropdown searches that full set (cap 20), while the Suggestions panel stays curated at the configured threshold. Accept/dismiss drop from both lists. Operator-asked 2026-06-09. Test: a 0.30 general prediction is hidden by default but surfaced with threshold_override=0.0; unsurfaced categories still excluded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,33 @@ async def test_threshold_filters_low_confidence_general(db):
|
||||
assert "Lowconf" not in names
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_threshold_override_surfaces_low_confidence(db):
|
||||
# The typed-dropdown "show everything the model saw" mode: threshold_override
|
||||
# surfaces stored predictions below the configured threshold (in canonical
|
||||
# formatting) so they can be picked instead of hand-typed (2026-06-09).
|
||||
img = _img(
|
||||
"d" * 64,
|
||||
{
|
||||
"lowconf": {"category": "general", "confidence": 0.30},
|
||||
"sword": {"category": "general", "confidence": 0.97},
|
||||
},
|
||||
)
|
||||
db.add(img)
|
||||
await db.flush()
|
||||
sl = await SuggestionService(db).for_image(img.id, threshold_override=0.0)
|
||||
names = [s.display_name for s in sl.by_category.get("general", [])]
|
||||
assert "Sword" in names
|
||||
assert "Lowconf" in names # below the configured threshold, surfaced anyway
|
||||
|
||||
# Unsurfaced categories are still excluded even with the override.
|
||||
img2 = _img("e" * 64, {"safe": {"category": "rating", "confidence": 0.99}})
|
||||
db.add(img2)
|
||||
await db.flush()
|
||||
sl2 = await SuggestionService(db).for_image(img2.id, threshold_override=0.0)
|
||||
assert "rating" not in sl2.by_category
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unsurfaced_category_dropped(db):
|
||||
img = _img(
|
||||
|
||||
Reference in New Issue
Block a user