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 tokens
python / 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 };
}

继续评估成本与接入