NWDAF Analytics Inference (Design Note)

July 17, 2026 · View on GitHub

Non-normative 6G research. NWDAF analytics are TS 23.288 / TS 29.520 functionality; the ML-serving abstraction and model backends here are prototype-level — no frozen Stage-3 specification covers model internals. Research shape for education, not a conformance target. Tracking issue: #26.

The inference abstraction

nextgcore-nwdafd's ml_service now defines a minimal load-by-id + predict surface (issue #26):

pub trait InferenceModel: Send + Sync {
    fn model_id(&self) -> &str;
    fn predict_series(&self, series: &[f64]) -> Option<(f64, f64)>; // (prediction, confidence)
}
pub fn load_model(model_id: &str) -> Result<Box<dyn InferenceModel>, String>;

The NF_LOAD analytics path is wired through it end to end: nrf_collector (samples from NRF NFStatusNotify) → AnalyticsEngine (compute_nf_load calls the active model) → Nnwdaf_AnalyticsInfo GET / EventsSubscription Notify (the emitted confidence member — the TS 29.520 prediction-confidence Uinteger — is the model's output; the wire shape is unchanged and stays spec-pure: the vendor predictedLoad key removed in G2-1 stays removed, so the numeric prediction surfaces via the engine API (NfLoadAnalytics.predicted_load), not as an invented wire member).

Models

idfile neededpredictionconfidence semantics
ols-linear (default)noOLS fit over last ≤5 samples, one step aheadR² of the fit (byte-identical to the pre-#26 inline math)
ewma[:<alpha>]noexponentially weighted moving average1 − mean abs one-step error (heuristic)
onnx:<path>yeslinear model applied to the last n samplesbacktest R² of the loaded model over the observed series

Selection: set NWDAF_PREDICTION_MODEL (e.g. ewma:0.5, onnx:/etc/nextgcore/nfload.onnx) before starting nextgcore-nwdafd; unset = ols-linear, behavior-identical to before issue #26. An invalid value logs a warning and keeps the default.

The ONNX backend (feature onnx-model, off by default)

Zero-dependency by design: a hand-rolled reader for a minimal, explicitly documented ONNX subset — exactly one ai.onnx.ml LinearRegressor node (coefficients + intercepts), the class skl2onnx exports for sklearn LinearRegression. Anything else in the graph is a hard error, never a silent approximation. Rationale: no C-linked runtime (repo rule), zero Cargo.lock growth (the pqc-tls precedent), and hand-rolled wire codecs are the house style. Test models are built as protobuf bytes in test source — no binary fixtures (per the never-commit-binaries decision).

Federation status

federation.rs keeps its real, tested local FedAvg aggregation (FlAggregationRound::aggregate, element-wise mean) and peer registry as an internal library; the genuinely dead scaffolding (FederatedRequest, the never-touched requests map) was removed. Honesty note: nothing federates over the wire — there is no cross-NWDAF protocol here.

Verification

cargo test -p nextgcore-nwdafd                          # default: OLS baseline, no model file
cargo test -p nextgcore-nwdafd --features onnx-model    # + ONNX subset reader tests
NWDAF_PREDICTION_MODEL=ewma cargo run -p nextgcore-nwdafd   # live model swap