Repository navigation
Commit 8e52d2e
feat(wd): drive inference from a profile sent by the caller
yu-server owns the tagger profile registry and its parser. This teaches the
sidecar to accept the inference-relevant part of a profile on the wire, so a
second family (camie) works without a second hardcoded recipe here — and
without a second copy of the profile parser in a second language.
Because half of that already existed and was unsafe. `load_input_size` and
`load_category_map_from_profile` picked "the first .json in the model
directory": `read_dir` order is unspecified, and for camie the first .json is
the 7 MB tag metadata, not a profile. Both are deleted here.
`profile` — `model_file`, `preprocess_spec`, `tag_source`, `output_spec`,
`default_thresholds`, `categories_mode`, `supports_categories`, deserialized
verbatim under their Python names. Omitted means the built-in WD recipe, which
is what every caller predating this field expects; that recipe is now
expressed as a profile too, so there is one code path rather than two.
`default_thresholds` is the *resolved* table. Whether the user's configured
thresholds or the profile's defaults win differs per adapter family, and that
decision belongs with the registry, not here.
The response carries `profile_applied`, so a caller can tell an old sidecar —
which would ignore the field and silently run the WD recipe against a camie
model — from one that honoured it.
A recipe this build cannot reproduce (`resize_strategy`, `channel_order`,
`layout`, `activation`, `tag_source.type`) is an error, and an `output_key`
naming a head the model does not export is an error. Approximating either
returns confident, well-formed, wrong tags; nothing downstream could detect it.
File names arriving in the profile are checked to be plain basenames before
being joined onto the model directory.
- **alpha** — the old code did `to_rgb8()`, which discards the alpha channel.
Python composites over the pad colour first, so a transparent PNG resolved
to white there and to whatever hid behind alpha=0 here.
- **scaled dimensions** — `DynamicImage::resize` rounds; Python's
`int(w * scale)` truncates. A one-pixel difference shifts the paste offset.
- **unmapped CSV categories** — Python falls through to the raw value; this
defaulted to "general", which would mislabel a whole category the profile
forgot to map.
- **ragged CSV rows** — Python's DictReader tolerates them; the csv crate
rejected them, so one side loaded the vocabulary and the other errored.
- **duplicate JSON keys** — Python raises; serde_json kept the last value.
The cached engine holds the vocabulary, thresholds and preprocess recipe, so
the model id alone no longer identifies it. The key now includes a fingerprint
of the resolved profile; the maps inside it are ordered so the fingerprint is
stable.
- **Against the real 752 MB camie export**, compared to tags produced by the
Python adapter on the same three fixtures: **identical tag sets, categories
and ratings** (16 / 23 / 20 tags), worst confidence delta **0.00005** — the
granularity of Python's `round(conf, 4)`. `tests/camie_parity.rs`, skipped
unless the model path is supplied.
- **Fault injection: 12 attempts, 11 caught.** Wrong output head, skipped
sigmoid, ignored channel order (both directions), ignored NCHW, rounded
instead of truncated, dropped mean, dropped scale, mean applied before
scale, lexicographic tag ordering, fixed threshold instead of the
per-category table, dropped alpha composite. The twelfth attempt failed to
compile and is recorded as **not** a detection.
- The tensor builder is split out so channel order, normalisation order and
layout are checked without the model — the camie fixtures are RGB/NCHW and
cannot discriminate a build that ignores those fields.
- `cargo test -p yu-hailo-infer-core`: 54 passed. Workspace serially: 65
passed. Two tests fail under parallel execution
(`panic_discards_the_active_handle`, `speech2text_transcribe_rejects_invalid_task`);
both pass serially and neither touches WD — a pre-existing isolation issue.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 891c73d commit 8e52d2e
7 files changed
Lines changed: 1631 additions & 153 deletions
File tree
- yu-hailo-infer-core
- src
- tests
- yu-hailo-infer/src
0 commit comments