GitHub Hot Board

GitHub Hot Board · Hồ sơ kho lưu trữ

receptron/laya

Run Laya, the open-source Jev-compatible System-1 decision model, from Node.js / TypeScript via ONNX Runtime (Mô tả đến từ chính kho lưu trữ.)

Dữ liệu tại October 25receptron

Thứ hạng tốt nhất

#50

Cột Mốc Trực Tiếp

985

Tổng sao

81

Tổng fork

2

Số ngày có mặt (30 ngày)

2 ngày trên bảng · +11 sao trong 30 ngày · ~+6/ngày

Trạng thái dự ánGiấy phép: MITPush gần nhất: October 17Issue mở (gồm PR): 5

Thu thập từ 2026-10-25; chưa rõ = chưa thu thập được

Gắn huy hiệu vào README của bạn · receptron/laya[![Gắn huy hiệu vào README của bạn](https://git.vaiox.xyz/api/badge/receptron/laya.svg)](https://git.vaiox.xyz/vi/repo/receptron/laya)
<a href="https://git.vaiox.xyz/vi/repo/receptron/laya"><img src="https://git.vaiox.xyz/api/badge/receptron/laya.svg" alt="Gắn huy hiệu vào README của bạn" height="20"></a>

Tài liệu dự án

@receptron/laya

Run Laya — the open-source, Jev-compatible System 1 decision model by Convai Innovations — from Node.js / TypeScript.

Laya does not generate text. You hand it a state (a ticket, an email, a JSON object) and typed questions, and it returns every answer with calibrated probabilities in one forward pass:

  • choice — pick one option, with a probability per option
  • score — an expected level on an ordered rubric, with the distribution
  • noul — a calibrated P(true) for a yes/no statement

This package runs the model with ONNX Runtime; PyTorch and Python are not needed at runtime. The request/response shape is the same as the Python reference implementation (RLAgent.system_one) and as TypeSafe Jev's system_one API, and the output matches the Python implementation to four decimal places.

Install

npm install @receptron/laya

Node.js 20 or newer; CI runs on Node 20, 22 and 24 (Linux, macOS, Windows). The @types/node version in devDependencies is only for type-checking this package and does not require Node 24.

The ONNX weights (about 1.7 GB, fp32) are downloaded from Hugging Face on first use and cached under ~/.cache/receptron-laya (override with LAYA_CACHE). Budget roughly 2 GB of RAM for the loaded model plus a few hundred MB per batch of questions.

The first Laya.load() therefore includes that download, so time it after the cache is warm. To fetch the weights ahead of time (in a build step or container image), call ensureBundle():

node -e 'import("@receptron/laya").then((m) => m.ensureBundle())'

Later loads only send a cheap freshness check and read from the cache (about 4 s on an Apple M4, measured in #13).

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", sales: "new purchases" },
    },
    urgency: {
      type: "score",
      instructions: "How urgent is this ticket?",
      criteria: ["not urgent", "somewhat urgent", "urgent", "critical"],
    },
    churn_risk: { type: "noul", instructions: "Is the customer likely to cancel or dispute?" },
  },
);

result.answers.department.choice; // "billing"
result.answers.department.probabilities; // { billing: 0.9415, support: 0.031, sales: 0.0275 }
result.answers.urgency.score; // 1.3886   (expected level, 0..3)
result.answers.churn_risk.noul; // 0.0988   (P(true))
result.answers.department.answer_confidence; // 0.9415   (max probability, on every answer type)
result.usage.input_tokens; // 267

await laya.close();

The answer types follow the question types, so result.answers.department is a ChoiceAnswer and result.answers.churn_risk a NoulAnswer without any casting.

To gate on confidence, use answer_confidence: the probability of the reported answer (max(p)), which is the quantity the checkpoint's temperatures are fitted for and means the same thing for every question type. confidence on choice / score answers is a different quantity (1 − normalized entropy).

Options

await Laya.load({
  modelDir: "./onnx", // use a local export instead of downloading (see below)
  repo: "receptron/laya-onnx", // Hugging Face repo that holds the ONNX bundle
  subfolder: "multilingual", // a checkpoint variant inside that repo
  revision: "main", // pin a commit hash for reproducible results; "main" follows the repo
  cacheDir: "/var/cache/laya",
  token: process.env.HF_TOKEN, // for private repos
  onProgress: ({ file, received, total }) => {}, // download progress
  executionProviders: ["cpu"], // onnxruntime-node execution providers
  sessionOptions: { intraOpNumThreads: 4 },
});

Every question of one systemOne call is batched into a single run; a call with three questions takes about 140 ms on an Apple-silicon CPU once the model is warm.

Exporting the ONNX bundle yourself

export/export_onnx.py turns the Hugging Face checkpoint (ModernBERT encoder + Laya's decision head) into one ONNX graph and copies the tokenizer and calibration values next to it. You only need this to build a bundle from a newer checkpoint or from a variant that is not published:

cd export
uv venv -p 3.12 .venv
uv pip install -p .venv/bin/python torch transformers safetensors onnx onnxscript onnxruntime huggingface_hub
.venv/bin/python -c "from huggingface_hub import snapshot_download; snapshot_download('convaiinnovations/laya', local_dir='model', allow_patterns=['model.safetensors','encoder/*','tokenizer/*','rl_agent_config.json','rl_common.py','rl_agent_api.py'])"
.venv/bin/python export_onnx.py model ../onnx   # prints the max logit difference vs. PyTorch (≈1e-5)

Then Laya.load({ modelDir: "./onnx" }). The bundle is the five files listed in BUNDLE_FILES: laya.onnx, laya.onnx.data, laya_config.json, tokenizer/tokenizer.json, tokenizer/tokenizer_config.json.

Limits

  • Each question's options must fit in head_max_len (192) tokens; systemOne throws otherwise. Fewer than about 20 options per choice question is the model's own recommendation.
  • The state is truncated to max_len (512 tokens for the English checkpoint) after the question header. A string or object state keeps its start; a list state (a conversation) keeps its newest end, as in training.
  • choice labels given as a list must be distinct; a repeated label throws instead of being merged.
  • Temperatures are clamped to [0.5, 5]. The published bundle uses 0.945 for choice questions with 11 or more options, where the upstream checkpoint ships 0.1006 (clamped to 0.5 by the Python laya package), so confidences for those questions differ from upstream by design.
  • A JSON state is serialized like Python's json.dumps(ensure_ascii=False) so that tokens match the reference implementation; non-integer numbers may format differently between JS and Python.

Development

yarn install
yarn test        # unit tests; the model test runs when ./onnx holds a bundle (or LAYA_MODEL_DIR)
yarn typecheck
yarn build
LAYA_MODEL_DIR=./onnx yarn example

License

MIT. The Laya model weights are published by Convai Innovations under Apache 2.0.

Thứ hạng hiện tại

  • 74

    Ngựa Ô

    985 sao · 81 fork · Star / ngày

    Ngựa ô →
  • 50

    Cột Mốc Trực Tiếp

    996 sao · 81 fork · Còn thiếu tới vạch

    Cột mốc →

Diễn biến 30 ngày

Tổng số sao

Diễn biến thứ hạng

Dự án tương tự · chủ đề chung

← Về bảng xếp hạng