🔥

Firebase & AI のオーケストレーションを実現!Genkit アーキテクチャ 8 選

2024/10/20に公開

こんにちは、cobo です。

今回は、Google I/O '24 で発表された Firebase の新機能の 1 つである Genkit についての記事です。

Genkit は生成 AI ワークフローのオーケストレーション、デプロイ、モニタリングを行うためのコードファーストのフレームワーク と言われています。

この記事では、オーケストレーション という部分にフォーカスし、Genkit が Firebase の指揮者 としてどのような構成(アーキテクチャ)を採ることができるのか紹介します。

1. Web API 構成

genkit-1
Web API 構成

クライアントからのリクエスト(例えば、質問文など)を受け付けて、それに対して、Genkit 内で用意されたプロンプトを基にレスポンスを返す、一番シンプルな Genkit の構成です。

サーバーサイドである Firebase で、Google AI Studio から払い出された Gemini の API キーを保持する形となります。

ですので、実際には、Genkit から Secret Manager という秘匿情報を管理するサービスを参照するようになっています。

補足イメージ

genkit-1-1-補足

sample
export const simpleFlow = onFlow(
  ai,
  {
    name: `simpleFlow`,
    outputSchema: z.string(),
    httpsOptions: {
      secrets: [googleAIapiKey],
      cors: true,
    },
  },
  async () => {
    const { text } = await ai.generate('Why is AI awesome?');
    return text
  }
)

2. Firebase 認証基盤を組み込んだ構成

genkit-2
Firebase 認証基盤を組み込んだ構成

Web API 構成 を、よりセキュアにした構成です。

Genkit コール時に、Firebase Authentication を使用して、アプリ側のユーザーを判断して、使用元を制限することができます。

例えば、匿名認証済みユーザーのみ許可、特定のメールアドレスのみ許可 などです。

sample
export const firebaseAuthFlow = onFlow(
  ai,
  {
    name: `firebaseAuthFlow`,
    outputSchema: z.string(),
    authPolicy: firebaseAuth((user) => {
      if (user.firebase?.sign_in_provider !== `anonymous`) {
        throw new Error(`Only anonymously authenticated users can access this function`)
      }
    }),
    httpsOptions: {
      secrets: [googleAIapiKey],
      cors: true,
    },
  },
  async () => {}
)

3. Firestore を生成 AI のコンテキストとした構成

genkit-3
Firestore を生成 AI のコンテキストとした構成

Firestore のデータを、生成 AI のコンテキストとして活用する構成です。

クライアントからのリクエストに加えて、Firestore に保存されているデータを参照して、より豊富な情報を基に回答を生成します。

例えば、チャットアプリでは、ユーザーの過去の対話履歴や設定情報を Firestore に保存しておき、それらを考慮した上で回答を生成することが可能です。

sample
export const generateChatMessageFlow = onFlow(
  ai,
  {
    name: `generateChatMessageFlow`,
    // クライアントからのリクエスト形式を zod にて定義
    inputSchema: z.object({
      userId: z.string(),
      chatId: z.string(),
    }),
    // クライアントへのレスポンス形式を zod にて定義
    outputSchema: z.object({
      response: z.string(),
    }),
    // Firebase Authentication の匿名認証の必須化
    authPolicy: firebaseAuth((user) => {
      if (user.firebase?.sign_in_provider !== `anonymous`) {
        throw new Error(`Only anonymously authenticated users can access this function`)
      }
    }),
    // Google AI の API キーを Secret Manager から取得
    httpsOptions: {
      secrets: [googleAIapiKey],
      cors: true,
    },
  },
  async (input) => {
    try {
      // Firestore の初期化
      const db = getFirestore()

      // チャット履歴のための Chats コレクションを取得
      const chatDoc = await db.collection(`chats`).doc(input.chatId).get()

      if (!chatDoc.exists) throw new Error(`Chat document not found`)

      // チャット履歴の取得
      const messagesSnapshot = await chatDoc.ref.collection(`messages`).get()

      // Firestore ドキュメントをメッセージオブジェクトに変換
      const messages = messagesSnapshot.docs.map((doc) => ({
        createdAt: doc.data().createdAt.toDate().toString(),
        isUser: doc.data().isUser,
        text: doc.data().text,
      }))

      // チャット履歴を使用して AI レスポンスを生成
      // ※ dotprompt を使用してプロンプトテンプレートを外部ファイル化
      const { output } = await generateChatMessagePrompt({ messages })

      // AI レスポンスを Firestore に保存
      await chatDoc.ref.collection(`messages`).add({
        createdAt: Timestamp.now(),
        isUser: false,
        text: output.response,
      })

      // Firestore にデータを保存しつつ、念のためクライアントにもレスポンスを返す
      return output
    } catch (error) {
      console.error(`Error in generateChatMessage:`, error)
      throw error
    }
  }
)

4. Cloud Storage for Firebase を生成 AI のコンテキストとした構成

genkit-4
Cloud Storage for Firebase を生成 AI のコンテキストとした構成

Cloud Storage for Firebase に保存されているファイル(画像、音声、動画など)を生成 AI のコンテキストとして活用する構成です。

クライアントからのリクエストに加えて、Storage 内のファイルを AI に与えることで、マルチモーダルな処理が可能となります。

Sample
export const analyzeImageFlow = onFlow(
  ai,
  {
    name: `analyzeImageFlow`,
    inputSchema: z.object({
      storageFileUrl: z.string(),
    }),
    outputSchema: z.object({
      analysis: z.string(),
    }),
    authPolicy: firebaseAuth((user) => {
      if (user.firebase?.sign_in_provider !== `anonymous`) {
        throw new Error(`Only anonymously authenticated users can access this function`)
      }
    }),
    httpsOptions: {
      secrets: [googleAIapiKey],
      cors: true,
    },
  },
  async (input) => {
    const { output } = await analyzeImagePrompt(input)
    return output
  }
)

5. Firebase 各種サービスをトリガーとした構成

genkit-5
Firebase 各種サービスをトリガーとした構成

Firebase の各種サービス (Firestore, Firebase Authentication, Storage など) のイベントをトリガーとして Genkit を起動する構成です。

これによって、特定のデータ変更や条件が満たされた際に、自動的に AI 処理を実行することができます。

6. Web コンテンツを解析する構成

genkit-6
Web コンテンツを解析する構成

外部の Web コンテンツを Genkit の入力として使用する構成です。

7. Observability を強化した構成

genkit-7
Observability を強化した構成

Genkit の動作をより詳細に監視、分析するために OpenTelemetry を組み込んだ構成です。

OpenTelemetry を Google Cloud の Observability ツールである、Cloud Logging, Cloud Monitoring, Cloud Trace などに統合することで、Genkit への入力から出力にかかるフローを視覚化することができます。

例えば、ユーザーからのリクエストが Genkit に到達し、Firestore から値を取得し、Gemini API を呼び出すといった一連のフローを OpenTelemetry でモニタリングすることができます。

トレースデータから、リクエストが正常に処理されたか、どの部分でパフォーマンスが低下したか、エラーが発生したかを視覚的に確認できます。

この構成を採ることで、Genkit サービスの信頼性を高めていくことができます。

sample
import { enableGoogleCloudTelemetry } from '@genkit-ai/google-cloud'

// Enable telemetry for Google Cloud monitoring and debugging
enableGoogleCloudTelemetry()

8. Vertex AI を連携した構成

genkit-8
Vertex AI を連携した構成

Genkit と Google Cloud の Vertex AI を連携させることで、より高度な AI 機能を実現します。

例えば、Genkit で生成した文章を Vertex AI の感情分析モデルでさらに分析することや、Imagen のモデルを活用して、画像生成の機能を実装することができます。

sample
export const generateImageFlow = onFlow(
  ai,
  {
    name: `generateImageFlow`,
    httpsOptions: {
      cors: true,
    },
    inputSchema: z.object({
      prompt: z.string(),
    }),
    authPolicy: firebaseAuth((user) => {
      if (user.firebase?.sign_in_provider !== `anonymous`) {
        throw new Error(`Only anonymously authenticated users can access this function`)
      }
    }),
  },
  async (input) => {
    const { media } = await generateImagePrompt(input)
    return media
  }
)

Genkit サンプルコード集

GitHubで編集を提案

Discussion