aroma: expand to 164 heads across a multi-industry corpus - #208
Merged
Merged
Conversation
Grow the aroma model from the food-only baseline to 164 odor-descriptor heads (170 total with the 6 taste heads), serving one head set across every "Mancer" mode. Flavormancer is the general flavor-chemistry base; the other modes specialize on top of it — Beveragemancer, Aromamancer (fragrance), Vapemancer (inhalation), Oilmancer (essential oils) — each adding its own characteristics and tools. Edibility is a per-molecule food-safe FLAG (open-gov registers), not corpus membership, so the corpus can include the fragrance space needed to read structure->smell well. Model / data - New heads span food (celery, maple, saffron, citrus subtypes, herbs/spices), fragrance/aroma-only (aldehydic, amber, oakmoss, vetiver, sandalwood, myrrh, labdanum, ...), and floral/fruit subtypes — each clears CV-AUROC >= 0.70. - Redistribute the diffuse "musty" percept into corky (distinct cork-taint scaffold) + earthy/mushroom (which it sharpens); consolidate the redundant tuberose head into its white-floral neighbours, de-inflating their small-n scores. - Deterministic builds: persistent resolve_cache.json ends the PubChem-flakiness that churned marginal heads build-to-build. Surfaces (kept in sync) - Canonical per-descriptor blurbs live once in predict.AROMA_DESC and flow to /api/aroma, /api/predict (now includes aroma), the workbench meter help, the MCP server, and the skill. Note picker offers every trained head. - Docs updated to 164 heads / 8,830 enriched molecules; AROMA-AUDIT documents the honesty rails (subtype/structural heads, ~1.00-AUROC single-scaffold classes, the count's +/-2 margin) and the fragrance-association provenance (public flavor/fragrance chemistry facts, some via Claude Opus 4.8; non- copyrightable per Feist; IP review noted in docs as the pre-commercial gate). Curated CSVs remain private (gitignored); framework + schema samples ship. Tests: 35 passed, 0 skipped (unit + e2e against the live 164-head app). Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
Remove redundant duplicate VOCAB entries (gardenia/ylang/magnolia/cucumber) introduced across the head-expansion passes. Values were identical, so this is a pure lint fix — dict keys dedupe, so the built dataset and the 164 trained heads are unchanged. Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
…2e gate Ruff 0.16.0 broadened its default rule set (bandit S, bugbear B, SIM, FURB, PLR, ...), surfacing ~82 findings repo-wide. CI installs ruff unpinned, so keep it latest and fix the debt properly rather than pin or blanket-ignore. Fixed outright (no noqa): - try/except/pass -> contextlib.suppress(), reasons preserved (23) - try/except/continue in loops -> sentinel + contextlib.suppress (7) - one blind-except return-fallback -> suppress + sentinel - mutable default args -> None sentinels (B006); bare open() -> context managers (SIM115); nested with -> combined (SIM117); v==v NaN trick -> math.isnan / np.isnan (PLR0124); collapsed nested ifs (SIM102); dict() -> literals, next(iter()), tuple startswith, import sorting, regex-flag aliases, unused-noqa removal. Kept as documented noqa (25, all with reasons): blind-except (BLE001) blocks that do real fallback work — retry-with-backoff, log-and-skip, return-partial. For best-effort network/RDKit/parquet code, catch-all-and-degrade is the correct defensive choice; narrowing to named types would risk crashing on an unlisted exception. No blanket config ignore, so future ruff rules still surface to triage. e2e: the session-scoped models_present gate now polls with a 3-minute deadline (was a single 15s query that could time out under load and cascade-skip all 9 model-dependent tests). Full suite now runs 0 skipped. (Remaining full-e2e flakiness under back-to-back load is a single-worker-server artifact; those tests pass in isolation and are not in the PR-blocking smoke set.) Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
This was referenced Jul 25, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Grows the aroma model from the food-only baseline to 164 odor-descriptor heads (170 total trained heads with the 6 taste heads), and reframes the corpus as multi-industry: one head set serves every "Mancer" mode. Flavormancer is the general flavor-chemistry base; Beveragemancer / Aromamancer (fragrance) / Vapemancer (inhalation) / Oilmancer (essential oils) specialize on top of it. Edibility is a per-molecule food-safe flag (open-gov registers), not corpus membership — so the corpus can include the fragrance space needed to read structure→smell well.
Closes #201.
What changed
Model / data
celery,maple,saffron, citrus subtypes, herbs/spices), fragrance/aroma-only (aldehydic,amber,oakmoss,vetiver,sandalwood,myrrh,labdanum, …), and floral/fruit subtypes — each clears CV-AUROC ≥ 0.70.mustypercept is redistributed intocorky(its distinct cork-taint scaffold, 0.98) +earthy/mushroom(sharpeningearthy0.88→0.95). The redundanttuberosehead is consolidated into its white-floral neighbours (jasmine/gardenia/ylang/champaca), nearly doubling their example counts and de-inflating small-n scores.resolve_cache.jsonends the PubChem-flakiness that used to churn marginal (n≈10) heads build-to-build (e.g.cocoaonce cratered 10→4 from one flaky build).Surfaces (kept in sync)
predict.AROMA_DESCand flow to/api/aroma,/api/predict(now includes aroma), the workbench meter help, the MCP server, and the skill. The note picker offers every trained head.AROMA-AUDIT.mddocuments the honesty rails and provenance (below).Honesty rails (so the count never over-claims)
lactonic) clear on shared scaffolds — flagged as slices of space we already cover, not orthogonal percepts.wintergreen,oakmoss,myrrh,cinnamon,musky) are narrow single-scaffold classes. Tested: adding diverse examples keeps them at 1.00 → the percept is the chemical family (easy separation, not fixable overfitting). Real robustness needs the GNN (research(model): GNN for structure→property vs the RandomForest heads #199).mustydoes not ship (diffuse, no shared substructure).Provenance
Food heads: HSDB (public domain) + open-gov food registers. Fragrance/aroma-only associations: general public flavor & fragrance chemistry facts (some supplied by Claude Opus 4.8), resolved to public-domain PubChem structures — non-copyrightable (Feist v. Rural); no proprietary compilation (Good Scents / Leffingwell / FlavorDB) is a source. A spot-verification + IP/provenance review is the standing pre-commercial gate (documented in
SOURCES.md, not advertised in the UI).Testing
Curated CSVs remain private (gitignored); framework + schema samples ship.
Follow-ups (not blocking)