
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 | サーバー側でモデルを呼ぶ | generateText、streamText、Output.object()(構造化出力)、ツール呼び出し |
| AI SDK UI | クライアント側の UI フック | useChat、useCompletion |
サーバーで Core を使ってモデルを呼び、クライアントで UI フックが結果(特にストリーミング)を受け取って画面に出す——という分担です。
プロバイダ非依存: モデルを差し替えられる
最初に効いてくるのが、モデルプロバイダに依存しない統一インターフェースです。OpenAI・Anthropic・Google・Azure・Amazon Bedrock などを、同じ書き方で呼べます。
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 を使うのが定番の組み合わせです。
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();
}'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 のスキーマを指定します。
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層構造: Core(
generateText/streamText/Output.object()/ツール呼び出し)と UI(useChat/useCompletion) - プロバイダ非依存。
model文字列の差し替えで OpenAI / Anthropic / Google などを切り替えられる - ストリーミングは
streamText+useChat、構造化出力はgenerateText+Output.object()+ Zod スキーマ - v6 で
useChatの形が刷新(useState+sendMessage+message.parts+DefaultChatTransport)。サーバーはconvertToModelMessages+toUIMessageStreamResponse() - ツール呼び出しでチャットを「行動するエージェント」へ。Next.js / RSC と素直に組み合わさる
- ただし API キー管理・コスト監視・出力内容の検証は引き続き開発者の責任
「AI 機能を足したいが、ストリーミングや構造化出力を一から書くのは面倒」——その隙間を埋めてくれるのが Vercel AI SDK です。まずは generateText 一発から始め、useChat と Output.object() まで広げていくのが、無理のない入り口です。