Recursive AI

Convert ONNX to the OneModel format

All onemodel recipes

Convert an ONNX file to OneModel’s own format once, load it with the same call, and get bit-identical outputs, with the weights read as memory-mapped views.

C#
using RecursiveAI.OneModel;
using RecursiveAI.OneModel.Format;
 
ModelFormat.Convert("wide.onnx", "wide.onemodel");
Console.WriteLine($"wide.onnx      {new FileInfo("wide.onnx").Length,8:N0} bytes");
Console.WriteLine($"wide.onemodel  {new FileInfo("wide.onemodel").Length,8:N0} bytes");
Console.WriteLine($"OneModel format? {ModelFormat.IsModelFormatFile("wide.onemodel")}");
 
float[] input = Enumerable.Range(0, 256).Select(i => i / 256f).ToArray();
using var fromOnnx = Model.Load("wide.onnx");
using var fromOwn = Model.Load("wide.onemodel");
float[] a = fromOnnx.Run(input), b = fromOwn.Run(input);
 
bool same = a.Zip(b).All(p => BitConverter.SingleToInt32Bits(p.First) == BitConverter.SingleToInt32Bits(p.Second));
Console.WriteLine($"Bit-identical outputs: {same}");
 
File.WriteAllBytes("broken.onemodel", File.ReadAllBytes("wide.onemodel")[..4000]);
try { Model.Load("broken.onemodel"); }
catch (ModelFormatException e) { Console.WriteLine($"{e.Kind}: {e.Message}"); }
Text
wide.onnx       655,516 bytes
wide.onemodel   656,320 bytes
OneModel format? True
Bit-identical outputs: True
Malformed: the header says the file is 656320 bytes; it is 4000 (truncated or extended) (broken.onemodel at byte 48, file_length)

The format

A .onemodel file is a 64-byte header, a JSON manifest of the graph, and the raw weights, each tensor aligned to 64 bytes so it loads as a view of a memory map instead of being copied out of protobuf. What is saved is the imported graph before any optimization, so a converted model optimizes and runs exactly as the ONNX file it came from. The layout is in the OneModel format.

  • Model.Load and Session.Load tell the two kinds apart by their first eight bytes (ONEMODEL), so the loading code doesn’t change.
  • ModelFormat.Save(model, path) writes a model you already imported; ModelFormat.Load returns its IrModel.
  • A damaged file fails with ModelFormatException, whose Kind, Offset and FieldPath say what is wrong and where.

Good to know

  • The format is version 1 and unstable until OneModel 1.0: a version 1 file may stop loading in a later preview. Keep the ONNX file and convert again after you update.
  • On a model this small the file sizes are about the same. The gain is in loading: aligned weights are mapped, not parsed and copied.