Documentation CLI & model reference
ReleasesGitHub

onnx-genai

ONNX Runtime GenAI Inference Engine

Usage:  onnx-genai -s -m chat_completion_model -e embedding_model -p port 

 -m path     : chat completion model
 -e path     : embedding model (pooling=mean)
 -r path     : rerank model
 -T path     : text to speach model
 -D path     : System One decision ONNX model (Kev, d1, LiquidAI d1, English Laya or Strands Decider v1, text only)
 -t path     : chat template
 -j          : chat template from stdin
 -d          : pooling=e2e 
 -b          : pooling=multi-vector 
 -l          : pooling=last-token
 -c          : pooling=cls
 -s          : server
 -p          : server listening port (default=8080)
 -h host     : server host (default=127.0.0.1)
 -i          : input
 -o          : output (default=stdout)
 -           : use stdin for input

The CLI is built for 4 platforms:

Dependencies

The bundled ONNX Runtime macOS library targets macOS 13.3 or later. Other dependencies may impose higher deployment requirements. GenAI and Extensions are separate libraries and retain the versions listed above.

OpenAI Compatible Endpoints

Cohere Compatible Endpoints

MongoDB Compatible Endpoints

[!TIP] The input_type property has no special effect. You must specifically add the prefixes “Represent the query for retrieving supporting documents: “ and “Represent the document for retrieval: “ if required by the model. https://www.mongodb.com/docs/

TypeSafe Compatible Endpoint

Load one decision model independently of chat, embeddings, reranking and speech:

onnx-genai -s -D /models/kev-0.6b-ONNX/onnx/model_q4.onnx
# Same adapter for kev-4b-ONNX:
onnx-genai -s -D /models/kev-4b-ONNX/onnx/model_q4.onnx
# d1 q8:
onnx-genai -s -D /models/d1-3B-ONNX/onnx/decoder_model_merged_quantized.onnx
# LiquidAI d1-2B or d1-Omni-2B q8 (text only):
onnx-genai -s -D /models/d1-2B-ONNX/onnx/decoder_q8.onnx
# Laya English encoder:
onnx-genai -s -D /models/laya-onnx/laya.onnx
# Strands Decider v1 q8 (fused readout, not a causal-LM export):
onnx-genai -s -D /models/strands-decider-2B-qwen3.5-v1-2610-onnx/onnx/model_q8.onnx

Supported exports: Kev-0.6B, Kev-4B, d1-3B, d1-2B, d1-Omni-2B, Laya English, and Strands Decider v1. These are decision models, not chat or embedding models; do not load them with -m, -e or -r.

For Kev/d1, keep config.json and tokenizer.json in the model directory, with the selected graph and all its external data files in onnx/. They may alternatively all be placed in one directory. Kev, d1 and Strands are identified by exactly one of kev, d1 or decider metadata in config.json, respectively (LiquidAI d1 by d1_attention), not the directory name or model_type. Kev uses the selected graph directly. d1 additionally loads the matching embed_tokens_quantized.onnx or embed_tokens_q4.onnx beside its selected decoder. The text-only adapter does not load the vision encoder.

LiquidAI’s own d1 exports, d1-2B and d1-Omni-2B (text only), are identified by d1_attention in config.json and are served as backend d1 too (d1-latest). Keep config.json, tokenizer.json, tokenizer_config.json and calibration.json at the repository root, with the selected onnx/decoder[_q4|_q8].onnx and all of its .onnx_data* shards beside it; the vision and audio encoders are not needed. A state and up to d1_set_size (16) questions are packed into one decoder row and read in a single pass without a cache (“set” attention: each question attends to the state and itself, the state reads every question). Answers therefore differ slightly from asking each question alone (at most about 0.02 in probability on the d1-2B q8 checks, with no change of decision). Prompts, option codes (d1_codes), readout tokens and the calibration.json temperature (per question bucket, else default) follow the checkpoint’s published reference code. Typed questions (text, number, date, box, boxes, multiple choice), the calibration.json tables and picture, video or audio input are not supported. d1-Omni-2B uses the same adapter with an empty audio input. decoder_q8 is verified on CPU; decoder_q4 also targets CPU, while the f16 decoders are meant for GPUs.

Strands uses the selected fused graph directly: onnx/model_q8.onnx needs onnx/model_q8.onnx_data (~1.7 GB); model.onnx and model_q4f16.onnx likewise need their corresponding external data. Keep the export’s tokenizer assets and configuration, not those from a differently named checkpoint. The official v1 checkpoint is a rank-48 LoRA plus dedicated option-scoring head on Qwen3.5-2B-Base; the community export fuses both. Official adapter-only weights and older hobson-v19/v21 exports are not interchangeable with this fused v1 layout.

The Laya adapter runs the 421M-parameter ModernBERT-large-based encoder plus decision head on CPU, English only. Use the community ONNX bundle receptron/laya-onnx pinned to revision d42786bdff8a7550316339c5fbf8f46caa83ea1b; preserve its layout:

laya-onnx/
  laya.onnx
  laya.onnx.data
  laya_config.json
  tokenizer/
    tokenizer.json
    tokenizer_config.json

laya_config.json alongside the selected graph identifies the native Laya backend. Both tokenizer files are required; external laya.onnx.data must stay beside the graph. Backend selection distinguishes Kev, D1, Laya and Strands; ambiguous Kev/d1/Strands config.json metadata mixed with Laya metadata is rejected, not resolved by preferring one backend. No backend flag is needed. This supports the shipped English ONNX export, not the multilingual checkpoint. An independent CPU comparison against official convaiinnovations/laya revision 7b928d828b7b0e022f929d9bd2e44165aa270148 measured a maximum raw-logit difference of 2.58e-5 in a four-row mixed-question batch using PyTorch 2.15.0 and ONNX Runtime 1.29.0. This is a bounded smoke comparison, not universal 1e-5 parity or model-quality validation. Published temperatures in laya_config.json are consumed as-is and must be finite and positive. In particular, choice:11+ = 0.945 is the community export’s calibration, not the official checkpoint’s 0.10058280825614929; probabilities for those questions deliberately follow the published ONNX bundle rather than the original checkpoint.

Runtime requirement: the published d1 export uses ONNX IR 13. The bundled ONNX Runtime has been upgraded to 1.29.0 in both the C++ build dependencies and the macOS/Windows deployment directories, so a runtime override is no longer needed. Older installations using 1.23.2 cannot load this graph. Laya and Strands use the same bundled CPU runtime 1.29.0; neither requires a runtime version bump.

For deployment, keep the 1.29.0 runtime alongside the rebuilt executable (on Windows, deploy its corresponding provider DLLs too). System One still requires an executable rebuilt from the updated source; replacing a runtime library alone does not add the endpoint to an older executable. Prefer Kev q4, Strands q8 and d1 q8 for initial CPU evaluation; other export precisions depend on runtime/kernel support. Probabilities may differ across quantizations and runtime versions. Quantized Kev probabilities can also vary slightly between a packed request and the same questions evaluated separately, despite the graph’s branch isolation.

curl http://127.0.0.1:8080/v1/systemone \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "kev-latest",
    "state": {"message": "I was charged twice. Please refund the extra charge."},
    "questions": {
      "refund": {"type": "noul", "instructions": "Is a refund requested?"},
      "team": {
        "type": "choice",
        "instructions": "Which team should handle this?",
        "criteria": {"billing": "Payments and refunds", "technical": "Software faults"}
      },
      "urgency": {
        "type": "score",
        "instructions": "How urgent is this?",
        "criteria": ["Routine", "Urgent", "Emergency"]
      }
    }
  }'

Use kev-latest for Kev, d1-latest for d1, laya-latest for Laya, strands-decider-latest for Strands, or the model ID returned by GET /v1/models (the model directory’s basename). Family aliases only resolve to the loaded backend (kev, d1, laya or strands-decider); an unknown model is rejected. The response contains model, answers keyed by question name, and usage with input_tokens and output_tokens: 0. Noul returns noul (probability of true); Choice returns choice, probabilities and confidence; Score returns a zero-based expected score, legend, probabilities and confidence. Laya uses this same response schema; no act fields are added.

Confidence follows TypeSafe’s documented formulas: Choice measures the largest probability above a uniform distribution, and Score measures probability-weighted distance from the modal level. A single option/level has confidence 1. These are distribution statistics, not guarantees of accuracy or Jev-equivalent calibration. Strands divides each option logit by decider.temperature_by_kind[type] (falling back to decider.temperature) before softmax; missing, nonpositive or nonfinite effective temperatures fail model loading. It does not generate answer letters or apply training-time ordinal smoothing at inference.

The endpoint accepts string/object/array state and structured instructions/descriptions. It rejects images, assets, box, unsupported fields, duplicate JSON keys and inputs exceeding limits:

Limit Value
JSON body 2 MiB
Named questions 1–64
Choice options 1–255
Score levels Kev/d1/Laya: 1–10; Strands: 2–10 (upstream schema)
Kev state and each state-plus-question row Model metadata, capped at 8,192 tokens
Kev complete packed request 8,192 tokens
d1 each complete question prompt Model context, capped at 8,192 tokens
d1 sum of question prompt tokens 32,768 tokens
LiquidAI d1 each packed row (state plus up to d1_set_size questions) 8,192 tokens; fewer questions go in a row when needed
LiquidAI d1 sum of packed row tokens 32,768 tokens
Laya complete question row (max_len in config) 512 tokens
Laya head (head_max_len in config) 192 tokens
Laya each option 48 tokens
Laya padded question batch 32,768 tokens
Strands each complete state-plus-question prompt decider.max_length (v1: 4,096), capped at 8,192 tokens
Strands sum of complete prompt tokens 32,768 tokens

Over-limit inputs are rejected, not truncated. Kev shares the state within a packed graph run. d1 and Strands evaluate each question independently, with fresh caches (Strands’ empty caches are inside the graph); their input usage counts repeated state tokens. Mixed question kinds and option counts do not share padding or logits. Strands follows the upstream engine’s strict-window path: the export’s max_question_fraction is a truncation policy, not an additional strict-mode limit, and is not applied. The exported models’ long-context behavior is not necessarily validated up to these serving limits.

Laya constructs each row in the reference order [CLS] type question: instructions [SEP] [MASK] options [SEP] state [SEP]. Structured state uses insertion-ordered JSON with Python-style spacing; structured instructions additionally use ASCII JSON escapes, as in the Python reference. Structured option descriptions use ordered JSON as an API extension to the reference’s text descriptions. Literal [MASK] in caller content is replaced with a space so it cannot inject option markers. It follows the reference equal-budget rule for options, but rejects the request if any option would need shrinking (including to meet the 48-token option cap). The remaining question/instruction head capacity is max(8, head_max_len - sum(option tokens including markers)); a head that would need truncation is rejected too. State plus the complete head and separators must fit max_len = 512. These are reject-not-truncate limits, not permission to silently shorten instructions, options or state. Question rows are batched with right padding; the marker-position tensor has width at least 2. The padded batch must fit 32,768 tokens, while usage.input_tokens sums the unpadded row lengths (including repeated state). The existing 1–64 question, 1–255 Choice option and 1–10 Score level limits remain unchanged for Laya.

Invalid requests return HTTP 422 with a detail array, an unloaded decision model returns 503, and inference failures return 500. Errors are logged. Decision inference has its own mutex and does not repurpose the other model slots. Without -s, -D selects decision evaluation from -i/stdin, with -o for a JSON response file; failures return a nonzero exit status. If both -m and -D are supplied in CLI mode, decision evaluation takes precedence.

Kev, the English Laya weights and Strands Decider (including the community fused v1 export) are Apache-2.0 licensed. d1 uses the LFM Open License v1.0, including commercial-use restrictions; review it before deploying. LiquidAI’s d1-2B and d1-Omni-2B exports use the same license.

Strands calibration is fitted per primitive on held-out short classification, not on arbitrary traffic or every quantization. The export author’s limited 11-case CPU comparison reports maximum probability differences against the upstream torch engine of 0.0021 (FP32, no argmax changes), 0.0504 (q8, no argmax changes), and 0.2074 (q4f16, one argmax change). Classification agreement is not numerical parity or evidence that confidence thresholds remain calibrated. Local q8 native/Python ORT 1.29.0 parity passed the basic three-question and structured five-question requests with exact token IDs/readout positions and a largest displayed probability difference of 1e-8 on the pinned export above. This is adapter parity, not a fresh official torch comparison. Windows and native 4D Strands execution remain unverified here. See the focused checks for pinned revisions, local results and unverified paths.

Converted ONNX Models

Quantisation

The fp32 format is accurate but consumes 4 bytes per weight and pretty slow on a CPU. It is generally not suitable for production. You should only use it as a reference.

The fp16 format consumes 2 bytes per weight. The CPU backend may be forced to perform calculations in float32 except on a CPU like Apple Silicon that has native 16-bit maths which is not as fast as an NVIDIA GPU. It is usually best to avoid this format on a CPU.

The int8 format takes advantage of NEON instructions on Apple Silicon and AVX2 AVX-512 VNNI instructions on Intel or AMD to accelerate maths. For encoders, the accuracy drop is said to be negligible ( less than 1%). You should always use the int8 format on a PC or Mac with no GPU.

The int4 format is designed to compress large language models. Just as a reference, a 7B parameter in native float32 format would requires 28GB of memory, and on a CPU the data must go through the processor for every single token generation. int4 reduces the bandwidth by 8. The format internally groups multiple weights (e.g. 32) to share a scale factor to maintain accuracy. However the quantisation is less precise compared to a GGUF (llama.cpp) model of a similar size.

Rerank

  fp16 fp32 int8 max_position_embeddings hidden_size num_hidden_layers
cross-encoder/ms-marco-MiniLM-L6-v2 45 91 23 512 384 6
cross-encoder/mmarco-mMiniLMv2-L12-H384-v1 235 470 118 512 384 12
BAAI/bge-reranker-v2-m3 1140 2270 569 8192 1024 24
BAAI/bge-reranker-base 556 1110 278 8192 768 12
BAAI/bge-reranker-large 1120 2240 561 8192 1024 24
jinaai/jina-reranker-v1-turbo-en 75 151 38 8192 384 6
jinaai/jina-reranker-v3     598 131072 1024 28
ibm-granite/granite-embedding-reranker-english-r2 299 599 150 8192 768 22
hotchpotch/japanese-reranker-tiny-v2 58 117 29 8192 256 3
hotchpotch/japanese-reranker-xsmall-v2 73 147 37 8192 256 10
hotchpotch/japanese-reranker-small-v2 140 280 70 8192 384 13
hotchpotch/japanese-reranker-base-v2 265 530 133 8192 512 19
cl-nagoya/ruri-v3-reranker-310m 630 1260 316 8192 768 25
Qwen/Qwen3-Reranker-0.6B     598 32768 1024 28
Qwen/Qwen3-Reranker-4B     4030 40960 2560 36
zeroentropy/zerank-2     4030 40960 2560 36
lightonai/ColBERT-Zero 298 596 151 8192 768 22

Embedding

  fp16 fp32 int8 max_position_embeddings hidden_size num_hidden_layers pooling
jhu-clsp/mmBERT-small 282   141 8192 384 22 mean
jhu-clsp/mmBERT-base 616   308 8192 768 22 mean
answerdotai/ModernBERT-base 298 596 151 8192 768 22 mean
answerdotai/ModernBERT-large 789 1580 397 8192 1024 28 mean
perplexity-ai/pplx-embed-v1-0.6b     614 32768 1024 28 mean
BAAI/bge-small-en-v1.5 66 133 33 512 384 12 cls
BAAI/bge-base-en-v1.5 278 435 116 512 768 12 cls
BAAI/bge-large-en-v1.5 668 1340 335 512 1024 24 cls
BAAI/bge-m3 1130 2270 568 8192 1024 24 cls
intfloat/e5-small-v2 66 133 33 512 384 12 mean
intfloat/e5-base-v2 218 435 109 512 768 12 mean
intfloat/e5-large-v2 668 1340 335 512 1024 24 mean
intfloat/multilingual-e5-small 235 470 118 512 384 12 mean
intfloat/multilingual-e5-base 555 1110 278 512 768 12 mean
intfloat/multilingual-e5-large 1120 2240 560 512 1024 24 mean
nomic-ai/nomic-embed-text-v1 274 547 138 8192 768 12 mean
nomic-ai/nomic-embed-text-v1.5 274 547 138 8192 768 12 mean
Snowflake/snowflake-arctic-embed-s 66 133 33 512 384 12 cls
Snowflake/snowflake-arctic-embed-l 668 1340 336 512 1024 24 cls
sentence-transformers/all-MiniLM-L6-v2 45 90 22 512 384 6 mean
sentence-transformers/all-MiniLM-L12-v2 66 133 33 512 384 12 mean
google/embeddinggemma-300m 607 1210 309 2048 768 24 mean
retrieva-jp/amber-base 264 529 133 8192 512 19 meqn
retrieva-jp/amber-large 629 1260 316 8192 768 25 mean
Alibaba-NLP/gte-base-en-v1.5 278 556 146 8192 768 12 cls
Alibaba-NLP/gte-large-en-v1.5 873 1750 445 8192 1024 24 cls
Alibaba-NLP/gte-multilingual-base 628 1260 340 8192 768 12 cls
Alibaba-NLP/gte-modernbert-base 298 596 150 8192 768 22 cls
sbintuitions/modernbert-ja-30m 73 147 37 8192 256 10 mean
sbintuitions/modernbert-ja-70m 140 280 70 8192 384 13 mean
sbintuitions/modernbert-ja-130m 264 529 133 8192 512 19 mean
sbintuitions/modernbert-ja-310m 629 1260 316 8192 768 25 mean
cl-nagoya/ruri-v3-30m 73 147 37 8192 256 10 mean
cl-nagoya/ruri-v3-70m 140 280 70 8192 384 13 mean
cl-nagoya/ruri-v3-130m 264 529 133 8192 512 19 mean
cl-nagoya/ruri-v3-310m 629 1260 316 8192 768 25 mean
cl-nagoya/ruri-base-v2 221 442 111 512 768 12 mean
cl-nagoya/ruri-large-v2 673 1350 338 512 1024 24 mean
ibm-granite/granite-embedding-small-english-r2 95 190 48 8192 384 12 cls
ibm-granite/granite-embedding-english-r2 298 596 150 8192 768 22 cls
ibm-granite/granite-embedding-30m-english 60 120 30 512 384 6 cls
ibm-granite/granite-embedding-125m-english 248 496 125 512 768 12 cls
ibm-granite/granite-embedding-107m-multilingual 213 427 107 512 384 6 cls
ibm-granite/granite-embedding-278m-multilingual 555 1110 278 512 768 12 cls
Alibaba-NLP/gte-Qwen2-1.5B-instruct     1680 32768 1536 28 last-token
Alibaba-NLP/gte-Qwen2-7B-instruct     7210 32768 3584 28 last-token
sbintuitions/sarashina-embedding-v1-1b     1230 8192 1792 24 last-token
sbintuitions/sarashina-embedding-v2-1b     1230 8192 1792 24 last-token

Chat Completion

  int4 max_position_embeddings hidden_size num_hidden_layers
MadeAgents/Hammer2.1-0.5b 864 32768 896 24
meta-llama/Llama-3.2-1B-Instruct 1860 8192 2048 16
meta-llama/Llama-3.2-3B-Instruct 3650 131072 3072 28
microsoft/Phi-4-mini-instruct 4860 131072 3072 32
microsoft/Phi-3.5-mini-instruct 2720 131072 3072 32
microsoft/Phi-4-mini-reasoning 4860 131072 3072 32
microsoft/Phi-4-reasoning 1090 32768 5120 40
microsoft/phi-4 1090 16384 5120 40
microsoft/Phi-4-reasoning-plus 1090 32768 5120 40
google/gemma-3-4b-it 5380 131072 2560 34
google/translategemma-4b-it 5380 131072 2560 34
google/gemma-3-1b-it 1900 32768 1152 26
google/gemma-3-270m-it 906 32768 640 18
google/functiongemma-270m-it 906 32768 640 18
google/gemma-2-2b-it 4010 8192 2304 26
google/gemma-2-2b-jpn-it 4010 8192 2304 26
ibm-granite/granite-3.0-2b-instruct 1990 4096 2048 40
ibm-granite/granite-3.3-2b-instruct 2020 131072 2048 40
ibm-granite/granite-3.1-8b-instruct 5980 131072 4096 40
ibm-granite/granite-3.2-8b-instruct 5980 131072 4096 40
ibm-granite/granite-3.3-8b-instruct 5980 131072 4096 40
ibm-granite/granite-3.2-2b-instruct 2020 131072 2048 40
ibm-granite/granite-3.1-2b-instruct 2020 131072 2048 40
ibm-granite/granite-3.0-8b-instruct 5920 4096 4096 40
utter-project/EuroLLM-1.7B-Instruct 1920 4096 2048 24
utter-project/EuroLLM-9B-Instruct 7490 4096 4096 42
h2oai/h2o-danube-1.8b-chat 1430 16384 2560 24
h2oai/h2o-danube2-1.8b-chat 1430 8192 2560 24
PleIAs/Pleias-RAG-1B 1290 4096 2048 22
PleIAs/Baguettotron 353 4096 576 80
deepseek-ai/deepseek-coder-1.3b-instruct 1080 16384 2048 24
OpenLLM-France/Lucie-7B-Instruct-v1.1 5110 32000 4096 32
HuggingFaceTB/SmolLM2-1.7B 1470 8192 2048 24
01-ai/Yi-Coder-1.5B-Chat 1440 131072 2048 24
OpenLLM-France/Claire-7B-FR-Instruct-0.1 6920 2048 4544 32
tiiuae/Falcon3-7B-Instruct 7460 32768 3072 28
tiiuae/Falcon3-3B-Instruct 3230 32768 3072 22
tiiuae/Falcon3-1B-Instruct 1670 8192 2048 18
Qwen/Qwen3-4B-Instruct-2507 4210 262144 2560 36
Qwen/Qwen2.5-1.5B-Instruct 1920 32768 1536 28
Qwen/Qwen2.5-7B-Instruct-1M 7120 1010000 3584 28
Qwen/Qwen2.5-3B-Instruct 3190 32768 2048 36
Qwen/Qwen2.5-1.5B 1920 131072 1536 28
Qwen/Qwen2.5-3B 3190 32768 2048 36
Qwen/Qwen2.5-7B 6670 131072 3584 28
Qwen/Qwen3-1.7B 2340 40960 2048 28
Qwen/Qwen3-4B-Thinking-2507 4210 262144 2560 36
elyza/Llama-3-ELYZA-JP-8B 6800 8192 4096 32
tokyotech-llm/Llama-3.1-Swallow-8B-Instruct-v0.3 6800 8192 4096 32
Rakuten/RakutenAI-7B-chat 5290 32768 4096 32
Rakuten/RakutenAI-7B-instruct 5290 32768 4096 32
rinna/llama-3-youko-8b-instruct 6800 8192 4096 32
rinna/gemma-2-baku-2b-it 4010 8192 2304 26
rinna/youri-7b-instruction 4660 4096 4096 32
rinna/youri-7b-chat 4660 4096 4096 32
cyberagent/calm2-7b-chat 5300 32768 4096 32
deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B 1970 131072 1536 28
deepseek-ai/DeepSeek-R1-Distill-Qwen-7B 6670 131072 3584 28
deepseek-ai/DeepSeek-R1-0528-Qwen3-8B 7290 131072 4096 36