ML Scoring (ONNX)

Score records with an ONNX model inside a rule using model_score.

ONNX (Open Neural Network Exchange) is a portable format for trained models. The model_score operator runs a registered ONNX model over the batch as a derived column and compares its output with an op and value. Model output can therefore participate in the same rule tree as deterministic predicates.

The model_score leaf

Name the registered model, list the input features in order, and set the threshold:

- model_score:
    model: fraud_logreg
    features: [amount, account_age_days, merchant.risk.score]
    op: gt
    value: 0.7

This leaf matches when the model's score for a record is greater than 0.7. Features may use dotted names like merchant.risk.score for nested input.

features must reference numeric BlazeRules fields. Categories and text required by a model must be encoded upstream into numeric feature columns before model_score evaluation.

Register the model

Register the ONNX artifact with the engine by name, then reference that name from the rule.

import blazerules

engine = blazerules.RuleEngine()
engine.register_model("fraud_logreg", "models/fraud_logreg.onnx")
engine.load_rules("rules.yaml")

result = engine.evaluate_ndjson(batch_bytes)

Model files can be loaded from a local path or an s3:// URL, the same as rule files.

register_model(...) can be called before or after load_rules(...). Models are resolved by name when the derived model channel is scored; re-registering a model name swaps the model used by later batches.

One backend, many model types

BlazeRules consumes the .onnx artifact and nothing else. XGBoost, LightGBM, scikit-learn, and neural networks all export to ONNX, so the model author's framework is irrelevant at inference time — export to .onnx and register it.

Both classification and regression models work, and the meaning of value follows the model's output:

  • A logistic/classification model ends in a sigmoid (or softmax) and emits a probability in [0,1], so op: gte, value: 0.8 means "≥ 80% confident."
  • A regression model emits a continuous value in its own units (dollars, a count, a latency), so op: gt, value: 120 compares against that raw prediction.

Multiple models may be registered. Each model_score leaf names one model, and independent models are scored in parallel over the batch.

Predictions are logged and visualized

When the agent receives --model and the ruleset uses model_score, each model's raw per-record prediction is written alongside the decision. Arrow output uses a model.<name> float column; NDJSON output uses a model_scores object. The dashboard presents these values on the Models page as prediction-distribution histograms and filterable per-record tables.

Derived columns are computed once per batch

model_score is a derived column. It is computed once per batch, and only when a rule actually references it. Rules that don't use the model add no inference cost, and there is no per-record interpreter overhead inside the rule tree.

🚧

ONNX support is a build option

model_score requires BLAZERULES_ENABLE_ONNX (default ON). A build with this option disabled rejects model_score rules during compilation and causes register_model to throw. See Error Reference and Troubleshooting.

Model scores are internal derived columns, not public input fields. The rule only sees the model_score predicate result. Missing or null numeric features are passed to ONNX as NaN; if a model is not registered, its feature count does not match, or inference fails, that model channel yields zero scores for the batch instead of throwing mid-batch.

The current ONNX integration feeds a numeric tensor in the exact order listed in features. It does not tokenize text, one-hot encode strings, or build categorical embeddings inside BlazeRules.

Related documentation


Did this page help you?