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.local に AI_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 API | AI SDK |
|---|---|---|
| はい/いいえ の型 | "type": "noul" | type: 'boolean' |
| その答え | noul | probability |
| 確信度 | 答えの中の confidence | result.providerMetadata.typesafe.confidence[キー] |
Score の legend | 返る | 返らない(自分が渡した criteria の配列を使う) |
| トークン数 | input_tokens | inputTokens |
| 答えたモデル | 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 であることを前提にした検算を自分のコードに入れないでください。
エラーと再試行
- 一時的な失敗(
429、529)は 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 に、質問のキーごとに入っています。
出典・参考リンク
- 一次情報 AI SDK Core: Evaluation
- 一次情報 TypeSafe Provider
- 一次情報 TypeSafe API reference