prism-system-one
prism-system-one is a lightweight decision model: given a piece of text (the state) and one or more questions about it, it returns a typed answer with a probability for every option, in a single forward pass. It answers three kinds of questions:
| Type | Question | Answer |
|---|---|---|
noul |
a yes/no question | the probability of yes |
choice |
pick one of 2โ255 named options | the chosen option and a probability for each |
score |
place the state on an ordered scale of 2โ10 levels | the expected level, and a probability for each level |
It is fine-tuned from LiquidAI/LFM2.5-Encoder-230M on a mix of 292 public classification, judging, grounding and safety tasks in 15 languages. Requests and responses follow the format of TypeSafe's Jev API, so code written for that format can call this model. This is an independent project, not affiliated with TypeSafe or Liquid AI.
Status: preview. The results below are from held-out tasks and internal tests. The model has not yet been evaluated on public decision-model benchmarks.
Intended use
Fast, cheap, calibrated decisions inside software: routing, triage, tagging, moderation pre-filters, judging, extraction checks. Keep a person or a stronger model in the loop where a wrong answer is costly. It is not suitable for unreviewed high-stakes decisions about people, such as moderation enforcement, hiring, credit or medical decisions.
Model details
- Architecture: the first 11 of the 14 layers of LFM2.5-Encoder-230M (a bidirectional encoder mixing short convolutions and attention), chosen so the last layer is an attention layer, plus three linear heads (noul, choice and score). The parameter count stays just under 200M.
- How questions are read: inspired by marker-based extraction models such as GLiNER, each question becomes a marker token followed by its instructions, then one marker per option (
<|option|>for choice options,<|level|>for score levels) followed by that option's text. All questions come first, then the state after a<|document|>marker. Each head reads the hidden state at its question's markers: the noul head at<|noul|>, the choice head at each<|option|>, the score head at each<|level|>. Probabilities are a sigmoid (noul) or a softmax over the question's own markers (choice, score). - Many questions, one pass: all questions about a state are answered together, and each question's options only compete with each other.
- Marker safety: user text is tokenized with special-token splitting, so a string like
<|option|>inside the state, instructions or option names is treated as plain text and cannot create an answer slot. - Context: trained on inputs of at most 2,048 tokens; the released config accepts up to 8,192 tokens (the base encoder's context), but quality beyond 2,048 tokens is untested.
Usage
The repository contains the weights, the tokenizer, decision_model.py and the lfm2_encoder/ folder it needs. It is not a standard AutoModel; load it with the included code:
import sys
from huggingface_hub import snapshot_download
path = snapshot_download("paulprt/prism-system-one")
sys.path.insert(0, path) # makes decision_model.py importable
from modeling_prism import PrismDecisionModel
model = PrismDecisionModel.from_pretrained(path, device="cuda") # or "mps" / "cpu"
request = {
"state": "Hi, I was charged twice for order #4411 and need it fixed today.",
"questions": {
"urgent": {"type": "noul", "instructions": "Does this convey urgency?"},
"intent": {"type": "choice", "instructions": "What does the customer want?",
"criteria": {"refund": "money back for a charge", "bug": None, "other": None}},
"severity": {"type": "score", "instructions": "How severe is the issue?",
"criteria": ["low", "medium", "high"]},
},
}
print(model.predict([request])[0])
Requires torch, safetensors and a recent transformers release with LFM2 support.
Request format
state: a string, a JSON object (parts can be referred to in instructions, e.g.`hypothesis`), or a list of strings.questions: a map from your own question key to{"type", "instructions", "criteria"}.noul: nocriteria.choice:criteriais{option_key: description or null}or a list of option names (2โ255, unique).score:criteriais a list of level descriptions from lowest to highest (2โ10).instructions, descriptions and levels can be strings, objects or arrays; objects are serialised with sorted keys.
Response format
One response per request, keyed by your question keys (values below are illustrative):
{
"model": "prism-system-one",
"answers": {
"urgent": {"type": "noul", "noul": 0.54},
"intent": {"type": "choice", "choice": "refund",
"probabilities": {"refund": 0.49, "bug": 0.12, "other": 0.39}, "confidence": 0.23},
"severity": {"type": "score", "score": 0.82, "confidence": 0.30,
"legend": {"0": "low", "1": "medium", "2": "high"},
"probabilities": {"0": 0.32, "1": 0.53, "2": 0.15}}
},
"usage": {"input_tokens": 61}
}
scoreis the expected level, $\sum_i i \cdot p_i$, a number from 0 to the top level that can fall between levels. The most likely single level is the key with the highest probability.confidencefollows Jev's definitions. For choice, $\frac{p_{\max} - 1/K}{1 - 1/K}$. For score, $1 - \frac{\sum_i p_i,|i - m|}{\text{MAD}{\text{unif}}}$, where $m$ is the most likely level and $\text{MAD}{\text{unif}}$ is the same average distance for an even spread. Noul answers carry no separate confidence; the probability itself expresses it.
Refusals
predict raises ValueError instead of guessing when a request is invalid or too long: a score question with fewer than 2 or more than 10 levels, a choice question with fewer than 2 or more than 255 options (or duplicate options), an unknown question type, no questions, or an input longer than max_length. Inputs are never truncated at inference.
Training
- Data: a private dataset built from public sources: 9.75M examples from 292 tasks, about 43% noul, 38% choice and 19% score questions, with yes/no questions balanced to 45โ55% positive and correct choice options spread uniformly across positions. Labels come from people, votes, rules, tests or simulators, never from LLMs.
- Objective: the average over all questions of binary cross-entropy (noul) and cross-entropy (choice and score; soft targets where annotator vote shares exist), plus, for score questions, the expected distance from the true level as a fraction of the scale:
- Setup: one epoch; 512 examples per update (batches of 128, gradient accumulation 4); AdamW with learning rate 1e-4 for the encoder and 1e-3 for the heads, weight decay 0.1, 3% linear warmup then cosine decay; bf16; gradient checkpointing; batches grouped by length; inputs up to 2,048 tokens; choice options shuffled every time, score levels never reordered.
- Hardware: one NVIDIA RTX PRO 6000 (96 GB).
Evaluation
Held-out task families
Four task families were kept out of training entirely and used only for evaluation. Accuracy against chance level, with the model's average confidence:
| Task | Type | Questions | Accuracy | Chance | Mean confidence |
|---|---|---|---|---|---|
| cefr_sentence_level | noul | 1,079 | 67.6% | 50.0% | 62.7% |
| cefr_sentence_level | score | 1,498 | 28.2% | 16.7% | 25.4% |
| financial_tweet_topic | choice | 1,500 | 58.6% | 9.8% | 64.8% |
| financial_tweet_topic | noul | 1,134 | 83.2% | 50.0% | 85.7% |
| mt_bench_human_winner | choice | 1,500 | 56.7% | 33.3% | 50.5% |
| mt_bench_human_winner | noul | 973 | 72.1% | 50.0% | 63.5% |
| support_urgency | noul | 786 | 59.2% | 50.0% | 65.6% |
Every question type on every held-out task is above chance. Rule-defined labels (support urgency) and fine-grained ordinal levels (CEFR) remain the hardest.
In-distribution test
On 5,000 test examples from the training tasks (examples never seen in training): noul 86.5%, choice 84.0% and score 60.7% accuracy. The final test loss (the training objective above) was 0.52.
Calibration
Expected calibration error (lower is better), with no post-hoc scaling:
| Evaluation set | noul | choice | score |
|---|---|---|---|
| In-distribution test | 0.013 | 0.017 | 0.026 |
| Held-out task families | 0.025 | 0.035 | 0.055 |
Temperatures fitted on a separate calibration set were close to 1 (1.02, 1.02 and 1.15) and did not consistently improve these numbers, so the released model uses a temperature of 1.0 for every question type.
Base rates: the training and calibration data are balanced, so yes-probabilities assume roughly even odds. If yes is rare in your application (for example 8% for toxicity), adjust the logit $z = \log\frac{p}{1-p}$ by the log-odds of your base rate $\pi$:
Hand-written checks
On 33 hand-written requests covering support, reviews, safety, entailment, judging, code, scales and five non-English languages (included as test_examples.py), the model answered 83% of yes/no and 81% of choice questions as labelled, and 45% of score questions exactly (73% within one level). It refused all six invalid requests and treated injected marker strings as plain text. This set is small and its labels are the author's judgement; it is a smoke test, not a benchmark.
Public benchmarks
Not yet evaluated.
Limitations
- Urgency and pressure: judgements of urgency are weak (for example, "block my card right away" was rated not urgent), consistent with the held-out support-urgency task.
- Scale extremes: score predictions tend to drift towards the middle of the scale ("strong" read as "moderate", "very informal" as "informal"). The expected-distance term in the loss may contribute to this when the model is uncertain.
- Reasoning: arithmetic, reasoning about time ("the tallest until 1930") and combining several facts from the same state are unreliable; an encoder of this size classifies well but does not reason step by step.
- Long inputs: trained on at most 2,048 tokens.
- Languages: intent classification is weaker outside English than sentiment.
- Levels see each other: unlike Jev, which judges each score level on its own, this model reads all levels of a question together, so their order and wording can influence each other.
- Narrow held-out evidence: generalisation to new tasks was measured on four task families only.
- Balanced priors: see the base-rate adjustment above.
Training data notes
- Sources: all training data comes from public datasets whose licenses allow commercial use. Some are share-alike (CC-BY-SA, CDLA-Sharing), some copyleft (GPL, LGPL), and two are OpenRAIL++ with use-based restrictions.
- Overlap with benchmarks: some training sources (for example ESCI, BANKING77, CLINC and ARC) also appear in public decision-model benchmarks. Only their training splits were used; compare benchmark results with this in mind.
- Offensive content: the safety and toxicity tasks contain offensive, hateful and sexual text by design.
License
The model weights and the code in lfm2_encoder/ are a derivative of LFM2.5-Encoder-230M and are released under the LFM Open License v1.0. Commercial use is licensed only for organisations with less than $10M in annual revenue; larger organisations need a separate agreement with Liquid AI.
Citation
@misc{prism_system_one_2026,
title = {prism-system-one: a lightweight decision model},
author = {Peret, Paul},
year = {2026},
url = {https://huggingface.co/paulprt/prism-system-one}
}
@article{liquidAI2026Encoders,
author = {Liquid AI},
title = {LFM2.5-Encoders: Fast at Long Context, Even on CPU},
journal = {Liquid AI Blog},
year = {2026},
note = {www.liquid.ai/blog/lfm2-5-encoders}
}
Model tree for paulprt/prism-system-one
Base model
LiquidAI/LFM2.5-230M-Base