Source code for foley.index.taxonomy.model

"""Data structures for the UCS/AudioSet taxonomy resolver (stdlib-only).

These are plain, immutable-ish records — the resolver logic lives in
:mod:`~foley.index.taxonomy.ucs`, :mod:`~foley.index.taxonomy.audioset`, and
:mod:`~foley.index.taxonomy.resolver`. Nothing here imports numpy/torch; the
whole taxonomy layer is a pure lookup over dicts (report 04 §5.3 — "taxonomies do
faceting and browse", the CLAP vector does the heavy retrieval).
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Optional


[docs] @dataclass(frozen=True) class UcsRow: """One Universal Category System entry. A ``catid`` (e.g. ``'DOORWood'``) is an OPAQUE key — the category prefix is variable-length and not reliably splittable — so ``catid -> (category, subcategory)`` is always a table lookup, never a string split (report 04 §5.2). ``confident=False`` marks an APPROXIMATE CatID reconstructed for the seed table; verify it against the UCS master before treating it as authoritative. """ catid: str category: str subcategory: str synonyms: tuple[str, ...] = () confident: bool = False
[docs] @dataclass class UcsTable: """A loaded UCS lookup: by CatID (exact + case-insensitive) and by synonym. Attributes: by_catid: ``CatID -> UcsRow`` (case-sensitive primary key). order: The CatIDs in stable insertion order (deterministic tie-breaking). """ by_catid: dict[str, UcsRow] = field(default_factory=dict) order: list[str] = field(default_factory=list) _ci_index: dict[str, str] = field(default_factory=dict) # lower(catid) -> catid
[docs] def get(self, catid: str) -> Optional[UcsRow]: """Look up a row by CatID: exact first, then case-insensitive.""" row = self.by_catid.get(catid) if row is not None: return row canonical = self._ci_index.get(catid.lower()) return self.by_catid.get(canonical) if canonical else None
def __contains__(self, catid: str) -> bool: return self.get(catid) is not None def __len__(self) -> int: return len(self.by_catid) def __iter__(self): return iter(self.by_catid.values())
[docs] @dataclass class AudioSetUcsMap: """AudioSet-label -> UCS-CatID overlap map (report 04 §5.3). Keyed primarily by lowercased label **name** (robust); ``by_mid`` carries the best-effort ``/m/...`` machine ids as a secondary key. Every target CatID is validated against the UCS table at load time (fail-fast on a broken map). """ by_name: dict[str, str] = field(default_factory=dict) by_mid: dict[str, str] = field(default_factory=dict)
[docs] def resolve(self, label: str) -> Optional[str]: """Map one AudioSet label (a MID or a name) to a UCS CatID (or ``None``).""" if label in self.by_mid: return self.by_mid[label] return self.by_name.get(label.lower())
[docs] @dataclass class CatIdResolution: """The result of resolving free tags/caption/labels to a UCS CatID. ``catid`` feeds :attr:`~foley.base.SoundRecord.ucs_category` and ``subcategory`` feeds :attr:`~foley.base.SoundRecord.ucs_subcategory` on ingest, and :attr:`~foley.base.SoundEvent.ucs_catid` on the query side. """ catid: Optional[str] = None category: Optional[str] = None subcategory: Optional[str] = None source: Optional[str] = None # 'filename' | 'keyword' | 'audioset' | None confidence: float = 0.0 # coarse per-stage band, 0..1 matched_terms: list[str] = field(default_factory=list) def __bool__(self) -> bool: """Truthy iff a CatID was resolved.""" return self.catid is not None