Jev Recipe / 出力契約比較

Jev vs JSON Mode:型付き意思決定と制約付き生成の比較

json_mode が保証するのは「有効な JSON」であって「正しい答え」ではありません。リトライコスト・レイテンシ・出力課金・較正済み信頼度を、Jev のゼロ生成型付き呼び出しと対比します。

JSON mode をやめる前の 6 つのチェック

01json_mode が実際に保証するものを名指す:構文的な妥当性です。response_format: {type: "json_object"} は、壊れた JSON リテラルを決して出力しないことだけを約束します——あなたのキー、列挙値、そして答え自体の正しさについては何も言いません。
02パイプラインに必要な3つの保証を分離する:構文の妥当性(json_mode)、スキーマ適合(structured outputs / json_schema)、値の正しさ(誰も保証しない)。制約付きデコーディングは最初の2つを埋めますが、3つ目——ルーティングを壊すのはこっち——は開いたままです。
03出荷前にリトライ税を値付けする:schema 通りの形状でも列挙値を幻覚すれば、完全な生成コストがそのまま掛かり、検証 failure のたびに再請求されます。分類量では、リトライは例外的な出来事ではなくコストモデルそのものです。
04信頼度を正直に扱う:トークン単位の logprob は「次の文字をどれほど確信してタイプしようとしていたか」の尺度であって、「その判断がどれほど正しいか」ではありません。RLCD 較正済みの確率だけが、0.85 のしきい値を精度の契約に変えます。
05処理量に対してレイテンシ曲線を確認する:生成時間は出力長に比例します——典型的な JSON ペイロードで 500ms〜2s+、リトライでその倍かけ。Jev の evaluate 呼び出しは、質問をいくつ詰めても一回のフォワードパスで約 70–100ms で型付きの答えを返します。
06制約付き生成が依然として正しい道具である場面を知る:自由形式のコンテンツ——要約、可変長リスト、ネストした生成フィールド——は Jev の守備範囲外です。有界な判断は Jev へ、生成ペイロードは制約付き呼び出しへ、同じパイプラインで住み分けさせましょう。
schema / 型付き決定契約
{
  "intent": {
    "type": "choice",
    "instructions": "この受信メッセージの種別を判定する",
    "criteria": {
      "billing": "支払い・請求・返金関連",
      "technical": "製品の不具合やバグ",
      "sales": "購入・アップグレード・価格の相談",
      "abuse": "安全性または悪用の報告"
    }
  },
  "is_actionable": {
    "type": "noul",
    "instructions": "このメッセージはチームの対応が必要か、それとも単なる情報共有か?"
  },
  "priority": {
    "type": "score",
    "instructions": "対応優先度を評価、1(空いたときで)から 5(手持ちを止めて即対応)"
  }
}
このスキーマは「JSON schema + 検証レイヤー」が近似的に表現しようとしてきたものです。Playground で走らせると、答えと較正済み信頼度が一回のパスで返ってくるのを確認できます。

出力契約:Jev の型付き決定ヘッド vs json_mode / structured outputs

METRIC
Jev
json_mode / structured outputs
実際に保証されるもの
決定ヘッドによる型付き回答——値レベルの契約:選択肢の1つ、スコア、yes/no
json_mode:有効な JSON 構文のみ;structured outputs:schema 通りの形状——フィールド値は生成されたまま
規模化したときの失敗モード
パース工程が存在しない——構造的にフォーマットエラー 0%
JSON としては有効だが値が誤り・欠落:幻覚した列挙ラベル、もっともらしい誤判定——失敗のたびに課金付きリトライ
レイテンシ特性
約 70–100ms で一定——生成なし、質問数に依存しない
出力長に比例——典型的なペイロードで 500ms〜2s+、リトライでさらに倍増
出力トークンコスト
$0——出力トークンが存在しない
試行ごとに完全な出力課金;リトライで丸ごと再請求
信頼度のセマンティクス
RLCD 較正済みの判断信頼度——0.85 ≈ しきい値上で 85% の精度
せいぜいトークン単位の logprob——サンプリング統計であり、判断の較正ではない
ペイロード内の自由形式コンテンツ
非対応——決定ヘッドは有界な値のみ返し、散文は決して書かない
本来の得意分野——要約、可変長リスト、ネストした生成フィールド

コード対照:制約付き生成 vs Jev 型付き呼び出し

python / openai json_mode + 値検証リトライループ
import json
import time
from openai import OpenAI

client = OpenAI()
VALID_QUEUES = {"billing", "technical", "sales", "abuse"}
MAX_RETRIES = 3

def route_ticket(ticket_text: str) -> dict:
    for attempt in range(MAX_RETRIES):
        resp = client.chat.completions.create(
            model="gpt-4o-mini",
            response_format={"type": "json_object"},
            messages=[
                {"role": "system", "content": 'Reply as JSON: {"queue": "...", "urgent": true|false}'},
                {"role": "user", "content": ticket_text},
            ],
        )
        payload = json.loads(resp.choices[0].message.content)  # json_mode: 必ずパースできる
        if payload.get("queue") in VALID_QUEUES:  # 値の検証: json_mode はここに何も言えない
            return payload
        time.sleep(2 ** attempt)  # 幻覚した列挙値 -> 生成全体を再請求
    raise ValueError("queue never converged")

# 典型経路: 試行ごとに 500-1500ms、リトライのたびに 20-60 出力トークンを請求
python / jev 型付きマルチ質問呼び出し
import requests

JEV_ENDPOINT = "https://api.typesafe.ai/v1/jev/evaluate"
AUTO_ROUTE_CONFIDENCE = 0.85

QUESTIONS = {
    "intent": {
        "type": "choice",
        "instructions": "この受信メッセージの種別を判定する",
        "criteria": {
            "billing": "支払い・請求・返金関連",
            "technical": "製品の不具合やバグ",
            "sales": "購入・アップグレード・価格の相談",
            "abuse": "安全性または悪用の報告",
        },
    },
    "is_actionable": {
        "type": "noul",
        "instructions": "このメッセージはチームの対応が必要か?",
    },
    "priority": {
        "type": "score",
        "instructions": "対応優先度を評価、1(空いたときで)から 5(手持ちを止めて即対応)",
    },
}

resp = requests.post(
    JEV_ENDPOINT,
    json={"state": {"message": "..."}, "questions": QUESTIONS},
    timeout=5,
)
resp.raise_for_status()
data = resp.json()

if data["intent"]["confidence"] >= AUTO_ROUTE_CONFIDENCE:
    lane = f"auto:{data['intent']['answer']}"  # 約70-100ms、入力トークンのみ、ゼロリトライ
else:
    lane = "review"
typescript / openai structured outputs(json_schema)
import OpenAI from "openai";
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";

const RouteDecision = z.object({
  queue: z.enum(["billing", "technical", "sales", "abuse"]),
  urgent: z.boolean(),
});

const client = new OpenAI();

const resp = await client.chat.completions.create({
  model: "gpt-4o-mini",
  response_format: zodResponseFormat(RouteDecision, "route_decision"),
  messages: [{ role: "user", content: ticketText }],
});

const decision = RouteDecision.parse(
  JSON.parse(resp.choices[0].message.content!),
);
// 形状は保証される。"queue" が正しいキューか——そしてモデルがどれだけ
// 確信しているか——は表現できない。手に入るのは推測であって、較正された判断ではない。
typescript / jev 型付きマルチ質問呼び出し
const JEV_ENDPOINT = "https://api.typesafe.ai/v1/jev/evaluate";
const AUTO_ROUTE_CONFIDENCE = 0.85;

const QUESTIONS = {
  intent: {
    type: "choice",
    instructions: "この受信メッセージの種別を判定する",
    criteria: {
      billing: "支払い・請求・返金関連",
      technical: "製品の不具合やバグ",
      sales: "購入・アップグレード・価格の相談",
      abuse: "安全性または悪用の報告",
    },
  },
  is_actionable: {
    type: "noul",
    instructions: "このメッセージはチームの対応が必要か?",
  },
  priority: {
    type: "score",
    instructions: "対応優先度を評価、1(空いたときで)から 5(手持ちを止めて即対応)",
  },
} as const;

const resp = await fetch(JEV_ENDPOINT, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    state: { message: ticketText },
    questions: QUESTIONS,
  }),
});
const data = await resp.json();

const lane =
  data.intent.confidence >= AUTO_ROUTE_CONFIDENCE
    ? `auto:${data.intent.answer}`
    : "review"; // 低信頼帯・安全フラグ -> 同じレビューキューへ

Jev vs JSON Mode FAQ

JSON mode とは何ですか?

OpenAI のチャット補完機能——response_format: {"type": "json_object"}——で、現在は主要プロバイダのほとんどが同等機能を提供しています。モデルを構文的に有効な JSON のみを出力するよう制約します:markdown のフェンスなし、前後の散文なし。ただし保証されるのはパース可能性だけです。キー、列挙値、そして答えの正しさはモデルの推測のまま——だから本番コードは今も json_mode 呼び出しをスキーマ検証とリトライループで包んでいるのです。

JSON mode と structured outputs は同じものですか?

いいえ。JSON mode(json_object)は有効な JSON 構文を保証します。structured outputs(json_schema)はさらに進んで、制約付きデコーディングによって schema に一致する形状を強制します。しかし両方ともペイロードをトークン単位で生成し続けます:レイテンシは出力長に比例し、出力トークンは課金され、値の正しさは保証されません。structured outputs は形状のギャップを埋めますが、判断品質のギャップは開いたままです。

JSON が有効なのに、なぜパイプラインは壊れ続けるのですか?

規模化したときに難しいのはパース可能性ではなく、値の正しさだからです。schema に適合しながら列挙値を幻覚した返答、「もっともらしいが誤った」ルーティング、欠落したフィールド——きれいにパースできてもアプリケーションは失敗する。そのたびに検証リトライが走り、生成全体を再請求される。実測の failure 率 × 1 呼び出しの出力コスト × QPS を掛け算してください。それが「較正なしの推測」の値札です。

json_mode や structured outputs から信頼度スコアを取得できますか?

判断に使える形では取得できません。logprob はサンプリング分布のもとで各トークンが生成されやすかった度合い——タイプする自信の尺度であり、判断の正確さの尺度ではありません。高いトークン確率で出力されたルーティングラベルでも、判断としては誤り得ます。Jev の確率は結果に対して RLCD 較正されており、0.85 のしきい値は精度の契約として振る舞います。この性質こそが、数値に対する自動化を安全にするものです。

Jev の代わりに JSON mode を使い続けるべきときは?

ペイロードに自由形式の生成コンテンツが必須のとき:要約、説明、可変長リスト、抽出した散文、テキストフィールドを含むネストしたオブジェクト。Jev の決定ヘッドは有界な値しか返せません——段落は書けません。本番のパターンは作業を分割することです:有界な質問(ルーティング・ゲート・スコアリング・yes/no)には Jev が約 95ms の1呼び出しで答え、制約付き生成の呼び出しが生成フィールドを埋める。

Instructor や OpenAI の Decision API(Luna)とはどう違いますか?

同じ問題の異なるレイヤーです。Instructor は生成を Pydantic 検証とリトライループで包むライブラリ——その軸は Jev vs Instructor 比較を。json_mode と structured outputs は API レベルでの生成への制約——このページです。OpenAI の GPT-6 Luna ベース Decisions API は別の非生成製品で、事前定義された回答集合から1つの答えと信頼度を返します——契約レベルの比較は Jev vs OpenAI Decision API を。どこでも矢印の向きは同じです:生成テキストのパースから離れ、型付き判断へ向かう。

構造化出力ファミリーをさらに深く