Cloud Functions for Firebase'i kullanarak akışları dağıtma

Cloud Functions for Firebase'da, Genkit işlemiyle (ör. bir Flow) hızlıca çağrılabilir işlev oluşturmanıza olanak tanıyan bir onCallGenkit yöntemi vardır. Bu işlevler, genkit/beta/clientveya otomatik olarak kimlik doğrulama bilgileri ekleyen Functions istemci SDK'sı kullanılarak çağrılabilir.

Başlamadan önce

  • Genkit'in akış kavramı ve bunların nasıl yazılacağı hakkında bilgi sahibi olmanız gerekir. Bu sayfadaki talimatlarda, dağıtmak istediğiniz bazı akışların tanımlanmış olduğu varsayılır.
  • Daha önce Firebase için Cloud Functions'i kullandıysanız bu faydalı olur ancak gerekli değildir.

1. Firebase projesi oluşturma

TypeScript Cloud Functions'in ayarlandığı bir Firebase projeniz yoksa aşağıdaki adımları uygulayın:

  1. Firebase konsolunu kullanarak yeni bir Firebase projesi oluşturun veya mevcut bir projeyi seçin.

  2. Cloud Functions'i dağıtmak için gereken Blaze planına yükseltin.

  3. Firebase CLI'yi yükleyin.

  4. Firebase CLI ile oturum açın:

    firebase login
    firebase login --reauth # alternative, if necessary
    firebase login --no-localhost # if running in a remote shell
  5. Yeni bir proje dizini oluşturun:

    export PROJECT_ROOT=~/tmp/genkit-firebase-project1
    mkdir -p $PROJECT_ROOT
  6. Dizininde bir Firebase projesini başlatın:

    cd $PROJECT_ROOT
    firebase init genkit

    Bu sayfanın geri kalanında, işlevlerinizi TypeScript'te yazmaya karar verdiğiniz varsayılmaktadır. Ancak JavaScript kullanıyorsanız Genkit akışlarınızı dağıtabilirsiniz.

2. Akış'ı onCallGenkit içine sarmalayın

Cloud Functions ile bir Firebase projesi oluşturduktan sonra, projenin functions/src dizininde akış tanımlarını kopyalayabilir veya yazabilir ve index.ts'a aktarabilirsiniz.

Akışlarınızın dağıtılabilmesi için onCallGenkit içine sarmanız gerekir. Bu yöntem, normal onCall işlevinin tüm özelliklerine sahiptir. Hem akış hem de JSON yanıtlarını otomatik olarak destekler.

Aşağıdaki akışa sahip olduğunuzu varsayalım:

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;
  }
);

Bu akışı onCallGenkit kullanarak çağrılabilir bir işlev olarak gösterebilirsiniz:

import { onCallGenkit } from 'firebase-functions/https';

export generatePoem = onCallGenkit(generatePoemFlow);

Yetkilendirme politikası tanımlama

Firebase'e dağıtılmış olsun veya olmasın, dağıtılan tüm akışların bir yetkilendirme politikası olmalıdır. Aksi takdirde, pahalı olabilecek üretken yapay zeka akışlarınızı herkes çağırabilir. Yetkilendirme politikası tanımlamak için onCallGenkit parametresinin authPolicy parametresini kullanın:

export const generatePoem = onCallGenkit({
  authPolicy: (auth) => auth?.token?.email_verified,
}, generatePoemFlow);

Bu örnekte, kimlik doğrulama politikası olarak manuel bir işlev kullanılmaktadır. Ayrıca https kütüphanesi, signedIn() ve hasClaim() yardımcılarını da dışa aktarır. Bu yardımcılardan birini kullanan aynı kod aşağıda verilmiştir:

import { hasClaim } from 'firebase-functions/https';

export const generatePoem = onCallGenkit({
  authPolicy: hasClaim('email_verified'),
}, generatePoemFlow);

API kimlik bilgilerini dağıtılan akışlar için kullanılabilir hale getirme

Yayınlanan akışlarınızın, kullandıkları uzak hizmetlerle kimlik doğrulaması yapması gerekir. Çoğu akışta, en azından kullandıkları model API hizmetine erişmek için kimlik bilgileri gerekir.

Bu örnekte, seçtiğiniz model sağlayıcıya bağlı olarak aşağıdakilerden birini yapın:

Gemini (Google Yapay Zeka)

  1. Google Yapay Zeka'nın bölgenizde kullanılabildiğinden emin olun.

  2. Google AI Studio'yu kullanarak Gemini API için API anahtarı oluşturun.

  3. API anahtarınızı Cloud Secret Manager'da depolayın:

    firebase functions:secrets:set GOOGLE_GENAI_API_KEY

    Bu adım, olası ücretli bir hizmete erişim sağlayan API anahtarınızın yanlışlıkla sızmasını önlemek için önemlidir.

    Gizli bilgileri yönetme hakkında daha fazla bilgi için Hassas yapılandırma bilgilerini depolama ve bunlara erişme başlıklı makaleyi inceleyin.

  4. src/index.ts dosyasını düzenleyin ve mevcut içe aktarma işlemlerinin ardından şunları ekleyin:

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

    Ardından, akış tanımında, Cloud işlevinin bu gizli değere erişmesi gerektiğini belirtin:

    export const generatePoem = onCallGenkit({
      secrets: [googleAIapiKey]
    }, generatePoemFlow);
    

Artık bu işlevi dağıttığınızda API anahtarınız Cloud Secret Manager'da depolanır ve Cloud Functions ortamından kullanılabilir.

Gemini (Vertex AI)

  1. Cloud Console'da, Firebase projeniz için Vertex AI API'yi etkinleştirin.

  2. IAM sayfasında, Varsayılan Compute hizmet hesabına Vertex AI Kullanıcısı rolünün atandığından emin olun.

Bu eğitim için ayarlamanız gereken tek gizlilik, model sağlayıcı içindir ancak genel olarak akışınızın kullandığı her hizmet için benzer bir işlem yapmanız gerekir.

Uygulama Kontrolü yaptırımı ekleme

Firebase Uygulama Kontrolü, API'nizin yalnızca uygulamanız tarafından çağrıldığını doğrulamak için yerleşik bir doğrulama mekanizması kullanır. onCallGenkit, Uygulama Kontrolü yaptırımını açık bir şekilde destekler.

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 politikası belirleme

Çağırılabilir işlevler varsayılan olarak herhangi bir alanın işlevinizi çağırmasına izin verir. Bunu yapabilen alanları özelleştirmek istiyorsanız cors seçeneğini kullanın. Doğru kimlik doğrulamasıyla (özellikle Uygulama Kontrolü) CORS genellikle gereksizdir.

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

Tam örnek

Daha önce açıklanan tüm değişiklikleri yaptıktan sonra dağıtılabilir akışınız aşağıdaki örneğe benzer şekilde görünür:

import { genkit } from 'genkit';
import { onCallGenkit, hasClaim } from 'firebase-functions/https';
import { defineSecret } from 'firebase-functions/params';

const apiKey = defineSecret("GOOGLE_GENAI_API_KEY");

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;
});

export const generateFlow = onCallGenkit({
  secrets: [apiKey],
  authPolicy: hasClaim("email_verified"),
  enforceAppCheck: true,
}, generatePoemFlow);

3. Akışları Firebase'e dağıtma

onCallGenkit kullanarak akışları tanımladıktan sonra bunları diğer Cloud Functions'ları dağıttığınız şekilde dağıtabilirsiniz:

cd $PROJECT_ROOT
firebase deploy --only functions

Artık akışı bir Cloud Functions işlevi olarak dağıttınız. Ancak akışın yetkilendirme politikası nedeniyle, dağıtılan uç noktanıza curl veya benzer bir yöntemle erişemezsiniz. Akışa nasıl güvenli bir şekilde erişeceğiniz sonraki bölümde açıklanmıştır.

İsteğe bağlı: Dağıtılan akışı deneyin

Akış uç noktanızı denemek için aşağıdaki minimum örnek web uygulamasını dağıtabilirsiniz:

  1. Firebase konsolunun Proje ayarları bölümünde, Hosting'i de ayarlama seçeneğini belirleyerek yeni bir web uygulaması ekleyin.

  2. Firebase Konsolu'nun Kimlik doğrulama bölümünde, bu örnekte kullanılan Google sağlayıcısını etkinleştirin.

  3. Proje dizininizde, örnek uygulamayı dağıtacağınız Firebase Hosting'i ayarlayın:

    cd $PROJECT_ROOT
    firebase init hosting

    Tüm istemler için varsayılan değerleri kabul edin.

  4. public/index.html yerine aşağıdakileri kullanın:

    <!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. Web uygulamasını ve Cloud Functions işlevini dağıtın:

    cd $PROJECT_ROOT
    firebase deploy

deploy komutu tarafından yazdırılan URL'yi ziyaret ederek web uygulamasını açın. Uygulama, bir Google Hesabı ile oturum açmanızı gerektirir. Ardından uç nokta isteklerini başlatabilirsiniz.

İsteğe bağlı: Geliştirici kullanıcı arayüzünde akışları çalıştırma

Geliştirici kullanıcı arayüzünde onCallGenkit kullanılarak tanımlanan akışları, defineFlow kullanılarak tanımlanan akışları çalıştırdığınız şekilde çalıştırabilirsiniz. Bu nedenle, dağıtım ve geliştirme arasında iki akış arasında geçiş yapmanız gerekmez.

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

veya

cd $PROJECT_ROOT/functions
npm run genkit:start

Artık genkit start komutu tarafından yazdırılan URL'ye giderek erişebilirsiniz.

İsteğe bağlı: Firebase Local Emulator Suite'i kullanarak geliştirme

Firebase, Genkit ile kullanabileceğiniz yerel geliştirme için bir emülatör paketi sunar.

Genkit geliştirici kullanıcı arayüzünü Firebase Emulator Suite ile kullanmak için Firebase emülatörlerini aşağıdaki gibi başlatın:

npx genkit start -- firebase emulators:start --inspect-functions

Bu komut, kodunuzu emülatörde ve Genkit çerçevesini geliştirme modunda çalıştırır. Bu işlem, Genkit reflection API'yi (geliştirici kullanıcı arayüzünü değil) başlatır ve gösterir.

Geliştirici kullanıcı arayüzünde Firestore'daki izlemeleri görmek için İncele sekmesine gidebilir ve Geliştirici/Üretim anahtarını açabilirsiniz. prod olarak ayarlandığında Firestore'dan iz yükler.