Recursive AI

Named inputs and outputs

All onemodel recipes

Run an ONNX model with more than one input or output through OneModel’s Session: list its inputs and outputs, pass named tensors in any order, and get the outputs back as tensors.

The model is scorer.onnx from the sample models: score = features × W + bias and best, the largest score of each row.

C#
using RecursiveAI.OneModel.Graph;
using RecursiveAI.OneModel.Tensors;
 
using var session = Session.Load("scorer.onnx");
foreach (var i in session.Inputs) Console.WriteLine($"in  {i.Name}: {i.DType} [{string.Join(", ", i.Dims)}]");
foreach (var o in session.Outputs) Console.WriteLine($"out {o.Name}: {o.DType} [{string.Join(", ", o.Dims)}]");
 
using var features = Tensor.FromSpan<float>([1f, 2f, 3f, 4f, 5f, 6f], Shape.Create(2, 3));
using var bias = Tensor.FromSpan<float>([0.5f, 1.5f], Shape.Create(1, 2));
 
var outputs = new Tensor[2];   // empty: the session allocates them, and we dispose them
session.Run(["bias", "features"], [bias, features], ["score", "best"], outputs);
using Tensor score = outputs[0], best = outputs[1];
 
Console.WriteLine($"score {score.Shape}: {string.Join(", ", score.Data<float>().ToArray())}");
Console.WriteLine($"best  {best.Shape}: {string.Join(", ", best.Data<float>().ToArray())}");
Text
in  features: F32 [batch, 3]
in  bias: F32 [1, 2]
out score: F32 [batch, 2]
out best: F32 [batch]
score [2,2]: 4.5, 6.5, 10.5, 12.5
best  [2]: 6.5, 12.5

How Session.Run works

  • Every model input is passed once, by name, in any order. Inputs are read, never changed and not kept.
  • Each element of outputs receives the output named at the same position. An empty Tensor is replaced by a new one that you own and dispose; a tensor of the right type and shape is overwritten in place, so a loop can reuse its outputs.
  • batch is a symbolic dimension: the session makes a plan for each set of input shapes it sees and caches it (16 by default, SessionOptions.MaxCachedPlans).
  • A wrong name, element type or shape is a SessionException (InvalidInput) before anything runs.

For a model with one input and one output, the span form session.Run<float, float>(inputName, input, shape, outputName, output) copies in and out of your buffers and allocates nothing once warm. Sessions are thread-safe. More in sessions and plans.