Evidence / Open models / Laya

What is Laya?

Laya is an open-weight decision model from Convai Innovations, released under Apache 2.0 on September 18, 2026. Like Jev, it takes a piece of text or JSON plus typed questions and returns Choice, Score, and Noul answers with probabilities instead of generated text.

It is not Jev. It is a separate model, a 421M-parameter encoder, built by a different company. TypeSafe didn't train, release, or endorse it. It copies Jev's question format and, optionally, its HTTP API. You can run it on your own CPU, NVIDIA GPU, or Mac.

Open source?Yes. Code and weights are Apache-2.0, commercial use allowed. The base model's training data and training script are not published.
Same model as Jev?No. Same question format, separate weights and training. Jev's internals aren't public, so how similar they are inside is unknown. On the same data, their answers differ.
Run it locally?Yes, offline after the first download (~808 MB for the English checkpoint). No GPU required.
Fastest way to try itpip install laya, then the short example below.
Current releaselaya 0.3.7 on PyPI (September 23, 2026), marked Beta. It went from 0.1.0 to 0.3.7 in five days, so pin the version.

Verified September 23, 2026, against the GitHub repository, the three Hugging Face model cards, PyPI, and the installed package. We also ran Laya ourselves; see install and self-hosting.

Who makes it

Convai Innovations publishes the weights on Hugging Face as convaiinnovations/laya ↗ and is the author of the laya package on PyPI ↗. The source lives at NandhaKishorM/laya ↗, the personal account of Nandakishor M, Convai's CEO according to that GitHub profile. There is no separate corporate repository.

“System 1” is Laya's own label, borrowed from the category TypeSafe named for Jev (see System One models). Sharing the vocabulary, and the Choice/Score/Noul format, tells you about the interface. It says nothing about shared internals.

Other things called Laya. The search results also contain aayushch/laya ↗, an unrelated notification app built on local LLMs, and LayaAir, a game engine. Several runtimes for Convai's model (laya-mlx, laya-coreml, @receptron/laya) come from independent developers. They're covered below.

Which Laya checkpoint to use

Three checkpoints, one family
CheckpointEncoder and sizeDefault context per questionUse it for
laya ↗
Router name: english
ModernBERT-large, 421M512 tokens, of which 192 are for the question and its optionsEnglish. The default choice.
laya-multilingual ↗
Router name: multilingual
mmBERT-base, 322M1,024 tokens (256 for the question)Anything that isn't English. It is faster, but weaker on English than laya.
laya-typed-decisions ↗
Router name: typed-decisions
ModernBERT-large, 421M1,024 tokens (256 for the question)Only the four workflows of the typed-decisions benchmark it was fine-tuned on. Its own card says to expect base-model quality, or worse, elsewhere.
01Sizes are whole models. 421M is the ModernBERT-large encoder (395M) plus Laya's decision head. We counted 421,293,827 parameters in the English checkpoint. 322M is mmBERT-base (307M) plus the head.
02“Up to 8k” is the encoder, not Laya. Both encoders accept 8,192 tokens. The checkpoints ship with the 512 and 1,024 settings above, and those include the state, the instructions, and every option. You can raise them at runtime with agent.cfg["max_len"]. The project hasn't published accuracy at longer settings.
03One repository holds all three. convaiinnovations/laya has the English weights at its root and the other two in multilingual/ and typed-decisions/ subfolders. The standalone repositories hold the same checkpoints. Only the checkpoint you load is downloaded.

What Router decides for you

The project recommends Router as the entry point. It picks a checkpoint per request, before the model runs, because the English checkpoint gives no warning when it can't read the input. On Khmer it scored 0.000 at 0.952 confidence, per the project's 51-language sweep.

It only chooses between english and multilingual. Non-Latin scripts go to multilingual. Latin-script text goes through a small word-list heuristic. When that heuristic can't tell, the text goes to default, which is "english".
!Short non-English Latin text often lands on English. In our run, “Esqueci minha senha” (Portuguese) and a Romanian question both routed to the English checkpoint. An open issue (#54 ↗) measured 64% of short German utterances going there on 0.3.4, costing about 20 accuracy points. If most traffic isn't English, use Router(default="multilingual"), pass lang=, or supply your own language detector via lang_guess=.
typed-decisions is never picked automatically unless you pass model="typed-decisions" or build the router with auto_task_detection=True. Even then it triggers only when your question IDs exactly match one of the benchmark's four workflows.
Memory and cold loads. Router() loads lazily and keeps two checkpoints resident. Router(preload=True), used in the project's quickstart, downloads and loads all three (about 1.16B parameters). With max_loaded=1, every language switch reloads a model, which the project measured at 7–10 seconds.

Install and run it

Checked against laya 0.3.7

Laya needs Python 3.10 or newer and installs PyTorch and Transformers as dependencies. It uses an NVIDIA GPU if present, then Apple-silicon GPU (MPS), then CPU.

Install
python3 -m venv .venv
.venv/bin/python -m pip install laya    # Python 3.10+; pulls in torch and transformers
laya_example.py
from laya import Router

router = Router()  # downloads and loads a checkpoint on first use

state = {"body": "We were billed twice for March. Refund the duplicate or we cancel."}
questions = {
    "team": {
        "type": "choice",
        "instructions": "Which team should handle this?",
        "criteria": {"billing": "charges, invoices, refunds",
                     "technical": "bugs and outages",
                     "sales": "pricing and new contracts"},
    },
    "urgency": {
        "type": "score",
        "instructions": "How urgent is this?",
        "criteria": ["not urgent", "soon", "blocking or deadline"],
    },
    "refund": {"type": "noul", "instructions": "The sender asks for money back."},
}

result = router.predict(state, questions)
a = result["answers"]
print(result["routing"]["model"])                     # english
print(a["team"]["choice"], a["team"]["confidence"])  # billing 0.9483
print(a["urgency"]["score"], a["refund"]["noul"])    # 1.7042 0.9115

We ran this exact script on a Mac against 0.3.7. The printed values are from that run and will differ slightly by hardware. Loading the English checkpoint prints a warning that one shipped temperature (for choices with 11+ options) was out of range and clamped, so confidence on those questions is uncalibrated. If laya.load() hangs, the project says to set USE_TF=0. The question format matches Jev's; see primitives for how Choice, Score, and Noul behave.

Self-host it behind Jev's API

The serve extra adds laya-serve, a FastAPI server for POST /v1/systemone that runs the Router. It is configured only by environment variables.

laya-serve
pip install "laya[serve]"
LAYA_HOST=127.0.0.1 LAYA_MODELS=english LAYA_API_KEY=change-me laya-serve
# POST http://127.0.0.1:8000/v1/systemone
BehaviorDefault in 0.3.7
Bind address0.0.0.0:8000, every network interface. Change with LAYA_HOST and LAYA_PORT.
AuthenticationNone. With LAYA_API_KEY set, it requires Authorization: Bearer <key>.
StartupPreloads all three checkpoints unless LAYA_MODELS lists fewer. Other variables: LAYA_DEVICE, LAYA_PRELOAD, LAYA_THREADS, LAYA_AUTO_TASK.
model fieldHonored only if it names a Laya checkpoint. Jev IDs like jev-latest are ignored and the Router picks.
Other routesGET /health. GET /v1/models returns 404.
We ran TypeSafe's SDKs against it. On September 23, 2026, TypeSafe's JavaScript SDK (0.6.0) and Python SDK (0.7.1), with only the base URL changed, each completed one Choice + Noul + Score request against a local laya-serve 0.3.7 running the English checkpoint, and parsed typed answers. Responses carry extra routing and action fields, which both SDKs tolerate. We didn't test streaming, retries, errors, concurrency, or the multilingual path.

That is SDK-level compatibility in the sense defined on open source. It is a wire contract, not equal behavior. Answers and probabilities come from Laya, so re-measure accuracy and thresholds when you switch.

On a Mac, in Node, or hosted

Only the first two rows are Convai's

Can I run Laya natively on my Mac? Yes, two ways. The official package runs on Apple silicon through PyTorch's MPS backend with no extra setup. For native MLX, there is an independent port.

RuntimeWhoRuns onNotes
laya (Python)Convai · Apache-2.0CPU, CUDA, Apple MPS · Python 3.10+Reference implementation. All three checkpoints, Router, fine-tuning.
laya-serveConvai · same packageSame as aboveJev-shaped HTTP. The repo also ships a Nix flake and a Docker quickstart.
laya-mlx ↗Independent · Apache-2.0Apple silicon · macOS 14+ · Python 3.11+Native MLX, no PyTorch. Uses Convai's original weights, converted to MLX format without retraining (aac6fef/laya-mlx and siblings), or loads the original IDs. All three checkpoints and a Router adapted from upstream. No training.
@receptron/laya ↗Independent · MITNode.js 20+ via ONNX RuntimeEnglish checkpoint by default, exported to ONNX, about 1.7 GB (fp32) on first use. Choice, Score, Noul. The project says output matches Python to four decimals.
impossiblThird-party hostedTheir serversLinked from Laya's README as a free, Jev-compatible endpoint. Not local, and your data leaves your network.

laya-mlx reports 13.4 ms (English) and 7.4 ms (multilingual) median for one short question on an M3 Max with 40 GPU cores, excluding model load. Those are the project's own measurements on that machine. It says it matched upstream's selected answer on 63 of 63 validation questions per checkpoint. The same developer publishes a Core ML port, laya-coreml, which we haven't checked.

How Laya works

These details come from the model cards and the package source. Laya is a bidirectional encoder with a small decision head. It never generates tokens.

01One sequence per question. For each question, Laya builds a sequence from the state, the instructions, and one [MASK] marker per option. All of a request's questions run as one batched forward pass, but each re-encodes the state. More questions means more compute, and the state is truncated separately in each.
02Options are scored where they sit. A two-layer transformer head scores each option at its marker, and a softmax over those scores gives the probabilities. Options are defined per request, so new labels need no retraining. If the options don't fit the question budget, the call fails.
03Answers follow Jev's shape. Choice returns a label and probabilities. Score returns the expected level on a zero-based rubric. Noul returns P(true), rendered internally as a two-option true/false question. Laya's confidence is entropy-based, not the chosen option's probability: a 0.71/0.29 choice reported confidence 0.13 in our run.
04Temperatures adjust the probabilities. Each checkpoint carries temperatures per question type and option count. Since 0.3.5 they're clamped to 0.5–5 at load.

What this does and doesn't tell you about Jev. TypeSafe hasn't published Jev's architecture, parameter count, or training data. Laya isn't a reconstruction of Jev. It is one design that implements the same interface. Output that always parses isn't the same as a correct answer: Laya can be confidently wrong, as the English checkpoint is on non-English text.

Base checkpoints vs. the fine-tuned one

Laya's training method is called RLCD, the same name TypeSafe uses for Jev's (see RLCD). Laya's version is described in its model card: the model outputs a distribution, noise is added for exploration, and the reward is a proper scoring rule, with a policy-gradient update. Whether TypeSafe does the same thing isn't public.

!The 0.766 headline is fine-tuned, on that benchmark's own training split. laya-typed-decisions was trained on 1,200 cases of the synthetic typed-decisions ↗ benchmark, then scored 0.766 on its 400-case test split. That benchmark's gold labels come from a small teacher model, so its card says scores measure agreement with the teacher, not correctness. The base checkpoints score 0.362 and 0.342 zero-shot, below the 0.461 you'd get by always guessing each question's most common answer. The project itself calls Laya “a fast base to specialise, not a zero-shot decision engine.”

What's published for your own training: a Kaggle notebook that fine-tunes on two free T4 GPUs (the project says 4–5 hours for about 30,000 questions), fits temperatures, and pushes to Hugging Face. The 0.3.7 notes say it now fits calibration on a held-out slice, though the README's fine-tuning section still says those samples come from training items. The data and script that produced the base checkpoints are not published; an open issue asking for them was answered with the fine-tuning notebook.

Calibration: fit it yourself

Laya's pages say “mathematically calibrated.” The project's own measurements are narrower than that, and they vary by checkpoint and task.

FindingSource
Both general checkpoints ship over-confident. Refitting one temperature per question type and option count on held-out data moved mean ECE 0.466 → 0.081 (English) and 0.314 → 0.106 (multilingual).Project, own suites
The multilingual checkpoint ships with no fitted temperatures. The typed-decisions checkpoint's temperatures were fitted on training data, so its card says to treat its confidence as uncalibrated.Model cards
On a zero-shot routing task, a contributed test found Laya under-confident instead.Project's BENCHMARKS.md
On a sentiment set, raw ECE was 0.107 for Laya and 0.151 for Jev on the same 600 items.Anthus, independent
action.act_probability reads 1.0 for almost every input and carries no usable signal.Project, issue #185 (open)

So the direction of the error depends on your task. Fit temperatures on held-out examples from your own workload, then pick thresholds on validation data. The README's 0.85 gating example is an illustration, not a recommended cutoff.

Known limits

The ones that change a decision
LimitEvidenceWorkaround
Choices with many optionsDocumented. All options share the 192–256-token question budget, so 77 labels get 3–4 tokens each. Banking77: 0.425 (project), 38.2% (independent).Stay under ~20 options, raise head_max_len, split into coarse and fine questions, or use predict_shortlist.
Short contextDocumented. The English checkpoint leaves about 320 tokens for the state; longer state is truncated.Pass only the fields a question needs, or test longer max_len settings on your data.
Noul follows its labelsDocumented and open (#156). A true/false or yes/no pair can decide the answer regardless of the state, most strongly on the English checkpoint.Check Noul on your data. If stuck, ask a two-option Choice with neutral keys (A/B).
Score is the weakest primitiveDocumented (SST-5: 0.372). The multilingual checkpoint almost never picks the first-listed level (#131, open).Route English Score questions to english; validate the rest.
Wrong-language routingReported in #54 and reproduced by us on 0.3.7 for short Portuguese and Romanian text.default="multilingual", lang=, or your own detector.
Weak zero-shot on new workflowsDocumented. Base checkpoints below majority-class on typed-decisions. Held-out toxicity moderation: 0.530.Fine-tune, or evaluate before relying on it.

“Documented” means the project states it in its README or model cards. Issue numbers refer to the Laya repository ↗, checked September 23, 2026. We haven't measured these ourselves except where noted.

Laya vs. Jev

The stable differences first. These don't depend on a benchmark.

DimensionLayaJev
Weights and licensePublic, Apache-2.0Not released. Hosted-use license only.
Where it runsYour hardware, offline if you wantTypeSafe, OpenRouter, Vercel, or Cloudflare
Context512 or 1,024 tokens per question, options included32k for state plus longest question; 64k per request
Options per ChoiceLimited by token budget; project advises under ~20Up to 255
LanguagesEnglish checkpoint plus a multilingual one, chosen by RouterTypeSafe says English is strongest
APIPython API, plus Jev-shaped HTTP via laya-servePOST /v1/systemone and SDKs
Fine-tuningYes, notebook publishedNo. The terms also bar distilling it.
CalibrationYour job: fit temperatures on your dataTrained for it, per TypeSafe; still validate thresholds
CostNo fees; you pay for hardware and upkeepPer input token; see pricing

Independent head-to-heads

We found two public comparisons that ran both models on the same items. Neither is ours.

Study and taskSampleLayaJev
Dhruv Mehra · AG News, 4 labels50090.6% · ECE 0.05684.3% · ECE 0.112
Dhruv Mehra · SST-2, 2 labels50092.0% · ECE 0.03295.4% · ECE 0.026
Dhruv Mehra · Banking77, 77 labels50038.2% · ECE 0.51176.4% · ECE 0.125
Anthus · sentiment, constructed corpus600 held out72.2% · ECE 0.10776.8% · ECE 0.151

Dhruv Mehra (September 22) used the English checkpoint on an Apple-silicon Mac and Jev 1.13 through OpenRouter, with identical questions. AG News is in Laya's training mix, according to the project's benchmark script, so that lead is partly in-distribution. Anthus (September 21) used Jev 1.13.0 from TypeSafe and the English checkpoint through laya-mlx 0.1.0; its Brier scores were nearly equal (0.189 vs. 0.188). Latency isn't comparable in either study, because Laya ran locally and Jev over the network. Four results on four tasks don't pick a winner. They do agree with the project on one point: Laya falls well behind on many-label choices.

How to read Laya's own Jev table

Laya's README and model card lead with a “Laya vs TypeSafe Jev” table. The project states that it has no TypeSafe API access and never ran Jev. Every Jev figure is copied from someone else's study. Here is where each row comes from.

RowLaya figureJev figureWhy it isn't like-for-like
typed-decisions0.7660.727Laya fine-tuned on this benchmark's training split; Jev zero-shot, from the dataset's leaderboard.
AG News · Emotion0.950 · 0.5950.910 · 0.480Laya: 400 examples each, and AG News was in its training mix. Jev: 100 examples each, from AbdelStark's pilot. Prompts differ, as the project notes.
Banking770.425 (77 labels)0.870 (72 labels)Different label sets and samples. Laya's table labels this row as Jev's lead.
ECE0.0810.246Laya after fitting temperatures on its own suites; Jev as returned, from a different benchmark (nibzard).
Latency, “7.8× faster”32.8 ms236–276 msLaya in-process on a T4 GPU; Jev over the internet including the network round trip.

The project does disclose most of this in its notes, and its README lists where Jev leads. The headline table and chart don't carry those caveats, and several articles repeat them without the notes. Treat the table as a list of pointers to other studies, not as one controlled run. For Jev's own evidence, see benchmarks.

Laya, hosted Jev, or neither

If you needLean toward
Data that never leaves your hardware, or offline useLaya. Budget time for evaluation and temperature fitting.
A model trained on your own labelsLaya, which is where the project says its value is.
Long documents, or dozens of options per questionHosted Jev (API & access), unless you can split the task to fit Laya's budget.
Good zero-shot results on a new task, with nothing to operateHosted Jev, then check it on a labeled sample. Neither is reliable everywhere.
Plain classification and you have labeled dataPossibly neither. A fine-tuned DistilBERT beat both on AG News and Banking77 in Dhruv Mehra's run. See classification.

Other open models and servers that copy Jev's interface, and what TypeSafe itself has open-sourced, are on Is Jev open source?

Not affiliated with, endorsed by, or operated by TypeSafe AI. Vendor claims are cited and attributed.