OpenJev is live on the ParalonCloud API. POST /v1/classify takes a premise and a hypothesis and returns entailment, contradiction or neutral with calibrated probabilities, in one forward pass, no generated text. It runs on the same prlc_ key as chat, embeddings and images, with the same free trial. Model id: openjev-4b.
If you have been following the last week, you know why this exists. On 15 September TypeSafe AI launched Jev, the first of what they call System One models: instead of writing text, the model reads a state and answers typed questions with probabilities, 40 to 200 times faster than a frontier LLM on the same decision. Jev is hosted-only, closed weights, behind a waitlist. Within three days several open projects calling themselves OpenJev appeared, and the Hacker News thread on one of them went past 500 points. The one we serve is AlexWortega/openjev (MIT): Qwen3.5-4B with the language-model head replaced by a three-class head, trained as a natural language inference cross-encoder.
You still cannot run Jev locally. You can call this today, and you can run it yourself with the recipe at the end.
What it does, in one primitive
The model answers exactly one question: given the premise, is the hypothesis entailed, contradicted, or undetermined? Everything else is phrasing.
| you want | premise | hypothesis |
|---|---|---|
| rerank search results | the query | The correct answer is: {passage} |
| grade an answer | {question}\nReference answer: {reference} | Answer: {candidate} |
| guardrail a reply | the model's reply | This text reveals a customer's personal data |
| check RAG against sources | the retrieved document | each sentence of the generated answer |
| route a message | the user's message | The user wants a refund / …reports a bug / …asks about pricing |
| classify without training | the document | each label, written as a sentence |
Take the highest entailment probability, or threshold it. No prompt engineering for output format, no JSON to parse, no retries on malformed text.
Call it
curl https://paraloncloud.com/v1/classify \
-H "Authorization: Bearer $PARALON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openjev-4b",
"pairs": [
{"premise": "The invoice was paid on March 3rd by bank transfer.",
"hypothesis": "The invoice has been settled."},
{"premise": "The invoice was paid on March 3rd by bank transfer.",
"hypothesis": "The invoice is still open."}
]
}'
{
"object": "list",
"model": "openjev-4b",
"data": [
{"index": 0, "label": "entailment", "probs": [0.0004, 0.9871, 0.0125], "num_classes": 3},
{"index": 1, "label": "contradiction", "probs": [0.9612, 0.0031, 0.0357], "num_classes": 3}
],
"usage": {"prompt_tokens": 58, "total_tokens": 58, "completion_tokens": 0}
}
probs are [contradiction, entailment, neutral]. You can also send input as raw strings if you want to format the pair yourself; the model's own template is Premise: …\nHypothesis: …. Up to 256 items per request, 4,096 tokens each. In Python it is one requests.post; there is no SDK method to learn.
Measured
Everything below was run on 21 September 2026 against the public endpoint, from outside our network, with a premium key. The worker is a single RTX 4090 running vLLM 0.29 with the weights in FP8.
Latency through the public API
| request | time |
|---|---|
| one pair, p50 of 20 | 180 ms |
| 16 pairs in one request | 198 ms (12 ms per item) |
| 64 pairs | 322 ms (5 ms per item) |
| 256 pairs | 784 ms (3.1 ms per item) |
| one 533-token premise | 213 ms |
On the worker itself a single pair is 18 ms. The other ~160 ms of a single-item call is the round trip: edge, gateway, tunnel to the node and back. So the rule is simple: batch. 256 pairs in 784 ms is about 10,000 tokens per second through the public API, and a client that sends one item per request is paying for the network, not the model.
Accuracy on a 20-pair smoke set, against an LLM judge
We wrote 20 pairs that a naive classifier gets wrong: negations, a changed meeting day, a price that is off by 10×, a drug dose, a grading pair with a reference answer, a refund complaint against three routing hypotheses, a credential-leak guardrail, and one French premise with an English hypothesis. Then we ran the same 20 through qwen3.8-27b as a judge, with a short rubric and temperature: 0, one pair per request, the way people actually use an LLM as a judge.
| OpenJev 4B | Qwen 3.8 27B as judge | |
|---|---|---|
| correct | 18 / 20 | 18 / 20 |
| time for all 20 | 245 ms, one request | 5,765 ms, 20 requests |
| per item | 12 ms | 288 ms |
| tokens | 545 in, 0 out | 2,025 in, 74 out |
| list price for 1,000 verdicts | $0.0014 | $0.018 |
Same score. Both models called "the user reports a bug in the app" a contradiction of a refund complaint where we had written neutral; on reflection they have a point. The two real misses differ: OpenJev failed the cross-lingual pair (French premise, English hypothesis: contradiction at 0.61 where entailment was right), and the 27B judge missed the credential guardrail in the negative case (called "sunny skies all week" neutral for "reveals a credential" instead of contradiction). Twenty pairs is a smoke test, not a benchmark; the point is the shape of the trade: the same answers, 24× faster and 13× cheaper, for questions that have a closed answer.
Reranking, the case most people will use it for: five passages from our docs against "How do I stop billing on a GPU rental?" came back in the right order in 193 ms, with the DELETE /rentals/{id} passage first. The absolute entailment probability of the winner was only 0.12, though. On technical text the ordering is reliable and the raw number is not a confidence you should show a user.
Where it is honest about its limits
- English. The base model is multilingual, the NLI training is not. Our one cross-lingual pair failed; do not send it French and expect entailment.
- It decides, it does not explain. No reasoning, no "why". If you need the why, that is a chat model's job.
- Single items are network-bound. 180 ms of which 18 is inference. Batch.
- Text only. The v2 checkpoint can read images; we serve a text-only copy (see below). If image NLI matters to you, tell us.
- 4,096-token input, no Batch API line type yet, and the same rate limits as chat.
We have not measured it against Jev itself. TypeSafe's model is hosted behind a waitlist and, as commenters on Hacker News pointed out, its terms reportedly restrict public benchmarking. "OpenJev" is a name several projects share; this article is about the AlexWortega checkpoint served on our network, nothing else.
How we got it onto vLLM (and how you can)
This is the part that cost a day, so here it is for free. vLLM has no Qwen3_5ForSequenceClassification in its registry, but its _normalize_arch falls back to Qwen3_5ForCausalLM and the as_seq_cls_model adapter loads the score head from the checkpoint, so --runner pooling --convert classify is enough… almost. The v2 checkpoint carries the Qwen3.5 vision tower, and the text-only class has nowhere to put those 297 model.visual.* tensors:
ValueError: There is no module or parameter named 'visual' in Qwen3_5Model
The fix is a text-only copy. Download only the subfolder, drop the vision tensors, rename the language-model prefix, and declare the text architecture:
from huggingface_hub import snapshot_download
from safetensors import safe_open
from safetensors.torch import save_file
import json, shutil
snapshot_download("AlexWortega/openjev", allow_patterns=["qwen3.5-4b-nli-v2/*"], local_dir="oj")
src, dst = "oj/qwen3.5-4b-nli-v2", "openjev-text"
out = {}
with safe_open(f"{src}/model.safetensors", "pt") as f:
for k in f.keys():
if ".visual." in k:
continue
out[k.replace("model.language_model.", "model.")] = f.get_tensor(k)
save_file(out, f"{dst}/model.safetensors", metadata={"format": "pt"})
for fn in ("tokenizer.json", "tokenizer_config.json", "chat_template.jinja"):
shutil.copy(f"{src}/{fn}", f"{dst}/{fn}")
cfg = json.load(open(f"{src}/config.json")); cfg["architectures"] = ["Qwen3_5ForCausalLM"]
json.dump(cfg, open(f"{dst}/config.json", "w"))
vllm serve ./openjev-text --served-model-name openjev-4b \
--runner pooling --convert classify --quantization fp8 \
--max-model-len 4096 --max-num-seqs 16 --gpu-memory-utilization 0.8
curl localhost:8000/classify -H 'Content-Type: application/json' \
-d '{"model":"openjev-4b","input":["Premise: A man is playing a guitar.\nHypothesis: Someone is making music."]}'
7.9 GB in bf16, about 4 GB with --quantization fp8 at load, which is what lets it share a 16 GB card. On a 4090 in bf16 we measured 18 ms for one pair, 2.8 ms per pair in a batch of 64, and 74 ms for a 533-token premise. On our network this exact script runs once per node inside the worker's start command, then every restart goes straight to vllm serve.
Price and how to start
openjev-4b is billed per input token at $0.05 per million, nothing for output, from prepaid credits on a premium key. A free key's 250,000-token trial covers it too: that is roughly 9,000 pairs of the size above, no card. Sign in to the Console, create a key, and point at https://paraloncloud.com/v1/classify. The Classify docs have the full request shape and errors; if you are building RAG, it sits next to embeddings on the same key.
If you want a second model behind /v1/classify, the 0.8B checkpoint for phones and edge, or the image-capable variant, say so on Discord. The endpoint is model-agnostic; the model is the part we can change in an afternoon.



