Laya

Laya is a small open model that decides instead of writing. You give it a piece of text and a few typed questions — yes/no, pick one, or a position on a scale — and it answers each with probabilities in a fraction of a second. TurboLLM runs it on its own Laya engine (Windows, macOS and Linux, on CPU or GPU), beside your chat model, and serves it in a playground and at POST /v1/systemone. This page walks through it from nothing to a working answer.

The exact model page

The model is https://huggingface.co/convaiinnovations/laya. In TurboLLM you refer to it as convaiinnovations/laya. That is the one repo this page was written and tested with, and the one that carries both checkpoints (English and multilingual).

Hugging Face also has GGUF conversions of Laya. Don't use those: they need a different runtime that llama.cpp can't load, and TurboLLM marks them as not loadable.

What Laya is

Laya is a System One decision model (Apache-2.0). It doesn't chat and it writes no prose: one pass over your text gives you a typed answer for every question you asked. The three question types are the ones on the Jev page, and the request and response use the same field names, so anything you write against one works against the other.

TypeYou askYou get
noulA yes/no questionA number between 0 and 1: the probability of yes
choicePick one from options you nameThe chosen option and a probability for every option
scoreWhere the text sits on an ordered scale you describeA score (the probability-weighted level) and a probability for every level

Laya or Jev?

TurboLLM serves both at /v1/systemone. They differ in how they run:

LayaJev
Runs onIts own Laya engine: Windows, macOS, Linux; CPU or GPUvLLM: Linux or WSL2, NVIDIA GPU
Model sizeAbout 1.5 GB (English and multilingual checkpoints)About 9 GB for the tested 4B checkpoint
Chat while it is loadedStill available. Laya loads beside your chat model.Workspace shows only the Jev Playground
Who works out the numbersLaya itself. TurboLLM passes the answers through.TurboLLM, from NLI entailment scores

Before you start

What has and hasn't been tested

Everything on this page, including every screenshot and number, was run on Windows with an NVIDIA GPU (CUDA). macOS (Apple GPU), Linux and CPU-only installs of the Laya engine haven't been verified yet, and the engine is marked experimental. They are built to work, but treat them as untested.

Set it up, step by step

  1. Install the Laya engine

    Open Engines, find the Laya card (“System One decision models”) and press Install. TurboLLM sets up an isolated Python environment for it and picks the PyTorch build that matches your machine, so this can take a while. The card shows progress.

    Do this before downloading the model. Until the Laya engine is installed, TurboLLM doesn't show a Laya model in your library.

    TurboLLM Engines screen: the Laya engine card with its Compatible badge, pros and cons, and the Install button, dark modeTurboLLM Engines screen: the Laya engine card with its Install button, light mode

    Laya is never the “active” engine, so you won't be asked to activate it, and your chat engine stays as it is. A Laya model simply always runs on the Laya engine.

  2. Find the exact model

    Open Models → Discover and search for laya. Pick convaiinnovations/laya, at the top of the results. You don't need to switch engines: the screenshots were taken with llama.cpp as the active chat engine.

    Or skip the search: press the link icon next to the search box (Import from URL) and paste the exact address:

    https://huggingface.co/convaiinnovations/laya
    localhost:6996
    TurboLLM Models, Discover tab, searching for laya: convaiinnovations/laya is the first result, followed by other repositories with laya in the name, dark modeTurboLLM Models, Discover tab, searching for laya, light mode
    Only this repo

    The search also lists other repos with “laya” in the name (other projects, and conversions). Pick convaiinnovations/laya exactly. Its name and the Download Laya model button are how you know you have the right one.

  3. Download it

    The repo panel says “Laya decision model — runs on the Laya engine” and shows the size (about 1.5 GB). Press Download Laya model. TurboLLM fetches the English and multilingual checkpoints together, as one folder named laya in your models folder. Progress shows in Downloads.

    localhost:6996
    The convaiinnovations/laya panel in Discover: the description, the total size, and the Download Laya model button, dark modeThe convaiinnovations/laya panel in Discover with the Download Laya model button, light mode
  4. Load it

    When the download finishes, open the Library tab. The row is named laya and carries a LAYA badge. Press Load. On the test machine it was ready in under ten seconds.

    Models library with the laya model row: LAYA badge, fp16, 1.5 GB, context 512, and a Load button, dark modeModels library with the laya model row and its Load button, light mode

    Once it is running the row turns green and the button becomes Eject:

    The laya model row while running, with a green dot, the word running, and an Eject button, dark modeThe laya model row while running, with an Eject button, light mode

    If you started the load from this browser, a toast appears with an Open playground button. TurboLLM never navigates for you.

    A toast reading laya is ready, with an Open playground button, dark modeA toast reading laya is ready, with an Open playground button, light mode

    Your chat model is not unloaded. Laya loads into its own slot beside it, and Chat, Code and Routines all keep working. For as long as Laya is loaded, the Workspace sidebar shows a link to the playground:

    The Workspace sidebar with the Chat, Code and Routines tabs and a link reading laya, Open playground, dark modeThe Workspace sidebar with a link reading laya, Open playground, light mode
  5. Ask it something in the playground

    Open the playground from the toast or the sidebar link. Press Run and you get answers for the example that is already there.

    localhost:6996
    The playground with the laya model running: a support-ticket state and three questions on the left, and the answers with probability bars on the right, dark modeThe playground with the laya model running, light mode

    It is the same JSON-first playground as the Jev Playground, and its parts work the same way:

    • Header. laya · Laya · running, and under it Checkpoints: english, multilingual.
    • Two editors that are the request. state is the text the questions are about (JSON, or plain text, which is sent as a string). questions is the JSON map of questions. What you type is exactly what gets sent.
    • Run (or Ctrl+Enter, Cmd+Enter on macOS). Nothing is sent until you run.
    • Answers. One card per question: the yes/no number, the chosen option with every option's probability, or the scale score with every level's probability.
    • Response and curl tabs. The raw JSON that came back, and the exact curl for the request you just ran, ready to copy into your own code.
    • Examples dropdown, for a support ticket with all three question types and other ready-made inputs.
  6. Try another language

    Laya carries a multilingual checkpoint and chooses between the two itself. Paste text in another script into state and run. Here the state is Hindi (“I was charged twice in March, please refund the duplicate amount”) and the questions are still in English:

    localhost:6996
    The playground with Hindi text in the state editor and English questions; the answers show refund about 0.99 and billing 0.95, and the footer says answered by the multilingual checkpoint, dark modeThe playground with Hindi text in the state editor, answered by the multilingual checkpoint, light mode

    The footer reads answered by the multilingual checkpoint. The response's routing block names the checkpoint and why it was chosen. See Which checkpoint answered.

To unload Laya, press Eject on its row in Models. Nothing is deleted.

Use it from your own code

POST /v1/systemone is on the same address and port as the rest of TurboLLM's API (http://localhost:6996 by default). For a Laya model the request is exactly the one described on the Jev page: state, model and a map of questions, each with a type, instructions and (for choice and score) criteria. The field names follow TypeSafe AI's public System One API.

On Windows PowerShell?

The curl tab uses bash quoting. In PowerShell 5.1, use the Python or JavaScript tab instead, or save the JSON to a file and run curl.exe http://localhost:6996/v1/systemone -H "Content-Type: application/json" -d "@request.json".

This is the request the playground runs for its support-ticket example:

curl http://localhost:6996/v1/systemone \
  -H "Content-Type: application/json" \
  -d @- <<'EOF'
{
  "model": "laya",
  "state": "I've been unable to connect my payment provider for three days and the integration keeps failing. I'm losing sales, please help as soon as possible.",
  "questions": {
    "urgent": { "type": "noul", "instructions": "Does the message convey urgency?" },
    "team": {
      "type": "choice",
      "instructions": "Which team should handle this message?",
      "criteria": {
        "billing": "Payment, invoices, refunds or subscription charges",
        "technical": "Bugs, outages or integration problems",
        "sales": "Pricing, plans, upgrades or discounts"
      }
    },
    "mood": {
      "type": "score",
      "instructions": "What is the customer's tone?",
      "criteria": [
        "Calm, just asking or stating facts",
        "Mildly annoyed but polite",
        "Clearly frustrated",
        "Very angry, strong language"
      ]
    }
  }
}
EOF

# Only when Require API key is on, add:
#   -H "Authorization: Bearer <your key>"
import requests

headers = {"Content-Type": "application/json"}
# headers["Authorization"] = "Bearer <your key>"  # only when Require API key is on

resp = requests.post(
    "http://localhost:6996/v1/systemone",
    headers=headers,
    json={
        "model": "laya",
        "state": "I've been unable to connect my payment provider for three days and the integration keeps failing. I'm losing sales, please help as soon as possible.",
        "questions": {
            "urgent": {"type": "noul", "instructions": "Does the message convey urgency?"},
            "team": {
                "type": "choice",
                "instructions": "Which team should handle this message?",
                "criteria": {
                    "billing": "Payment, invoices, refunds or subscription charges",
                    "technical": "Bugs, outages or integration problems",
                    "sales": "Pricing, plans, upgrades or discounts",
                },
            },
            "mood": {
                "type": "score",
                "instructions": "What is the customer's tone?",
                "criteria": [
                    "Calm, just asking or stating facts",
                    "Mildly annoyed but polite",
                    "Clearly frustrated",
                    "Very angry, strong language",
                ],
            },
        },
    },
)
if not resp.ok:
    raise RuntimeError(resp.json()["error"]["message"])

body = resp.json()
answers = body["answers"]
print("urgent", answers["urgent"]["noul"])
print("team", answers["team"]["choice"], answers["team"]["probabilities"])
print("mood", answers["mood"]["score"])
print("answered by", body["routing"]["model"], "-", body["routing"]["reason"])
const res = await fetch("http://localhost:6996/v1/systemone", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    // "Authorization": "Bearer <your key>", // only when Require API key is on
  },
  body: JSON.stringify({
    model: "laya",
    state: "I've been unable to connect my payment provider for three days and the integration keeps failing. I'm losing sales, please help as soon as possible.",
    questions: {
      urgent: { type: "noul", instructions: "Does the message convey urgency?" },
      team: {
        type: "choice",
        instructions: "Which team should handle this message?",
        criteria: {
          billing: "Payment, invoices, refunds or subscription charges",
          technical: "Bugs, outages or integration problems",
          sales: "Pricing, plans, upgrades or discounts",
        },
      },
      mood: {
        type: "score",
        instructions: "What is the customer's tone?",
        criteria: [
          "Calm, just asking or stating facts",
          "Mildly annoyed but polite",
          "Clearly frustrated",
          "Very angry, strong language",
        ],
      },
    },
  }),
});
if (!res.ok) throw new Error((await res.json()).error.message);

const { answers, routing } = await res.json();
console.log("urgent", answers.urgent.noul);
console.log("team", answers.team.choice, answers.team.probabilities);
console.log("mood", answers.mood.score);
console.log("answered by", routing.model, "-", routing.reason);

The real response to that request, unedited (Windows, 2026-09-25):

{
  "model": "laya|laya|1486444724",
  "answers": {
    "urgent": {
      "type": "noul",
      "noul": 0.7621,
      "confidence": 0.7621,
      "answer_confidence": 0.7621,
      "action": { "act_probability": 1 }
    },
    "team": {
      "type": "choice",
      "choice": "billing",
      "probabilities": { "billing": 0.5867, "technical": 0.219, "sales": 0.1943 },
      "confidence": 0.1227,
      "answer_confidence": 0.5867,
      "action": { "act_probability": 1 }
    },
    "mood": {
      "type": "score",
      "score": 1.8595,
      "legend": {
        "0": "Calm, just asking or stating facts",
        "1": "Mildly annoyed but polite",
        "2": "Clearly frustrated",
        "3": "Very angry, strong language"
      },
      "probabilities": { "0": 0.0206, "1": 0.1974, "2": 0.6838, "3": 0.0981 },
      "confidence": 0.3595,
      "answer_confidence": 0.6838,
      "action": { "act_probability": 1 }
    }
  },
  "usage": { "input_tokens": 222, "output_tokens": 0 },
  "routing": { "model": "english", "reason": "English Latin text" }
}

Laya put this ticket about a failing payment integration under billing (0.59) rather than technical (0.22). That is the real result, not a tidied one. It is a reason to run Laya on your own messages and read the numbers before you rely on them. See What the numbers are.

The response fields

FieldDescription
modelThe id of the model that answered.
answers.<id>One entry per question, under the ids you chose. type is noul, choice or score.
noulYes/no: the probability of yes, 0 to 1.
choice, probabilitiesPick one: the chosen option, and a probability for every option (they sum to 1).
score, legend, probabilitiesScale: the probability-weighted level, the level descriptions you sent (keyed by index), and a probability for every level.
confidenceLaya's own measure for that answer. It is a different number from the confidence TurboLLM works out for a Jev model, so don't compare them.
answer_confidence, action.act_probabilityExtra fields Laya adds. In the runs on this page, answer_confidence was the yes number for a yes/no question, the winning option's probability for a pick-one, and the probability of the level nearest the score for a scale. act_probability was 1 every time. Don't build on either without checking them on your own data.
usageinput_tokens as Laya counted them, and output_tokens, which is always 0.
routingWhich checkpoint answered and why. Only on Laya responses. See below.

Which checkpoint answered

The laya folder holds two checkpoints, and Laya picks one for each request. routing.model is english or multilingual, and routing.reason says why. The two reasons seen in the runs above:

Staterouting.modelrouting.reason
EnglishenglishEnglish Latin text
Hindimultilingualnon-Latin script (devanagari, 100% of letters); the English checkpoint cannot read it

This is the same Hindi request as the screenshot, and its real response:

{
  "model": "laya|laya|1486444724",
  "answers": {
    "refund": { "type": "noul", "noul": 0.9889, "confidence": 0.9889, "answer_confidence": 0.9889, "action": { "act_probability": 1 } },
    "department": {
      "type": "choice",
      "choice": "billing",
      "probabilities": { "billing": 0.9493, "technical": 0.0054, "sales": 0.0453 },
      "confidence": 0.8019,
      "answer_confidence": 0.9493,
      "action": { "act_probability": 1 }
    }
  },
  "usage": { "input_tokens": 117, "output_tokens": 0 },
  "routing": {
    "model": "multilingual",
    "reason": "non-Latin script (devanagari, 100% of letters); the English checkpoint cannot read it"
  }
}

The request behind it had "model": "laya", the Hindi sentence as state, and two English questions: a noul (Does the customer ask for a refund?) and a choice between billing, technical and sales.

How fast

On the machine these numbers came from (Windows, NVIDIA GPU, 2026-09-25), the first request, which had to load Laya, took about 9 seconds. Once it was loaded, requests took 0.27 to 0.36 seconds end to end over HTTP, for the English ticket above and for the Hindi one. That is one machine and a few requests, not a benchmark.

Errors you may meet

Status, codeMeaning
400 laya_model_wrong_endpointYou called a chat, embeddings or messages endpoint with the Laya model. It only answers /v1/systemone.
404The model name matches nothing in your library.
422 invalid_requestThe request broke a rule (a missing field, a question with no criteria, too many questions, and so on). The message names the field.
503Laya isn't loaded and Auto model-swap is off. Load it from Models.
502 engine_errorThe Laya engine itself returned an error. The message says what it reported.

What the numbers are, and what they aren't

Troubleshooting

What you seeWhat to do
The Laya model isn't in your library after the downloadInstall the Laya engine first (step 1). Until it is installed, TurboLLM doesn't show a Laya model. Then check the Library tab again.
The engine install failsThe Laya card shows the error. The install needs internet access and several GB of free disk. Fix that and press Install again.
You downloaded a GGUF or other conversion and it won't loadThose conversions use a runtime llama.cpp can't load, and TurboLLM marks them as not loadable. Download convaiinnovations/laya instead (huggingface.co/convaiinnovations/laya).
Chat says the model can't chatRight: Laya only answers System One questions. Chat with your chat model. Laya loads beside it, so both are available.
The first API call is slowWith Auto model-swap on, that call loads Laya. Later calls are quick. Load it from Models first to avoid the wait.
Delete is refusedEject the model first. A loaded model can't be deleted.

Next

POST /v1/systemone →

The full request reference: every field, every limit and how question types work.

Jev →

The other System One model TurboLLM serves, on vLLM, with /v1/classify and /v1/rerank.

Run any engine →

How engines work in TurboLLM, and where the Laya engine fits.

The model page →

Laya's own model card on Hugging Face: convaiinnovations/laya.