Application Integration¶
ABERRANT exposes its built-in components through a typed, immutable catalog. Applications can discover supported models, generate configuration forms, validate deployment configuration, and build pipelines without maintaining class import paths or model-specific warm-up formulas.
Reuse resolved configuration¶
Resolve once when initializing a service or evaluator. Resolution applies constructor defaults, validates types and feature widths, and resolves capabilities without constructing or learning any algorithms.
from aberrant.catalog import DetectorConfig
resolved = DetectorConfig.from_mapping(
{
"transformers": [{"id": "standard_scaler"}],
"model": {"id": "online_isolation_forest", "params": {"seed": 42}},
}
).resolve()
canonical = resolved.config.as_dict()
capabilities = resolved.capabilities.as_dict()
fingerprint = resolved.fingerprint
first = resolved.build()
second = resolved.build() # Independent components and learned state.
resolve_detector_config(mapping_or_config) is the equivalent module function.
Constructor inspection is shared within one resolution; parameters resolve once
per component occurrence. Builds reuse the construction plan, never a learned
model. Persist canonical configuration and learned detector state using the
application's checkpoint policy; keep resolved plans as process-local metadata.
Caller-supplied runtime dependencies retain their own ownership and lifetime.
normalized() and fingerprint() keep their narrower validation boundary:
they do not construct algorithms or require compatible pipeline feature counts.
Fingerprints use the existing canonical JSON representation and reject non-JSON
values, including Python runtime dependencies, even when those are buildable.
Algorithm constructor invariants are checked when building.
Configuration exceptions retain their messages and subclasses and expose an
immutable tuple of ConfigurationIssue records through error.issues. A record
contains a stable code, a tuple loc of object keys and array indexes, and a
message. A nested engine field can have location
("model", "params", "similarity_engine", "params", "warm_up").
Independent parameter failures are collected. Constructor-only invariants use
the component's params location when a field cannot be identified reliably.
Use these locations directly in forms; do not parse human-readable messages.
The stable codes are documented on aberrant.base.ConfigurationIssue.
Public schemas and default parameters are detached containers. Applications may constrain them for resource limits or presentation without modifying the library catalog or changing executable fingerprints.
Inspect the catalog¶
MODEL_CATALOG, TRANSFORMER_CATALOG, and SIMILARITY_ENGINE_CATALOG are
read-only mappings keyed by stable component identifiers. Each entry exposes
its public import path, family, optional extra, availability in the current
environment, constructor parameter schema, and operational capabilities.
Identifiers and the versioned configuration shape are part of the public API;
new catalog entries may be added compatibly within 1.x.
from aberrant.catalog import get_model_spec
spec = get_model_spec("random_cut_forest")
parameter_schema = spec.parameter_schema()
capabilities = spec.capabilities(
{
"sample_size": 256,
"shingle_size": 4,
"warmup_samples": 128,
"normalize_score": True,
}
)
assert capabilities.warmup.minimum == 131
assert capabilities.score_kind.value == "zero_to_one"
assert capabilities.state.value == "bounded"
catalog_manifest() returns a detached JSON-compatible description of all
entries. Parameter schemas describe JSON types, defaults, required fields, and
literal choices. Nested component parameters carry an
x-aberrant-component-kind schema extension. Constructors remain the authority
for numeric ranges and cross-parameter invariants. Applications should add their
own resource ceilings for values such as tree counts and window sizes.
Bulk discovery does not import optional runtimes. Optional components retain
availability metadata, but their parameters and model capabilities are
None in catalog snapshots. Inspect a selected component explicitly with
spec.parameter_schema() or spec.capabilities(params) when needed; these
calls may load its optional runtime.
Catalog warm-up is the minimum history required by the algorithm's scoring contract. It is not a recommendation for threshold calibration. A production application can require a longer calibration period without replacing the model-specific metadata.
Always supply counts in warmup.unit to remaining() and is_satisfied().
For SDOStream the unit is observers: use model.n_observers, since observer
insertion is sampled and learned event counts cannot determine readiness.
Its minimum accounts for both warm_up_observers and x_neighbors.
Geometric and harmonic moving averages use retained_values: supply
len(model.window), since geometric learning ignores nonpositive inputs and
harmonic learning ignores zeros. Geometric readiness requires two retained
values, or three with absoluteValues=True; harmonic readiness requires one.
feature_schema distinguishes fixed-key models from feature-evolving or
engine-defined behavior. requires_unit_interval identifies hard input-domain
requirements such as Half-Space Trees; it does not imply that applications must
use a particular transformer when their source data already satisfies them.
Build from configuration¶
The versioned detector format contains an ordered transformer list and one terminal model. Only catalog identifiers are accepted; configuration cannot select an arbitrary Python import path.
from aberrant.catalog import DetectorConfig
config = DetectorConfig.from_mapping(
{
"version": 1,
"transformers": [
{
"id": "feature_schema_guard",
"params": {"features": ["temperature", "pressure", "flow"]},
},
{"id": "standard_scaler"},
{
"id": "random_projection",
"params": {"n_components": 2, "seed": 17},
},
],
"model": {
"id": "online_isolation_forest",
"params": {"num_trees": 25, "window_size": 512, "seed": 17},
},
}
)
detector = config.build()
minimum_model_warmup = config.capabilities().warmup.minimum
config_fingerprint = config.fingerprint()
Parsing rejects unknown fields and unsupported format versions. Construction
rejects unknown component IDs, missing or extra constructor arguments, invalid
JSON types, model constructor validation failures, and statically detectable
feature-width mismatches. These failures derive from ConfigurationError, so
configuration faults can be separated from stream-processing failures.
Entries with declarative: false require runtime Python objects and remain
available for direct construction, but are intentionally rejected by
DetectorConfig.
config.normalized() validates parameter types and materializes constructor
defaults. The fingerprint is a SHA-256 digest of that canonical configuration,
so omitting a default and specifying it explicitly produce the same value. It
is useful checkpoint metadata, but it is not a serialization format for learned
model state and does not replace the package version in a checkpoint envelope.
Enforce an event schema¶
Place FeatureSchemaGuard first when an application knows its input fields. It
rejects missing, additional, non-string, non-numeric, and non-finite features
with ValidationError before downstream transformers can update their state.
from aberrant.model.iforest import OnlineIsolationForest
from aberrant.transform import FeatureSchemaGuard, StandardScaler
detector = (
FeatureSchemaGuard(features=["temperature", "pressure"])
| StandardScaler()
| OnlineIsolationForest(window_size=512, seed=7)
)
With no explicit features, the first successfully learned event establishes a
sorted schema. The guard does not remove message metadata or choose which fields
belong to a model; that remains an application boundary decision.
Configure KNN and FAISS¶
FAISS has a stable public import at aberrant.similarity. Declarative KNN
configuration accepts a nested similarity-engine component:
from aberrant.catalog import create_model
knn = create_model(
"knn",
{
"k": 5,
"similarity_engine": {
"id": "faiss",
"params": {"window_size": 1000, "warm_up": 20},
},
},
)
This requires aberrant[faiss]. The catalog reports the engine as unavailable
when that extra is not installed and raises MissingOptionalDependencyError
when construction is attempted.
Some macOS PyTorch and faiss-cpu wheel combinations bundle separate OpenMP
runtimes and abort when both are activated in one process. ABERRANT does not set
the unsafe KMP_DUPLICATE_LIB_OK workaround. Use a compatible native package
set or run FAISS-backed and PyTorch-backed detectors in separate processes.
Ownership boundary¶
The catalog owns facts about ABERRANT components and their construction. The application still owns message decoding, tenant or sensor routing, calibration policy, resource budgets, model-instance concurrency, checkpoint I/O and signing, alert delivery, circuit breaking, and health endpoints.