Zenn
Open9

Firebase Genkitを使ってみる

hosaka313hosaka313

What

Firebase Genkitを使ってみるメモ。Firebase Authenticationを組み込んだNuxt3フロントエンドで認証付きリクエストをしたり、テレメトリを眺めたり。

Projectの作成

$firebase init genkit

https://firebase.google.com/docs/genkit/firebase?hl=ja&authuser=0

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add, 
but for now we'll just set up a default project.

? Please select an option: Use an existing project
? Select a default Firebase project for this directory: **********
i  Using project **********

=== Genkit Setup
? Genkit's Firebase integration uses Cloud Functions for Firebase with TypeScript.
Initialize Functions to continue? Yes
Let's create a new codebase for your functions.
A directory corresponding to the codebase will be created in your project
with sample code pre-configured.

See https://firebase.google.com/docs/functions/organize-functions for
more information on organizing your functions using codebases.

Functions can be deployed with firebase deploy.

? Do you want to use ESLint to catch probable bugs and enforce style? No
✔  Wrote functions/package.json
✔  Wrote functions/tsconfig.json
✔  Wrote functions/src/index.ts
✔  Wrote functions/.gitignore
? Do you want to install dependencies with npm now? No

? Install the Genkit CLI globally or locally in this project? Just this project
i  genkit: Installing Genkit CLI version 0.9.12

Providerの選択

? Select a model provider: 
❯ Google Cloud Vertex AI 
  Google AI 
  None 
hosaka313hosaka313

sample

以下のsampleが生成された。

// Import the Genkit core libraries and plugins.
import {genkit, z} from "genkit";
import {vertexAI} from "@genkit-ai/vertexai";

// Import models from the Vertex AI plugin. The Vertex AI API provides access to
// several generative models. Here, we import Gemini 1.5 Flash.
import {gemini15Flash} from "@genkit-ai/vertexai";

// From the Firebase plugin, import the functions needed to deploy flows using
// Cloud Functions.
import {firebaseAuth} from "@genkit-ai/firebase/auth";
import {onFlow} from "@genkit-ai/firebase/functions";

const ai = genkit({
  plugins: [
    // Load the Vertex AI plugin. You can optionally specify your project ID
    // by passing in a config object; if you don't, the Vertex AI plugin uses
    // the value from the GCLOUD_PROJECT environment variable.
    vertexAI({location: "us-central1"}),
  ],
});

// Define a simple flow that prompts an LLM to generate menu suggestions.
export const menuSuggestionFlow = onFlow(
  ai,
  {
    name: "menuSuggestionFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    authPolicy: firebaseAuth((user) => {
      // By default, the firebaseAuth policy requires that all requests have an
      // `Authorization: Bearer` header containing the user's Firebase
      // Authentication ID token. All other requests are rejected with error
      // 403. If your app client uses the Cloud Functions for Firebase callable
      // functions feature, the library automatically attaches this header to
      // requests.

      // You should also set additional policy requirements as appropriate for
      // your app. For example:
      // if (!user.email_verified) {
      //   throw new Error("Verified email required to run flow");
      // }
    }),
  },
  async (subject) => {
    // Construct a request and send it to the model API.
    const prompt =
      `Suggest an item for the menu of a ${subject} themed restaurant`;
    const llmResponse = await ai.generate({
      model: gemini15Flash,
      prompt: prompt,
      config: {
        temperature: 1,
      },
    });

    // Handle the response from the model API. In this sample, we just
    // convert it to a string, but more complicated flows might coerce the
    // response into structured output or chain the response into another
    // LLM call, etc.
    return llmResponse.text;
  }
);
hosaka313hosaka313

とりあえずサンプルコードをsrc/index.tsに貼り付け。

下記でlocalhost:4000にサーバーが立ち上がる。

npx genkit start -- npx tsx --watch src/index.ts
http://localhost:4000/flows

hosaka313hosaka313

デプロイ

どうデプロイされるのかわからないのでデプロイしてみる。

$npm run deploy

Cloud Run関数のURLが生成されるのでアクセスしてみる。

当然、UnAuthorized。

未認証の呼び出しOnになっているのでGenkitのauthPolicyが効いているっぽい。

hosaka313hosaka313

Firebase Hostingから呼び出す

https://firebase.google.com/docs/functions/callable?hl=ja&gen=2nd

フロント

Nuxt3でFirebase Authenticationを実装していたので、それを流用。

<template>
  <div>
    <GoogleButton
      label="Let's Call Genkit!"
      @click="getSuggestion"
    />
    {{ result }}
  </div>
</template>

<script setup lang="ts">
import { httpsCallable } from 'firebase/functions'

const { $functions } = useNuxtApp()

const menusuggestionflow = httpsCallable($functions, 'menuSuggestionFlow')

const subject = ref('Japanese')
const result = ref('')

const getSuggestion = async () => {
  try {
    // Firebase Functionsの呼び出し
    // 認証済みユーザーのIDトークンは自動的に付与される
    const response = await menusuggestionflow(subject.value)
    result.value = response.data as string
  }
  catch (error) {
    console.error('Error calling function:', error)
  }
}
</script>

corsエラー

以下の設定を追加。

  {
    name: "menuSuggestionFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    authPolicy: firebaseAuth((user) => {
      // By default, the firebaseAuth policy requires that all requests have an
      // `Authorization: Bearer` header containing the user's Firebase
      // Authentication ID token. All other requests are rejected with error
      // 403. If your app client uses the Cloud Functions for Firebase callable
      // functions feature, the library automatically attaches this header to
      // requests.

      // You should also set additional policy requirements as appropriate for
      // your app. For example:
      // if (!user.email_verified) {
      //   throw new Error("Verified email required to run flow");
      // }
    }),
    httpsOptions: {
      cors: ["*"]
    }

できた

超絶適当だが、Firebase Authを済ませた状態ならちゃんと戻ってきた。emulatorだとダメだった。

hosaka313hosaka313

モニタリング

以下を足すのだそう。

import { enableFirebaseTelemetry } from "@genkit-ai/firebase";

enableFirebaseTelemetry();

IAM権限追加

Compute Engine default service account に以下を追加。

  • Cloud Trace エージェント
  • モニタリング指標の書き込み
  • ログ書き込み

リクエストを送って待つ

反映まで10分くらいかかった。

出てきた。

hosaka313hosaka313

トレースも取れたよ

個別。

特定のユーザーに対してrate limitをかけたい、とかはまだできない...?

hosaka313hosaka313

感想

あまり丁寧には見れていないが、トレース周りをやってくれるのはありがたい。また、認証部分をカプセルできるのも自前より安心。
動きが激しいので、急にサービス終了しないかがちょっと心配。

ログインするとコメントできます