🐡

Firebase Genkit と Next.js で構築する:お手軽生成 AI WebApp

2024/12/19に公開

こんにちは!クラウドエースの河野です。
この記事では Firebase GenkitNext.js を使って、生成 AI を活用したシンプルな Web アプリを構築する方法を、初心者にも分かりやすく解説します。

このガイドで得られるもの

  • Firebase Genkit を使った生成 AI 機能の効率的な実装方法
  • Next.js を活用したレスポンシブな Web アプリの作成
  • Vertex AI を用いた Google Cloud とのスムーズな連携

前提条件

以下のツールがインストールされていることを確認してください:

  • Node.js:v20.0 以上
  • npm または yarn:パッケージ管理ツール

また、以下の Google Cloud 関連サービスが設定済みである必要があります:

  1. Google Cloud プロジェクトの作成
  2. Vertex AI API の有効化
  3. 必要な API キーや認証情報の準備
  4. Gcloud CLI で認証を実行 gcloud auth application-default login

Firebase Genkit と Next.js の概要

Firebase Genkit は、Firebase プロジェクトに AI 機能を簡単に統合するためのツールキットです。
これにより、開発者は高度な AI モデルを利用して、ユーザーインタラクションを強化することができます。
Next.js は、React ベースのフレームワークであり、サーバーサイドレンダリングや静的サイト生成などの機能を提供します。
この二つを組み合わせることで、スケーラブルでパフォーマンスの高い Web アプリケーションを構築することが可能です。

Firebase Genkit の特徴

  • 簡単な統合:Firebase プロジェクトに数行のコードで AI 機能を追加可能
  • 柔軟なカスタマイズ:AI モデルの設定やカスタマイズが容易
  • スケーラビリティ:Firebase のインフラを活用して、スケーラブルなアプリケーションを構築

Next.js の特徴

  • サーバーサイドレンダリング:SEO に強く、初期表示が高速
  • 静的サイト生成:ビルド時に静的ファイルを生成し、パフォーマンスを向上

次のセクションでは、具体的なプロジェクトのセットアップ手順について説明します。

プロジェクトのセットアップ

まずは Next.js プロジェクトを作成し、必要なパッケージをインストールしましょう。
今回は npm を例に挙げています。

Next.js のプロジェクト作成

Next.js プロジェクトを作成します。{appName} は適宜変更してください。
Tailwind CSS はインストールしておくと後半で手軽に同じものを再現できます。

 npx create-next-app@latest {appName}
 cd {appName}

Firebase Genkit と Vertex AI プラグインのインストール

Genkit のコアライブラリと Vertex AI 用のプラグインをインストールします。

npm i --save genkit
npm i --save @genkit-ai/vertexai

AI チャット機能の実装

Firebase Genkit を使って実際にチャットで送られた内容から結果を返す処理を実装します。

環境変数ファイルの作成

プロジェクトルートに .env.local ファイルを作成し、Google Cloud プロジェクト情報を記述します。

.env.local
GCLOUD_PROJECT="~~~" # Google Cloud Project ID を指定
GCLOUD_LOCATION="asia-northeast1" # Google Cloud での API 利用時に指定するロケーション指定
GENKIT_ENV="dev"

Genkit の設定

Genkit の操作用ファイルをプロジェクトルートに lib/genkit.ts として作成します。
今回は chatbot ではなく、シンプルに入力された質問に対して既存の学習データから返事を生成するようにします。
zod を使用することで、型指定を手軽に行え、出力する値や入力する値を指定できるのも特徴です。

genkit.ts
'use server'; // サーバーサイドで実行されるコンポーネントを指定
import { genkit, z } from 'genkit';
import vertexAI, { gemini15Flash } from '@genkit-ai/vertexai';

const ai = genkit({
  plugins: [vertexAI()],
  model: gemini15Flash,
});

// chat モデルの詳細なデータを与えて口調や返答をカスタマイズする
const chat = ai.chat({ system: `
  name: "P",
  personality: "明るい",
  age: 20,
  dialect: "関西弁",
` });

const chatWithAI = ai.defineFlow(
  {
   name: "chatWithAI",
   inputSchema: z.object({ message: z.string() }),
   outputSchema: z.string(),
  },
  async ({ message }) => {
   const response = await chat.send(message);
   return response.text;
  }
);

export { chatWithAI};

チャットページの作成

次に、フロントエンドのチャットページを構築します。

page.tsx
'use client';  // クライアントサイドで実行されるコンポーネントを指定
import { useEffect, useState } from 'react';
import { chatWithAI  } from '@/lib/genkit';

interface Message {
  sender: 'user' | 'ai';
  text: string;
}

export default function ChatPage() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);

  const sendMessage = async (e: React.FormEvent) => {
   e.preventDefault();
   if (!input.trim()) return;

   const userMessage: Message = { sender: 'user', text: input };
   setMessages((prev) => [...prev, userMessage]);
   setInput('');
   setLoading(true);

   try {
    const response = await chatWithAI({ message: input });
    const aiMessage: Message = { sender: 'ai', text: response };
    setMessages((prev) => [...prev, aiMessage]);
   } catch (error) {
    console.error('送信エラー:', error);
    const errorMessage: Message = { sender: 'ai', text: '通信エラーが発生しました。' };
    setMessages((prev) => [...prev, errorMessage]);
   } finally {
    setLoading(false);
   }
  };
  
  useEffect(() => {
   const greetingMessage: Message = { sender: 'ai', text: 'こんにちは!' };
   setMessages((prev) => [...prev, greetingMessage]);
  }, []);

  return (
   <div className="flex flex-col h-screen bg-gray-100">
    <header className="bg-blue-600 text-white p-4 text-center text-xl">
      AI チャットボット
    </header>
    <div className="flex-1 p-4 overflow-y-auto">
      {messages.map((msg, index) => (
       <div
        key={index}
        className={`mb-4 flex ${msg.sender === 'user' ? 'justify-end' : 'justify-start'}`}
       >
        <div
          className={`rounded-lg px-4 py-2 max-w-md ${msg.sender === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-300 text-gray-800'}`}
        >
          {msg.text}
        </div>
       </div>
      ))}
      {loading && (
       <div className="mb-4 flex justify-start">
        <div className="rounded-lg px-4 py-2 bg-gray-300 text-gray-800">
          AI が応答中...
        </div>
       </div>
      )}
    </div>
    <form onSubmit={sendMessage} className="p-4 bg-white flex">
      <input
       type="text"
       value={input}
       onChange={(e) => setInput(e.target.value)}
       placeholder="メッセージを入力..."
       className="flex-1 border border-gray-300 rounded-l-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
      />
      <button
       type="submit"
       className="bg-blue-600 text-white px-4 py-2 rounded-r-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
       disabled={loading}
      >
       送信
      </button>
    </form>
   </div>
  );
}

開発サーバーの起動と確認

以下のコマンドを実行し、必要なパッケージをインストールします。
その後、Genkit UI を使用して開発サーバーを起動します。

npm i --save-dev genkit-cli tsx
npx genkit start -o -- npm run dev

# もし npx を使わない場合は、グローバルインストールしてください
# npm i -g genkit-cli tsx
# genkit start -o -- npm run dev

実際に読み込みが終わると以下の画面が表示されます。
Genkit-Top

  • http://localhost:3000 にアクセスすると、AI チャット画面が表示されます。
  • http://localhost:4000 にアクセスすると、Genkit UI が表示されます。

もし、Genkit UI がうまく読み込まれない場合は、実際の WebApp(Next.js) で該当の機能(会話)を行い、実際に Flow が読み込むと画面に反映されることもあります。

実際に今回作成した Next.js のアプリ画面は以下の画像です。
Next.js

まとめ

この記事では、Firebase Genkit と Next.js を使用して、簡単な生成 AI Web アプリを構築する方法を紹介しました。
これにより、AI を活用した Web アプリケーションを迅速に開発し、公開することが可能になります。
ぜひ、この記事を参考にして、あなた自身のプロジェクトに活用してみてください。

Discussion