GUIDES / ツール連携

AI SDK の experimental_evaluate で Jev を使う

AI SDK v7 の experimental_evaluate から Jev を呼ぶ方法。Gateway 経由と直結、Noul が boolean になる点、確信度の取り出し方、環境変数名の違いを実行結果つきで説明する。

JevAI SDKVercel

Vercel AI SDK(ai v7)の experimental_evaluate を使うと、Jev を数行で呼べます。モデルを文字列で指定すれば Vercel AI Gateway 経由、@ai-sdk/typesafe-ai を使えば TypeSafe の API に直結です。

experimental です。 AI SDK の公式ドキュメントに「この API と評価モデルの仕様は experimental で、patch リリースでも変わり得る」とあります。このページは ai@7.0.105 で動かした結果です。

最小の例(Gateway 経由)

pnpm add ai@7.0.105

experimental な API は patch リリースでも変わり得るので、バージョンを固定して入れます。更新するときは、動作を確かめてから上げます。

// index.ts
import { experimental_evaluate as evaluate } from 'ai';

const result = await evaluate({
  model: 'typesafe-ai/jev',
  state: 'Help! My payouts have been failing for 3 days.',
  questions: {
    is_urgent: { type: 'boolean', instructions: 'Does this convey urgency?' },
  },
});

console.log(result.answers.is_urgent.probability); // 0.95

モデルを文字列で渡すと、既定では Vercel AI Gateway で解決されます。認証は環境変数 AI_GATEWAY_API_KEY(または Vercel の OIDC)です。

node --env-file=.env.local index.ts

.env.localAI_GATEWAY_API_KEY=… を書いておきます(Git には入れません)。Node.js 22.18 以降は TypeScript のファイルをそのまま実行できます。

3種類をまとめて聞く

const result = await evaluate({
  model: 'typesafe-ai/jev',
  state: { message: '助けてください!3日前から入金がずっと失敗しています。', plan: 'business' },
  questions: {
    is_urgent: { type: 'boolean', instructions: 'Does `message` convey urgency?' },
    department: {
      type: 'choice',
      instructions: 'Which team should handle `message`?',
      criteria: {
        billing: 'Payments, invoicing, refunds',
        technical: 'Bugs, outages, integrations',
        sales: 'Pricing, upgrades, new accounts',
      },
    },
    frustration: {
      type: 'score',
      instructions: 'How frustrated is the customer?',
      criteria: ['Calm', 'Frustrated', 'Very angry'],
    },
  },
});

実際に返ってきた値(2026-09-21):

{
  "answers": {
    "is_urgent":   { "type": "boolean", "probability": 0.95 },
    "department":  { "type": "choice", "choice": "billing",
                     "probabilities": { "sales": 0, "technical": 0.05, "billing": 0.95 } },
    "frustration": { "type": "score", "score": 1.08,
                     "probabilities": { "0": 0, "1": 0.92, "2": 0.08 } }
  },
  "usage": { "inputTokens": 435, "outputTokens": 73, "totalTokens": 508 },
  "rounding": { "probabilityDecimals": 2, "scoreDecimals": 2 },
  "providerMetadata": { "typesafe": { "confidence": { "department": 0.92, "frustration": 0.88 } } }
}

criteria のキーから型が推論されるので、result.answers.department.choice'billing' | 'technical' | 'sales' の型になります。存在しない選択肢を switch に書くと、コンパイル時に気づけます。

TypeSafe の API と呼び名が違うところ

比較項目TypeSafe の REST APIAI SDK
はい/いいえ の型"type": "noul"type: 'boolean'
その答えnoulprobability
確信度答えの中の confidenceresult.providerMetadata.typesafe.confidence[キー]
Score の legend返る返らない(自分が渡した criteria の配列を使う)
トークン数input_tokensinputTokens
答えたモデルmodel: "jev-1.13.0"result.response.modelId(Gateway 経由では typesafe-ai/jev が入っていた)

AI SDK は特定のベンダーに寄らない名前として boolean を使い、TypeSafe の noul に対応づけています。probability は常に「true である確率」で、答えへの確信度ではありません。

確信度を使うなら、こう取り出します。

const confidence = result.providerMetadata?.typesafe?.confidence as
  | Record<string, number>
  | undefined;

if ((confidence?.department ?? 0) < 0.7) {
  // 確信度が低いので人に回す
}

Gateway 経由でどのバージョンが答えたかを厳密に記録したい場合、response.modelId にはバージョン ID が入っていなかったので、その用途では直結か REST のほうが確実です。

Gateway を通さず直結する

pnpm add ai@7.0.105 @ai-sdk/typesafe-ai
import { typeSafeAi } from '@ai-sdk/typesafe-ai';
import { experimental_evaluate as evaluate } from 'ai';

const result = await evaluate({
  model: typeSafeAi.evaluationModel('jev-latest'),
  state: { message: 'I was charged twice. Please refund the duplicate.' },
  questions: {
    requestsRefund: { type: 'boolean', instructions: 'Is the customer requesting money back?' },
  },
});

環境変数の名前に注意してください。 AI SDK のプロバイダーが読むのは TYPESAFE_AI_API_KEY です。TypeSafe の公式 SDK や公式ドキュメントの例が使う TYPESAFE_API_KEY とは名前が違います。同じキーを両方の名前で設定するか、createTypeSafeAi({ apiKey }) で明示します。

import { createTypeSafeAi } from '@ai-sdk/typesafe-ai';
const typeSafeAi = createTypeSafeAi({ apiKey: process.env.TYPESAFE_API_KEY });

直結の側は、公式ドキュメントの記述を確かめたもので、このサイトでは実行していません(実行したのは Gateway 経由です)。

丸めと合計

TypeSafe は確率とスコアを小数2桁に丸めて返します。result.rounding にその桁数が入ります。値はそのまま保たれるので、確率の合計がちょうど 1 にならないことがあります。 合計が 1 であることを前提にした検算を自分のコードに入れないでください。

エラーと再試行

  • 一時的な失敗(429529)は AI SDK が再試行します。回数は maxRetries(既定 2)
  • 認証エラーや不正な入力は再試行されず、例外になります
  • モデルが対応していない質問の型が1つでもあると、呼び出し全体が Experimental_EvaluationUnsupportedQuestionTypeError で失敗します。一部だけ成功することはありません
  • 中断は abortSignal、追加のヘッダは headers

ほかのモデルに差し替えられるが、同じものではない

experimental_evaluate は OpenAI・Anthropic・Google の言語モデルでも動きます。テストや比較には便利です。ただし AI SDK の公式ドキュメントは次のように注意しています。

  • 言語モデルのアダプタは、全質問を1つのプロンプトで評価する。TypeSafe 本来の、質問ごとに独立した評価にはならない
  • 例に出てくるモデル ID は互換性を示すためのもので、性能で選んだ既定値ではない
  • どのモデルを使うかは、正解つきの自分のデータで比べて決める

使い分け

やりたいこと向いている入口
すでに AI SDK を使っている。手早く試したいexperimental_evaluate(このページ)
仕様変更の影響を受けたくない本番の処理REST API か TypeSafe の公式 SDK
答えたバージョン ID を確実に記録したいREST API(model にバージョン ID が返る)

質問の書き方そのものは入口によらず同じです。3つの質問タイプの書き方Jev が苦手なこと を先に読んでおくと、instructions の書き方でつまずきにくくなります。

よくある質問

experimental_evaluate は本番で使ってよいですか?

公式が「この API と評価モデルの仕様は experimental で、patch リリースでも変わり得る」と明記しています。使うなら ai のバージョンを固定し、更新のたびに動作を確かめてください。変更の影響を避けたい処理は、REST API か TypeSafe の公式 SDK を直接使う選択肢もあります。

Jev 以外のモデルでも同じコードが動きますか?

動きます。OpenAI、Anthropic、Google などの言語モデルにも評価用のアダプタがあります。ただし AI SDK の公式ドキュメントは、言語モデルのアダプタは全質問を1つのプロンプトで評価し、TypeSafe 本来の「質問ごとに独立して評価する」動きは提供しない、と注意しています。

confidence が答えに入っていません。

AI SDK の答えの型には confidence がありません。Choice と Score の確信度は result.providerMetadata.typesafe.confidence に、質問のキーごとに入っています。

出典・参考リンク

  1. 一次情報 AI SDK Core: Evaluation
  2. 一次情報 TypeSafe Provider
  3. 一次情報 TypeSafe API reference