מעבר מגרסה 0.9 לגרסה 1.0

בגרסה 1.0 של Genkit יש שיפורים רבים בתכונות שמשפרים את הפונקציונליות הכוללת, וגם כמה שינויים שעלולים לגרום לכשל. אם פיתחתם אפליקציות באמצעות Genkit 0.9, תצטרכו לעדכן את קוד האפליקציה כשתשדרגו לגרסה האחרונה של Genkit. במדריך הזה מפורטים השינויים המשמעותיים ביותר, ומוסבר איך להעביר את האפליקציות הקיימות בצורה חלקה.

ממשקי API בגרסת בטא

אנחנו משיקים ערוץ API לא יציב בגרסת בטא, ומשאירים את ממשקי ה-API של סשנים, צ'אטים ו-Genkit בגרסת בטא בזמן שאנחנו ממשיכים לשפר אותם. באופן ספציפי, הפונקציות הבאות נמצאות כרגע במרחב השמות beta:

  • ai.chat
  • ai.createSession
  • ai.loadSession
  • ai.currentSession
  • ai.defineFormat
  • ai.defineInterrupt

הקודם:

import { genkit } from 'genkit';
const ai = genkit({...})
const session = ai.createSession({ ... })

חדש:

import { genkit } from 'genkit/beta';
const ai = genkit({...})
const session = ai.createSession({ ... })

הקודם:

import { runFlow, streamFlow } from 'genkit/client';

חדש:

import { runFlow, streamFlow } from 'genkit/beta/client';

חדש: חבילת @genkit-ai/express

החבילה החדשה הזו מכילה כלי עזר שיעזרו לכם ליצור בקלות שרת Express.js באמצעות Genkit. פרטים נוספים זמינים בדף הזה.

startFlowServer הועבר מחלק מהאובייקט genkit לחבילה החדשה @genkit-ai/express. כדי להשתמש ב-startFlowServer, צריך לעדכן את הייבוא.

הקודם:

const ai = genkit({ ... });
ai.startFlowServer({
  flows: [myFlow1, myFlow2],
});

חדש:

import { startFlowServer } from '@genkit-ai/express';
startFlowServer({
  flows: [myFlow1, myFlow2],
});

שינויים בתהליכים

יש כמה שינויים בתהליכים בגרסה 1.0:

  • ai.defineStreamingFlow אוחד עם ai.defineFlow,
  • השדה onFlow הוחלף על ידי onCallGenkit,
  • run הועבר ל-ai.run,
  • יש שינויים בעבודה עם אימות.

הפונקציה run של בלוקים מותאמים אישית של מעקב הועברה לחלק מהאובייקט genkit. במקום זאת, צריך להשתמש ב-ai.run כדי להפעיל אותה.

הקודם:

ai.defineFlow({name: 'banana'}, async (input) => {
  const step = await run('myCode', async () => {
    return 'something'
  });
})

חדש:

ai.defineFlow({name: 'banana'}, async (input) => {
  const step = await ai.run('myCode', async () => {
    return 'something'
  });
})

ai.defineStreamingFlow הוסרה. במקום זאת, יש להשתמש ב-ai.defineFlow. בנוסף, הערך streamingCallback הועבר לשדה בתוך הארגומנט השני של פונקציית הזרימה, והוא נקרא עכשיו sendChunk.

הקודם:

const flow = ai.defineStreamingFlow({name: 'banana'}, async (input, streamingCallback) => {
  streamingCallback({chunk: 1});
})

const {stream} = await flow()
for await (const chunk of stream) {
  // ...
}

חדש:

const flow = ai.defineFlow({name: 'banana'}, async (input, {context, sendChunk}) => {
  sendChunk({chunk: 1});
})

const {stream, output} = flow.stream(input);
for await (const chunk of stream) {
  // ...
}

האימות של FlowAuth נקרא עכשיו context. אפשר לגשת לאימות כשדה בתוך ההקשר:

הקודם:

ai.defineFlow({name: 'banana'}, async (input) => {
  const auth = getFlowAuth();
  // ...
})

חדש:

ai.defineFlow({name: 'banana'}, async (input, { context }) => {
  const auth = context.auth;
})

onFlow הועבר לחבילה firebase-functions/https והשם שלו שונה ל-onCallGenkit. קטע הקוד הבא מציג דוגמה לשימוש בו.

ישן

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

export const generatePoem = onFlow(
  ai,
  {
    name: "jokeTeller",
    inputSchema: z.string().nullable(),
    outputSchema: z.string(),
    streamSchema: z.string(),
  },
  async (type, streamingCallback) => {
    const { stream, response } = await ai.generateStream(
      `Tell me a longish ${type ?? "dad"} joke.`
    );
    for await (const chunk of stream) {
      streamingCallback(chunk.text);
    }
    return (await response).text;
  }
);

חדש:

import { onCallGenkit } from "firebase-functions/https";
import { defineSecret } from "firebase-functions/params";
import { genkit, z } from "genkit";

const apiKey = defineSecret("GOOGLE_GENAI_API_KEY");

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

export const jokeTeller = ai.defineFlow(
  {
    name: "jokeTeller",
    inputSchema: z.string().nullable(),
    outputSchema: z.string(),
    streamSchema: z.string(),
  },
  async (type, { sendChunk }) => {
    const { stream, response } = ai.generateStream(
      `Tell me a longish ${type ?? "dad"} joke.`
    );
    for await (const chunk of stream) {
      sendChunk(chunk.text);
    }
    return (await response).text;
  }
);

export const tellJoke = onCallGenkit({ secrets: [apiKey] }, jokeTeller);

כללי מדיניות האימות הוסרו מ-defineFlow. הטיפול בכללי מדיניות האימות תלוי עכשיו בשרת.

הקודם:

export const simpleFlow = ai.defineFlow(
  {
    name: 'simpleFlow',
    authPolicy: (auth, input) => {
      // auth policy
    },
  },
  async (input) => {
    // Flow logic here...
  }
);

קטע הקוד הבא מציג דוגמה לטיפול באימות ב-Express.

חדש:

import { UserFacingError } from 'genkit';
import { ContextProvider, RequestData } from 'genkit/context';
import { expressHandler, startFlowServer } from '@genkit-ai/express';

const context: ContextProvider<Context> = (req: RequestData) => {
  return {
    auth: parseAuthToken(req.headers['authorization']),
  };
};

export const simpleFlow = ai.defineFlow(
  {
    name: 'simpleFlow',
  },
  async (input, { context }) => {
    if (!context.auth) {
      throw new UserFacingError("UNAUTHORIZED", "Authorization required.");
    }
    if (input.uid !== context.auth.uid) {
      throw new UserFacingError("UNAUTHORIZED", "You may only summarize your own profile data.");
    }
    // Flow logic here...
  }
);

const app = express();
app.use(express.json());
app.post(
  '/simpleFlow',
  expressHandler(simpleFlow, { context })
);
app.listen(8080);

// or

startFlowServer(
  flows: [withContextProvider(simpleFlow, context)],
  port: 8080
);

פרטים נוספים זמינים במסמכי התיעוד בנושא אימות.

קטע הקוד הבא מציג דוגמה לטיפול באימות ב-Cloud Functions for Firebase:

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

const ai = genkit({ ... });;

const simpleFlow = ai.defineFlow({
  name: 'simpleFlow',
}, async (input) => {
  // Flow logic here...
});

export const selfSummary = onCallGenkit({
  authPolicy: (auth, data) => auth?.token?.['email_verified'] && auth?.token?.['admin'],
}, simpleFlow);

הנחיות

ביצענו כמה שינויים ושיפורים בהנחיות.

אפשר להגדיר תבניות נפרדות להנחיות ולהודעות מערכת:

const hello = ai.definePrompt({
  name: 'hello',
  system: 'talk like a pirate.',
  prompt: 'hello {{ name }}',
  input: {
    schema: z.object({
      name: z.string()
    })
  }
});
const { text } = await hello({name: 'Genkit'});

לחלופין, אפשר להגדיר הנחיות עם כמה הודעות בשדה messages:

const hello = ai.definePrompt({
  name: 'hello',
  messages: '{{ role "system" }} talk like a pirate. {{ role "user" }} hello {{ name }}',
  input: {
    schema: z.object({
      name: z.string()
    })
  }
});

במקום תבניות של הנחיות, אפשר להשתמש בפונקציה:

ai.definePrompt({
  name: 'hello',
  prompt: async (input, { context }) => {
    return `hello ${input.name}`
  },
  input: {
    schema: z.object({
      name: z.string()
    })
  }
});

אפשר לגשת להקשר (כולל פרטי האימות) מתוך ההנחיה:

const hello = ai.definePrompt({
  name: 'hello',
  messages: 'hello {{ @auth.email }}',
});

פונקציות סטרימינג לא דורשות await

הקודם:

const { stream, response } = await ai.generateStream(`hi`);
const { stream, output } = await myflow.stream(`hi`);

חדש:

const { stream, response } = ai.generateStream(`hi`);
const { stream, output } = myflow.stream(`hi`);

ל-Embed יש סוג החזרה חדש

הוספנו תמיכה בהטמעות (embeddings) של מודלים מרובת-מודולים. במקום להחזיר רק וקטור הטמעה אחד, הפונקציה Embed מחזירה מערך של אובייקטים להטמעה, שכל אחד מהם מכיל וקטור הטמעה ומטא-נתונים.

הקודם:

const response = await ai.embed({embedder, content, options});  // returns number[]

חדש:

const response = await ai.embed({embedder, content, options}); // returns Embedding[]
const firstEmbeddingVector = response[0].embedding;  // is number[]