Von 0.9 auf 1.0 migrieren

Genkit 1.0 enthält viele Funktionsverbesserungen, die die Gesamtfunktionalität verbessern. Es gibt auch einige Änderungen, die die Kompatibilität beeinträchtigen. Wenn Sie Anwendungen mit Genkit 0.9 entwickelt haben, müssen Sie Ihren App-Code aktualisieren, wenn Sie auf die neueste Version von Genkit umstellen. In diesem Leitfaden werden die wichtigsten Änderungen beschrieben und erläutert, wie Sie Ihre vorhandenen Anwendungen reibungslos migrieren.

Beta-APIs

Wir führen einen instabilen Beta-API-Kanal ein und lassen die Session-, Chat- und Genkit-Client-APIs in der Betaphase, da wir sie weiter optimieren. Konkret sind derzeit die folgenden Funktionen im Namespace beta verfügbar:

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

Alt:

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

Neu:

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

Alt:

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

Neu:

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

Neues @genkit-ai/express-Paket

Dieses neue Paket enthält Dienstprogramme, die das Erstellen eines Express.js-Servers mit Genkit erleichtern. Weitere Informationen dazu finden Sie auf dieser Seite.

startFlowServer wurde aus dem Genkit-Objekt in dieses neue @genkit-ai/express-Paket verschoben. Wenn Sie startFlowServer verwenden möchten, müssen Sie Ihre Importe aktualisieren.

Alt:

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

Neu:

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

Änderungen an Aufrufabfolgen

Bei Version 1.0 gibt es mehrere Änderungen an Abläufen:

  • ai.defineStreamingFlow wurde in ai.defineFlow konsolidiert.
  • onFlow wurde durch onCallGenkit ersetzt.
  • run wurde zu ai.run verschoben.
  • Es gibt Änderungen bei der Authentifizierung.

Die Funktion run für benutzerdefinierte Trace-Blöcke wurde in das genkit-Objekt verschoben. Verwenden Sie stattdessen ai.run, um sie aufzurufen.

Alt:

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

Neu:

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

ai.defineStreamingFlow wurde entfernt. Verwenden Sie stattdessen ai.defineFlow. Außerdem wurde streamingCallback in ein Feld im zweiten Argument der Ablauffunktion verschoben und heißt jetzt sendChunk.

Alt:

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

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

Neu:

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 auth“ heißt jetzt „context“. Du kannst auf „auth“ als Feld im Kontext zugreifen:

Alt:

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

Neu:

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

onFlow wurde in das firebase-functions/https-Paket verschoben und in onCallGenkit umbenannt. Das folgende Snippet zeigt ein Beispiel für die Verwendung.

Alt

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

Neu:

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

Authentifizierungsrichtlinien wurden aus defineFlow entfernt. Die Verarbeitung von Authentifizierungsrichtlinien ist jetzt serverabhängig.

Alt:

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

Das folgende Snippet zeigt ein Beispiel für die Authentifizierung in Express.

Neu:

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

Weitere Informationen finden Sie in der Authentifizierungsdokumentation.

Das folgende Snippet zeigt ein Beispiel für die Authentifizierung in 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);

Prompts

Wir haben einige Änderungen und Verbesserungen an den Prompts vorgenommen.

Sie können separate Vorlagen für Prompts und Systemnachrichten definieren:

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

Alternativ können Sie im Feld „Nachrichten“ Prompts für mehrere Nachrichten definieren:

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

Anstelle von Promptvorlagen können Sie auch eine Funktion verwenden:

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

Sie können über den Prompt auf den Kontext (einschließlich Authentifizierungsinformationen) zugreifen:

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

Für Streamingfunktionen ist kein await erforderlich.

Alt:

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

Neu:

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

„Embed“ hat einen neuen Rückgabetyp

Wir haben die Unterstützung für multimodale Einbettungen hinzugefügt. Anstatt nur einen einzelnen Einbettungsvektor zurückzugeben, gibt „Embed“ ein Array von Einbettungsobjekten zurück, die jeweils einen Einbettungsvektor und Metadaten enthalten.

Alt:

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

Neu:

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