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 — letting a model verdict participate in the same rule tree as your deterministic checks.
The model_score leaf
model_score leafName 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.7This 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 be numeric BlazeRules fields. If your upstream payload carries a category or text value that a model needs, encode it upstream into numeric feature columns before passing it to model_score.
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], soop: gte, value: 0.8means "≥ 80% confident." - A regression model emits a continuous value in its own units (dollars, a count, a latency), so
op: gt, value: 120compares against that raw prediction.
Register as many models as you like — each model_score leaf names its own model, and independent models are scored in parallel over the batch.
Predictions are logged and visualized
When you run the agent with --model and rules that use model_score, each model's raw per-record prediction is written into the decision log alongside the decision: a model.<name> float column in Arrow output, or a model_scores object in NDJSON output. This is near-free — the prediction is already computed for the rule — and only happens when a model is configured. The dashboard reads these into a Models page with a prediction-distribution histogram and a filterable per-record prediction table per model.
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_scorerequires the engine to be built withBLAZERULES_ENABLE_ONNX(defaultON). When built with itOFF,model_scorerules are rejected at compile time andregister_modelthrows. See the error reference and troubleshooting pages if you hit this.
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.
Where to go next
Updated 4 days ago