Jev Recipe / 架构对比
Jev vs Instructor:告别 JSON 重试与长尾延迟的确定性决策
对比 Instructor Pydantic 重试循环与 Jev 原生 typed call:在同一工单路由场景下,看清延迟、token 成本与格式错误率的工程差距。
从 Instructor 迁移到 Jev 的 3 个步骤
01先定义与 Instructor Pydantic 模型等价的 bounded Choice schema —— 队列、评分或二值门禁。
02用一次 Jev evaluate 调用替换「生成 → 解析 → 校验 → 重试」循环,单次前向推理返回 typed 概率。
03在业务代码里用 confidence 阈值分流到人工复核,而不是用指数退避重试风暴掩盖格式错误。
schema / 共享决策契约
{
"routing": {
"type": "choice",
"instructions": "把工单分到正确队列",
"criteria": {
"billing": "付款、退款或发票",
"technical": "产品故障或使用问题",
"sales": "购买、升级或报价",
"abuse": "安全或滥用举报"
}
}
} 此 schema 与 Instructor Pydantic 模型等价,可直接在 Playground 验证零重试结果。
架构基准对比:Jev vs Instructor / Guardrails
METRIC
Jev
Instructor / Guardrails
中位延迟 (P50)
~100ms
单次前向推理,无 token 生成
2500ms+
自回归输出 + 解析 + 校验
输出 token 成本
$0.00 / M tokens(零输出 token)
完整生成计费($0.60–$15 / M out)
格式 / Schema 错误率
0%
原生 typed Choice / Score / Noul 输出
5~15% Pydantic 校验失败(边界案例)
重试行为
零重试,一次调用即得 typed 结果
指数退避重试(2^n × 基础延迟)
校准置信度
RLCD 概率与真实准确率对齐
模型自报,不适合做路由门限
代码对比:重试循环 vs 零重试 typed 调用
python / instructor 重试循环
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) # 指数退避
# 典型路径:1800ms+ 延迟,每次尝试计费 20~50 output tokenspython / jev 零重试 typed 调用
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": "把工单分到正确队列",
"criteria": {
"billing": "付款、退款或发票",
"technical": "产品故障或使用问题",
"sales": "购买、升级或报价",
},
}
},
},
timeout=5,
)
response.raise_for_status()
return response.json()["routing"]
# 典型路径:~100ms,仅消耗 input tokens,0% 格式错误typescript / instructor 重试循环
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 零重试 typed 调用
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: "把工单分到正确队列",
criteria: {
billing: "付款、退款或发票",
technical: "产品故障或使用问题",
sales: "购买、升级或报价",
},
},
},
}),
});
if (!response.ok) throw new Error("Jev evaluate failed");
const data = await response.json();
return data.routing as { answer: string; confidence: number };
}