Skip to content
MrJev

JEV-CPU

A CPU port of SemIf that swaps only the model loader and reuses the scoring code unchanged, so you can read a decision out of a small model's option logits on a laptop with no GPU.

View on GitHub →

Hands-on review

A CPU port of SemIf that swaps the loader and nothing else. It ran offline on a laptop CPU in about a second — with the accuracy a 0.6B model buys.

Good for

  • Trying the read-the-logits pattern with no GPU and no account
  • A port that changes the loader and leaves the scoring code alone
  • Decisions in about a second on an ordinary CPU, fully offline

Watch out for

  • A 0.6B model: upstream's own table puts it far below the 4B and Jev
  • Upstream SemIf added its own llama.cpp CPU backend the day after this
  • Comments, UI labels and output are in Korean

Tested Sep 22, 2026 at b49b5bf5776a · python:3.13 + CPU torch in Docker with --network none, its 22 tests and a real decision from a cached Qwen3-0.6B

How we reviewed this: we ran its tests and then a real decision in --network none with a locally cached Qwen3-0.6B, and diffed its vendored SemIf engine against upstream to check the “unchanged” claim. We made no Jev calls; this project makes none by design.

What it is

SemIf reads a decision out of a model’s option logits — no answer sentence, no JSON to repair, no decoding loop — and targets a CUDA GPU holding a 4B model. JEV-CPU’s observation is that the GPU is forced in exactly one place:

if not torch.cuda.is_available() or torch.cuda.device_count() != 1:
    raise ValueError("Expose exactly one CUDA GPU ...")
...
dtype=torch.bfloat16, device_map={"": "cuda:0"}   # ← GPU pinned

Everything downstream follows device = next(model.parameters()).device, and torch.cuda.synchronize is already guarded. So JEV-CPU swaps in a CPU float32 loader and reuses the rest.

It does what it says

In a container with no network at all:

[load] Qwen/Qwen3-0.6B @ c1899de…  (CPU / float32)
[load] done in 2.7s (params=0.60B)

=== decision: route ===
  → billing   100.0%  ████████████████████████
    tech        0.0%
    sales       0.0%
  (forward 0.5s, 116 tok, readout: native full-vocabulary
   last-position logits restricted to declared answer slots)

Half a second for a routing decision on an ordinary CPU, and the readout line states the mechanism rather than asserting it. 22 tests pass, 1 skipped.

The “unchanged engine” claim

The README says src/semif_phase1/ is the “Upstream SemIf engine, unchanged”. Diffing it against upstream’s current main shows five files differing, which looks damning until you check which direction the changes run:

difference whose
a synchronize(device) helper replacing inline CUDA guards upstream’s, added with Apple Silicon support
an MPS-specific looped path in shared.py upstream’s, same commit
llamacpp_backend.py missing entirely upstream’s, added 2026-09-21

All of it landed upstream on 21–22 September, after this fork. JEV-CPU’s own edits are the CUDA guards that let the scoring run on a CPU at all. The claim is accurate for the commit it vendored; it is just that upstream moved in the same week.

Which is the thing to know before installing

Upstream SemIf added its own llama.cpp CPU backend — “for direct, serial, and shared scoring” — on 21 September, one day after this repository was created. So the gap JEV-CPU exists to fill has largely closed at the source, by a different contributor, while this was being written.

That takes nothing away from the work: the observation was right, the port is clean, and it arrived first. But if you are choosing today, check whether upstream’s own CPU path does what you need before adding a fork to your dependencies.

What a 0.6B model costs you

This is the caveat the CPU story buys, and the repository ships the evidence itself. From the vendored upstream README, on a 102-row subset — these are SemIf’s own measurements, not ours:

system authored balanced accuracy perturbation TypeSafe subset agreement
Qwen3-0.6B (Q8_0) 0.440 0.528 0.407
MiniCPM5-2B 0.686 0.693 0.637
Qwen3.5-4B 0.813 0.766 0.845
published Jev 0.883

The model JEV-CPU runs on your CPU is the top row. It demonstrates the pattern beautifully — you can watch a decision come out of the logits in a second, on a laptop, with nothing installed but torch — and on the authors’ own numbers it agrees with the reference far less often than the 4B does.

So read this as a way to understand and try the technique, not as a local replacement for a hosted decision model. The repository does not claim otherwise; it is simply the number a reader most needs and it sits in a vendored file rather than the front page.

Things to know

The shim’s comments, the web UI labels and the CLI output are in Korean (→ 선택: is “choice”). Everything is legible without it, but as with JevLoop, the reasoning lives in the comments.

The package is installable (pip install -e .) and its tests need that or PYTHONPATH=src; there is no documented test command, which cost us a run. The model revision defaults to main, so a fully offline run needs QWEN_REV pinned to a cached commit.

MIT, fourteen stars, three days old. The independence notice is properly done: not affiliated with or endorsed by SemIf’s author, TypeSafe, or Jev.

Verdict

A good, small, honest piece of work: it found the single line that forced a GPU, changed that line, and left the scoring alone — and we could confirm all three.

Install it to see the pattern without a GPU or an account, which is genuinely worth an afternoon. Do not install it expecting the 4B’s answers on a laptop; the repository’s own table says what the 0.6B gets you.

And check upstream first, which now has a CPU backend of its own.

For the same read-the-logits idea at a larger scale, see SemIf; for an open model reproduction with its own published protocol, von.

See how it compares with other tools in Best Jev tools, tested hands-on.

Review updated Sep 22, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.

More in Open Models & Reproductions

Laya

★ 18k▲ 2.9k

NandhaKishorM/laya

Non-autoregressive decision engine over 100+ languages: three checkpoints and a router that detects the script and dispatches per request. Its benchmarks end with a limits section naming the datasets it does not generalise to and the headline figure that came from a training split.

PythonReviewed

kev

★ 4.7k▲ 4.3k

jaredpalmer/kev

Jev-style decision models from 0.5B to 8B, built as LoRA adapters on Qwen and served behind a Jev-compatible /v1/systemone API.

PythonReviewed

SemIf

★ 3.9k▲ 2.1k

TheoLeeCJ/SemIf

Jev-style decisions from a frozen 4B model on a single RTX 3090, with a browser demo. Formerly OpenJev.

PythonReviewed

Get new Jev projects every week

New Jev releases, pricing changes, and the best new projects, once a week. No spam; unsubscribe anytime.

Powered by Buttondown. See our privacy policy.