🙌
Vercel AI SDK + Next.jsで簡易チャットページ(OllamaとOpenAI)
はじめに
Next.jsでVercel AI SDKを使用した簡単なテキストチャットページを作成します。
以前にも記事を書きましたが、実装内容が古くなりましたので新たに記事にしてみました。
LLMは、OpenAIのGPT-4o miniと、ローカルLLMであるOllamaでgemma3:4bを使ってみました。
※ マシンスペックが足りないなど環境がない方は、Ollamaの部分は読み飛ばしてください。
以前の記事
読者対象
- Next.js開発の経験者
事前準備
-
OpenAI プラットフォームから API キーを作成&取得しておく。
https://platform.openai.com/ -
Ollamaも使いたい場合は起動しておきます。
参考ドキュメント
セットアップ
環境
node v23.1.0
ステップ
- Next.jsを作成する
- .env.localにOPENAI_API_KEYを記述する
OPENAI_API_KEY=your-api-key
- app/api/chat/route.tsを作成する
- app/page.tsxを作成する
- components/Chat.tsを作成する
Next.jsを作成
Typescript + App router
yarn create next-app simple-ai-chat --typescript
cd simple-ai-chat
yarn add ai @ai-sdk/openai zod
yarn add ollama-ai-provider
package.json(抜粋)
"dependencies": {
"@ai-sdk/openai": "^1.2.5",
"ai": "^4.1.61",
"next": "15.2.2",
"ollama-ai-provider": "^1.2.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"zod": "^3.24.2"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "15.2.2",
"tailwindcss": "^4",
"typescript": "^5"
}
コード
OpenAIの場合
- app/api/chat/route.ts
import { openai } from "@ai-sdk/openai";
import { streamText } from "ai";
// Vercel edgeを使う場合
export const runtime = "edge";
// ストリーミング応答を最大 30 秒まで許可
export const maxDuration = 30;
export const POST = async (req: Request) => {
const { messages } = await req.json();
// システムプロンプトの設定
const systemPrompt =
"フレンドリーに会話してください。語尾は必ず「にゃん」をつけて。";
// temperatureの設定
const temperature = 0.5;
const result = streamText({
model: openai("gpt-4o-mini"),
messages,
system: systemPrompt,
temperature: temperature,
});
return result.toDataStreamResponse();
}
Ollamaの場合
- app/api/chat/route.ts
- OllamaのデフォルトURLは
http://localhost:11434/api
になっています。
import { streamText } from "ai";
import { ollama } from "ollama-ai-provider";
// ストリーミング応答を最大 30 秒まで許可
export const maxDuration = 30;
export const POST = async (req: Request) => {
const { messages } = await req.json();
// システムプロンプトの設定
const systemPrompt =
"フレンドリーに会話してください。語尾は必ず「にゃん」をつけて。";
// temperatureの設定
const temperature = 0.5;
const result = streamText({
model: ollama("gemma3:4b"),
messages,
system: systemPrompt,
temperature: temperature,
});
return result.toDataStreamResponse();
}
- app/page.ts
import { Chat } from "@/components/Chat";
const Top = () => {
return (
<>
<Chat />
</>
);
};
export default Top;
- conponents/Chat.tsx
"use client";
import { useChat } from "@ai-sdk/react";
import { Message } from "ai";
export const Chat = () => {
const { messages, input, handleInputChange, handleSubmit } = useChat({});
// チャット履歴をコンソール出力
const logMessages = () => {
if (messages.length > 0) console.log(messages);
};
return (
<>
<div className="mx-auto w-full max-w-md py-24 flex flex-col">
<p className="font-bold text-lg">AI CHAT</p>
{messages.map((m: Message) => (
<div key={m.id} className="w-96 mb-2 p-2">
{m.role === "user" ? "User: " : "AI: "}
{m.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input
name="box"
className="w-96 flex rounded bottom-0 border border-gray-300 text-gray-200 mb-2 p-2"
value={input}
onChange={handleInputChange}
placeholder="メッセージを入力..."
/>
<button
type="submit"
className="w-96 rounded bg-sky-500 hover:bg-sky-700 mb-2 p-2"
>
Send message
</button>
</form>
<button
onClick={logMessages}
className="w-96 rounded bg-gray-700 hover:bg-gray-500 mb-2 p-2"
>
メッセージをコンソールに表示
</button>
<p className="w-96 text-slate-500 text-xs">
Chromeブラウザで画面を右クリックして「検証」を選ぶと、
DEVツールのコンソールからメッセージの値が確認できます。
会話の履歴の状態や格納内容が確認できます。
</p>
</div>
</>
);
};
動作確認
ストリーミング回答するシンプルなテキストチャット
メッセージをコンソールに表示
をクリックしたあとに、DEVツールのコンソールでメッセージの値が確認できます。どんなふうに格納されているのか確認できます。
まとめ
クライアント側のuseChatの仕様が変わっていたので、今回また新しく記事にしてみました。
Ollama利用でもollama-ai-providerを使う実装にしています。
エラー処理や細かいところは未実装なものですが、はじめてチャットページを作成するときの参考になればと思います。
Discussion