WebアプリにAIを組み込むの、もっと簡単にならない?

ミドリ: タツヤさん、Next.jsで作ったWebアプリにChatGPTみたいなチャット機能をつけたいんですけど、ストリーミングの実装がめちゃくちゃ面倒で挫折しかけてます……。

タツヤ: あー、自前でReadableStreamを扱って、Server-Sent Eventsのパーサー書いて、UIの状態管理して……ってやろうとしたんでしょ。

ミドリ(surprised): はい、まさにそれです。トークンが1文字ずつ流れてくるのを画面に表示するだけなのに、なんでこんなに大変なんだと。

タツヤ: その悩み、Vercel AI SDKで一発解決だよ。ストリーミング、状態管理、マルチプロバイダー対応……全部やってくれる。

Vercel AI SDKとは何か

ミドリ(thinking): 名前は聞いたことあるんですけど、具体的に何をしてくれるんですか?

タツヤ: Vercel AI SDKは、Webアプリに生成AI機能を組み込むためのオープンソースライブラリ。2つのレイヤーで構成されてる。

レイヤー名称役割
バックエンドAI SDK CoreLLMの呼び出し、ストリーミング処理、ツール実行
フロントエンドAI SDK UIReact/Next.js用のフック(useChat, useCompletion等)

ミドリ: バックエンドとフロントエンド両方カバーしてるんですね。

タツヤ: そう。しかもプロバイダー非依存。OpenAI、Anthropic Claude、Google Gemini、Mistral、Cohere……主要なLLMプロバイダーが全部統一インターフェースで使える。

ミドリ: プロバイダーを切り替えるのにコードの書き直しが要らない?

タツヤ: モデル名を1行変えるだけ。openai('gpt-4o')anthropic('claude-sonnet-4-20250514')に変えれば、バックエンドもフロントエンドもそのまま動く。

10分で作るチャットUI

ミドリ: 実際にどれくらい簡単なのか見せてください!

タツヤ: よし、Next.js App Routerでストリーミングチャットを作ってみよう。

ステップ1:インストール

npm install ai @ai-sdk/openai

ミドリ: パッケージ2つだけ?

タツヤ: それだけ。Claudeを使いたいなら@ai-sdk/anthropic、Geminiなら@ai-sdk/googleを追加するだけ。

ステップ2:APIルートの作成

// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';

export async function POST(req: Request) {
  const { messages } = await req.json();

  const result = streamText({
    model: openai('gpt-4o'),
    messages,
    system: 'あなたは親切なAIアシスタントです。日本語で回答してください。',
  });

  return result.toDataStreamResponse();
}

ミドリ: え、バックエンドこれだけですか!?

タツヤ: これだけ。streamTextがLLMの呼び出しとストリーミング処理を全部やってくれる。toDataStreamResponse()でストリーミング対応のHTTPレスポンスに変換される。

ステップ3:チャットUIの作成

// app/page.tsx
'use client';
import { useChat } from 'ai/react';

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit } = useChat();

  return (
    <div>
      {messages.map((m) => (
        <div key={m.id}>
          <strong>{m.role === 'user' ? 'あなた' : 'AI'}:</strong>
          <p>{m.content}</p>
        </div>
      ))}
      <form onSubmit={handleSubmit}>
        <input value={input} onChange={handleInputChange} placeholder="メッセージを入力..." />
        <button type="submit">送信</button>
      </form>
    </div>
  );
}

ミドリ: フロントエンドもこれだけ!? useChatフックが全部やってくれるんですね。

タツヤ: メッセージの状態管理、入力フォームの制御、APIへの送信、ストリーミングレスポンスの逐次表示……全部useChatが裏でやってる。開発者はUIのデザインだけに集中できる。

useChatフックの主要機能

ミドリ: useChatって、他にどんな機能がありますか?

タツヤ: messages(会話履歴)、isLoading(ストリーミング中フラグ)、stop(生成中断)、reload(再生成)、error(エラー情報)……ChatGPTライクなUIに必要な機能が全部揃ってる。stopisLoadingを組み合わせれば、ストリーミング中だけ「停止」ボタンを表示するUIも簡単に作れる。

ミドリ: useCompletionっていうフックもあるんですか?

タツヤ: useChatが会話型なのに対して、useCompletionは単発のテキスト生成用。要約や翻訳みたいな「入力→結果」の一方通行ならuseCompletionが向いてるよ。

マルチプロバイダー対応の実践

ミドリ: プロバイダーの切り替えが簡単って言ってましたけど、実際のコードで見せてもらえますか?

タツヤ: バックエンド側でモデルを1行変えるだけ。openai('gpt-4o')anthropic('claude-sonnet-4-20250514')google('gemini-2.0-flash')に差し替えればOK。フロントエンドのコードは一切変更不要。

ミドリ: 用途によってモデルを使い分けられるんですね。

タツヤ: 実運用では、リクエストごとにプロバイダーを動的に切り替えるパターンが多い。モデル名をMapで管理して、リクエストのproviderパラメータで切り替えれば、1つのAPIルートで全プロバイダーに対応できる。

Tool Calling:AIに「行動」させる

ミドリ: チャットだけじゃなくて、AIに何か行動させることもできるんですか?

タツヤ: AI SDKのTool Calling機能を使えばできる。tool()関数でツールを定義して、Zodでパラメータを型安全に指定する。AIが「東京の天気を教えて」と聞かれたら、自動的にweatherツールを呼び出して、実際のAPIを叩いて結果を返してくれる。

ミドリ: Function Callingの面倒な部分が全部抽象化されてるんですね。

タツヤ: そう。descriptionparameters(Zodスキーマ)、execute(実行関数)の3つを定義するだけ。天気API、データベース検索、計算機……何でもツールにできる。

Edge Runtimeでのデプロイ

ミドリ: Vercelにデプロイするときに特別な設定は要りますか?

タツヤ: export const runtime = 'edge';を1行追加するだけでEdge Runtimeで動く。コールドスタートが数ミリ秒で、Node.js Serverless Functionsの数百ミリ秒と比べて桁違いに速い。ユーザーが送信してからAIの最初のトークンが出るまでのラグが激減するよ。

実運用での注意点

ミドリ: 実際に本番で運用するとき、注意すべきことはありますか?

タツヤ: 5つの重要ポイントがある。

まとめ:AIの民主化はフロントエンドから

ミドリ: 今日の話をまとめるとどうなりますか?

タツヤ: Vercel AI SDKの価値は、生成AIをWebアプリに組み込むハードルを劇的に下げたこと。従来なら数日かかったストリーミングチャットの実装が、数時間で完了する。

ミドリ: しかもプロバイダー非依存だから、将来モデルを変えたくなっても簡単に切り替えられる。

タツヤ(nodding): その通り。2026年はLLMの進化が速すぎて、1つのプロバイダーに固定するのはリスクが高い。AI SDKのような抽象レイヤーを挟んでおけば、3ヶ月後に出てくる新しいモデルにも即座に対応できる

ミドリ(confused): フロントエンドエンジニアでもAI機能が作れる時代になったんですね。

タツヤ: まさに。AI開発の専門知識がなくても、ReactとAPIの基本がわかれば、本格的なAI機能が組み込める。AI SDKは「AIの民主化」の最前線にあるツールだよ。


次のアクション

Vercel AI SDKを使ったAI機能の組み込みを始めてみましょう。