Vercel AI SDKは、OpenAI、Anthropic、Googleなどのモデルを共通に近いAPIで呼ぶTypeScript向けSDKです。Next.jsでは、server routeでproviderを選び、generateTextやstreamTextへ渡せます。
共通APIにしても、全モデルの機能が同じになるわけではありません。Tool Calling、画像入力、構造化出力、usage、finish reasonの対応差を確認し、providerごとのテストを残します。
この記事では、AI SDK CoreとUIの違い、3provider切替、テキスト生成、ストリーミング、本番のfallback・ログ・費用管理を解説します。
情報確認日:2026年7月17日(日本時間)
結論:AI SDK Coreでprovider切替を分離する
Browser
↓ POST /api/generate
Next.js Route Handler
↓ getModel(provider)
AI SDK Core
├─ @ai-sdk/openai
├─ @ai-sdk/anthropic
└─ @ai-sdk/google
↓
各provider API
| 領域 | 役割 |
|---|---|
| AI SDK Core | generateText、streamText、tool、structured outputなど |
| AI SDK UI | React・Next.js等のchat・streaming UI hook |
| Provider package | 各事業者の認証・model・固有機能を接続 |
Next.jsプロジェクトへ導入する
npx create-next-app@latest ai-sdk-demo --ts --app
cd ai-sdk-demo
npm install ai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google
APIキーとmodel IDはserverの環境変数へ設定します。実際の値は公開repositoryへ保存しません。
OPENAI_API_KEY=...
OPENAI_MODEL=...
ANTHROPIC_API_KEY=...
ANTHROPIC_MODEL=...
GOOGLE_GENERATIVE_AI_API_KEY=...
GOOGLE_MODEL=...
AI SDKのpackage majorは更新されるため、導入時は現行Get startedとmigration guideを確認します。この記事は2026年7月17日時点のAI SDK 7を基準にしています。
3つのproviderを切り替える
lib/models.tsを作ります。
import { anthropic } from "@ai-sdk/anthropic";
import { google } from "@ai-sdk/google";
import { openai } from "@ai-sdk/openai";
import type { LanguageModel } from "ai";
export type ProviderName = "openai" | "anthropic" | "google";
const required = (name: string): string => {
const value = process.env[name];
if (!value) throw new Error(`${name} is not set`);
return value;
};
export function getModel(provider: ProviderName): LanguageModel {
switch (provider) {
case "openai":
return openai(required("OPENAI_MODEL"));
case "anthropic":
return anthropic(required("ANTHROPIC_MODEL"));
case "google":
return google(required("GOOGLE_MODEL"));
}
}
model IDをcodeへ固定せず、環境ごとに設定します。providerを利用者が自由入力するのではなく、許可した値のenumとして検証します。
generateTextで応答を得る
app/api/generate/route.tsを作ります。
import { generateText } from "ai";
import { getModel, type ProviderName } from "@/lib/models";
const providers = new Set<ProviderName>([
"openai",
"anthropic",
"google",
]);
export async function POST(request: Request) {
const body: unknown = await request.json();
if (
!body ||
typeof body !== "object" ||
!("provider" in body) ||
!("prompt" in body) ||
typeof body.provider !== "string" ||
!providers.has(body.provider as ProviderName) ||
typeof body.prompt !== "string" ||
body.prompt.length < 1 ||
body.prompt.length > 2000
) {
return Response.json({ error: "Invalid input" }, { status: 400 });
}
const result = await generateText({
model: getModel(body.provider as ProviderName),
system: "簡潔な日本語で回答してください。",
prompt: body.prompt,
});
return Response.json({
text: result.text,
finishReason: result.finishReason,
usage: result.usage,
});
}
generateTextは応答完了後に結果を返すため、短い分類、下書き、server-side batchに向きます。finishReasonとusageも保存すると、途中終了と費用を確認できます。
streamTextで逐次表示する
import { streamText } from "ai";
import { getModel } from "@/lib/models";
export async function POST(request: Request) {
const { prompt } = await request.json();
if (typeof prompt !== "string" || prompt.length > 2000) {
return Response.json({ error: "Invalid input" }, { status: 400 });
}
const result = streamText({
model: getModel("openai"),
prompt,
onFinish({ finishReason, usage }) {
console.info({ finishReason, usage });
},
});
return result.toTextStreamResponse();
}
chat UIではAI SDK UIのhookを組み合わせられます。本文生成だけならtext stream、message・tool・metadataを扱うchatならUI message streamを選びます。
provider差を吸収しすぎない
| 機能 | 共通化 | 確認 |
|---|---|---|
| 基本text | しやすい | system、停止理由、token |
| 画像入力 | 一部可能 | 形式、size、model対応 |
| Tool Calling | API形状は共通化可能 | parallel、strict、streaming差 |
| 構造化出力 | schema共通化可能 | 対応model、制限、失敗処理 |
| reasoning | 固有差が大きい | providerOptionsと課金 |
| usage | 共通fieldあり | providerの課金項目との差 |
Provider support表で対応機能を確認し、アプリが必須とする機能ごとに3providerで同じintegration testを実行します。
fallbackを設計する
失敗したら無条件に別providerへ送る設計は、データ処理地域、契約、費用、品質を変える可能性があります。fallback可能なデータと用途を明示します。
- timeout、429、5xxなど再試行可能な失敗を分類する
- 同じproviderで回数を制限して再試行する
- 別providerへ送ってよいデータか確認する
- 必須機能と出力schemaを満たすmodelだけを候補にする
- 切替をログと画面へ記録する
本番前チェックリスト
- APIキーをserver-side secretへ置いた
- providerとmodelをallowlistで制限した
- 入力長、出力上限、timeoutを設定した
- usage、finish reason、処理時間、providerを記録した
- 429・5xxの再試行に上限がある
- providerごとの評価とintegration testがある
- fallback時のデータ送信規程を確認した
- 利用者ごとの認証、rate limit、予算上限がある
- package・provider・model変更を回帰評価する
JSON出力をアプリで使う場合はAIにJSONを出力させる方法、Tool Callingの基本はTool Callingとはも参考になります。
まとめ
Vercel AI SDKでは、AI SDK Coreとprovider packageを分け、Next.jsのserver routeでmodelを選びます。generateTextは完了後の応答、streamTextは逐次表示に使います。
共通APIは便利ですが、modelの能力差は残ります。providerごとの対応機能、評価、ログ、費用、fallbackのデータ条件を確認して本番へ進めてください。