Laya Node.js / TypeScript via ONNX
Run Laya from Node.js and TypeScript using ONNX Runtime, with the same typed-decision request and response shape.
npm install @receptron/layaThe ONNX weights are downloaded on first use. Budget memory for the model and question batches. To run Laya in the browser instead, onnx-community publishes fp32 and fp16 ONNX conversions of all three checkpoints for Transformers.js and WebGPU (onnx-community/laya-ONNX, laya-multilingual-ONNX, laya-typed-decisions-ONNX).
import { Laya } from "@receptron/laya";
const laya = await Laya.load();
const result = await laya.systemOne(state, questions);@receptron/laya runs Laya from Node.js and TypeScript with ONNX Runtime, so neither PyTorch nor Python is needed at runtime. The request and response shape matches the Python reference implementation and TypeSafe Jev's system_one API, and the project states that output matches the Python implementation to four decimal places.
Requirements
- Node.js 20 or newer.
- The ONNX weights (about 1.7 GB, fp32) download from Hugging Face on first use and are cached under
~/.cache/receptron-laya(override withLAYA_CACHE). - Budget roughly 2 GB of RAM for the loaded model, plus a few hundred MB per batch of questions.
Usage
import { Laya } from "@receptron/laya";
const laya = await Laya.load();
const result = await laya.systemOne(
{ subject: "Refund not received", body: "I cancelled two weeks ago and still have no refund..." },
{
department: {
type: "choice",
instructions: "Which team should handle this ticket?",
criteria: { billing: "payments, refunds, invoices", support: "product help and bugs" },
},
churn_risk: { type: "noul", instructions: "Is the customer likely to cancel or dispute?" },
},
);
result.answers.department.choice; // "billing"
result.answers.churn_risk.noul; // P(true)
await laya.close();
Answer types follow question types, so result.answers.department is typed as a ChoiceAnswer without casting.
Speed
Every question in one systemOne call is batched into a single run. The README reports about 140 ms for a three-question call on an Apple Silicon CPU once the model is warm.
Options
Laya.load() accepts a local modelDir, a Hugging Face repo and subfolder (for example the multilingual variant), a pinned revision for reproducible results, cacheDir, a token for private repos, download progress callbacks, and ONNX Runtime executionProviders and sessionOptions such as intraOpNumThreads.
You can also export your own bundle from a Hugging Face checkpoint with the included export/export_onnx.py; the script prints the max logit difference against PyTorch (about 1e-5).
Limits
- Each question's options must fit in
head_max_len(192 tokens);systemOnethrows otherwise. Keepchoicequestions under about 20 options. - The state is truncated to
max_len(512 tokens for the English checkpoint). - JSON states are serialized like Python's
json.dumps(ensure_ascii=False); non-integer numbers may format differently between JavaScript and Python.
Upstream also ships its own TypeScript package, laya-ts, inside the Laya repository, which is described as giving the same answers as the Python package.
Source: receptron/laya · MIT (model weights Apache 2.0).
Last verified against the project README: September 24, 2026.