Alpha · local runtime · explicit criteria
Just Judgment Machine
PE:TL;DR
The payoff is a fast, solid judgment. Fit it on a few cases you have already labeled, in the buckets you use. The next case comes back in a few milliseconds, on your machine: a weight over those buckets, and a record of how the judgment was made.
A chat model can make the same choice. It also writes a paragraph. On the comparison below, a 9B chat model took about 390 ms for each of 400 notes. The fitted head took a few milliseconds on all 3,080. Use a chat model when you need the writing. Use JJM when the question is closed and there are many of them.
JJM does not try to talk. It makes the judgment: a weight for each option you allowed, the method and the model that produced it, and a pass, hold, or reject against checks you declared. Your application decides what happens next.
Alpha · Apache-2.0 · runs on your machine
What you might hand it
- A support note, to sort into the teams you already use.
- A receipt, a log, or a short passage, to see whether it settles the question.
- An application or a review, to place into the ratings you defined, once you have labelled a few.
- A tool result or a document snippet, to return as one of the answers you allowed.
What you send
A JSON request with a snapshot and explicit criteria. A choice has two to 26 options you define. An assertion has three outcomes: the supplied evidence supports the claim, contradicts it, or does not settle it.
{
"state": {
"content": {
"ticket": "I was charged twice for the same subscription."
}
},
"criteria": [{
"id": "route-ticket",
"kind": "choice",
"question": "Which team should own this ticket?",
"options": [
{ "id": "billing" },
{ "id": "technical" },
{ "id": "other" }
]
}],
"requirements": { "min_top_mass": 0.5 }
}
Shortened from examples/route-ticket.json. The file also names the scope, the profile, and the evidence list.
What you get back
- A weight over every option you allowed.
- Provenance. The method, the model, and digests of the inputs.
- Your check. Pass, hold, or reject against requirements you declared. A pass means those requirements were met. The next action stays with your application.
Weights are a normalized readout. A request that requires a validated scope abstains until that scope has an accepted held-out report. That status records the report. It is the same head output.
{
"results": [{
"criterion_id": "route-ticket",
"prediction": {
"weights": {
"billing": 0.892,
"technical": 0.005,
"other": 0.103
},
"semantics": "normalized_readout",
"selected": "billing"
},
"acceptance": { "status": "pass" },
"provenance": {
"method": "mock:normalized",
"model": { "id": "jjm/synthetic-no-model" }
}
}]
}
Shortened from the no-model command below, with the weights rounded. They are a hash of the input, so this pass is not a judgment that the ticket is billing. The full envelope also includes the digests, the checks, and that notice.
What has been tried
Banking77, mapped to eight teams, scored against the human labels, on one laptop GPU.
| Right | Time per note | |
|---|---|---|
| Fitted head | 97.1% of 3,080 | a few milliseconds |
| Nimble, a 9B decision model | 91.6% of 3,080 | 694 ms |
| A 9B chat model, asked to pick | 88% of 400 | 390 ms |
The head had seen the human training labels. The other two had seen none. About 64 labels per team is where the head matches Nimble, and it stays at a few milliseconds. The 97.1% is the earlier fit. A refit scored 96.8%. The head's time is a batch of short notes, about 5 ms each. One note at a time is about 11 ms. The other times are medians.
On fit rank for one candidate, the chat-wrapped reranker encoding tracked the teacher's ranks.
The figures and the hardware are in the experiment log.
Limits
- The eight-ticket walkthrough has been run on the author's machine. It downloads one small encoder and fits those eight rows.
- Routing was measured on Banking77, eight teams, human labels, on one laptop GPU. The fitted head used the training labels. About 64 labels per team is where it lines up with Nimble on that set.
- Fit rank was measured on one candidate. The chat-wrapped reranker encoding is the input that tracked the teacher's ranks.
Try it with no model
The synthetic path needs no download. Its weights are a hash of the input, so they carry no meaning. They show the envelope.
uv sync
uv run jjm evaluate --request examples/route-ticket.json
The fitted-head walkthrough is in the repository README. JJM depends on AnyJev, Apache-2.0. JJM is not affiliated with TypeSafe AI or Jev.
Built by Catalyst Forge LLC.