Jev recipe / architecture comparison
Jev vs Instructor: Zero-Retry Structured Decisions
Compare Instructor Pydantic retry loops with Jev native typed calls. See latency, token cost, and format-error differences on the same routing decision.
Migrate from Instructor to Jev in three steps
01Define the same bounded Choice schema you would enforce with Instructor Pydantic models — queues, scores, or binary gates.
02Replace the generate → parse → validate → retry loop with one Jev evaluate call that returns typed probabilities in a single forward pass.
03Route low-confidence results to human triage in application code instead of exponential backoff retry storms.
schema / shared decision contract
{
"routing": {
"type": "choice",
"instructions": "Route this support ticket",
"criteria": {
"billing": "Payment or invoice",
"technical": "Product malfunction",
"sales": "Buying or upgrade question",
"abuse": "Safety or abuse report"
}
}
} This schema mirrors your Instructor Pydantic model — validate zero-retry results in the Playground.
Architecture benchmark: Jev vs Instructor / Guardrails
METRIC
Jev
Instructor / Guardrails
Median latency (P50)
~100ms
single forward pass, no generation
2500ms+
autoregressive output + parse + validate
Output token cost
$0.00 / M tokens (zero output tokens)
Full generation pricing ($0.60–$15 / M out)
Format / schema error rate
0%
native typed Choice / Score / Noul output
5–15% Pydantic validation failures on edge cases
Retry behavior
Zero retries required
Exponential backoff loops (2^n × base delay)
Calibrated confidence
RLCD probabilities tied to real accuracy
Self-reported; uncalibrated for routing gates
Side-by-side code: retry loop vs zero-retry
python / instructor retry loop
import time
import instructor
from openai import OpenAI
from pydantic import BaseModel, ValidationError
class RouteDecision(BaseModel):
queue: str
client = instructor.from_openai(OpenAI())
MAX_RETRIES = 3
def route_ticket(ticket_text: str) -> RouteDecision:
for attempt in range(MAX_RETRIES):
try:
return client.chat.completions.create(
model="gpt-4o-mini",
response_model=RouteDecision,
messages=[{"role": "user", "content": ticket_text}],
)
except ValidationError:
if attempt == MAX_RETRIES - 1:
raise
time.sleep(2 ** attempt) # exponential backoff
# Typical path: 1800ms+ latency, 20–50 output tokens billed per attemptpython / jev zero-retry typed call
import requests
def route_ticket(ticket_text: str) -> dict:
response = requests.post(
"https://api.typesafe.ai/v1/jev/evaluate",
json={
"state": {"message": ticket_text},
"questions": {
"routing": {
"type": "choice",
"instructions": "Route this support ticket",
"criteria": {
"billing": "Payment or invoice",
"technical": "Product malfunction",
"sales": "Buying or upgrade question",
},
}
},
},
timeout=5,
)
response.raise_for_status()
return response.json()["routing"]
# Typical path: ~100ms, input tokens only, 0% format errorstypescript / instructor retry loop
import OpenAI from "openai";
import Instructor from "@instructor-ai/instructor";
import { z } from "zod";
const RouteDecision = z.object({ queue: z.string() });
const client = Instructor({ client: new OpenAI(), mode: "TOOLS" });
async function routeTicket(ticket: string, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.chat.completions.create({
model: "gpt-4o-mini",
response_model: RouteDecision,
messages: [{ role: "user", content: ticket }],
});
} catch {
if (attempt === maxRetries - 1) throw new Error("schema validation failed");
await new Promise((r) => setTimeout(r, 2 ** attempt * 1000));
}
}
}typescript / jev zero-retry typed call
async function routeTicket(ticket: string) {
const response = await fetch("https://api.typesafe.ai/v1/jev/evaluate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
state: { message: ticket },
questions: {
routing: {
type: "choice",
instructions: "Route this support ticket",
criteria: {
billing: "Payment or invoice",
technical: "Product malfunction",
sales: "Buying or upgrade question",
},
},
},
}),
});
if (!response.ok) throw new Error("Jev evaluate failed");
const data = await response.json();
return data.routing as { answer: string; confidence: number };
}