Vercel AI SDKを使った生成AIチャットアプリをNext.js & Cloudflareで実装する
タグ:
Next.jsとVercel AI SDKを使って、Cloudflare Workers AI上で動作する生成AIチャットアプリを実装する方法を解説。プロジェクト設定からストリーミングレスポンス対応、チャットUIの構築までの手順を紹介。
目次
Next.js アプリケーションを簡単に構築できる AI SDK を使ってみたので、簡単にまとめてみました。シンプルなチャットアプリをCloudflare Workers AI で作ってみています。
アプリケーションのセットアップ
まずは Cloudflare の CLI ツールを使ってプロジェクトを作成していきます。
npm create cloudflare@latest
対話形式でプロジェクトの設定を進めていきます。
╭ Create an application with Cloudflare Step 1 of 3
│
├ In which directory do you want to create your application?
│ dir ./cf-vercel-ai
│
├ What would you like to start with?
│ category Framework Starter
│
├ Which development framework do you want to use?
│ framework Next.js
│
├ Continue with Next.js via `npx [email protected] cf-vercel-ai`
│
Need to install the following packages:
[email protected]
Ok to proceed? (y)
続いて Next.js の初期設定を行います。TypeScript や ESLint、Tailwind CSS などの使用について聞かれるので、お好みで選択してください。
Ok to proceed? (y) y
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack for `next dev`? … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
Vercel AI SDK のセットアップ
次に必要なパッケージをインストールします。Workers AI を Vercel AI SDK で使うためのプロバイダーも一緒にインストールしておきましょう。
npm i workers-ai-provider ai @ai-sdk/openai zod
wrangler.jsonc
に AI バインディングの設定を追加します。
"ai": {
"binding": "AI"
}
次のコマンドで、env.d.ts
を更新します。
wrangler types --env-interface CloudflareEnv env.d.ts
これで Workers AI を使う準備が整いました。
最初の API を作成
まずはシンプルなテキスト生成 API を作ってみます。app/api/hello/route.ts
を作成して、以下のコードを記述してください。
import { getRequestContext } from "@cloudflare/next-on-pages";
import { createWorkersAI } from 'workers-ai-provider';
import { generateText } from 'ai';
export const runtime = 'edge'
export async function GET() {
const ai = getRequestContext().env.AI
const workersai = createWorkersAI({ binding: ai });
const result = await generateText({
model: workersai('@cf/meta/llama-2-7b-chat-int8'),
prompt: 'Write a 50-word essay about hello world.',
});
return new Response(result.text);
}
ストリーミングレスポンスへの対応
リアルタイムで応答を返したい場合は、streamText
を使用します。先ほどのコードを少し修正してみましょう。
import { getRequestContext } from "@cloudflare/next-on-pages";
import { createWorkersAI } from 'workers-ai-provider';
import { generateText, streamText } from 'ai';
export const runtime = 'edge'
export async function GET() {
const ai = getRequestContext().env.AI
const workersai = createWorkersAI({ binding: ai });
const result = streamText({
model: workersai('@cf/meta/llama-2-7b-chat-int8'),
prompt: 'Write a 50-word essay about hello world.',
})
return result.toDataStreamResponse();
}
streamText
を使うことで、生成されたテキストを逐次的にクライアントへ送信できるようになります。
AI SDK を使ったチャット UI の構築
ここからが本題です。Vercel AI SDK の useChat
フックを使って、対話型のチャットインターフェースを作成していきます。
チャット用 API の作成
app/api/chat/route.ts
を作成します。これはクライアントで使う useChat
が呼び出す API のデフォルトパスが /api/chat
で、POST
リクエストを投げるためです。streamText
の引数が prompt
から messages
に変わっている点にも注意してください。
import { getRequestContext } from "@cloudflare/next-on-pages";
import { createWorkersAI } from 'workers-ai-provider';
import { CoreMessage, streamText } from 'ai';
export const runtime = 'edge'
export async function POST(req: Request) {
const { messages } = await req.json<{messages: CoreMessage[]}>()
const ai = getRequestContext().env.AI
const workersai = createWorkersAI({ binding: ai });
const result = streamText({
model: workersai('@cf/meta/llama-2-7b-chat-int8'),
messages,
})
return result.toDataStreamResponse();
}
messages
には次のような形式でデータが送られてきます。
[
{
role: 'user',
content: 'hello my name is hidetaka',
parts: [ { type: 'text', text: 'hello my name is hidetaka' } ]
}
]
チャット UI の実装
Client Component を作成します。app/chat-ui.tsx
というファイルを作って、以下のコードを記述しましょう。
'use client';
import { useChat } from '@ai-sdk/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
{messages.map(m => (
<div key={m.id} className="whitespace-pre-wrap">
{m.role === 'user' ? 'User: ' : 'AI: '}
{m.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input
className="fixed dark:bg-zinc-900 bottom-0 w-full max-w-md p-2 mb-8 border border-zinc-300 dark:border-zinc-800 rounded shadow-xl"
value={input}
placeholder="Say something..."
onChange={handleInputChange}
/>
</form>
</div>
);
}
app/page.tsx
で呼び出します。
import Chat from "./chat-ui";
export default function Home() {
return (
<div>
<Chat />
</div>
);
}
これでチャットアプリケーションが完成しました!

useChat の便利な機能
useChat
フックの素晴らしいところは、現在の会話履歴を自動的に管理してくれることです。
実際の会話例を見てみましょう。
User: hello my name is hidetaka
AI: Nice to meet you Hidetaka! That's a unique and name. Where you from? What you here today?
User: do you remember my name?
AI: I remember that your name is Hidetaka! I'm impressed by memory How can I you, Hetaka?
2回目のリクエスト時には、messages
に以下のような履歴が含まれています。
[
{
role: 'user',
content: 'hello my name is hidetaka',
parts: [ { type: 'text', text: 'hello my name is hidetaka' } ]
},
{
role: 'assistant',
content: 'Nice to meet you Hidetaka! That\'s a unique and name. Where you from? What you here today?',
parts: [
{
type: 'text',
text: 'Nice to meet you Hidetaka! That\'s a unique and name. Where you from? What you here today?'
}
]
},
{
role: 'user',
content: 'do you remember my name?',
parts: [ { type: 'text', text: 'do you remember my name?' } ]
}
]
このように、会話の文脈を保持しながらやり取りができるため、より自然な対話が可能になります。
参考リンク
今回の実装で参考にしたドキュメントはこちらです:
- Cloudflare Pages – Get started with C3
- Vercel AI SDK – Cloudflare Workers AI Provider
- Vercel AI SDK – Getting Started with Next.js App Router
Cloudflare Workers AI と Vercel AI SDK を組み合わせることで、エッジで動作する高速なチャットアプリケーションを簡単に構築できました。ぜひ皆さんも試してみてください!