Skip to content

How to pass GOOGLE_GENAI_API_KEY when using onFlow() #1586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gregfenton opened this issue Jul 15, 2024 · 7 comments
Closed

How to pass GOOGLE_GENAI_API_KEY when using onFlow() #1586

gregfenton opened this issue Jul 15, 2024 · 7 comments

Comments

@gregfenton
Copy link

gregfenton commented Jul 15, 2024

Related issues

Possibly #1567

[REQUIRED] Version info

node:

18.20.2

firebase-functions:

5.0.1

firebase-tools:

13.13.2

firebase-admin:

[email protected]
[email protected]
[email protected]

─ @genkit-ai/[email protected]
─ @genkit-ai/[email protected]

[REQUIRED] Test case

Cloud Functions code:

import * as z from "zod";

import {generate} from "@genkit-ai/ai";
import {configureGenkit} from "@genkit-ai/core";
import {firebase} from "@genkit-ai/firebase";
import {googleAI} from "@genkit-ai/googleai";
import {onInit} from "firebase-functions/v2/core";

import {gemini15Flash} from "@genkit-ai/googleai";

import {firebaseAuth} from "@genkit-ai/firebase/auth";
import {onFlow} from "@genkit-ai/firebase/functions";

import {defineSecret} from "firebase-functions/params";
import {onCall} from "firebase-functions/v2/https";
const genAiApiKey = defineSecret("GOOGLE_GENAI_API_KEY");

onInit(() => {
  console.log("GLF: onInit() genAiApiKey:", genAiApiKey?.value());

  configureGenkit({
    plugins: [firebase(), googleAI({apiKey: genAiApiKey.value()})],
    logLevel: "debug",
    enableTracingAndMetrics: true,
  });
});

export const menuSuggestionFlow = onFlow(
  {
    name: "menuSuggestionFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    httpsOptions: {cors: true},
    authPolicy: firebaseAuth((user) => {}),
  },
  async (subject) => {
    const apiKey = process.env.GOOGLE_GENAI_API_KEY; // Access the secret here
    
    const prompt = `Suggest an item for the menu of a ${subject} themed restaurant`;
    const llmResponse = await generate({
      model: gemini15Flash,
      prompt: prompt,
      config: {
        temperature: 1,
        apiKey: apiKey,
      },
    });

    return llmResponse.text();
  },
);

export const testApiKey = onCall({secrets: ["GOOGLE_GENAI_API_KEY"]}, async () => {
  const apiKey = genAiApiKey.value();
  console.log("API Key:", apiKey);

  return {result: apiKey};
});

[REQUIRED] Steps to reproduce

Follow steps from Deploy a flow as a Cloud Function but replace code in functions/src/index.ts with:

import * as z from "zod";

import {generate} from "@genkit-ai/ai";
import {configureGenkit} from "@genkit-ai/core";
import {firebase} from "@genkit-ai/firebase";
import {googleAI} from "@genkit-ai/googleai";
import {onInit} from "firebase-functions/v2/core";

import {gemini15Flash} from "@genkit-ai/googleai";

import {firebaseAuth} from "@genkit-ai/firebase/auth";
import {onFlow} from "@genkit-ai/firebase/functions";

import {defineSecret} from "firebase-functions/params";
import {onCall} from "firebase-functions/v2/https";
const genAiApiKey = defineSecret("GOOGLE_GENAI_API_KEY");

onInit(() => {
  console.log("GLF: onInit() genAiApiKey:", genAiApiKey?.value());

  configureGenkit({
    plugins: [firebase(), googleAI({apiKey: genAiApiKey.value()})],
    logLevel: "debug",
    enableTracingAndMetrics: true,
  });
});

export const menuSuggestionFlow = onFlow(
  {
    name: "menuSuggestionFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    httpsOptions: {cors: true},
    authPolicy: firebaseAuth((user) => {}),
  },
  async (subject) => {
    const apiKey = process.env.GOOGLE_GENAI_API_KEY; // Access the secret here
    
    const prompt = `Suggest an item for the menu of a ${subject} themed restaurant`;
    const llmResponse = await generate({
      model: gemini15Flash,
      prompt: prompt,
      config: {
        temperature: 1,
        apiKey: apiKey,
      },
    });

    return llmResponse.text();
  },
);

export const testApiKey = onCall({secrets: ["GOOGLE_GENAI_API_KEY"]}, async () => {
  const apiKey = genAiApiKey.value();
  console.log("API Key:", apiKey);

  return {result: apiKey};
});

[REQUIRED] Expected behavior

Running web client app returns a generated list of restaurant menu items.

[REQUIRED] Actual behavior

Error is logged to browser's JS Console:

Uncaught (in promise) FirebaseError: Please pass in the API key or set the GOOGLE_GENAI_API_KEY or GOOGLE_API_KEY environment variable.
For more details see https://firebase.google.com/docs/genkit/plugins/google-genai

In Logs Explorer I get the error:

Error: Please pass in the API key or set the GOOGLE_GENAI_API_KEY or GOOGLE_API_KEY environment variable.
For more details see https://firebase.google.com/docs/genkit/plugins/qooqle-genai
  at googleAIModel (/workspace/node_modules/@genkit-ai/googleai/lib/gemini.js:393:11)
  at /workspace/node_modules/@genkit-ai/googleai/lib/index.js:76:53
  at Array.map (<anonymous>) 
  at /workspace/node_modules/@genkit-ai/googleai/lib/index.js:75:59
  at Generator.next (<anonvmous> 
  at /workspace/node_modules/@genkit-ai/googleai/lib/index.js:36:6
  at new Promise (<anonymous>)
  at -_async (/workspace/node_modules/@genkit-ai/googleai/lib/index.js:20:18)
  at /workspace/node_modules/@genkit-ai/googleai/lib/index.js:55:16
  at /workspace/node_modules/@genkit-ai/core/lib/plugin.js:48:40

Were you able to successfully deploy your functions?

Yes, they deployed fine. And the function testApiKey when called from the same HTML client runs fine and displays the proper API key value from the Secrets Manager.

@google-oss-bot
Copy link
Collaborator

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@chrisraygill
Copy link

chrisraygill commented Jul 15, 2024

@kevinthecheung is this just a docs gap or does it look like a Genkit bug? @mbleigh maybe related to #1567?

@taeold
Copy link
Contributor

taeold commented Jul 16, 2024

Hi @gregfenton.

It looks like the flow you defined isn't bound to the secret:

export const menuSuggestionFlow = onFlow(
  {
    name: "menuSuggestionFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    httpsOptions: {cors: true},
    authPolicy: firebaseAuth((user) => {}),
    secrets: [genAiApiKey], # LOOK HERE
  },

See the documentation for more info.

It's a common footgun, and I wish there was a more intuitive way to bind secrets to functions. If you have any idea, please let us know.

(FWIW, this issue is unrelated to #1567)

@gregfenton
Copy link
Author

gregfenton commented Jul 16, 2024

@taeold I added that line to the onFlow() parameters, but that leads to the error:

Object literal may only specify known properties, and 'secrets' does not exist in type 'FunctionFlowConfig<ZodString, ZodString, ZodTypeAny>'.ts(2353)

Seems that TS is telling the truth.

FYI: I use Cloud Functions and Secrets Manager daily.

It is onFlow() that is new to me 😁

Is there reference documentation for onFlow() similar to onCall() ? I can't seem to find it.

@taeold
Copy link
Contributor

taeold commented Jul 16, 2024

@gregfenton Based on https://github.com/firebase/genkit/blob/main/js/plugins/firebase/src/functions.ts#L51, it looks like the correct syntax might be:

export const menuSuggestionFlow = onFlow(
  {
    name: "menuSuggestionFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    httpsOptions: {cors: true, secrets: [genAiApiKey] }, # LOOK HERE
    authPolicy: firebaseAuth((user) => {}), 
  },

Do you mind giving this a try?

Refernce docs would be nice, and I expect them to be incoming!

@gregfenton
Copy link
Author

gregfenton commented Jul 16, 2024

@taeold That totally fixed it! 🥳

Wasn't obvious to me that HttpOptions are actually "HTTP Cloud Function options".

Wait....OMG....was this there the whole time? Please tell me this was the Firebase Genkit team just being super responsive and not that I totally can't read/messed up???!!! 🫣

image

@gregfenton
Copy link
Author

image

You all rock!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants