Migracja z wersji 0.9 do 1.0

Genkit 1.0 wprowadza wiele ulepszeń funkcji, które poprawiają ogólną funkcjonalność. Zawiera też zmiany powodujące niezgodności. Jeśli aplikacje były tworzone za pomocą Genkit 0.9, po przejściu na najnowszą wersję Genkit należy zaktualizować kod aplikacji. Z tego przewodnika dowiesz się, jakie są najważniejsze zmiany, i jak sprawnie przenieść istniejące aplikacje.

Interfejsy API w wersji beta

Wprowadzamy niestabilny kanał interfejsu API w wersji beta. Interfejsy API klienta dotyczące sesji, czatu i Genkit pozostają w wersji beta, ponieważ nadal je ulepszamy. W obecności w przestrzeni nazw beta znajdują się obecnie te funkcje:

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

Stara nazwa:

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

Nowość:

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

Stara nazwa:

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

Nowość:

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

Przedstawiamy nowy pakiet @genkit-ai/express

Ten nowy pakiet zawiera narzędzia ułatwiające tworzenie serwera Express.js za pomocą Genkit. Więcej informacji znajdziesz na tej stronie.

startFlowServer zostało przeniesione z części obiektu genkit do nowego pakietu @genkit-ai/express. Aby używać funkcji startFlowServer, musisz zaktualizować importy.

Stara nazwa:

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

Nowość:

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

Zmiany w procesach

Wprowadziliśmy kilka zmian w wersji 1.0:

  • Grupa ai.defineStreamingFlow została scalona z grupą ai.defineFlow,
  • Wartość onFlow została zastąpiona wartością onCallGenkit,
  • run zostało przeniesione do ai.run,
  • Wprowadziliśmy zmiany w zakresie działania funkcji uwierzytelniania.

Funkcja run do niestandardowych bloków śledzenia została przeniesiona do obiektu genkit. Aby ją wywołać, użyj funkcji ai.run.

Stara nazwa:

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

Nowość:

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

Funkcja ai.defineStreamingFlow została usunięta. Użyj zamiast niej funkcji ai.defineFlow. Ponadto zmienna streamingCallback została przeniesiona do pola w 2 argumentach funkcji przepływu i ma teraz nazwę sendChunk.

Stara nazwa:

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

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

Nowość:

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

Autoryzacja FlowAuth nazywa się teraz kontekst. Do uwierzytelniania możesz uzyskać dostęp jako pola w kontekście:

Stara nazwa:

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

Nowość:

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

Obiekt onFlow został przeniesiony do pakietu firebase-functions/https i przemianowany na onCallGenkit. Poniżej znajdziesz przykład użycia tej funkcji.

Stary

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

Nowość:

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

Zasady uwierzytelniania zostały usunięte z defineFlow. Obsługa zasad autoryzacji zależy teraz od serwera.

Stara nazwa:

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

Poniższy fragment kodu pokazuje przykład obsługi uwierzytelniania w Express.

Nowość:

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

Więcej informacji znajdziesz w dokumentacji autoryzacji.

Ten fragment kodu pokazuje przykład obsługi uwierzytelniania w 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);

Prompty

Wprowadziliśmy kilka zmian i ulepszeń dotyczących promptów.

Możesz zdefiniować oddzielne szablony dla promptów i komunikatów systemowych:

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

Możesz też zdefiniować prompty z wieloma wiadomościami w polu wiadomości:

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

Zamiast szablonów promptów możesz użyć funkcji:

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

Możesz uzyskać dostęp do kontekstu (w tym informacji uwierzytelniających) z poziomu prompta:

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

Funkcje przesyłania strumieniowego nie wymagają await

Stara nazwa:

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

Nowość:

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

Nowy typ zwracanych danych w funkcji osadzania

Dodaliśmy obsługę zagęszczeń multimodalnych. Zamiast zwracać tylko jeden wektor dystrybucyjny, funkcja Embed zwraca tablicę obiektów dystrybucyjnych, z których każdy zawiera wektor dystrybucyjny i metadane.

Stara nazwa:

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

Nowość:

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