Load the .onnx file with Model.Load, pass the input as a float[] with its shape, and read the output array. The program below runs the MNIST digit classifier from the ONNX model zoo on a handwritten “7” from the MNIST test set. OneModel is pure managed C#: no ONNX Runtime, no native libraries.
dotnet new console -o RunOnnx && cd RunOnnx dotnet add package RecursiveAI.OneModel --version 0.3.0-preview.1 dotnet add package RecursiveAI.OneImage --version 1.10.4 curl -LO https://github.com/onnx/models/raw/main/validated/vision/classification/mnist/model/mnist-12.onnx curl -O https://recursiveai.org/onemodel/samples/digit.png
Put this in Program.cs and run dotnet run:
using OneImage; using RecursiveAI.OneModel; using var model = Model.Load("mnist-12.onnx"); foreach (var i in model.Session.Inputs) Console.WriteLine($"Input {i.Name}: {i.DType} [{string.Join(", ", i.Dims)}]"); foreach (var o in model.Session.Outputs) Console.WriteLine($"Output {o.Name}: {o.DType} [{string.Join(", ", o.Dims)}]"); // 28 x 28 gray pixels, 0 to 255, white on black: what this model was trained on on Gray8[] pixels = Image.Load("digit.png").ToArray<Gray8>(); float[] input = pixels.Select(p => (float)p.V).ToArray(); float[] scores = model.Run(input, [1, 1, 28, 28]); // one score per digit, 0 to 9 int digit = Array.IndexOf(scores, scores.Max()); Console.WriteLine($"Predicted digit: {digit}"); Console.WriteLine($"Scores: {string.Join(", ", scores.Select(s => $"{s:F0}"))}");
Input Input3: F32 [1, 1, 28, 28] Output Plus214_Output_0: F32 [1, 10] Predicted digit: 7 Scores: -553, 138, 2179, 2320, -3467, -1778, -6442, 8063, -1860, 1034
Model.Load reads the ONNX file and plans it for this CPU; Run takes the values in row-major order and returns the model’s output as a new array. This model returns ten raw scores, one per digit, and the highest wins; ONNX Runtime gives the same ten scores for this image, to the nearest whole number. Load the model once and call Run as often as you like, from any number of threads.
Inputs, shapes and outputs
model.Session.InputsandOutputsgive each tensor’s name, element type and dimensions, read from the model. A named dimension such asbatchtakes any size.Runacceptsfloat[],long[](token ids) andint[], and an optional shape: leave it out when the model’s input shape is fixed except for its first dimension.- A span form,
model.Run<float, float>(input, shape, output), writes into your buffer and allocates nothing once warm. - For a model with several inputs or outputs, use a
Session: see Run an ONNX model with multiple inputs.
Limits
- OneModel is a preview (0.3.0-preview.1, .NET 10). The API may change before 1.0, and there is no GPU backend: it runs on SIMD CPU kernels.
- Not every operator is implemented. A model that needs a missing one fails in
Model.Loadwith every missing operator listed: see When an ONNX model won’t load. Coverage is in conformance. - Preprocessing is yours. OneModel runs the graph; resizing, normalizing and tokenizing happen in your code, exactly as the model was trained. Here OneImage decodes the PNG; this model wants unscaled 0 to 255 values.
- Inference only. Training isn’t in this preview.
For bit-identical results on every machine, see Deterministic ONNX inference. Everything else starts in getting started.