Model or dataset
razorback16/openjev avatar
razorback16/openjev

openjev turns a model into a decision server with typed answers

Open, Jev-compatible System One decision server on DiffusionGemma

744 stars67 forksPythonApache-2.0

At a glance

What is it?
openjev is a self-hostable server that returns probabilities and confidence for yes/no, choice and score questions by reading them straight out of an open model. It speaks the Jev wire API, so existing SDKs work unchanged.
Who is it for?
Adopt openjev when you need decisions with a probability attached, when you want them served from your own GPU with open weights, and when you already use TypeSafe's SDK so the wire compatibility removes integration work. Do not choose it if you need a hosted service with no GPU, if you need prose output rather than typed answers, or if the model catalogue does not cover your task.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The contract is a probability, not a paragraph

The pitch is unusually specific: send the server a state and a set of typed questions, and get back a probability and a confidence for each answer in tens of milliseconds. The key design decision is stated without hedging. OpenJev reads the answers directly from the model probabilities and parses no text, so an answer cannot go off-schema. That is the whole argument for the project, and it is a good one. A system that decides based on parsing generated text inherits every failure mode of generation: format drift, refusal, truncation, a sentence that happens to be phrased differently. Here the output shape is fixed by the request, and the values are read from a distribution. The audience is developers building routing, triage or classification logic who want a decision that carries its own uncertainty rather than a string they have to defend. The name System One comes from the model family TypeSafe introduced, and openjev positions itself as an independent, open implementation of that idea rather than a client of the hosted one.

Reading answers out of a diffusion canvas

The default model is DiffusionGemma 26B-A4B from NVIDIA and Google, listed as 26B total parameters with 4B active, served with the openjev-latest alias for openjev-0.1. What is unusual is how it is read: as a diffusion canvas rather than as a text generator. The server asks many questions in chunks of about twelve per read, and those chunks run in parallel. The Server-Timing header exposes how the time splits, with fields for model, server and total durations, such as `server-timing: model;dur=41.2, server;dur=2.8, total;dur=44.0`. The model figure is the time spent in the model, summed over the request reads, and it can exceed total when the reads run in parallel. The server figure is everything else, meaning schema compile, tokenization, validation and serialization. Neither includes your network. That breakdown is unusually honest for a project description, and it tells you where to optimise: if the model term dominates, the hardware or the model size is the constraint, and if the server term dominates, the schema work is. The same DiffusionGemma also serves text generation under the separate model id diffusiongemma-26b, so the server exposes both a decision path and an OpenAI-style chat completions path from one weight set.

Three question types, one confidence formula

The typed question set is small on purpose. A noul question is the yes/no form and takes optional criteria with a true and a false entry, returning the probability of yes as noul. A choice question takes a mapping of option names to descriptions and returns the chosen option along with the full probability vector and a confidence. A score question takes a list of ordered levels, one to ten of them, and returns a weighted expected level, the legend, the probabilities and a confidence. A score with a single level is answered directly, in the same way a choice with one option is. Confidence is defined as one minus the normalised entropy of the probability distribution, so it is 1 when the model is certain and 0 when the distribution is uniform. That definition is worth understanding precisely, because it is a property of the distribution shape rather than a calibration claim, and a model that is confidently wrong will report high confidence. The response also carries usage counters, where input_tokens counts prompt tokens including image tokens, and output_tokens stays at zero unless you set think.

Existing SDKs work because the wire API matches

Adoption friction is low if you already speak the protocol. OpenJev uses the same wire API as TypeSafe's Jev, so their SDKs work against it unchanged, and it also answers OpenAI's Decisions API, so the OpenAI SDK's client.decisions.create works too. The endpoint table lists POST /v1/systemone taking state, model and questions and returning model, answers and usage, plus POST /v1/decisions for the OpenAI shape, POST /v1/chat/completions for text generation, and GET /v1/models. Trying it against the free hosted instance on Codiv takes three environment variables:

bash
pip install typesafe-sdk
export TYPESAFE_BASE_URL=https://api.codiv.ai   # or http://127.0.0.1:8080 for your own server
export TYPESAFE_API_KEY=sk-codiv-...

Then a typed request in Python:

python
from typesafe_sdk import TypeSafeClient

client = TypeSafeClient()
r = client.system_one(
    "Everything is down and we have a demo with our biggest client at noon.",
    {
        "urgent": {"type": "noul", "instructions": "Does the customer need a reply within the hour?"},
        "team":   {"type": "choice", "instructions": "Which team should handle it?",
                   "criteria": {"outage": "service down", "billing": "charges, refunds", "feature": "requests, how-to"}},
        "tone":   {"type": "score", "instructions": "How upset is the customer?",
                   "criteria": ["calm", "annoyed", "furious"]},
    },
)

The same call over HTTP:

bash
curl https://api.codiv.ai/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" -H "Content-Type: application/json" \
  -d '{"model": "openjev-latest", "state": "I was charged twice this month.",
       "questions": {"is_billing": {"type": "noul", "instructions": "Is this a billing issue?"}}}'

Note that the state is a plain sentence and the criteria carry the domain vocabulary, which is where a triage system injects its own knowledge.

Error shapes are specified because clients depend on them

The documentation says the error shapes are the same as Jev, checked against the live API, and then lists them, which is a level of care most projects skip. A field of the wrong shape returns 422 with a FastAPI validation list. A question the server cannot ask, meaning no options, too many options or too many score levels, returns 400 with a plain text reason. An unknown model or question type returns 400 with the api_usage_error code. Authentication problems return 401 or 403 with a detail object carrying error_type and message. Rate limits give 429 and an overloaded server gives 529. The differences from Jev are equally worth noting. Model names are OpenJev's own, with jev-latest and jev-preview accepted as aliases, so TypeSafe SDK defaults resolve, but a pinned Jev version such as jev-1.13.0 gets a 400 Unknown model. A server running only one of the other models maps the Jev aliases to that model, which is convenient but means a client that assumes the latest alias means DiffusionGemma may get something else entirely.

Running it yourself means sharing one GPU between three services

The compose file is where the operational cost becomes visible. OpenJev runs vLLM with DiffusionGemma structured reads and the Jev-compatible API on port 8080 in one container, and two small encoder models run beside it on the same GPU, each in its own container, with the openjev container passing their requests through so a single port serves all three models. The main service looks like this:

yaml
services:
  openjev:
    build: {context: ., dockerfile: docker/Dockerfile}
    image: razorback16/openjev:0.7.0
    environment:
      OPENJEV_CANVAS: "64"
      OPENJEV_MAX_NUM_SEQS: ${OPENJEV_MAX_NUM_SEQS:-64}
      OPENJEV_MAX_MODEL_LEN: ${OPENJEV_MAX_MODEL_LEN:-65536}
      OPENJEV_GPU_UTIL: ${OPENJEV_GPU_UTIL:-0.9}
      OPENJEV_API_KEY: ${OPENJEV_API_KEY:-}
      OPENJEV_ORIGIN_SECRET: ${OPENJEV_ORIGIN_SECRET:-}
      # with the clm or jevk5 profile, add clm-v0.1=http://clm:8080 or jevk5-0.3=http://jevk5:8080
      OPENJEV_MODEL_ROUTES: ${OPENJEV_MODEL_ROUTES:-laya-1.0=http://laya:8080,verdict-1.4=http://verdict:8080}
      HF_TOKEN: ${HF_TOKEN:-}

The rest of the service definition sets the volumes for the Hugging Face cache, a vLLM cache and a flashinfer cache holding NVFP4 MoE kernels that are compiled on first start in about four minutes, publishes port 8080 bound to 127.0.0.1 unless you change OPENJEV_BIND, requests host IPC, and reserves all GPUs:

yaml
    volumes:
      - ${HF_HOME:-~/.cache/huggingface}:/root/.cache/huggingface
      - vllm-cache:/root/.cache/vllm
      - flashinfer-cache:/root/.cache/flashinfer   # its NVFP4 MoE kernels, compiled on first start (about 4 min)
    ports:
      - "${OPENJEV_BIND:-127.0.0.1}:8080:8080"
    ipc: host
    deploy: &gpu
      resources:
        reservations:
          devices: [{driver: nvidia, count: all, capabilities: [gpu]}]
    restart: unless-stopped

The memory arithmetic is documented as well: the encoder models take 2.5 GB for Laya and 1.2 GB for Verdict, measured at a full batch, and the guidance is to lower OPENJEV_GPU_UTIL to leave vLLM's neighbours that much room. That is the kind of detail that saves an afternoon, since the default of 0.9 leaves very little space. On Apple silicon the picture is different: the mlx extra installs mlx-vlm for an in-process backend selected with OPENJEV_BACKEND=mlx, and the small encoder models use laya and verdict extras that both need PyTorch.

A catalogue of other people's models and two licence questions

The model table is longer than the headline model, and reading it carefully changes what you are adopting. Besides DiffusionGemma there is Laya at 421M with 1024 text tokens and up to 255 choices running on PyTorch on GPU or CPU, Verdict at 151M with 512 tokens and up to 24 choices, CLM which is contrastive heads over Qwen3-8B, JevK5 which is Qwen3.5-4B with a distilled LoRA read by its answer letters, and two Cloudflare models, Clef and Clef-flash, which use a joint schema head on Qwen3.8-27B and Qwen3.5-9B in NVFP4 and need vLLM on NVIDIA Blackwell. The project states that all the weights of the DiffusionGemma family are Apache-2.0 and that the server itself is Apache-2.0, with Laya, Verdict, CLM, JevK5 and Clef being other people's models credited to their authors. That is the licence distinction to hold on to: the server licence and the model licences are separate questions, and the Clef models in particular come with a size and hardware requirement that rules them out for many machines. OpenJev itself is independent and states plainly that it is not affiliated with or endorsed by TypeSafe AI.

Development is active but releases live outside GitHub

The maintenance picture needs two signals. The last push to the repository was on 2026-10-13, so the code is being worked on, and the package version in pyproject.toml is 0.7.2 with a requires-python floor of 3.10 and a build backend of setuptools at version 69 or newer. The dependencies are deliberately light for a server: fastapi, uvicorn with the standard extra, httpx, transformers at 4.56 or newer, tokenizers and jinja2, with pytest, typesafe-sdk and openai in the test extra. There is a CHANGELOG.md at the root and a tests directory, and the compose file builds from docker/Dockerfile plus one Dockerfile per encoder model, all of which start from a shared base image so the layers are reused. The other signal is that the repository has no GitHub releases. If you plan to pin a version in production, you have to take it from the compose image tag or the package version rather than from a release list, and the example tag in the compose file is an older 0.7.0 while the package metadata already says 0.7.2. That gap is small but it is exactly the kind of thing to check before you write a deployment around a version number.

Editorial conclusion

Adopt openjev when you need decisions with a probability attached, when you want them served from your own GPU with open weights, and when you already use TypeSafe's SDK so the wire compatibility removes integration work. Do not choose it if you need a hosted service with no GPU, if you need prose output rather than typed answers, or if the model catalogue does not cover your task. Before starting, confirm the GPU memory headroom the encoder services need and whether OPENJEV_GPU_UTIL leaves room for them, decide whether you run vLLM or the in-process MLX backend on Apple silicon, and read the model rows carefully, because several of the listed models are other people's work with their own terms.

Frequently asked questions

What is openjev and what does it return?

openjev is an Apache-2.0 decision server that takes a state plus typed yes/no, choice and score questions and returns a probability and a confidence for each answer, in tens of milliseconds. It reads the answers from the model probabilities and parses no text.

Can I use the TypeSafe SDK or the OpenAI SDK with openjev?

Yes. openjev uses the same wire API as TypeSafe's Jev, so their SDKs work unchanged, and it also answers OpenAI's Decisions API, so client.decisions.create from the OpenAI SDKs works. Point the client at your own server with TYPESAFE_BASE_URL=http://127.0.0.1:8080.

How is the confidence value calculated?

Confidence is 1 minus H(p) divided by ln K, so it is 1 when the distribution over answers is certain and 0 when it is uniform. It describes the shape of the distribution rather than being a calibration guarantee.

What hardware does openjev need to run itself?

The compose setup runs vLLM with DiffusionGemma on an NVIDIA GPU, with the small encoder models Laya and Verdict running in their own containers on the same GPU, taking 2.5 GB and 1.2 GB respectively at a full batch. On Apple silicon the in-process MLX backend is used instead, selected with OPENJEV_BACKEND=mlx.

Which models does openjev serve?

The default is DiffusionGemma 26B-A4B under the openjev-latest alias, and the catalogue also lists Laya, Verdict, CLM, JevK5, Clef and Clef-flash, each with its own size, context length and hardware requirement. The server also accepts jev-latest and jev-preview as aliases.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Project website
  4. razorback16/openjev on GitHub
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/razorback16-openjev.svg)](https://hysenlabs.com/projects/razorback16-openjev)

Was this useful?