Vercel AI SDK 実践入門 - 生成AIを Next.js アプリに「機能」として組み込む

Vercel AI SDK 実践入門 - 生成AIを Next.js アプリに「機能」として組み込む

作成日:
更新日:

「自分のアプリに AI 機能を足したい」となったとき、OpenAI や Anthropic の API を直接叩くこともできますが、ストリーミング・ツール呼び出し・構造化出力・UI 連携まで自前で書くのは骨が折れます。ここを引き受けてくれるのが Vercel AI SDK です。

ポイントは、これが「チャットボットを作るための道具」にとどまらず、生成AIを自分のプロダクトの機能として組み込むための TypeScript ツールキットだということ。この記事では、Core と UI の役割分担、プロバイダ非依存の設計、Zod を使った構造化出力、そして Next.js との組み合わせ方を、最小コードで整理します(現行はメジャー v6 系)。

2層構造: Core と UI

AI SDK は大きく2層に分かれています。ここを押さえると全体像がつかめます。

役割主な API
AI SDK Coreサーバー側でモデルを呼ぶgenerateTextstreamTextOutput.object()(構造化出力)、ツール呼び出し
AI SDK UIクライアント側の UI フックuseChatuseCompletion

サーバーで Core を使ってモデルを呼び、クライアントで UI フックが結果(特にストリーミング)を受け取って画面に出す——という分担です。

プロバイダ非依存: モデルを差し替えられる

最初に効いてくるのが、モデルプロバイダに依存しない統一インターフェースです。OpenAI・Anthropic・Google・Azure・Amazon Bedrock などを、同じ書き方で呼べます。

generateText の最小例
import { generateText } from 'ai';
 
const { text } = await generateText({
  model: 'anthropic/claude-sonnet-4.5',
  prompt: 'What is love?',
});

model の文字列を差し替えるだけでプロバイダを変えられるので、「とりあえず動かして、後でモデルを比較・乗り換える」がやりやすい。ベンダーロックインを避けつつ AI 機能を入れたいときに効きます(Claude Fable 5 のような新モデルが出ても、文字列の差し替えで試せます)。

ストリーミング: streamText と useChat

チャット系 UI の体験を左右するのがストリーミング(応答が少しずつ流れて表示される)です。サーバーで streamText、クライアントで useChat を使うのが定番の組み合わせです。

サーバー(Next.js Route Handler)
import { streamText, convertToModelMessages } from 'ai';
 
export async function POST(req: Request) {
  const { messages } = await req.json();
  const result = streamText({
    model: 'anthropic/claude-sonnet-4.5',
    messages: convertToModelMessages(messages),
  });
  return result.toUIMessageStreamResponse();
}
クライアント(useChat / v6)
'use client';
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import { useState } from 'react';
 
export function Chat() {
  const [input, setInput] = useState('');
  const { messages, sendMessage } = useChat({
    transport: new DefaultChatTransport({ api: '/api/chat' }),
  });
 
  return (
    <form onSubmit={(e) => { e.preventDefault(); sendMessage({ text: input }); setInput(''); }}>
      {messages.map((m) => (
        <div key={m.id}>
          {m.role}: {m.parts.map((p, i) => (p.type === 'text' ? <span key={i}>{p.text}</span> : null))}
        </div>
      ))}
      <input value={input} onChange={(e) => setInput(e.target.value)} />
    </form>
  );
}

NOTE

v6 で useChat の形が変わりました。入力状態は自分の useState で持ち、送信は sendMessage({ text })、メッセージ本文は message.parts を走査して描画します(旧来の handleSubmit / message.content ではありません)。サーバー側も convertToModelMessages で変換し、toUIMessageStreamResponse() で返すのが v6 の形です。useChatメッセージ管理とストリーミング受信・送信を担い、ストリーミング表示の定型処理を肩代わりしてくれます。

構造化出力: Output.object と Zod

「チャットを返すだけ」を超えてプロダクトの機能にするうえで効くのが、構造化出力です。LLM の出力を、自由文ではなく決まった形の JSONとして受け取れます。v6 では generateText(または streamText)の output パラメータに Output.object() を渡し、そこに Zod のスキーマを指定します。

generateText + Output.object + Zod スキーマ
import { generateText, Output } from 'ai';
import { z } from 'zod';
 
const { output } = await generateText({
  model: 'anthropic/claude-sonnet-4.5',
  output: Output.object({
    schema: z.object({
      title: z.string(),
      tags: z.array(z.string()),
      summary: z.string(),
    }),
  }),
  prompt: '次の記事を要約して構造化して: ...',
});
 
output.title; // 型は string
output.tags;  // 型は string[]

スキーマで縛るので、返ってくるオブジェクトに型が付き、形のズレも検証される。「LLM の出力をそのままアプリのデータとして使う」ときの定番パターンです。Zod 4 の記事で書いた「スキーマ1つで指示と検証を兼ねる」発想が、ここでそのまま活きます。

ツール呼び出し: モデルに「行動」させる

さらに踏み込むと、ツール呼び出し(tool calling)で、モデルに「関数を呼ぶ」判断をさせられます。天気を調べる・DB を引く・計算する、といった処理をツールとして渡しておくと、モデルが必要に応じて呼び出します。チャットを「会話」から「行動するエージェント」へ引き上げる仕組みで、LangChain.js などと同じ方向性を、より薄いレイヤーで実現できます。

Next.js / RSC との相性

AI SDK は Next.js(App Router / Pages Router)と React Server Components に対応し、Vue・Svelte・Node.js などでも動きます。当ブログのような Next.js 構成なら、Route Handler で Core を呼び、クライアントコンポーネントで UI フックを使うという素直な構成にそのまま乗ります。

WARNING

AI SDK は実装を楽にしますが、LLM 特有の注意点まで消してはくれません。API キーは必ずサーバー側に置く(クライアントに露出させない)、レート制限とコストを監視する、構造化出力でも「形は正しいが内容が誤っている」可能性に備える——これらは依然として開発者の責任です。便利さに任せて、検証やガードを省かないこと。

まとめ

  • Vercel AI SDK は、生成AIをプロダクトの機能として組み込む TypeScript ツールキット(現行 v6 系)
  • 2層構造: CoregenerateText/streamText/Output.object()/ツール呼び出し)と UIuseChat/useCompletion
  • プロバイダ非依存model 文字列の差し替えで OpenAI / Anthropic / Google などを切り替えられる
  • ストリーミングは streamTextuseChat、構造化出力は generateTextOutput.object() + Zod スキーマ
  • v6 で useChat の形が刷新(useStatesendMessagemessage.partsDefaultChatTransport)。サーバーは convertToModelMessagestoUIMessageStreamResponse()
  • ツール呼び出しでチャットを「行動するエージェント」へ。Next.js / RSC と素直に組み合わさる
  • ただし API キー管理・コスト監視・出力内容の検証は引き続き開発者の責任

「AI 機能を足したいが、ストリーミングや構造化出力を一から書くのは面倒」——その隙間を埋めてくれるのが Vercel AI SDK です。まずは generateText 一発から始め、useChatOutput.object() まで広げていくのが、無理のない入り口です。

参考リンク