News & Updates8 min read

OpenJev Is Live on an OpenAI-Compatible API: an Open Jev Alternative You Can Call Today

TypeSafe's Jev is hosted-only and behind a waitlist. OpenJev, the open NLI cross-encoder built on Qwen3.5, is now served on ParalonCloud behind POST /v1/classify: a label and calibrated probabilities per input, 3 ms per item in a batch, no generated text. Measured against a 27B LLM judge on the same pairs, with the vLLM recipe so you can run it yourself.

Three indicator bars in front of a graphics card, only the middle one lit emerald: one decision, no text

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 wantpremisehypothesis
rerank search resultsthe queryThe correct answer is: {passage}
grade an answer{question}\nReference answer: {reference}Answer: {candidate}
guardrail a replythe model's replyThis text reveals a customer's personal data
check RAG against sourcesthe retrieved documenteach sentence of the generated answer
route a messagethe user's messageThe user wants a refund / …reports a bug / …asks about pricing
classify without trainingthe documenteach 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

requesttime
one pair, p50 of 20180 ms
16 pairs in one request198 ms (12 ms per item)
64 pairs322 ms (5 ms per item)
256 pairs784 ms (3.1 ms per item)
one 533-token premise213 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 4BQwen 3.8 27B as judge
correct18 / 2018 / 20
time for all 20245 ms, one request5,765 ms, 20 requests
per item12 ms288 ms
tokens545 in, 0 out2,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.

Keep reading

Related Articles

The Paralon capybara seated as a judge with a glowing gavel, weighing two floating sheets on a holographic balance
Guides & Tutorials
12 min

LLM-as-a-Judge with an Open Model: 990 Planted Errors, 99.6% Caught, and What the Rubric Changes

We used Qwen 3.8 27B over an OpenAI-compatible API as a judge of dataset labels, and scored it against errors we planted ourselves so every number is exact. With a written rubric the judge caught 491 of 493 wrong labels and also rejected 58 labels the dataset called correct, 43 of them the same systematic mistake in the generator. Without the rubric it agreed with the dataset more and missed 20 planted errors. The rubric is not a tuning knob; it decides what the judge measures.

LLM-as-a-judgeevaluationdata quality
The Paralon capybara holding a magnifying lens up to a floating cloud of glowing connected dots
Guides & Tutorials
11 min

Semantic Search with an Open Embeddings API: 990 Tickets, 5 Languages, and Where Keyword Search Still Wins

We indexed 990 support tickets with a 384-dimension open embedding model over an OpenAI-compatible /v1/embeddings endpoint and searched them 1,290 ways, scored against known intents and a TF-IDF keyword baseline. Same-language, keyword search was better. Across languages it collapsed to chance while embeddings held 47 to 58% precision. Adding a 27B reranker over the top ten lifted every language by 17 to 37 points for $0.09 per thousand queries. The whole index cost a tenth of a cent.

embeddingssemantic searchRAG
The Paralon capybara sorting a stream of glowing paper sheets into a row of green trays
Guides & Tutorials
13 min

Document Classification with an Open LLM API: 7,218 Documents, No Training Data, $0.05 per Thousand

We classified the full 20 Newsgroups test split with Qwen 3.8 27B over an OpenAI-compatible API, zero-shot, ten documents per request, with the label set enforced by a JSON schema. 72% accuracy on twenty classes with no labeled data, 70,000 documents an hour on one key, and a third of all errors inside three categories that overlap by definition. Few-shot examples doubled the cost and moved accuracy half a point.

text classificationzero-shotstructured output