ONNX Runtime Module
The onnxruntime module loads and runs ONNX models directly on device, suitable for text, embeddings, classification, detection, and general-purpose tensor inference workflows.
Only supported on iOS 13 and later
Load the module
local ort = require("onnxruntime")
Unlike coreml, this is not a built-in global module; it is loaded on demand.
After require("onnxruntime") succeeds, it also injects two native copy bridges into the built-in coreml APIs:
coreml.multi_array_from_ort_tensor(tensor[, data_type])multi_array:to_ort_tensor([data_type])
Both conversions are native-layer copies and do not go through Lua tables.
Module-level functions
Runtime and basic information
onnxruntime.version()onnxruntime.providers()onnxruntime.configure(opts)
Notes:
providers()returns the execution providers actually available in the current ORT runtimeconfigure()sets global runtime defaults and must be called before creating any session
Tensors, images, and numeric helpers
onnxruntime.tensor(type, shape[, data])onnxruntime.tensor_from_bytes(type, shape, bytes)onnxruntime.tensor_from_cv_mat(mat[, opts])onnxruntime.tensor_from_quad(mat, quad[, opts])onnxruntime.tensor_from_quads(mat, quads[, opts])onnxruntime.tensor_from_image(image[, opts])onnxruntime.tensor_from_images(images[, opts])onnxruntime.image_from_tensor(tensor[, opts])onnxruntime.clamp(tensor, min, max)onnxruntime.sigmoid(tensor)onnxruntime.exp(tensor)onnxruntime.where(condition, x, y)onnxruntime.matmul(lhs, rhs)onnxruntime.concat(tensors[, axis])onnxruntime.stack(tensors[, axis])
Notes:
clamp(),sigmoid(),exp(), andmatmul()are equivalent to the same-namedtensor:methods, with the tensor passed as the first argumentwhere()supports mixing scalars, booleans, and tensors, and applies broadcasting rules- Image preprocessing, OpenCV bridges, and
image_from_tensor()details are documented in the Tensor Module
Detection, decoding, and post-processing helpers
onnxruntime.nms(boxes, scores[, opts])onnxruntime.box_points(rotated_boxes)onnxruntime.xywh_to_xyxy(boxes)onnxruntime.xyxy_to_xywh(boxes)onnxruntime.rotated_iou(lhs_box, rhs_box)onnxruntime.rotated_nms(boxes, scores[, opts])onnxruntime.create_decoder(schema)onnxruntime.decode_yolo(output[, opts])onnxruntime.decode_yolo_obb(output[, opts])onnxruntime.decode_matrix_candidates(output, schema[, opts])onnxruntime.decode_dense_detection(output, opts)onnxruntime.records_from_boxes(boxes, scores, class_ids[, keep_indices])onnxruntime.obb_records_from_rows(rows, scores, class_ids[, angles[, keep_indices[, opts]]])onnxruntime.points_to_records(points[, opts])onnxruntime.threshold_masks(masks, threshold)onnxruntime.crop_masks_by_boxes(masks, boxes)onnxruntime.resize_masks(masks, width, height[, opts])onnxruntime.mask_iou(lhs_mask, rhs_mask)onnxruntime.mask_to_polygon(mask[, opts])onnxruntime.proto_masks(proto, coeffs, boxes, image_width, image_height[, opts])onnxruntime.project_masks(proto, coeffs, boxes, image_width, image_height[, opts])onnxruntime.db_postprocess(score_map[, opts])onnxruntime.tracker([opts])onnxruntime.reshape_keypoints(points[, keypoint_count[, keypoint_dim|opts]])onnxruntime.scale_boxes(boxes, transform)onnxruntime.clip_boxes(boxes, clip_width, clip_height)onnxruntime.scale_points(points, transform[, opts])onnxruntime.scale_keypoints(points, transform[, opts])onnxruntime.clip_keypoints(points, clip_width, clip_height[, opts])onnxruntime.ctc_greedy_decode(logits[, opts])onnxruntime.sample_logits(logits[, opts])
Notes:
tensor_from_quad()/tensor_from_quads()requirerequire("image.cv")first and are useful when OCR pipelines need to crop quadrilateral regions directly into tensorsbox_points()takes a rotated-box tensor shaped[5],[1, 5], or[N, 5]; it does not take five separate scalar argumentscreate_decoder()returns a decoder object with:decode(),:task(), and:schema()tracker()returns a tracker object with:update(),:reset(),:state(), and:close()records_from_boxes(),obb_records_from_rows(), andpoints_to_records()reshape tensor outputs into Lua-friendly record tablesproto_masks()andproject_masks()currently share the same implementation;project_masks()is an aliasmask_iou()computes the intersection-over-union between two masks directly, and also accepts a thirdoptsargument withcompare_size = true, or explicitwidth/heightdb_postprocess()is intended for DB / DBNet-style text-detection post-processing; each returned detection containsscore,points, andboxdecode_dense_detection()requiresopts.strides, and it must be a non-empty array of positive integers; it also requiresdecode_widthanddecode_height, and currently supports onlybox_encoding = "grid_center_log_wh"ctc_greedy_decode()supportsblank_index,merge_repeated,apply_softmax,return_probabilities, andcharsetctc_greedy_decode()always returnsindices;textappears only whencharsetis provided;confidenceappears only whenapply_softmaxorreturn_probabilitiesis enabled;probabilitiesandprobability_confidenceappear only whenreturn_probabilitiesis enablednms()androtated_nms()returnint64tensors with 1-based indicessample_logits()supportsargmax,temperature,top_k,top_p,min_p, andseedsample_logits()returns a scalar index for 1D logits, and anint64tensor for batched logits
Structured values
onnxruntime.value(value)onnxruntime.optional(value, type_info)onnxruntime.sequence(items)onnxruntime.map(key_type, value_type, pairs)onnxruntime.sparse_tensor(type, dense_shape, indices, values)onnxruntime.sparse_tensor_from_dense(tensor)
These are useful when model inputs or outputs are not plain tensors — for example optionals, sequences, maps, or sparse tensors.
The current behavior can be summarized like this:
onnxruntime.value(x)Ifxis already an ORT tensor / value / sequence / map / sparse tensor, it is returned as-is; ifxis a Lua table, it becomes asequence; otherwise the scalar is wrapped as a tensoronnxruntime.optional(value, type_info)The second argument is required;type_infomay be a string or a type-info table such as the result ofsession:input_info(...)/output_info(...); an empty optional is written asonnxruntime.optional(nil, type_info)onnxruntime.map(key_type, value_type, pairs)At the moment,key_typeonly supports"string"or"int64"onnxruntime.sparse_tensor(type, dense_shape, indices, values)Currently only numeric /boolsparse tensors are supported, built in COO form;indicesmay be flat or nestedonnxruntime.sparse_tensor_from_dense(tensor)Currently does not supportstringtensors
Common object methods:
value:type()/value:has_value()/value:get()sequence:length()/sequence:get(i)/sequence:items()map:get(key)/map:set(key, value)/map:keys()/map:pairs()sparse_tensor:dense_shape()/sparse_tensor:values()/sparse_tensor:indices()/sparse_tensor:format()/sparse_tensor:to_dense()
Sessions and inference
onnxruntime.session(model_path[, opts])onnxruntime.session_from_bytes(model_bytes[, opts])onnxruntime.run_options([opts])onnxruntime.load_custom_op_library(path)
Session objects handle model loading, input/output inspection, inference execution, and IOBinding. See the Session Module.
Supported element types
The tensor APIs currently support these type names:
"float32"/"float""float16""bfloat16""uint8""uint16""uint32""uint64""int8""int16""int32""int64""double"/"float64""bool""string"
Notes:
tensor_from_bytes()andcopy_from_bytes()only support numeric andbooltensorsbytes()is not available forstringtensorstensor:to("string")currently only supportsstring -> string
Provider notes
onnxruntime.providers() returns what the runtime reports as available, but the provider strings currently recognized by the session option parser are:
"cpu""coreml"
Notes:
provider/providersalso accept aliases such asCPUExecutionProviderandCoreMLExecutionProvider; they are normalized internally to"cpu"and"coreml"- If no provider is specified, or the provider list is empty, session creation appends the CPU provider automatically
- If the provider list contains
"coreml"andfallback_to_cpu = true, the implementation may also append CPU as a fallback path - If you pass
providers = {"coreml", "cpu"}, the session tries CoreML first and CPU second
Working with CoreML
If you want to reuse the coreml tokenizer or an MLMultiArray preprocessing pipeline, a common pattern is:
local ort = require("onnxruntime")
local tokenizer = assert(coreml.new_text_tokenizer({
type = "wordpiece",
vocab_path = XXT_HOME_PATH.."/models/demo/vocab.txt",
context_length = 52,
}))
local input_ids = assert(tokenizer:encode("hello", {
output = "ort_tensor",
}))
Or convert an existing MLMultiArray directly into an ORT tensor:
local ort = require("onnxruntime")
local tensor = assert(multi_array:to_ort_tensor("int64"))