Skip to main content

Jiamu Zhang1     Tianze Yang1     Yucheng Shi2     Evan Chen1
Zixiang Nie1     Kelly Wan1     Liangjie Hong1     Ninghao Liu3     Liang Wu1

1 Nokia, Sunnyvale, CA, USA      2 Tencent Hunyuan      3 The Hong Kong Polytechnic University

Reverse the option order: the raw logit readout flips its answer, AnyJev L0 gives the same answer both ways
Qwen3-8B on a real BANKING77 item. Every number is a model output.

⚡ Serve it

A Tacit model, in Python.

from anyjev import Tacit

tacit = Tacit.from_pretrained("morriszjm/Tacit-9B")          # transformers, one GPU
d = tacit.decide(state="Customer: my package was due last Monday and it still has not arrived.",
                 question="What does the customer want?",
                 options=["track_order", "cancel_order", "refund", "change_address"])
d["answer"], d["probs"], d["route"]    # an option, {option: probability}, "one_forward" or "cot"

kind is "choice" (default), "yes_no" or "score" (options are ordered levels, lowest first). decide_batch([...]) takes a list of such dicts.

Send the hardest decisions to reasoning, with a cap.

tacit = Tacit.from_pretrained("morriszjm/Tacit-9B", adaptive=True, tau=0.5, max_cot_share=0.2, cot_window=1000)

A decision whose top two options are less than tau apart in log-probability is answered again with thinking on. After the reasoning, the answer is read as a label distribution, so it also has probabilities and cannot fail to parse. At most max_cot_share of the last cot_window decisions escalate, however hard the traffic gets. Every escalation is reported (route == "cot", with the first pass kept), and tacit.stats counts them.

On vLLM. A stock server; the client needs only the tokenizer.

pip install "anyjev[client]"
vllm serve morriszjm/Tacit-9B --host 127.0.0.1 --port 8000
tacit = Tacit.from_pretrained("morriszjm/Tacit-9B", engine="server",
                              base_url="http://127.0.0.1:8000", adaptive=True)

engine="vllm" (pip install "anyjev[vllm]") runs vLLM in the same process instead.

An HTTP endpoint for many clients sharing one cap.

python -m anyjev.serve --model morriszjm/Tacit-9B --upstream http://127.0.0.1:8000 --adaptive --port 8100
curl -s 127.0.0.1:8100/v1/decide -H 'Content-Type: application/json' \
  -d '{"state": "Customer: my package has not arrived.", "question": "What does the customer want?", "options": ["track_order", "refund"]}'

POST /v1/decide takes one decision or {"items": [...]}; GET /v1/stats reports the escalation share. The gateway listens on 127.0.0.1 and has no authentication of its own.

argument default meaning
adaptive False send low-confidence decisions to the model's own reasoning
tau 0.5 low confidence: the log-probability gap between the top two options is below tau
max_cot_share 0.2 at most this share of the last cot_window decisions escalates; None removes the cap
cot_window 1000 how many recent decisions the cap counts; None counts every decision since loading
cot_max_tokens 8192 reasoning budget of one decision
engine "transformers" "vllm" runs vLLM in this process; "server" uses a running vllm serve at base_url

Any other model, training-free. The Decider reads the same typed decisions from any open causal LM, with no training and no labels.

from anyjev import Decider, Question
from anyjev.backends.hf import HFBackend          # or anyjev.backends.vllm.VLLMBackend(url, model)

d = Decider(HFBackend("Qwen/Qwen3-8B"))           # level="L0" by default
route = Question.choice("Which team should handle this?",
                        ["billing", "technical", "sales", "other"], name="route")
r = d.decide("My card was charged twice for one order.", [route])["route"]
r.distribution, r.level                           # {option: probability}, "L0"

L0 reads a K-option choice once per rotation of the options. With the rotation budget, it reads only as many rotations as the decision needs:

d = Decider(backend, adaptive_shifts=True, canonical_order=True)
d.calibrate_adaptive(route, unlabelled_tickets, target=0.01)   # a few hundred states, no labels

The stopping threshold is calibrated against our own full-cycle answer, so it needs no labels. At a certified 1% disagreement it read 7.2 rotations instead of 18. That was 2.2× the decisions per second on vLLM and 2.3×–2.7× on transformers, with accuracy unchanged (docs/rotation_budget.md).

✨ What it is

Give the model a state and a typed question (a choice, a yes/no or a score). You get back a decision with a probability over the options, read from the model's next-token distribution. Nothing is parsed. There are two ways in:

  • AnyJev Training-Free (Decider) works on any open LLM, with no training. Raw label logits change their answer when the options are reordered and carry the model's preference for some labels. L0 removes both without a single label.
  • AnyJev Self-Distilled (Tacit) uses the Tacit checkpoints. They are trained by self-distillation: the model learns to give, in one forward pass, the answers it reaches when it reasons. No human labels and no other model are involved. One prefill per decision; with adaptive=True, a capped share of decisions goes to reasoning.
⚪ raw logits 🔵 L0
zero labels
Labels required none none
Answer flips when options are reversed 0.230 0.073
Accuracy 0.747 0.803
Calibration error (ECE) 0.240 0.184
Auto-decidable at ≤5% error 7.7% 46.3%

Qwen3-8B, BANKING77 20-way, 300 test items · bench/results_v01/2026-09-22/Qwen__Qwen3-8B.json

The last row matters most. Accuracy moves six points, but the share of decisions confident enough to automate at ≤5% error goes from 7.7% to 46.3%, with no labels at all.

📊 Tacit results

model base JevBench public (231) bev-decision test (46,320)
Tacit-9B Qwen3.5-9B 0.823 0.725
Tacit-8B Qwen3-8B 0.749 0.662
Tacit-4B Qwen3-4B 0.723 0.663
Tacit-2B Qwen3.5-2B 0.671 0.626
Tacit-1.7B Qwen3-1.7B 0.623 0.598

Accuracy with one forward pass per decision (adaptive=False), the options in the benchmark's order, on every item of both test sets (JevBench public set; bev-decision test split) · bench/results_tacit/2026-10-05/one_forward.json

Results with escalation (adaptive=True) will be published together with the evaluation harness.

🧠 How it works

How one decision is read: ask a typed question, read it over every cyclic shift of the options, divide out the label prior estimated without labels, and return a decision that carries its level

needs does does not
raw nothing one prompt, softmax restricted to the option labels correct order or label bias
L0 nothing averages position bias out over the K rotations, divides out the label prior calibrate against labels
Tacit one_forward a Tacit checkpoint one prompt, read like raw from a model trained to answer in one pass correct order bias
Tacit cot adaptive=True reasons first, then reads the label distribution after the thought run beyond its cap

Every Decision carries its level, and require="L0" makes downstream code refuse a weaker one. Every Tacit decision carries its route. The contract in full →

Every number in this README is read from committed JSON. Not affiliated with TypeSafe AI or Jev.

🧭 Roadmap

  • choice, noul and score from one prefill; L0 with zero labels
  • The rotation budget: L0 at about 7 of 18 rotations, with a stopping threshold certified without labels
  • Tacit-1.7B, 2B, 4B, 8B and 9B on Hugging Face; Tacit in the library on transformers, vLLM and vllm serve, with capped escalation to reasoning and an HTTP gateway
  • 🚧 Results with escalation on JevBench and bev-decision, released with the evaluation harness
  • 🚧 Label-free early exit: read a decision from part of the model's depth, choosing the depth by agreement with the full model
  • Agent-loop evaluation: the same decisions inside a real agent
  • More log-prob backends (SGLang, llama.cpp, MLX, Ollama), span readout beyond 26 options

Dated plan and help-wanted files: ROADMAP.md. Known limitations: docs/limitations.md.

🤝 Contributing and citation

Backends are one file each, and several are help wanted (ROADMAP.md, CONTRIBUTING.md). Changes: CHANGELOG.md. Credits: CREDITS.md.

Technical Report:

@misc{zhang2026anyjevtechnicalreport,
      title={AnyJev Technical Report}, 
      author={Jiamu Zhang and Tianze Yang and Yucheng Shi and Evan Chen and Zixiang Nie and Kelly Wan and Liangjie Hong and Ninghao Liu and Liang Wu},
      year={2026},
      eprint={2610.00831},
      archivePrefix={arXiv},
      primaryClass={cs.LG},
      url={https://arxiv.org/abs/2610.00831}, 
}

Software:

@software{anyjev2026,
  title  = {AnyJev: Turn any LLM into a Jev-style decision model},
  author = {Zhang, Jiamu and Yang, Tianze and Shi, Yucheng and Wu, Liang},
  year   = {2026},
  url    = {https://github.com/nokia-applied-research/AnyJev}
}

Apache-2.0, see LICENSE. The Tacit models carry their base models' Apache-2.0 license. Datasets keep their own licenses, see THIRD_PARTY.md.

Metadata

Release files for anyjev 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for anyjev 0.3.0
File Size Uploaded
anyjev-0.3.0.tar.gz 75.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for anyjev 0.3.0
File Interpreter ABI Platform
anyjev-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 136.5 kB

Release files / anyjev-0.3.0.tar.gz

Download URL anyjev-0.3.0.tar.gz
Size 75.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8a8c004c88803fbb407546e4e7c059dc0fb19e08b95d2c4ea3b1089a6fd00b76
BLAKE2b-256 checksum
How to use checksums
10fbbcd57670036f0faf249eec3d01d6db249cfa128092f88cb3d3254c8faa6c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / anyjev-0.3.0-py3-none-any.whl

Download URL anyjev-0.3.0-py3-none-any.whl
Size 61.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
24217f23eecb3859353d625b89e0047d02c70c8ce993f956e118d7e39b9dcf3f
BLAKE2b-256 checksum
How to use checksums
8a6980b0efe02d63f9ee96ed312919b7faf801a7b6c8bf7b6622ebbb8c57685d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page