feat(fc2b): add Camie tagger ONNX wrapper
CPU-only, lazy-loaded, process-singleton ONNX session. Parses Camie's string-category selected_tags.csv (vs WD14's integer Danbooru ids). STORE_FLOOR (0.05) keeps the stored predictions JSON compact; SURFACED_CATEGORIES gates which categories the suggestion UI shows (meta/rating/year stored but never surfaced). Inference itself isn't unit-tested (1GB model not in CI); the missing- model error path and pure-logic surface are. Full inference runs in the local integration suite. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
"""Tagger unit tests. The ONNX model isn't available in CI (it's a 1GB
|
||||
download into /models), so these test the pure-logic surface: STORE_FLOOR
|
||||
constant, SURFACED_CATEGORIES set, TagPrediction dataclass, and the
|
||||
load()-missing-file error path. Full inference is exercised by the local
|
||||
integration suite against a real /models volume.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from backend.app.services.ml.tagger import (
|
||||
STORE_FLOOR,
|
||||
SURFACED_CATEGORIES,
|
||||
TagPrediction,
|
||||
Tagger,
|
||||
get_tagger,
|
||||
)
|
||||
|
||||
|
||||
def test_surfaced_categories():
|
||||
assert SURFACED_CATEGORIES == {"artist", "character", "copyright", "general"}
|
||||
|
||||
|
||||
def test_store_floor_is_low():
|
||||
assert 0 < STORE_FLOOR < 0.2
|
||||
|
||||
|
||||
def test_tag_prediction_dataclass():
|
||||
p = TagPrediction(name="x", category="general", confidence=0.9)
|
||||
assert p.name == "x"
|
||||
assert p.category == "general"
|
||||
assert p.confidence == 0.9
|
||||
|
||||
|
||||
def test_get_tagger_singleton():
|
||||
assert get_tagger() is get_tagger()
|
||||
|
||||
|
||||
def test_load_raises_when_model_missing(tmp_path):
|
||||
t = Tagger(model_dir=tmp_path / "nonexistent")
|
||||
with pytest.raises(RuntimeError, match="model.onnx missing"):
|
||||
t.load()
|
||||
Reference in New Issue
Block a user