ทำให้โฟลว์ใช้งานได้โดยใช้ Cloud Functions for Firebase

Genkit มีปลั๊กอินที่ช่วยคุณในการติดตั้งใช้งานโฟลว์ไปยัง Cloud Functions สําหรับ Firebase เมื่อติดตั้งใช้งานแล้ว ขั้นตอนจะพร้อมใช้งานเป็นปลายทาง HTTPS และเข้าถึงได้ในรูปแบบฟังก์ชันที่เรียกใช้ได้โดยใช้ไลบรารีไคลเอ็นต์ Cloud Functions

ก่อนเริ่มต้น

  • ติดตั้ง Firebase CLI
  • คุณควรคุ้นเคยกับแนวคิดโฟลว์ของ Genkit และวิธีเขียนโฟลว์ วิธีการในหน้านี้ถือว่าคุณกําหนดขั้นตอนการทํางานบางอย่างไว้แล้วซึ่งต้องการทําให้ใช้งานได้
  • ประสบการณ์การใช้งาน Cloud Functions สําหรับ Firebase มาก่อนจะเป็นประโยชน์ แต่ก็ไม่จําเป็น

1. ตั้งค่าโปรเจ็กต์ Firebase

หากยังไม่มีโปรเจ็กต์ Firebase ที่มีการตั้งค่า TypeScript Cloud Functions ให้ทำตามขั้นตอนต่อไปนี้

  1. สร้างโปรเจ็กต์ Firebase ใหม่โดยใช้คอนโซล Firebase หรือเลือกโปรเจ็กต์ที่มีอยู่

  2. อัปเกรดโปรเจ็กต์เป็นแพ็กเกจ Blaze ซึ่งจําเป็นต่อการติดตั้งใช้งาน Cloud Function

  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

ใช้ฟังก์ชัน onFlow() ของปลั๊กอิน Firebase แทนการกําหนดเวิร์กโฟลว์ด้วย Genkit.defineFlow() การใช้ฟังก์ชันนี้จะรวมตรรกะเวิร์กโฟลว์ไว้ในตัวแฮนเดิลคำขอของ Cloud Functions ซึ่งคล้ายกับ onCall

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

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

โปรดทราบว่า onFlow ไม่ใช่เมธอดของ Genkit แต่เป็นฟังก์ชันที่ใช้อินสแตนซ์ Genkit เป็นพารามิเตอร์แรก มิเช่นนั้น ไวยากรณ์จะคล้ายกับ defineFlow

กําหนดนโยบายการให้สิทธิ์

ขั้นตอนการทํางานที่ติดตั้งใช้งานทั้งหมดไม่ว่าจะติดตั้งใช้งานใน Firebase หรือไม่ก็ตามควรมีนโยบายการให้สิทธิ์ หากไม่มี ทุกคนจะเรียกใช้ขั้นตอนการทํางาน Generative AI ที่มีราคาสูงได้ หากต้องการกำหนดนโยบายการให้สิทธิ์ ให้ใช้พารามิเตอร์ 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 ที่เป็นไปตามนโยบายของคุณ SDK ของไคลเอ็นต์ Cloud Functions มีเมธอดฟังก์ชันที่เรียกใช้ได้ซึ่งทํางานนี้ให้อัตโนมัติ โปรดดูตัวอย่างในส่วนลองใช้ขั้นตอนที่ติดตั้งใช้งานแล้ว

ทำให้ข้อมูลเข้าสู่ระบบ API พร้อมใช้งานสำหรับเวิร์กโฟลว์ที่ติดตั้งใช้งาน

เมื่อติดตั้งใช้งานแล้ว ขั้นตอนจะต้องมีวิธีตรวจสอบสิทธิ์กับบริการระยะไกลที่ใช้ เวิร์กโฟลว์ส่วนใหญ่จะต้องมีข้อมูลเข้าสู่ระบบเป็นอย่างน้อยสำหรับการเข้าถึงบริการ API ของโมเดลที่ใช้

ในตัวอย่างนี้ ให้ทําอย่างใดอย่างหนึ่งต่อไปนี้ ทั้งนี้ขึ้นอยู่กับผู้ให้บริการโมเดลที่คุณเลือก

Gemini (AI ของ Google)

  1. ตรวจสอบว่า AI ของ Google พร้อมให้บริการในภูมิภาคของคุณ

  2. สร้างคีย์ API สำหรับ Gemini API โดยใช้ Google AI Studio

  3. จัดเก็บคีย์ API ใน Secret Manager ของ Cloud โดยทำดังนี้

    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 จะจัดเก็บไว้ใน Secret Manager ของ Cloud และพร้อมใช้งานจากสภาพแวดล้อม Cloud Functions

Gemini (Vertex AI)

  1. ในคอนโซลระบบคลาวด์ ให้เปิดใช้ Vertex AI API สําหรับโปรเจ็กต์ Firebase

  2. ในหน้า IAM ให้ตรวจสอบว่าบัญชีบริการ Compute เริ่มต้นได้รับบทบาทผู้ใช้ Vertex AI

ข้อมูลลับเพียงอย่างเดียวที่คุณต้องตั้งค่าสำหรับบทแนะนํานี้คือข้อมูลลับของผู้ให้บริการโมเดล แต่โดยทั่วไปแล้ว คุณต้องทําสิ่งคล้ายกันสําหรับบริการแต่ละรายการที่โฟลว์ใช้

กำหนดนโยบาย CORS

หากจะเข้าถึงโฟลว์จากเว็บแอป (ซึ่งคุณจะทําได้ในส่วนลองใช้โฟลว์ที่ติดตั้งใช้งาน) ให้ตั้งค่านโยบาย CORS ในพารามิเตอร์ httpsOptions ดังนี้

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 แล้ว คุณจะทําให้โฟลว์ใช้งานได้เช่นเดียวกับการทําให้ฟังก์ชันอื่นๆ ของ Cloud ใช้งานได้ ดังนี้

cd $PROJECT_ROOT
firebase deploy --only functions

ตอนนี้คุณทำให้โฟลว์ทํางานเป็น Cloud Function แล้ว แต่คุณจะเข้าถึงปลายทางที่ติดตั้งใช้งานด้วย curl หรือโปรแกรมที่คล้ายกันไม่ได้เนื่องจากนโยบายการให้สิทธิ์ของขั้นตอน ไปที่ส่วนถัดไปเพื่อดูวิธีเข้าถึงขั้นตอนดังกล่าวอย่างปลอดภัย

ไม่บังคับ: ลองใช้ขั้นตอนที่ติดตั้งใช้งาน

หากต้องการลองใช้ปลายทางของโฟลว์ ให้ติดตั้งใช้งานเว็บแอปตัวอย่างขั้นต่ำต่อไปนี้

  1. ในส่วนการตั้งค่าโปรเจ็กต์ของคอนโซล Firebase ให้เพิ่มเว็บแอปใหม่โดยเลือกตัวเลือกเพื่อตั้งค่าโฮสติ้งด้วย

  2. ในส่วนการตรวจสอบสิทธิ์ของคอนโซล Firebase ให้เปิดใช้ผู้ให้บริการ Google ซึ่งจะใช้ในตัวอย่างนี้

  3. ในไดเรกทอรีโปรเจ็กต์ ให้ตั้งค่า Firebase Hosting ซึ่งคุณจะใช้เพื่อทำให้แอปตัวอย่างใช้งานได้ โดยทำดังนี้

    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. ติดตั้งใช้งานเว็บแอปและ Cloud Function โดยทำดังนี้

    cd $PROJECT_ROOT
    firebase deploy

เปิดเว็บแอปโดยไปที่ URL ที่พิมพ์โดยคำสั่ง deploy แอปจะกำหนดให้คุณลงชื่อเข้าใช้ด้วยบัญชี Google จากนั้นคุณจะเริ่มคําขออุปกรณ์ปลายทางได้

ไม่บังคับ: เรียกใช้ขั้นตอนใน UI ของนักพัฒนาแอป

คุณสามารถเรียกใช้โฟลว์ที่กําหนดโดยใช้ onFlow ใน UI สําหรับนักพัฒนาแอปได้เช่นเดียวกับการเรียกใช้โฟลว์ที่กําหนดโดยใช้ defineFlow จึงไม่ต้องสลับไปมาระหว่าง 2 รูปแบบระหว่างการติดตั้งใช้งานกับการพัฒนา

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

หรือ

cd $PROJECT_ROOT/functions
npm run genkit:start

ตอนนี้คุณไปยัง URL ที่พิมพ์โดยคำสั่ง genkit start เพื่อเข้าถึงได้แล้ว

ไม่บังคับ: การพัฒนาโดยใช้ Firebase Local Emulator Suite

Firebase มีชุดโปรแกรมจำลองสําหรับการพัฒนาซอฟต์แวร์ในเครื่อง ซึ่งคุณใช้กับ Genkit ได้

หากต้องการใช้ Genkit Dev UI กับชุดโปรแกรมจำลอง Firebase ให้เริ่มโปรแกรมจำลอง Firebase ดังนี้

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

ซึ่งจะเรียกใช้โค้ดในโปรแกรมจำลองและเรียกใช้เฟรมเวิร์ก Genkit ในโหมดการพัฒนา ซึ่งจะเปิดและแสดง Genkit reflection API (แต่ไม่ใช่ UI สําหรับนักพัฒนาซอฟต์แวร์)

หากต้องการดูร่องรอยจาก Firestore ใน UI ของนักพัฒนาซอฟต์แวร์ ให้ไปที่แท็บ "ตรวจสอบ" แล้วสลับสวิตช์ "Dev/Prod" เมื่อสลับเป็น "prod" ระบบจะโหลดร่องรอยจาก Firestore