Skip to content

Fallback Model Registry

nli_model is a configurable, revision-pinned default, but a single hardcoded id has no recourse if that repository is delisted or unreachable on the Hugging Face Hub — the NLI scorer then drops all the way to its word-overlap heuristic. The fallback registry keeps an ordered chain of vetted, revision-pinned alternates and resolves the primary to the first available model in the chain, so a deployment degrades to a strong alternate model instead of the heuristic floor.

Built-in NLI chain

The nli role's alternates are MNLI-style sequence classifiers the DeBERTa backend loads directly, each already pinned in the revision registry:

  1. yaxili96/FactCG-DeBERTa-v3-Large (the configured primary)
  2. MoritzLaurer/DeBERTa-v3-large-mnli-fever-anli-ling-wanli
  3. roberta-large-mnli

Embedding and reranker fallbacks are intentionally omitted: a different-dimension embedding model is not a drop-in replacement (it invalidates an existing index), so that swap is a deliberate re-indexing decision, not an automatic failover.

Enabling

Off by default — it probes the Hub at startup, so it is opt-in:

from director_ai.core.config import DirectorConfig

scorer = DirectorConfig(model_fallback_enabled=True).build_scorer()
# If FactCG is delisted, the scorer is built on the first reachable alternate
# rather than falling through to the heuristic.

Resolution

FallbackModelRegistry.resolve(role, primary) tries the primary first, then each vetted fallback, and returns the first whose availability probe passes. If none is reachable it returns the primary unchanged, letting the scorer's own heuristic floor take over — it never raises on a missing model.

Availability is decided by an injected AvailabilityProbe (default: a cheap Hugging Face model_info metadata call, no weights downloaded), so resolution is deterministic and fully tested offline. Probe results are cached per model for the registry's lifetime. Every chain entry must be revision-pinned, enforced at construction.

from director_ai.core.model_registry import FallbackModelRegistry

registry = FallbackModelRegistry()
resolved = registry.resolve("nli", "yaxili96/FactCG-DeBERTa-v3-Large")
print(resolved.model_id, resolved.revision, resolved.is_fallback)

Full API

director_ai.core.model_registry.FallbackModelRegistry

FallbackModelRegistry(*, probe: AvailabilityProbe | None = None, chains: dict[str, tuple[str, ...]] | None = None)

Resolve a role's primary model to the first available vetted alternate.

Parameters:

Name Type Description Default
probe AvailabilityProbe | None

Availability check; defaults to a Hugging Face model_info probe.

None
chains Mapping[str, tuple[str, ...]] | None

Per-role fallback chains; defaults to :data:FALLBACK_CHAINS. Every chain entry must resolve to an immutable revision (be pinned), else a :class:ValueError is raised at construction.

None

candidates

candidates(role: str, primary: str, *, primary_revision: str | None = None) -> list[tuple[str, str | None]]

The primary followed by the role's fallbacks (primary not repeated).

resolve

resolve(role: str, primary: str, *, primary_revision: str | None = None) -> ResolvedModel

Return the first available model for role.

Tries the primary first, then each vetted fallback. If none is reachable, returns the primary unchanged (the scorer's heuristic floor then applies).

director_ai.core.model_registry.ResolvedModel dataclass

ResolvedModel(model_id: str, revision: str | None, role: str, is_fallback: bool)

The model a role resolved to, and whether it is a fallback.