マルチモデルAI統合における課題
クライアントから「GPT-4からClaude 3.5に切り替えたい」と言われ、ストリーミングロジックを書き直すために徹夜した経験はありませんか?プロバイダーごとにデータ構造やストリーミングの処理方法が異なるため、手動で実装する場合、メッセージ配列の管理、ネットワークエラーの処理、UI状態の維持などは非常に複雑になります。
Vercel AI SDKはこの問題を解決するために誕生しました。これは抽象化レイヤー(abstraction layer)として機能し、単一のコードセットであらゆるAIモデルとの通信を可能にします。それでは、OpenAI、Anthropic、Googleの「3大巨頭」をサポートするチャットアプリを実際に構築してみましょう。
実装方法の比較
コードを書く前に、現在主流の選択肢を比較してみましょう:
- 従来のFetch API: シンプルですが、ストリーミング処理においては悪夢です。
ReadableStreamを手動で処理し、ステートを管理する必要があり、不適切な実装はメモリリークの原因となります。 - LangChain: RAGやAgentのような複雑なタスクには非常に強力です。しかし、シンプルなチャットインターフェースを作成するだけなら、ライブラリが重く、学習コストも高くなります。
- Vercel AI SDK: Next.jsエコシステムにおける最適解です。
useChatフックを提供しており、UI処理のコードを80%削減し、サーバーからのスムーズなデータストリーミングを標準でサポートしています。
なぜVercel AI SDKを使うべきか?
最大の利点は統一性(Unified)です。ロジックを一度書くだけで済みます。GPT-4oからClaude 3.5 Sonnetへの切り替えも、変数を1つ変更するだけで、わずか5秒で完了することもあります。
ただし、このツールはJavaScript/TypeScriptに強く依存しています。バックエンドがPythonやGoで動作している場合、強力なReactフックの恩恵を十分に受けることはできません。しかし、Next.jsユーザーにとっては、これ以上ない強力な味方となります。
詳細な実装手順
1. Next.jsプロジェクトの初期化
まず、App Routerを使用した新しいNext.jsプロジェクトを作成します:
npx create-next-app@latest my-ai-chat
cd my-ai-chat
次に、コアライブラリと対応する各プロバイダーをインストールします:
npm install ai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google zod
2. 環境変数の設定
ルートディレクトリに.env.localファイルを作成します。OpenAI、Anthropic、Google AI Studioのダッシュボードから取得したAPIキーをここに入力してください。
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_GENERATIVE_AI_API_KEY=...
3. APIルート(バックエンド)の作成
app/api/chat/route.tsでAI呼び出しのロジックを処理します。クライアントからのリクエストに基づいて、バックエンドが自動的にモデルを選択するように構成します。
import { openai } from '@ai-sdk/openai';
import { anthropic } from '@ai-sdk/anthropic';
import { google } from '@ai-sdk/google';
import { streamText } from 'ai';
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages, modelType } = await req.json();
let selectedModel;
if (modelType === 'claude') {
selectedModel = anthropic('claude-3-5-sonnet-20240620');
} else if (modelType === 'gemini') {
selectedModel = google('models/gemini-1.5-pro-latest');
} else {
selectedModel = openai('gpt-4o');
}
const result = await streamText({
model: selectedModel,
messages,
});
return result.toDataStreamResponse();
}
複雑なJSONリクエストをデバッグする際、バラバラのテキストを目で追う代わりに、JSON Formatterを使用すると、データ構造をより素早く確認できます。
4. チャットインターフェース(フロントエンド)の作成
app/page.tsxでuseChatフックを使用します。このフックは、メッセージリストと入力状態の管理を自動的に行います。
'use client';
import { useChat } from 'ai/react';
import { useState } from 'react';
export default function Chat() {
const [modelType, setModelType] = useState('openai');
const { messages, input, handleInputChange, handleSubmit } = useChat({
body: { modelType },
});
return (
<div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
<select
value={modelType}
onChange={(e) => setModelType(e.target.value)}
className="mb-4 p-2 border rounded text-black"
>
<option value="openai">GPT-4o</option>
<option value="claude">Claude 3.5 Sonnet</option>
<option value="gemini">Gemini 1.5 Pro</option>
</select>
{messages.map(m => (
<div key={m.id} className="mb-4">
<span className="font-bold">{m.role === 'user' ? 'あなた: ' : 'AI: '}</span>
{m.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input
className="fixed bottom-0 w-full max-w-md p-2 mb-8 border rounded shadow-xl text-black"
value={input}
placeholder="何か質問してください..."
onChange={handleInputChange}
/>
</form>
</div>
);
}
実践的なアドバイス:タイムアウトエラーの回避
ストリーミング実装における一般的なエラーはmaxDurationに関するものです。VercelのHobbyプラン(無料版)では、Serverless Functionは10秒後にタイムアウトします。GPT-4のような「低速な」モデルでは、レスポンスの完了までに15〜20秒かかることがあります。
これを解決するには、常にexport const maxDuration = 30;を宣言してください(Proプランの最大制限は300秒です)。また、useChatから提供されるisLoading変数を利用してローディング状態を表示し、ユーザーがアプリがフリーズしたと感じないように工夫しましょう。
おわりに
Vercel AI SDKは単なるライブラリではなく、Web上でAIアプリケーションを構築するための新しい標準です。何十ページもの異なるAPIドキュメントを読む時間を省き、ユーザーエクスペリエンスの向上に集中することができます。
次のステップとして、**Tool Calling**機能を試してみてください。これは、AIがJavaScript関数を自ら呼び出して、リアルタイムの天気データを取得したり、データベースをクエリしたりできるようにする技術です。

