Show it a screen. Ask it anything typed.
Send a state with screenshots, photos or video and a set of typed questions. Get one calibrated probability per option back, in one forward pass.
Loading results.json
A state can hold screenshots, photos and video frames, next to the text an agent or a pipeline already has.
Each question gets one calibrated distribution over its options, read off the model's own logits in a single forward pass. Nothing is generated.
The server speaks TypeSafe's System One API. The official typesafe-sdk works after changing one environment variable, and a request adds media with one extra field.
Rows drawn at random from the test set, with the probabilities OneJev-27B gave them. Hover a window to hold it, click the picture to pin it.
Five recorded agent runs from the test set, on a phone and on a desktop. Each run is cut where the question is asked, so the model sees only the steps and screens up to that point.
Qwen3.8-27B is the network OneJev-27B started from, asked the same question in the same way before training.
A web agent is halfway through a task on a real website. The question lists fifty elements on the page, and the model gives each one a probability of being the next thing to click.
Long cooking videos, sampled from the start of the recording up to the moment of the question. OneJev says which step is happening now, which one comes next, and how far along the cook is.
Short clips with questions that need motion to answer: which of 174 hand actions, which of 47 dives, what caused a collision.
Fine-grained questions with up to two hundred options, a satellite tile and a map. Every card is a row of the test set.
DecisionBench is scored state-macro as on its card. TypeSafe uses the 354 rows of TypeSafe's public evaluation that Jev answered, with Jev's published answers as its row. MMBench (dev) and MMStar check that general vision is kept. The best cell in each row is magenta, the runner-up pale pink.
pip install git+https://github.com/OmniJev/OneJev.git qev serve --model OmniJev/OneJev-4B --port 8000
Requests without media are plain System One requests, and the official SDK works against the same server with TYPESAFE_BASE_URL=http://localhost:8000.
from qev import Client, Choice, Noul, Score
from qev.media import data_uri
c = Client("http://localhost:8000")
r = c.system_one(
state={"task": "Pay the open invoice from ACME", "screen": "<image:1>"},
media=[{"type": "image", "data": data_uri("screenshot.png")}],
questions={"done": Noul("The invoice has been paid"),
"next": Choice("What should the agent do next?",
{"click": "click an element", "type": "type text", "scroll": "scroll", "stop": "stop"}),
"progress": Score("How far along is the task?", ["not started", "halfway", "almost done", "done"])},
)
r.answers["done"].noul # probability of yes
r.answers["next"].probabilities # one probability per option
r.answers["progress"].score # expected levelThe prompt is the state followed by one question and its lettered options. Every question of a request shares the state, so the state is prefilled once, the cache is forked, and each question runs as a short branch. All branches go through the model together. The answer is the softmax over the logits of the option letters at the last position, computed in float32.
Images and video frames sit inside the state, so the vision encoder also runs once per request. Qwen's vision models place tokens with multimodal RoPE, where text after an image continues from the image's largest position. Every branch token gets the position it would have had in the full prompt, and the branches reproduce the full-prompt probabilities: to 1e-5 in float32, and to at most 0.016 in bfloat16 over 229 real test questions.
The server checks this on a synthetic image at load time and refuses to start if a future library version breaks it.
state: text + <image:1> + <video:1> | | vision encoder, once | prefill, once v [ shared cache ] |-- question 1 + options A..D -> softmax(A..D) |-- question 2 + options A..B -> softmax(A..B) |-- ... '-- question N + options A..K -> softmax(A..K) every branch in one batch, nothing decoded
POST /v1/systemone takes TypeSafe's request (state, questions, model) plus an optional media list. The state refers to each item once, in order, as <image:N> or <video:N>.
Questions are noul (yes or no), choice (up to 255 options) and score (up to 10 ordered levels), answered in TypeSafe's response format. A request whose placeholders do not match its media, or that sends a local path to a server started without --media-root, gets a 422.
| item | fields |
|---|---|
| image | {"type": "image", "url": ...}, {"type": "image", "data": ...} with base64 or a data URI, or "path" under --media-root |
| video | {"type": "video", "frames": [...], "fps": 2.0}, frames extracted beforehand; fps sets the timestamps the model sees |
OneJev comes in four sizes, full-parameter fine-tunes of Qwen3.5-0.8B, Qwen3.5-4B, Qwen3.5-9B and Qwen3.8-27B, all trained on the same questions. Answers come from what actually happened (whether the run succeeded, what the agent did next, which step of the recipe is on screen) or from each dataset's own labels; part of the business-rule set was labelled by Qwen3.5-27B.
One epoch with the vision tower frozen, learning rate 5e-6 with cosine decay, 64 questions per step, cross-entropy plus an equal-weight Brier term on the option letters. The 9B and 27B runs shard weights, gradients and optimizer state with FSDP. 589 training questions that shared a task with a test question were removed before training.