Repository navigation
Releases
jev-style 0.6.3 — official local setup and source clarity
Clarify official local installation, release-specific teacher-label training sources, and the distinction between local weights, hosted JevStyle API and third-party Jev access or agent simulation. Add the official installation, current service-status and reproducible routing-evidence links.
This is a documentation-only release. Runtime behavior, dependencies, model revisions and weights are unchanged from 0.6.2. The corrected README is now available on PyPI.
jev-style 0.6.2 — PyPI documentation sync
Synchronize the PyPI description with JevStyle’s local classification, routing, and scoring positioning. Add direct entry points for model selection, sourced benchmark protocols, runnable application guides, and project information.
This is a documentation and metadata release. Runtime behavior, dependencies, model revisions, and weights are unchanged from 0.6.1.
Validation: 233 tests passed; wheel/sdist metadata checks and a clean-install smoke test passed.
0.6.1: Try local decision workflows faster
Start with a live demo or a short local setup, then copy a complete workflow into your project.
- Put platform-specific installation and model selection before benchmark details.
- Add runnable support-ticket, fallback-routing and receipt-review recipes with clearly labelled synthetic inputs.
- Add a Semantic Router 1.1.1 integration example for the local systemone API.
- Refresh current-model links and PyPI metadata; add contribution guidance and issue templates.
- Include the current 2B v4 Space source alongside the existing 0.8B Space source.
Try the demo: https://huggingface.co/spaces/chaoliangUNSW/jev-style-2b
Recipes: https://github.com/lawrence3699/jev-style/tree/main/examples/recipes
Guides: https://jevstyle.com/use-cases/local-llm-routing/
Validation: 233 local tests pass; the PR test matrix passes on macOS and Ubuntu with Python 3.10, 3.12 and 3.13. Package checks pass. Model revisions and inference behavior match 0.6.0. Synthetic examples and protocol tests do not establish model quality or cost savings.
jev-style 0.6.0
- Jev-Style-2B-Decision-v4 (
--release 2b-v4), all three builds pinned: torch @ c9504148, MLX @ a14bbe4d,
GGUF @ 9111d5d2. The first Jev-Style model that reads images (PyTorch build; the MLX and GGUF builds read text
only), 32,768 tokens per call. Its PyTorch runtime ships the reference scorer it was evaluated with (src/macjev/)
and needs the image processor, so thetorchextra now also installspillowandtorchvision. Its MLX build
needs mlx-lm 0.31.3 exactly and its GGUF build thejev-score-v2scorer, as for2b-v3(one binary serves both).
Trained in part on soft labels distilled from TypeSafe Jev 1.14 via its public API (see its model card). --release 2bnow means2b-v4(JevStyle(release="2b"),JEV_STYLE_RELEASE=2b,local:2btargets). Use
2b-v3to keep the v3 weights;cascade-9band the example cascades name2b-v3explicitly and are unchanged.
The default release is still0.8b-v3.- Images in requests, the way TypeSafe's API takes them (Jev 1.13 / 1.14):
assetswithdata_base64, or
multipart bodies with one file part per image, plus the headerTypeSafe-Danger-Zone-Images: true. A string value
instatethat names an asset becomes the image (<|image_k|>in reading order); a reference in a question's
instructions or criteria is refused (this model reads images as part of the state). TypeSafe's limits: still PNG
or JPEG, 16 MiB per image, 280 to 1,568 px per side, 32 MiB in total. Models that read text only (0.8B, 2B v3,
every MLX and GGUF build) keep answering 400images_not_supported.GET /v1/modelsreportsimagesandbox. - Python client:
JevStyle.decide(..., assets={...})andjev_style.decide(..., assets=...)send images
(in-process, or over HTTP with the header), andjev_style.image(path_or_bytes)builds anassetsentry. - CUDA graphs under
auto: a runtime whose owncuda_graphsdefault is auto (the 2B v4) now makes the choice
itself: graphs with bfloat16 on CUDA, none in float32, where its forward is compute-bound and recording costs about
a minute for little gain. The v3 runtimes keep 0.4.0's behaviour (on whenever they run on CUDA).
--cuda-graphs on|off,JEV_STYLE_CUDA_GRAPHSandcuda_graphs=still override it;JEV_STYLE_CUDA_GRAPHS=auto
now means auto. - Downloads: a cached snapshot of the pinned revision is used without a network call only when it holds every
file the build needs (checked against itsmanifest.json). With huggingface_hub before 2.x, a snapshot holding
only some of them (another MLX precision or GGUF quant, or one file fetched withhf_hub_download) was used as
is and loading failed withjev_style_decision*.py not foundor a missing weights file. jev-style releasesno longer prints an empty alias field for a release without an alias.
Install: pip install -U "jev-style[torch]" (or [mlx] on Apple silicon), then jev-style serve --release 2b.
jev-style 0.5.0
Compatibility with TypeSafe's API as of Jev 1.14 and the official SDKs (Python 0.7.5, JavaScript 0.7.0).
- Compressed request bodies. The official SDKs now compress bodies of 1 KiB or more with zstd by default, which
older servers rejected with 422invalid_json.POST /v1/systemoneaccepts one layer of
Content-Encoding: gzip,x-gziporzstd(window up to 8 MiB). Checked end to end withtypesafe-sdk0.7.5
and its default compression. New core dependency:zstandard. - Request rules as in TypeSafe's API. Body over 32 MiB (compressed or decompressed): 413
payload_too_large.
Unsupported or multi-layerContent-Encoding: 415unsupported_content_encoding. 400 for a malformed compressed
body (invalid_compressed_body), a byte order mark or invalid UTF-8 (invalid_encoding), more than 64 nested
levels instate,instructionsorcriteria(nesting_too_deep; very deep bodies used to fail with 500), and
NaN, Infinity or numbers too large to represent (non_finite_number). Validation errors stay 422. - Over-long inputs: 400
max_tokens_exceeded(was 422input_budget_exceeded), the code TypeSafe returns.
The Playground understands both. - Score
confidenceuses TypeSafe's ordinal formula (docs.typesafe.ai/confidence):
max(0, 1 - sum_i p_i |i - m| / MAD_unif), so probability on a neighbouring level costs less than probability
far away. It was the Choice formula. Probabilities,scoreand Choice confidence are unchanged; cascade routing
still uses normalized p_max, so frozen thresholds keep their meaning. - Text only, said clearly.
assets(images), multipart bodies andboxquestions get 400
images_not_supported/unsupported_question_typeinstead of a validation error. GET /v1/modelsalways givesrelease_dateas a string (the official SDKs refusednullfrom the fake engine
and cascades); a cascade reports the date its routing was frozen.- Official model names (
jev-latest,jev-preview,jev-1.14.0, ...) keep working in themodelfield.
jev-style 0.4.0
- CUDA graphs for the PyTorch backend, on by default. On CUDA the torch runtime records CUDA graphs at start-up
and replays them. Measured on an RTX 5090 in float32 on 4,992 calibration questions against the ordinary path:
0 top-1 answers changed, largest probability difference 0.00086 (0.8B) and 0.0024 (2B), median latency 41.6 ->
11.3 ms (0.8B) and 86.2 -> 13.9 ms (2B). Recording the graphs adds about 7-11 s to start-up; inputs longer than
4,096 tokens and several questions over a long shared state use the ordinary path.--cuda-graphs auto|on|off
(auto = on when the model runs on CUDA),$JEV_STYLE_CUDA_GRAPHS,cuda_graphs=inJevStyleand
models.load_release. A runtime without the CUDA-graph path loads as before underauto;onis refused there. - New torch pins. The PyTorch builds of
0.8b-v3and2b-v3are pinned to revisions that ship the CUDA-graph
runtime:0.8b-v3torch @ b023d1f9,2b-v3torch @ 5bad2d53 (the 0.8B pin before that, d53c8f82, failed
verify=Truebecause of a stray manifest entry). The MLX and GGUF pins are unchanged. - Confidence cascades (
jev_style.cascade). Acascade.jsonlists tiers (smallest first: an in-process release,
a Hub repo, or anyPOST /v1/systemoneserver) and one threshold per tier below the top. Tier 1 answers every
question in one call; questions below its threshold (normalized p_max computed from the probabilities, never the
tier's ownconfidence), or that it failed on, go to the next tier in one call with the same state. The top tier
is final; if it fails, the last successful answer is used; if every tier fails, the error is returned as a single
model would return it (plustier,tier_model,tier_errors). Optional per-tiermax_options. Answers add
tierandtier_model,timing.tiersreports each tier;modelis the cascade id,backendiscascade.
select()replays recorded per-tier answers offline with the same rules. jev-style serve --cascade FILE,jev-style decide --cascade FILE,JevStyle(cascade=FILE), and the eval engine
NAME=cascade:FILE.- JevK5 tiers.
"protocol": "jevk5"talks to allebee/jevk5'sjevk5-serve(0.3.x): structured option
descriptions are sent as text, single-option choices are not sent (it rejects them), its{"error": "<message>"}
bodies and its answer shapes (nolegend,confidence= p_max) are read correctly.examples/cascade/holds a
2B -> JevK5-9B and a 0.8B -> 2B -> JevK5-9B file (placeholder thresholds);scripts/cascade_smoke.pyruns one on
fake engines. - In-process JevK5 tiers: the target
jevk5:<Hub repo or local folder>runs allebee/jevk5 in this process, with
the codejevk5-serveruns (jevk5.server.normalized, thenmodel.decide; one bad question fails the request as
its HTTP 400 does), so a tier answers the same in-process and over HTTP. A Hub repo is downloaded at its revision
(pinned for JevK5-9B), checked against itsSHA256SUMS(by default for the pinned release; tier keyverify), and
refused without itsjevk5_config.json, without which JevK5 would run uncalibrated. All JevK5 calls run on one
worker thread. jevk5 is not on PyPI and is not a dependency: a missing install fails before any download and
names the command,pip install "jevk5[fast] @ git+https://github.com/allebee/jevk5@v0.3.3".jevk5:also works
as an eval engine. - Named cascades (
jev_style.cascades.CASCADES):--cascade,JevStyle(cascade=...)andcascade:eval
engines take a name as well as a file.cascade-9b(jev-style-cascade-9b): Jev-Style 2B Decision v3
in-process (PyTorch float32, CUDA graphs) -> JevK5-9B v0.3.3 by alibiserikbay (third party, Apache-2.0) in-process,
one threshold on normalized confidence, calibration set sha256580962e4.... A named cascade whose threshold is
still a placeholder is refused./v1/modelsreports the cascade id and its tiers. jev-style releases [--json]lists the model releases (with their pinned revisions) and the named cascades.
jev-style download --cascade NAME|FILEdownloads every tier ahead of time (the JevK5 snapshot is checked as a
load checks it; jevk5 itself is not needed for that).--cuda-graphsnow also applies to a cascade's local tiers, like--deviceand--dtype.jev_style.client.parse_target/from_target: one resolver for engine targets, shared byeval --serverand the
cascade tiers. The HTTP client now reports{"error": "<message>"}bodies by their message.
jev-style 0.3.0
- Jev-Style-2B-Decision-v3.
--release 2b(orJevStyle(release="2b"), orfrom_pretrainedwith any of its
three repos) loads the new 2B at pinned revisions: PyTorch, MLX (bf16 / 8-bit; needs mlx-lm 0.31.3) and GGUF
(F16 / Q8_0 / Q4_K_M; scorerjev-score-v2, found through--scoreror$JEV_SCORE_V2_BIN). The default stays
the 0.8B. [mlx]now pins mlx-lm 0.31.3 (the 2B MLX runtime checks it; the 0.8B was tested on it).autoskips an MLX
build whose requirements are not met.- Several model releases.
jev_style.models.RELEASESlists each release with its three builds (PyTorch main repo,
-MLX,-GGUF). Pick one with--release(serve,decide,download,mcp),JevStyle(release=...),
$JEV_STYLE_RELEASE, an eval enginelocal:<release>[:backend], orJevStyle.from_pretrained(<any of its repos>).
Only releases whose builds are all pinned are offered by the CLI. - The server reports the loaded release:
modelin answers,/v1/modelsand/healthz(id, release date,
description) come from the release instead of being fixed to the 0.8B model. - MLX prefix sharing is enabled per build, only where it was shown to give identical scores (0.8B v3 MLX).
- A release that is not pinned yet can still be loaded from a local folder (
model_dir), or from its main branch
withtrust_remote_code=True. models.load_release()returns the build as well;models.load()keeps its 0.2 return value.- Fail fast without a backend. With only
pip install jev-style(the client), loading the model used to download
1-2 GB and then stop atNo module named 'torch'. It now stops before the download withMissingBackendError,
which names the extra to install ([mlx]on Apple silicon,[torch]elsewhere); the CLI prints it as one line. - MCP Registry. Listed as
io.github.lawrence3699/jev-style(server.jsonat the repo root).mcpis now a core
dependency, souvx jev-style mcpworks without extras;jev-style[mcp]still resolves. The README carries the
registry'smcp-nameownership line, andrelease.ymlpublishesserver.jsonto the registry after the PyPI job
(GitHub OIDC, no token; the version is taken from the tag). - The MCP server reports the package version (it said 0.1.0).
jev-style 0.2.0 — now on PyPI
- On PyPI.
pip install "jev-style[mlx]"on Apple silicon,pip install "jev-style[torch]"elsewhere; the
README and the skills no longer install from a git URL. JevStyle.from_pretrained(repo_id): load a release by its Hub repo id; the repo picks the backend (main repo =
PyTorch,-MLX,-GGUF). The three v3 repos load at their pinned revisions. Any other repo runs the runtime file it
ships, so it is refused unless you passtrust_remote_code=True.- Module-level shortcuts:
jev_style.decide(...),jev_style.classify(text, labels)andjev_style.configure(...)
share one lazily created client ($JEV_STYLE_URL, else the local model). jev-style eval --server ...compares engines: the local model, other builds, or any server that implements
POST /v1/systemone, on the same questions, with 95 % paired bootstrap intervals for the accuracy and Brier
differences.--key NAME=ENV_VARand--model NAME=MODELper engine.- MLX: the state is read once for many questions (bit-identical answers, up to 8x faster).
- Packaging: version read from
jev_style/__init__.py; the source distribution now holds only the package, tests
and examples (about 210 KB instead of 6.6 MB); README links are absolute so they work on PyPI.
No change to answers: the pinned model revisions are the same as in 0.1.0.
pip install "jev-style[mlx]" # Apple silicon
pip install "jev-style[torch]" # everything elseJev-Style 0.1.0
First public release of Jev-Style: a small, calibrated decision model that runs on your own machine, packaged for AI agents.
What's in it
jev-style serve: local systemone-compatible API (/v1/systemone), Playground and demos for Jev-Style-0.8B-Decision-v3. MLX on Apple silicon; PyTorch on CUDA, MPS or CPU; llama.cpp GGUF optional.- Six agent skills:
npx skills add lawrence3699/jev-style. They cover serve, use, eval, adopt, guard and MCP. - Claude Code guard: a
PreToolUsehook that answers allow, ask or deny, and falls back to ask on any failure. On the 49 bundled labelled calls it agrees with the labels on 77.6 %, and no deny-labelled call was allowed. - MCP server:
jev-style mcp, with toolsdecide,noul,choice,scoreandmodel_info. jev-style eval: accuracy, Brier and ECE on your own labels, the share of decisions you can automate at a 1, 5 or 10 % error budget, and a refitted temperature.- Claude Code plugin marketplace:
/plugin marketplace add lawrence3699/jev-style.
Install
uv tool install "jev-style[all] @ git+https://github.com/lawrence3699/jev-style@v0.1.0" # Apple silicon
uv tool install "jev-style[torch,mcp] @ git+https://github.com/lawrence3699/jev-style@v0.1.0" # Linux / Windows / Intel
jev-style serveThe weights download from the Hugging Face Hub at a pinned revision on first run (about 1.5 GB). Tests run on a fake engine, with no download.
