Instructions to use haohan84/v-jev with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use haohan84/v-jev with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="haohan84/v-jev") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("haohan84/v-jev") model = AutoModelForCausalLM.from_pretrained("haohan84/v-jev", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use haohan84/v-jev with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "haohan84/v-jev" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "haohan84/v-jev", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/haohan84/v-jev
- SGLang
How to use haohan84/v-jev with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "haohan84/v-jev" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "haohan84/v-jev", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "haohan84/v-jev" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "haohan84/v-jev", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use haohan84/v-jev with Docker Model Runner:
docker model run hf.co/haohan84/v-jev
v-jev 1.0 (4B)
v-jev is a 4B decision model in the Jev style. It turns a state and a set of typed questions into decisions: it reads the state as text or JSON and returns a probability for every allowed option of every question in a single forward pass. There is no free-form text generation and no output parsing.
v-jev is post-trained from Qwen/Qwen3.5-4B (text part only), using only that backbone's own answers and questions derived from them. No dataset answers and no benchmark data were used.
There are two checkpoints, trained on the same questions with differently extracted answers:
| Checkpoint (folder) | Trained on | Character |
|---|---|---|
v-jev-1.0-high-base (high-base/) |
The backbone's answer after it reasoned, which it gives with near certainty | Decisive and consistent; its probabilities are too sharp |
v-jev-1.0-base (base/) |
The same answer, mixed 70/30 with the backbone's probabilities before reasoning, plus questions where the backbone's answer was taken out of the list | Keeps the backbone's doubt, and answers "none of these" when no listed option fits |
Research release Β· one training run, one seed Β· only English was tested.
Model
- Backbone: Qwen/Qwen3.5-4B with a rank-16 LoRA merged in.
- Answer tokens: 78 added tokens:
<opt_1>β¦<opt_64>for choices,<lvl_0>β¦<lvl_9>for scores,<no>and<yes>, the placeholder<ans>, and<na>. - One pass: the state, every question and one
<ans>per question go into a single prompt, with thinking off. The model runs once. - Output: at each
<ans>, the logits of the answer tokens that question allows. Apply a softmax per question to get probabilities. A separate read of<na>gives the probability that the question cannot be answered from the state.
Files
| File | Purpose |
|---|---|
base/, high-base/ |
One checkpoint each: model.safetensors (merged weights, bf16, 8.4 GB), config.json, generation_config.json |
config.json |
Model configuration (Qwen3_5ForCausalLM), the same as in both folders; there are no weights at the root, so always load with subfolder= |
tokenizer.json, tokenizer_config.json, chat_template.jinja |
Tokenizer with the 78 added tokens, and the chat template, shared by both checkpoints |
inference.py |
Prompt building, the model, and VJev.ask |
LICENSE |
Apache-2.0 license |
Both checkpoints load with plain transformers; the tokenizer is at the repo root:
from transformers import AutoModelForCausalLM, AutoTokenizer
tok = AutoTokenizer.from_pretrained("haohan84/v-jev")
lm = AutoModelForCausalLM.from_pretrained("haohan84/v-jev", subfolder="base", dtype="bfloat16") # or "high-base"
The model is only half the method: the answers are read at the <ans> positions of a prompt in a
fixed format, which inference.py builds.
Usage
Tested with torch 2.14 and transformers 5.x (with Qwen3.5 support) on a single RTX 5090. It needs
about 9 GB of GPU memory. Install flash-linear-attention and causal-conv1d for the backbone's
linear-attention layers; without them transformers falls back to a much slower pure-PyTorch path.
from inference import VJev
jev = VJev("base") # or "high-base"; add repo="haohan84/v-jev" to load from the Hub
answers = jev.ask(
"Customer writes: Our nightly export has failed three nights in a row. If this is not fixed by Thursday we will look at other vendors.",
{
"export_failing": {"type": "noul", "instructions": "Is a scheduled data export currently failing?"},
"team": {
"type": "choice",
"instructions": "Which team should own the issue?",
"criteria": {"engineering": "Fixes broken product functionality", "billing": "Handles invoices, charges and refunds"},
},
"churn_risk": {
"type": "score",
"instructions": "How likely is the customer to leave?",
"criteria": ["No sign of leaving", "Mild dissatisfaction", "Mentions alternatives", "States an intent to leave"],
},
},
)
# {"export_failing": {"type": "noul", "noul": <p(yes)>, "na": <p>},
# "team": {"type": "choice", "probabilities": {"engineering": <p>, "billing": <p>}, "na": <p>},
# "churn_risk": {"type": "score", "probabilities": {"0": <p>, "1": <p>, "2": <p>, "3": <p>}, "na": <p>}}
python inference.py [base|high-base] runs an example. The request and answer shapes follow
POST /v1/systemone of the Jev standard; na is an addition.
Input format
| Field | Description |
|---|---|
state |
Any string or JSON value describing the situation to decide on |
questions |
Mapping of question ID to question |
Each question has:
type:noul(yes/no),choice(named options), orscore(ordered levels)instructions: what to decidecriteria: forchoice, a mapping of option ID to description, 2 to 64 options; forscore, a list of 2 to 10 level descriptions indexed from 0 (or an object of them, lowest first, and the answer is keyed by its IDs); fornoul, optional, an object withtrueandfalsedescriptions
64 options is what one question holds and what the model was trained on. inference.py also takes a
choice of 65 to 256 options, which it asks in rounds: the options are shuffled into groups of 63
plus "none of these", each group's winner goes on, and a final question picks among the winners. Its
answer adds none, the final question's probability of "none of these", and all_groups_none: true
when every group picked "none of these". Options out of the final get 0. The model never trained on
this form and the benchmarks do not use it, so treat it as untested.
The state and the question texts are treated as data. inference.py breaks up every added token of
the tokenizer written out in them, both the answer tokens (<ans>, <opt_3>, ...) and the backbone's
own (<think>, <tool_call>, <|im_end|>, ...), so they stay text. A random test of 200,000 texts
built from pieces of these tokens left none of them intact. The state is inserted as is, so it can still
contain text that looks like the prompt's own Questions: or Answers: lines. It cannot add answer
positions, but it can sway the answers; do not rely on the model to resist instructions written into the state.
Training and the benchmarks used prompts of at most 4,608 tokens. inference.py accepts longer ones (up to
max_tokens, by default the backbone's context length), but the model is untested there.
Training
- Data: 7,055 questions about BEV texts and Open-Jev states: 4,704 with up to 16 options and 2,351 with 17 to 64 options (intent routing and tool choice).
- Answers: the frozen backbone answered each question itself, with thinking on and a 2,048-token cap on its reasoning; its answer was read after the reasoning. A question was kept only if the backbone finished reasoning within the cap. The datasets' own answers were not used.
- The two checkpoints:
v-jev-1.0-high-baselearns these answers as they are. After reasoning the backbone has committed to one option, so nearly every target is close to 100%.v-jev-1.0-baselearns 70% of each such answer plus 30% of the backbone's probabilities read directly, with thinking off, which carry its doubt. - Left out: three sources the backbone cannot answer by reasoning (taste ratings, click-through guesses, a tile-game simulation).
- "None of these": the questions above almost never have it as their answer (75 of 4,704 normal
questions, none of the long-option ones).
v-jev-1.0-basealso trains on 1,800 questions made from them: in 1,200 the backbone's own answer is taken out of the list and "none of these" added, with 0.7 on "none of these" and 0.3 on the remaining options in the backbone's proportions; in 600 "none of these" is added and every option kept, at probability 0. The 0.7 is our rule, not an answer the backbone gave.v-jev-1.0-high-basehas no such questions. - Trained parts: rank-16 LoRA on the attention projections (alpha 32) and the 78 new token rows, for 3 epochs. Both are merged into the file.
Results
All numbers are our own runs. Neither checkpoint was trained on any of these benchmarks, and the training texts were cleaned of banking77 and clinc150 messages.
Benchmarks
| Benchmark | v-jev-1.0-high-base | v-jev-1.0-base |
|---|---|---|
| JevBench-mini (coherence) | 76.1 | 66.4 |
| JevBench-mini (accuracy) | 89.4 | 89.2 |
| typed-decisions (accuracy) | 68.5 | 66.8 |
| typed-decisions (KL from gold, lower is better) | 1.375 | 0.451 |
| typed-decisions (Brier, lower is better) | 0.300 | 0.210 |
| typed-decisions (mean top probability; gold 0.66) | 0.91 | 0.78 |
| When2Call (accuracy) | 60.3 | 65.0 |
| Amazon ESCI (accuracy) | 63.1 | 63.3 |
| BANKING77, 1,000 messages (accuracy) | 71.6 | 70.9 |
| CLINC150, in scope (accuracy) | 86.4 | 83.9 |
| CLINC150, out of scope (accuracy) | 25.0 | 79.9 |
| 17 to 64 options in one question, 132 questions (accuracy) | 90.2 | 91.7 |
Scores are percentages except KL, Brier and mean top probability. The better value is in bold where the two differ by at least one point (or 0.01 for KL and Brier); differences of a few points between the two are within what one training seed can change. typed-decisions is scored with each case's five questions in one request. BANKING77 and CLINC150 are asked in rounds of 15 options plus "none of these".
typed-decisions leaderboard
Placed in the zero-shot table of the typed-decisions dataset card as of Oct 13, 2026. Our rows are not on the leaderboard.
| # | Model | Accuracy | KL from gold | Brier |
|---|---|---|---|---|
| 1 | meraGPT Decider 1 | 0.768 | 0.096 | 0.052 |
| 2 | Liquid AI d1 | 0.742 | 0.475 | 0.155 |
| 3 | TypeSafe Jev 1.13.0 | 0.727 | 1.442 | 0.148 |
| 4 | Featherless Simple Jev (35B) | 0.716 | 0.488 | 0.176 |
| 5 | prima-ratio + 12B | 0.702 | 0.564 | 0.234 |
| β | v-jev-1.0-high-base | 0.685 | 1.375 | 0.300 |
| 6 | OpenDecider-small | 0.671 | 0.211 | 0.117 |
| β | v-jev-1.0-base | 0.668 | 0.451 | 0.210 |
| 7 | Bongard-mini | 0.594 | 0.256 | 0.132 |
| 8 | Jeff-Gemma4-E2B | 0.561 | 0.403 | 0.219 |
| 9 | Jeff-Qwen3.5-2B | 0.511 | 0.460 | 0.237 |
| 10 | Jeff-Qwen3.5-0.8B | 0.483 | 0.679 | 0.313 |
JevBench-mini leaderboard
Placed among the 21 entries of JevBench-mini 0.1.0 as of Oct 13, 2026. Our rows are not on the leaderboard. Selected rows; the columns are wording, batch independence, probability measure, logical order and choice set.
| # | Model | Coherence (95% interval) | REP | BAT | MEA | LOG | CHO | Accuracy |
|---|---|---|---|---|---|---|---|---|
| 1 | Open-Jev-9B | 83.9 (82.5β85.2) | 81.9 | 100.0 | 50.2 | 87.1 | 100.0 | 88.4 |
| 3 | JevAny-Qwen-4B (pointer) | 79.4 (77.2β81.4) | 81.7 | 100.0 | 52.2 | 78.3 | 84.7 | 88.8 |
| 7 | Jebadiah 9B v2 | 76.9 (74.4β79.3) | 79.2 | 100.0 | 48.0 | 83.8 | 73.6 | 89.1 |
| β | v-jev-1.0-high-base | 76.1 (73.0β78.9) | 86.9 | 73.3 | 64.0 | 81.2 | 75.0 | 89.4 |
| 8 | Von 1.3 | 75.9 (74.7β77.1) | 83.1 | 100.0 | 16.4 | 80.0 | 100.0 | 72.2 |
| 10 | OneJev-4B | 72.5 (69.9β74.7) | 79.7 | 100.0 | 43.6 | 71.2 | 68.1 | 89.2 |
| 15 | Bespoke-Nimble-9B | 69.2 (66.5β72.1) | 76.4 | 68.3 | 50.5 | 87.1 | 63.9 | 89.1 |
| 16 | CLM v0.1 | 66.8 (65.5β68.1) | 59.2 | 100.0 | 25.5 | 49.6 | 100.0 | 63.5 |
| β | v-jev-1.0-base | 66.4 (63.4β69.4) | 79.4 | 65.0 | 51.5 | 69.6 | 66.7 | 89.2 |
| 17 | OpenThai-SystemOne | 64.2 (61.2β67.0) | 76.9 | 70.8 | 39.7 | 61.3 | 72.2 | 82.4 |
Bold: above all 21 leaderboard entries in that column. v-jev-1.0-high-base would place between
ranks 7 and 8, v-jev-1.0-base between 16 and 17; both intervals overlap those of many neighbouring
entries. Batch independence is low because all questions of a request share
one prompt, so a later question can see the earlier ones; 18 of the 21 entries answer each question
in its own pass and score 100 there.
Which one to use
v-jev-1.0-basewhen the probabilities are used (thresholds, ranking, asking a human when the state lacks evidence), or when the right answer may be missing from the options. It answers "none of these" on 79.9% of CLINC150 out-of-scope messages, against 25.0% forv-jev-1.0-high-base.v-jev-1.0-high-basewhen only the top answer is used, every question has a right option, and answers must agree with each other (coherence 76.1 against 66.4).
Limitations
v-jev-1.0-high-baseis over-confident. Its mean top probability is 0.91 on typed-decisions, where the gold's is 0.66, and 0.95 on When2Call at 60.3% accuracy. Do not read its probabilities as calibrated without fitting a temperature. It also rarely answers "none of these" (CLINC150 out of scope 25.0%).- Both under-use "cannot answer" on When2Call (recall 23% and 33%). There it is one of four fixed kinds of action, not "none of these" after a list, and neither checkpoint trained on that form.
<na>is a separate signal. It flags a question that does not fit the state: 97% of questions asked about another state, 83% to 85% of off-topic requests, and 1.2% to 2.0% of real questions. The benchmarks above do not use it.- Neither knows more than its backbone. Both were trained on Qwen3.5-4B's own answers; the
"none of these" questions of
v-jev-1.0-basewere made from them by rule.
License
Released under the Apache-2.0 license, following the base model Qwen/Qwen3.5-4B. The training texts come from BEV (a mix of sources under CC BY, CC BY-SA, Apache-2.0, MIT and BSD; the collection's own licence is not stated) and Open-Jev; only their texts were used, with the backbone's own answers.
- Downloads last month
- 35