アプリから Genkit フローを呼び出す

Cloud Functions for Firebase には、Genkit アクション(Flow)を使用して呼び出し可能関数を作成できる onCallGenkit メソッドがあります。これらの関数は、genkit/beta/client または Cloud Functions クライアント SDK で呼び出すことができます。この場合、認証情報が自動的に追加されます。

始める前に

  • Genkit のフローのコンセプトと、フローを作成する方法を理解している必要があります。このページで説明する手順では、デプロイするフローがある程度定義されていることを前提としています。
  • 以前に Cloud Functions for Firebase を使用したことがある場合は役立ちますが、必須ではありません。

Firebase プロジェクトを設定します

  1. Firebase コンソールを使用して新しい Firebase プロジェクトを作成するか、既存のプロジェクトを選択します。

  2. プロジェクトを Blaze プランにアップグレードします。これは、Cloud Functions の本番環境デプロイに必要です。

  3. Firebase CLI をインストールします。

  4. Firebase CLI を使用してログインします。

    firebase login
    firebase login --reauth # alternative, if necessary
    firebase login --no-localhost # if running in a remote shell
  5. 新しいプロジェクト ディレクトリを作成します。

    export PROJECT_ROOT=~/tmp/genkit-firebase-project1
    mkdir -p $PROJECT_ROOT
  6. ディレクトリ内で Firebase プロジェクトを初期化します。

    cd $PROJECT_ROOT
    firebase init functions

ここからは、関数を JavaScript で記述することを前提としています。

onCallGenkit でフローをラップする

Cloud Functions を使用して Firebase プロジェクトを設定したら、プロジェクトの functions ディレクトリにフロー定義をコピーまたは作成できます。これを説明するフローの例を以下に示します。

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

const jokeTeller = ai.defineFlow({
  name: "jokeTeller",
  inputSchema: z.string().nullable(),
  outputSchema: z.string(),
  streamSchema: z.string(),
}, async (jokeType = "knock-knock", {sendChunk}) => {
  const prompt = `Tell me a ${jokeType} joke.`;

  // Call the `generateStream()` method to
  // receive the `stream` async iterable.
  const {stream, response: aiResponse} = ai.generateStream(prompt);

  // Send new words of the generative AI response
  // to the client as they are generated.
  for await (const chunk of stream) {
    sendChunk(chunk.text);
  }

  // Return the full generative AI response
  // to clients that may not support streaming.
  return (await aiResponse).text;
},
);

このようなフローをデプロイするには、firebase-functions/https で使用可能な onCallGenkit でラップします。このヘルパー メソッドには、呼び出し可能関数のすべての機能があり、ストリーミングと JSON レスポンスを自動的にサポートします。

const {onCallGenkit} = require("firebase-functions/v2/https");
exports.tellJoke = onCallGenkit({
  // Bind the Gemini API key secret parameter to the function.
  secrets: [apiKey],
},
// Pass in the genkit flow.
jokeTeller,
);

デプロイされたフローに対して API 認証情報を使用できるようにする

デプロイされたフローには、依存するリモート サービスで認証する方法が必要になります。ほとんどのフローで、使用するモデル API サービスにアクセスするための認証情報が最低限必要です。

この例では、選択したモデル プロバイダに応じて、以下のいずれかを行います。

Gemini(Google AI)

  1. Google AI がお住まいの地域で利用可能であることを確認します。

  2. Google AI Studio を使用して Gemini API の API キーを生成します。

  3. API キーを Cloud Secret Manager に保存します。

    firebase functions:secrets:set GOOGLE_GENAI_API_KEY

    このステップは、従量制となり得るサービスへのアクセスを許可する API キーが誤って漏洩するのを防ぐために重要です。

    シークレットの管理の詳細については、機密性の高い構成情報の保存とアクセスをご覧ください。

  4. src/index.js を編集し、既存のインポートの後に以下を追加します。

    const {defineSecret} = require("firebase-functions/params");
    // Store the Gemini API key in Cloud Secret Manager.
    const apiKey = defineSecret("GOOGLE_GENAI_API_KEY");
    

    次に、呼び出し可能関数の定義で、関数にこのシークレット値へのアクセスが必要であることを宣言します。

    // Bind the Gemini API key secret parameter to the function.
    secrets: [apiKey],
    

この関数をデプロイすると、API キーが Cloud Secret Manager に保存され、Cloud Functions 環境から使用できるようになります。

Gemini(Vertex AI)

  1. Cloud コンソールで、Firebase プロジェクトの [Vertex AI API を有効にする] を選択します。

  2. [IAM] ページで、デフォルトのコンピューティング サービス アカウントVertex AI ユーザーロールが付与されていることを確認します。

このチュートリアルで設定する必要があるシークレットはモデル プロバイダ用のものだけですが、一般的には、フローで使用する各サービスに対して同様の設定を行う必要があります。

(省略可)App Check の適用を追加する

Firebase App Check はネイティブ証明書を使用して、API がアプリケーションからのみ呼び出されていることを検証します。onCallGenkit は、App Check の適用を宣言型の方法でサポートします。

export const generatePoem = onCallGenkit({
  enforceAppCheck: true,
  // Optional. Makes App Check tokens only usable once. This adds extra security
  // at the expense of slowing down your app to generate a token for every API
  // call
  consumeAppCheckToken: true,
}, generatePoemFlow);

CORS(クロスオリジン リソース シェアリング)を構成する

cors オプションを使用して、関数にアクセスできるオリジンを制御します。

デフォルトでは、すべての送信元からのリクエストを許可するように、呼び出し可能関数には CORS が構成されています。一部のクロスオリジン リクエストを許可する場合は、許可するドメインまたは正規表現のリストを渡します。次に例を示します。

export const tellJoke = onCallGenkit({
  cors: 'mydomain.com',
}, jokeTeller);

サンプルコードの全文

上記の変更をすべて行った後、デプロイ可能なフローは以下のようになります。

const {onCallGenkit} = require("firebase-functions/v2/https");
const {defineSecret} = require("firebase-functions/params");

// Dependencies for Genkit.
const {gemini15Flash, googleAI} = require("@genkit-ai/googleai");
const {genkit, z} = require("genkit");

// Store the Gemini API key in Cloud Secret Manager.
const apiKey = defineSecret("GOOGLE_GENAI_API_KEY");

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

const jokeTeller = ai.defineFlow({
  name: "jokeTeller",
  inputSchema: z.string().nullable(),
  outputSchema: z.string(),
  streamSchema: z.string(),
}, async (jokeType = "knock-knock", {sendChunk}) => {
  const prompt = `Tell me a ${jokeType} joke.`;

  // Call the `generateStream()` method to
  // receive the `stream` async iterable.
  const {stream, response: aiResponse} = ai.generateStream(prompt);

  // Send new words of the generative AI response
  // to the client as they are generated.
  for await (const chunk of stream) {
    sendChunk(chunk.text);
  }

  // Return the full generative AI response
  // to clients that may not support streaming.
  return (await aiResponse).text;
},
);

exports.tellJoke = onCallGenkit({
  // Bind the Gemini API key secret parameter to the function.
  secrets: [apiKey],
},
// Pass in the genkit flow.
jokeTeller,
);

Firebase にフローをデプロイする

onCallGenkit を使用してフローを定義したら、他の関数をデプロイする場合と同様にデプロイできます。

cd $PROJECT_ROOT
firebase deploy --only functions