jev
A visual guide to Jev, a model for typed decisions.
a model for typed decisions.
Most of the models we’ve become familiar with over the last couple of years are LLMs; we feed words, they return words.
This has been quite useful, especially when we need a model to be generative or reason through a problem. But the thing is, much of the work that we want most agents to do involves evaluating an input and deciding what to do next. We’re asking for a decision, but generating it as text, token by token, for our software to then parse and act on is both extremely slow and quite expensive.
This is where Jev comes in. It takes text or structured data as input and returns typed decisions with probabilities, making those decisions not only faster and cheaper, but also practical in places where using a model previously wasn’t.
we define the decision at call time.
What Jev's doing isn't new, models like BERT have been able to do classification for a while, which is assigning an input to a category i.e., identifying a message as a complaint or an enquiry. But the difference is, these previous models were specialised and were typically trained on specific datasets and categories, changing the categories means retraining the model.
With Jev, we finally have a general-purpose classifier where we can define the categories in the request and change them without retraining the model, and what makes this even more interesting is that, according to TypeSafe, its training data is 100% synthetic.
It's probably worth mentioning that we can already constrain an LLM to an output schema to create the same/similar behaviour, but the difference here is in how the values are computed, which makes all difference.
The linter below runs this live: we can write a rule in natural language and every function beneath it is judged against it as we type. Not only does this work for code, but also for prose. Try updating the rule.
Judging…
function formatPrice(pence: number): string {
return `£${(pence / 100).toFixed(2)}`;
}function formatPrice(pence: number): string {
return `£${(pence / 100).toFixed(2)}`;
}function getUser(id: string) {
const user = db.find(id);
if (!user) throw new Error("error");
return user;
}function getUser(id: string) {
const user = db.find(id);
if (!user) throw new Error("error");
return user;
}function saveOrder(order: Order) {
validate(order);
db.write(order);
email.sendReceipt(order);
analytics.track("order_saved");
}function saveOrder(order: Order) {
validate(order);
db.write(order);
email.sendReceipt(order);
analytics.track("order_saved");
}async function fetchOrders(userId: string) {
try {
return await api.get(`/orders/${userId}`);
} catch {
return [];
}
}async function fetchOrders(userId: string) {
try {
return await api.get(`/orders/${userId}`);
} catch {
return [];
}
}function retryDelay(attempt: number): number {
return Math.min(attempt * 750, 30000);
}function retryDelay(attempt: number): number {
return Math.min(attempt * 750, 30000);
}function deleteAccount(id: string) {
db.remove(id);
}function deleteAccount(id: string) {
db.remove(id);
}input in, typed decisions out.
The output schema uses three primitives depending on the kind of judgement involved. A Choice selects from options we define and returns the probability distribution across them, while a Score evaluates the input and returns a numerical score. When the question is whether a statement is true, TypeSafe’s Noul returns that probability directly as a value between zero and one.
We can also ask several questions about the same input in one request, which TypeSafe says Jev evaluates in parallel, provided none depends on another’s answer.
Choice and Score also return a confidence value derived from their distributions, whereas Noul has no separate confidence field. This gives the calling code access to uncertainty alongside the result, so it can take that uncertainty into account when deciding what should happen next.
application behaviour could become more context-dependent.
All software comes down to state, and decisions that need to be made against that state when certain conditions are met. Sometimes the condition is as simple as “does x have a value?”, but often the condition we want met is contingent on a judgement, such as “is this urgent?” or “does this say enough?”, and for those we end up reaching for proxies, i.e., a character minimum in place of the judgement.
Jev, through its ability to return typed decisions with probabilities, increases our ability to make judgements, cheaply and quickly enough to replace the proxies with the judgement itself.
That changes the kind of software we can actually build: software whose behaviour isn’t fully written in advance, where we can build features without having to anticipate every workflow someone might need.
Let's look at this somewhat trivial example below: submitting the bug report is guarded by a sentence rather than a required-field check. Try describing a bug, or rewriting the condition entirely.