Contents
Next.jsとTypeScriptのプロジェクト作成
Next.jsアプリケーションを作成する際には、create-next-appコマンドを使用するのが一般的です。
プロジェクト初期化は以下の流れで行います:
-
プロジェクトディレクトリを作成し、以下のコマンドで初期化します:
bash
npx create-next-app@latest my-mastra-app --typescript -
生成されたプロジェクト構造には
pages/やapp/(Next.js App Router)が含まれます。TypeScriptのサポートは自動的に有効になっているため、.tsファイルを作成して開発を進められます。 -
パッケージ管理ツールとして
npmとyarnが選択肢になりますが、大規模なプロジェクトではyarnが依存関係のロックファイル(yarn.lock)により安定性向上を図れます。 npm install: 標準的な運用yarn add: 依存関係のロックファイル(yarn.lock)による安定性向上
必要な依存関係のインストール
MastraとLLMプロバイダーを統合するためには、以下のようなライブラリが必要です:
| パッケージ名 | 説明 |
|---|---|
mastra |
AIエージェントフレームワークのコアパッケージ |
axios |
外部APIとの通信に使用 |
zod |
型検証ライブラリ(オプション) |
インストールは以下のように実行します:
|
1 2 |
npm install mastra axios zod |
Mastraエージェントの基本構造設計
Mastraを用いたAIエージェント開発では、ロジックの明確な分離と型安全なインターフェース設計がカギとなります。特に天気アプリケーションのように外部APIと連携するケースでは、責務範囲の明確化が重要です。
エージェントロジックの定義方法
Mastraではエージェントを「ワークフロー」として定義します。このワークフロー内で実行されるタスク(例えば天気情報の取得)は、以下のように関数で分離できます:
- 外部API呼び出し:
getWeatherData(city: string): Promise<WeatherResponse> - LLMへのプロンプト生成:
createPrompt(data: WeatherResponse): string - 応答の整形:
formatResponse(llmOutput: string): string
このように分離することで、エラー発生時のデバッグや将来的な拡張が容易になります。
TypeScriptインターフェースの設計
型定義はエージェントロジックを安定させます。天気アプリケーションの場合、以下のようなインターフェースを定義します:
|
1 2 3 4 5 6 |
interface WeatherResponse { temperature: number; humidity: number; description: string; } |
このWeatherResponse型を使って、LLMへの入力や出力の型チェックを行い、不整合を防ぎます。また、zodライブラリを使用すれば、データ構造の検証が自動化されます。
LLMプロバイダーとの接続設定
MastraはLLMプロバイダー(例: Google Gemini, OpenAIなど)と柔軟に連携できます。ただしセキュリティの観点から、APIキー管理には注意が必要です。
APIキーの環境変数管理
VercelやNext.jsでは、.env.localファイルでAPIキーを管理するのがベストプラクティスです。以下のように定義します:
|
1 2 3 4 |
MASTRA_API_KEY=[YOUR_MASTRA_API_KEY] LLM_PROVIDER_API_KEY=[YOUR_LLM_PROVIDER_API_KEY] WEATHER_API_KEY=[YOUR_WEATHER_API_KEY] |
このファイルは .gitignore に追加し、リポジトリへのコミットを防ぎます。作成手順:
- プロジェクトルートで
.env.localファイルを作成(例:touch .env.local) - 上記の環境変数を記載
プロキシ経由での安全な通信
公開環境ではAPIキーを直接送信するのではなく、プロキシ経由で通信を行うとセキュリティが向上します。VercelのEdge Functionsで中継処理を実装すれば、ユーザーサイドでAPIキーが見えなくなります。
RAG機能の実装例
RAG(Retrieval-Augmented Generation)は、外部データソースとLLMを組み合わせて精度の高い応答を生成する手法です。ここでは天気情報APIとの統合をデモとして示します。
外部データソースとの連携方法
-
天気データの取得: OpenWeatherMap APIなどからリアルタイムデータをフェッチ(※LLM提供者用APIキーではなく、weather API専用キーを使用すること):
typescript
const response = await fetch(https://api.weatherapi.com/v1/current.json?key=${WEATHER_API_KEY}&q=${city});
const weatherData = await response.json(); -
LLMへのプロンプト構築: 取得した天気データとユーザーの質問を組み合わせたプロンプトを作成:
typescript
const prompt =今、${weatherData.location.name}の天気は、${;
weatherData.current.condition.text
}で、気温は${weatherData.current.temp_c}度です。この情報に基づいて回答してください。 -
LLMからの応答: MastraがプロンプトをLLMに送信し、結果を返却(API呼び出し例: OpenAI):
typescript
const result = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
Authorization:Bearer ${LLM_PROVIDER_API_KEY},
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: prompt }]
})
});
const llmOutput = await result.json();
console.log(llmOutput.choices[0].message.content); // 例: "今日は雨のため外出はご注意ください"
このようにRAGを活用することで、LLM単体では得られない正確な情報を提供できます。
ストリーミング処理の実現方法
MastraはLLMからのリアルタイム応答(ストリーミング)をサポートしており、ユーザーにプログレス表示やインタラクティブなUIを提供する際に有効です。
リアルタイム応答のためのイベントハンドリング
以下のようにonStreamイベントを登録することで、LLMからの逐次応答を処理できます:
|
1 2 3 4 5 6 |
const stream = await mastra.executeStream(prompt); stream.on('data', (chunk) => { console.log(`受信データ: ${chunk}`); }); |
UI側でのプログレス表示
Next.jsアプリケーションでストリーミング応答をUIに反映するには、useStateとuseEffectを用います。以下は例です:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
const [response, setResponse] = useState(''); useEffect(() => { const stream = await mastra.executeStream(prompt); let tempText = ''; stream.on('data', (chunk) => { tempText += chunk; setResponse(tempText); }); }, []); |
この処理により、LLMからの文字列が順次表示され、ユーザーにインタラクティブな体験を提供できます。
Vercelデプロイ時の注意点
Vercelでのデプロイでは、Next.jsとMastraの特性を考慮した構成設計が必要です。特にServer Componentsとの連携やEdge Functionsの活用が重要になります。
Edge Functionsの活用方法
VercelでEdge Functionsを使うには以下のように手順を踏みます:
- プロジェクトルートに
edge-functions/ディレクトリを作成 - その中にエンドポイントファイル(例:
get-weather.ts)を配置 - ファイルの内容は以下のようにする(APIキーなど機密情報を扱う処理はEdge Functions内で実装):
ts
// edge-functions/get-weather.ts
import { fetch } from 'next/fetch';
export default async function handler(req: Request) {
const city = new URL(req.url).searchParams.get('city');
const response = await fetch(https://api.weatherapi.com/v1/current.json?key=${process.env.WEATHER_API_KEY}&q=${city});
return Response.json(await response.json());
}
- Vercelのプロジェクト設定でEdge Functionsを有効化(
vercel.jsonに定義)
パフォーマンス最適化ポイント
Next.jsのServer ComponentsはVercelとの連携が簡単ですが、以下のような点に注意してください:
- Edge Functionsで重い処理を実行: LLMの呼び出しやRAGデータ取得はEdge Functions内で実施し、クライアントサイドの負荷を抑える
- キャッシュ戦略: 静的な天気情報などはVercelのキャッシュ機能で最適化
- Server ComponentsとClient Componentsの境界線: LLMや外部API呼び出しはServer Componentで実行し、UI操作や表示はClient Componentに分離
結論
本記事ではNext.jsとMastraの統合方法について具体的な手順を解説しましたが、実際には公式ドキュメントでの最新情報やエッジケースに合わせた調整が必要です。
初心者向けには、シンプルな天気アプリケーションのソースコードリポジトリを参考にしてください。GitHubやVercelのプロジェクトテンプレートで提供されているので、すぐに実験が可能です。
公式ドキュメント: https://mastra.ai/guides/getting-started/next-js
ぜひご自身のプロジェクトにMastraを取り入れ、LLMを活用したAIエージェント開発をお試しください。