Skip to content

Commit 8e52d2e

Browse files
eauesqueclaude
andcommitted
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

0 commit comments

Comments
 (0)