Bermigrasi dari 0.9 ke 1.0

Genkit 1.0 memperkenalkan banyak peningkatan fitur yang meningkatkan fungsi keseluruhan; versi ini juga memiliki beberapa perubahan yang dapat menyebabkan gangguan. Jika telah mengembangkan aplikasi dengan Genkit 0.9, Anda perlu mengupdate kode aplikasi saat mengupgrade ke Genkit versi terbaru. Panduan ini menguraikan perubahan yang paling signifikan, dan menjelaskan cara memigrasikan aplikasi yang ada dengan lancar.

API Beta

Kami memperkenalkan saluran API Beta yang tidak stabil, dan membiarkan API klien sesi, chat, dan Genkit dalam versi beta saat kami terus meningkatkan kualitasnya. Lebih khusus lagi, fungsi berikut saat ini berada dalam namespace beta:

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

Lama:

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

Baru:

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

Lama:

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

Baru:

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

Memperkenalkan paket @genkit-ai/express baru

Paket baru ini berisi utilitas untuk mempermudah pembuatan server Express.js dengan Genkit. Anda dapat menemukan detail selengkapnya tentang hal ini di halaman ini.

startFlowServer telah dipindahkan dari bagian objek genkit ke paket @genkit-ai/express baru ini; untuk menggunakan startFlowServer, Anda harus memperbarui impor.

Lama:

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

Baru:

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

Perubahan pada Alur

Ada beberapa perubahan pada alur di versi 1.0:

  • ai.defineStreamingFlow telah digabungkan menjadi ai.defineFlow,
  • onFlow telah diganti dengan onCallGenkit,
  • run telah dipindahkan ke ai.run,
  • Ada perubahan pada cara kerja autentikasi.

Fungsi run untuk blok rekaman aktivitas kustom telah dipindahkan ke bagian objek genkit; gunakan ai.run untuk memanggilnya.

Lama:

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

Baru:

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

ai.defineStreamingFlow telah dihapus; sebagai gantinya, gunakan ai.defineFlow. Selain itu, streamingCallback telah dipindahkan ke kolom di dalam argumen kedua fungsi alur dan kini disebut sendChunk.

Lama:

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

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

Baru:

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) {
  // ...
}

Autentikasi FlowAuth kini disebut konteks. Anda dapat mengakses autentikasi sebagai kolom di dalam konteks:

Lama:

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

Baru:

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

onFlow dipindahkan ke paket firebase-functions/https dan telah diganti namanya menjadi onCallGenkit. Cuplikan berikut menunjukkan contoh cara menggunakannya.

Lama

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

Baru:

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

Kebijakan autentikasi telah dihapus dari defineFlow. Penanganan kebijakan autentikasi sekarang bergantung pada server.

Lama:

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

Cuplikan berikut menunjukkan contoh penanganan autentikasi di Express.

Baru:

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

Untuk mengetahui detail selengkapnya, lihat dokumentasi autentikasi.

Cuplikan berikut menunjukkan contoh penanganan autentikasi di Cloud Functions untuk 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);

Perintah

Kami telah melakukan beberapa perubahan dan peningkatan pada perintah.

Anda dapat menentukan template terpisah untuk pesan perintah dan sistem:

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

Atau, Anda dapat menentukan perintah multi-pesan di kolom pesan:

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

Anda dapat menggunakan fungsi, bukan template perintah:

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

Anda dapat mengakses konteks (termasuk informasi autentikasi) dari dalam perintah:

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

Fungsi streaming tidak memerlukan await

Lama:

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

Baru:

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

Sematan memiliki jenis nilai yang ditampilkan baru

Kami telah menambahkan dukungan untuk penyematan multimodal. Daripada hanya menampilkan satu vektor penyematan, Embed menampilkan array objek penyematan, yang masing-masing berisi vektor dan metadata penyematan.

Lama:

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

Baru:

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