Развертывание потоков с помощью облачных функций для Firebase

Genkit включает плагин, который поможет вам развернуть потоки в Cloud Functions для Firebase. Потоки после развертывания доступны как конечные точки HTTPS и доступны как вызываемые функции с использованием клиентских библиотек Cloud Functions.

Прежде чем начать

  • Установите Firebase CLI .
  • Вы должны быть знакомы с концепцией потоков Genkit и тем, как их писать. Инструкции на этой странице предполагают, что у вас уже определены некоторые потоки, которые вы хотите развернуть.
  • Было бы полезно, но не обязательно, если вы уже использовали Cloud Functions для Firebase.

1. Настройте проект Firebase

Если у вас еще нет проекта Firebase с настроенными облачными функциями TypeScript, выполните следующие действия:

  1. Создайте новый проект Firebase с помощью консоли Firebase или выберите существующий.

  2. Обновите проект до плана Blaze, который необходим для развертывания облачных функций.

  3. Войдите в систему с помощью Firebase CLI:

    firebase login
    firebase login --reauth # alternative, if necessary
    firebase login --no-localhost # if running in a remote shell
  4. Создайте новый каталог проекта:

    export PROJECT_ROOT=~/tmp/genkit-firebase-project1
    mkdir -p $PROJECT_ROOT
  5. Инициализируйте проект Firebase в каталоге:

    cd $PROJECT_ROOT
    firebase init genkit

    В оставшейся части этой страницы предполагается, что вы решили писать свои функции на TypeScript, но вы также можете развернуть потоки Genkit, если используете JavaScript.

2. Обновление определений потока

После настройки проекта Firebase с Cloud Functions вы можете скопировать или записать определения потоков в каталоге functions/src проекта и экспортировать их в index.ts .

Чтобы ваши потоки можно было развернуть, вам необходимо внести некоторые небольшие изменения в их определение. Основная логика останется прежней, но вы добавите некоторую дополнительную информацию, чтобы сделать их более плавными и безопасными после развертывания.

Предположим, у вас есть следующий поток:

const generatePoemFlow = ai.defineFlow(
  {
    name: "generatePoem",
    inputSchema: z.string(),
    outputSchema: z.string(),
  },
  async (subject: string) => {
    const { text } = await ai.generate(`Compose a poem about ${subject}.`);
    return text;
  }
);

В следующих разделах описаны изменения, которые необходимо внести перед развертыванием.

Определите потоки с помощью onFlow

Вместо определения потока с помощью Genkit.defineFlow() используйте функцию onFlow() плагина Firebase. Использование этой функции оборачивает вашу логику потока в обработчик запросов Cloud Functions, аналогичный onCall .

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

export const generatePoem = onFlow(
  ai,
  {
    // ...
  },
  async (subject: string) => {
    // ...
  }
);

Обратите внимание, что onFlow — это не метод Genkit , а функция, которая принимает экземпляр Genkit в качестве первого параметра. В остальном синтаксис аналогичен defineFlow .

Определить политику авторизации

Все развернутые потоки, независимо от того, развернуты ли они в Firebase или нет, должны иметь политику авторизации; без него ваши потенциально дорогостоящие генеративные потоки ИИ были бы доступны кому угодно. Чтобы определить политику авторизации, используйте параметр authPolicy в определении потока:

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

export const generatePoem = onFlow(
  ai,
  {
    name: "generatePoem",
    // ...
    authPolicy: firebaseAuth((user, input) => {
      if (!user.email_verified) {
        throw new Error("Verified email required to run flow");
      }
    }),
  },
  async (subject: string) => {
    // ...
  }
);

Эта политика использует помощник firebaseAuth() чтобы разрешить доступ только зарегистрированным пользователям вашего приложения с проверенными адресами электронной почты. На стороне клиента вам необходимо установить заголовок Authorization: Bearer для токена Firebase ID, который соответствует вашей политике. Клиентские SDK Cloud Functions предоставляют вызываемые методы функций, которые автоматизируют это; пример см. в разделе «Опробуйте развернутый поток» .

Сделайте учетные данные API доступными для развернутых потоков.

После развертывания вашим потокам потребуется какой-то способ аутентификации с любыми удаленными службами, от которых они зависят. Большинству потоков как минимум потребуются учетные данные для доступа к используемому ими сервису API модели.

В этом примере выполните одно из следующих действий в зависимости от выбранного вами поставщика модели:

Близнецы (ИИ Google)

  1. Убедитесь, что Google AI доступен в вашем регионе .

  2. Создайте ключ API для Gemini API с помощью Google AI Studio.

  3. Сохраните свой ключ API в Cloud Secret Manager:

    firebase functions:secrets:set GOOGLE_GENAI_API_KEY

    Этот шаг важен для предотвращения случайной утечки вашего ключа API, который предоставляет доступ к потенциально измеряемой услуге.

    Дополнительные сведения об управлении секретами см. в разделе Хранение и доступ к конфиденциальной информации о конфигурации .

  4. Отредактируйте src/index.ts и добавьте следующее после существующего импорта:

    import {defineSecret} from "firebase-functions/params";
    const googleAIapiKey = defineSecret("GOOGLE_GENAI_API_KEY");
    

    Затем в определении потока объявите, что облачной функции необходим доступ к этому секретному значению:

    export const generatePoem = onFlow(
      {
        name: "generatePoem",
        // ...
        httpsOptions: {
          secrets: [googleAIapiKey],  // Add this line.
        },
      },
      async (subject) => {
        // ...
      }
    );
    

Теперь, когда вы развернете эту функцию, ваш ключ API будет храниться в Cloud Secret Manager и доступен из среды Cloud Functions.

Близнецы (Vertex AI)

  1. В облачной консоли включите API Vertex AI для вашего проекта Firebase.

  2. На странице IAM убедитесь, что учетной записи службы вычислений по умолчанию предоставлена ​​роль пользователя Vertex AI .

Единственный секрет, который вам нужно настроить для этого руководства, — это поставщик модели, но в целом вы должны сделать что-то подобное для каждой службы, которую использует ваш поток.

Установите политику CORS

Если вы будете получать доступ к своему потоку из веб-приложения (что вы сделаете в разделе «Попробуйте развернутый поток» ), в параметре httpsOptions установите политику CORS:

export const generatePoem = onFlow(
  ai,
  {
    name: "generatePoem",
    // ...
    httpsOptions: {
      cors: '*',
    },
  },
  async (subject: string) => {
    // ...
  }
);

Вероятно, вам понадобится более строгая политика для рабочих приложений, но для данного руководства этого достаточно.

Полный пример

После внесения всех описанных выше изменений ваш процесс развертывания будет выглядеть примерно так:

const googleAIapiKey = defineSecret("GOOGLE_GENAI_API_KEY");

export const generatePoem = onFlow(
  ai,
  {
    name: "generatePoem",
    inputSchema: z.string(),
    outputSchema: z.string(),
    authPolicy: firebaseAuth((user, input) => {
      if (!user.email_verified) {
        throw new Error("Verified email required to run flow");
      }
    }),
    httpsOptions: {
      secrets: [googleAIapiKey],
      cors: '*',
    },
  },
  async (subject: string) => {
    const { text } = await ai.generate(`Compose a poem about ${subject}.`);
    return text;
  }
);

3. Развертывание потоков в Firebase

После того как вы определили потоки с помощью onFlow , вы можете развернуть их так же, как и другие облачные функции:

cd $PROJECT_ROOT
firebase deploy --only functions

Теперь вы развернули поток как облачную функцию! Но вы не сможете получить доступ к развернутой конечной точке с помощью curl или аналогичного средства из-за политики авторизации потока. Перейдите к следующему разделу, чтобы узнать, как безопасно получить доступ к потоку.

Необязательно: попробуйте развернутый поток

Чтобы опробовать конечную точку потока, вы можете развернуть следующий минимальный пример веб-приложения:

  1. В разделе «Настройки проекта» консоли Firebase добавьте новое веб-приложение, выбрав опцию также настроить хостинг.

  2. В разделе «Аутентификация» консоли Firebase включите провайдера Google , который вы будете использовать в этом примере.

  3. В каталоге вашего проекта настройте хостинг Firebase, где вы будете развертывать пример приложения:

    cd $PROJECT_ROOT
    firebase init hosting

    Примите значения по умолчанию для всех запросов.

  4. Замените public/index.html следующим:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Genkit demo</title>
      </head>
      <body>
        <div id="signin" hidden>
          <button id="signinBtn">Sign in with Google</button>
        </div>
        <div id="callGenkit" hidden>
          Subject: <input type="text" id="subject" />
          <button id="generatePoem">Compose a poem on this subject</button>
          <p id="generatedPoem"></p>
        </div>
        <script type="module">
          import { initializeApp } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-app.js";
          import {
            getAuth,
            onAuthStateChanged,
            GoogleAuthProvider,
            signInWithPopup,
          } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-auth.js";
          import {
            getFunctions,
            httpsCallable,
          } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-functions.js";
    
          const firebaseConfig = await fetch("/__/firebase/init.json");
          initializeApp(await firebaseConfig.json());
    
          async function generatePoem() {
            const poemFlow = httpsCallable(getFunctions(), "generatePoem");
            const subject = document.querySelector("#subject").value;
            const response = await poemFlow(subject);
            document.querySelector("#generatedPoem").innerText = response.data;
          }
    
          function signIn() {
            signInWithPopup(getAuth(), new GoogleAuthProvider());
          }
    
          document.querySelector("#signinBtn").addEventListener("click", signIn);
          document
            .querySelector("#generatePoem")
            .addEventListener("click", generatePoem);
    
          const signinEl = document.querySelector("#signin");
          const genkitEl = document.querySelector("#callGenkit");
    
          onAuthStateChanged(getAuth(), (user) => {
            if (!user) {
              signinEl.hidden = false;
              genkitEl.hidden = true;
            } else {
              signinEl.hidden = true;
              genkitEl.hidden = false;
            }
          });
        </script>
      </body>
    </html>
    
  5. Разверните веб-приложение и облачную функцию:

    cd $PROJECT_ROOT
    firebase deploy

Откройте веб-приложение, посетив URL-адрес, напечатанный командой deploy . Приложение требует входа в систему с учетной записью Google, после чего вы можете инициировать запросы к конечным точкам.

Необязательно: запускайте потоки в пользовательском интерфейсе разработчика.

Вы можете запускать потоки, определенные с помощью onFlow в пользовательском интерфейсе разработчика, точно так же, как вы запускаете потоки, определенные с помощью defineFlow , поэтому нет необходимости переключаться между ними между развертыванием и разработкой.

cd $PROJECT_ROOT/functions
npx genkit start -- npx tsx --watch src/index.ts

Необязательно: разработка с использованием пакета локального эмулятора Firebase.

Firebase предлагает набор эмуляторов для локальной разработки , которые вы можете использовать с Genkit.

Чтобы использовать Genkit с пакетом эмуляторов Firebase, запустите эмуляторы Firebase следующим образом:

GENKIT_ENV=dev firebase emulators:start --inspect-functions

Это запустит ваш код в эмуляторе и запустит платформу Genkit в режиме разработки, которая запускает и предоставляет API отражения Genkit (но не пользовательский интерфейс Dev).

Затем запустите пользовательский интерфейс Genkit Dev с опцией --attach , чтобы подключить его к вашему коду, работающему внутри эмулятора Firebase:

npx genkit start --attach http://localhost:3100 --port 4001

Чтобы увидеть трассировки из Firestore в пользовательском интерфейсе разработчика, вы можете перейти на вкладку «Проверка» и переключить переключатель «Разработка/Прод». При переключении на «prod» будут загружаться трассировки из Firestore.