Migracja z wersji 0.5

Wersja Genkit 0.9 wprowadza kilka zmian powodujących niezgodność oraz ulepszenia funkcji, które poprawiają ogólną funkcjonalność. Jeśli aplikacje były do tej pory tworzone za pomocą Genkit 0.5, po przejściu na najnowszą wersję trzeba będzie zaktualizować kod aplikacji. Z tego przewodnika dowiesz się, jakie są najważniejsze zmiany i jak sprawnie przenieść dotychczasowe aplikacje.

Krótki przewodnik

Te kroki pomogą Ci szybko przejść z Genkit 0.5 na Genkit 0.9. Więcej informacji o tych zmianach znajdziesz w szczegółowym zgłoszeniu poniżej.

1. Instalowanie nowego interfejsu wiersza poleceń

  • Odinstaluj stary interfejs wiersza poleceń

    npm uninstall -g genkit && npm uninstall genkit
    
  • Instalowanie nowego interfejsu wiersza poleceń

    npm i -D genkit-cli
    

2. Aktualizowanie zależności

  • Usuwanie poszczególnych pakietów Genkit core

    npm uninstall @genkit-ai/ai @genkit-ai/core @genkit-ai/dotprompt @genkit-ai/flow
    
  • Zainstaluj nowy skonsolidowany pakiet genkit

    npm i --save genkit
    
  • Zaktualizuj wszystkie wersje wtyczek (przykład poniżej)

    npm upgrade @genkit-ai/firebase
    

3. Zmienianie importowanych danych

  • Usuwanie importów poszczególnych pakietów Genkit Core

    import { … } from '@genkit-ai/ai';
    import { … } from '@genkit-ai/core';
    import { … } from '@genkit-ai/flow';
    
  • Usuwanie importów zod

    import * as z from 'zod';
    
  • Importowanie plików genkitzod z poziomu genkit

    import { z, genkit } from 'genkit';
    

4. Zaktualizuj kod

Usuń bloki configureGenkit

Konfiguracja Genkit jest teraz wykonywana na poziomie instancji. Telemetria i rejestrowanie są konfigurowane globalnie i oddzielnie od instancji Genkit.

  • Zastąp bloki configureGenkit blokami ai = genkit({...}). Zachowaj tylko konfigurację wtyczki.

    import { genkit } from 'genkit';
    
    const ai = genkit({ plugins: [...]});
    
  • Konfigurowanie telemetrii za pomocą enableFirebaseTelemetry lub enableGoogleCloudTelemetry

    W przypadku Firebase:

    import { enableFirebaseTelemetry } from '@genkit-ai/firebase';
    
    enableFirebaseTelemetry({...});
    

    W przypadku Google Cloud:

    import { enableGoogleCloudTelemetry } from '@genkit-ai/google-cloud';
    
    enableGoogleCloudTelemetry({...});
    
  • Ustaw poziom rejestrowania niezależnie ```js import { logger } from 'genkit/logging';

    logger.setLogLevel('debug'); ```

Więcej informacji o konfigurowaniu telemetrii i rejestrowania znajdziesz w dokumentacji Monitorowanie i rejestrowanie.

Więcej informacji o konfigurowaniu instancji Genkit znajdziesz w dokumentacji Pierwsze kroki.

Przeniesienie działań Genkit do wywołania z poziomu instancji genkit

Działania (przepływy, narzędzia, programy pobierające, indeksatory itp.) są definiowane w poszczególnych instancjach. W Changelog znajdziesz wszystkie funkcje, które musisz zmienić, ale poniżej podajemy przykłady kilku najpopularniejszych.

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

const ai = genkit({ plugins: [...]});

// Flows and tools are defined on the specific genkit instance
// and are directly callable.
const sampleFlow = ai.defineFlow(...);
const sampleTool = ai.defineTool(...);

async function callMyFlow() {
  // Previously, text output could accessed via .text()
  // Now it is either .output() or .text
  return await sampleFlow().output();
}

// onFlow now takes the Genkit instance as first argument
// This registers the flow as a callable firebase function
onFlow(ai, ...);
const flows = [ sampleFlow, ... ];
// Start the flow server to make the registered flows callable over HTTP
ai.startFlowServer({flows});

5. Uruchom

# run the DevUI and your js code
genkit start -- <command to run node>
# run a defined flow
genkit flow:run <flowName>

Historia zmian

1. Zmiany w CLI

W wersji Genkit 0.9 interfejs wiersza poleceń (CLI) został znacznie zaktualizowany. Zmieniło się polecenie uruchamiające Genkit, a interfejs wiersza poleceń został wyodrębniony do osobnego pakietu, który należy teraz zainstalować osobno.

Aby zainstalować interfejs wiersza poleceń:

npm i -g genkit-cli

Wprowadziliśmy pewne zmiany w komendach genkit start:

Uruchamia kod aplikacji Genkit i interfejs programisty:

genkit start -- [start command]
genkit start -- tsx src/index.ts
genkit start -- go run main.go

Obsługiwany jest też tryb oglądania:

genkit start -- tsx --watch src/index.ts

Uruchamia TYLKO kod aplikacji w trybie dewelopera Genkit:

genkit start --noui -- <start command>
genkit start --noui -- tsx src/index.ts

Uruchamia interfejs dla dewelopera:

genkit start

Wcześniej polecenie genkit start uruchamiało jednocześnie interfejs dla deweloperów i kod aplikacji. Jeśli masz potoki CI/CD, które korzystają z tego polecenia, konieczne może być ich zaktualizowanie.

Interfejs programisty będzie bezpośrednio współpracować z serwerem przepływów, aby ustalić, które przepływy są zarejestrowane, i umożliwiać wywoływanie ich bezpośrednio za pomocą przykładowych danych wejściowych.

2. Uproszczone pakiety i importy

Wcześniej biblioteki Genkit były podzielone na kilka modułów, które trzeba było instalować i importować osobno. Te moduły zostały teraz scalone w jeden import. Dodatkowo moduł Zod jest teraz ponownie eksportowany przez Genkit.

Stara wersja:

npm i @genkit-ai/core @genkit-ai/ai @genkit-ai/flow @genkit-ai/dotprompt

Nowość:

npm i genkit

Stara wersja:

import { … } from '@genkit-ai/ai';
import { … } from '@genkit-ai/core';
import { … } from '@genkit-ai/flow';
import * as z from 'zod';

Nowość:

import { genkit, z } from 'genkit';

Wtyczki Genkit nadal trzeba instalować i importować osobno.

3. Konfigurowanie Genkit

Wcześniej inicjowanie Genkit odbywało się raz globalnie przez wywołanie funkcji configureGenkit. Zasoby Genkit (np. przepływy, narzędzia, prompty) byłyby automatycznie połączone z tą globalną konfiguracją.

Wersja Genkit 0.9 wprowadza instancje Genkit, z których każda zawiera konfigurację. Zobacz te przykłady:

Stara wersja:

import { configureGenkit } from '@genkit-ai/core';

configureGenkit({
  telemetry: {
    instrumentation: ...,
    logger: ...
  }
});

Nowość:

import { genkit } from 'genkit';
import { logger } from 'genkit/logging';
import { enableFirebaseTelemetry } from '@genkit-ai/firebase';

logger.setLogLevel('debug');
enableFirebaseTelemetry({...});

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

Przeanalizujmy to:

  • Funkcja configureGenkit() została zastąpiona przez funkcję genkit() i zwraca skonfigurowaną instancję Genkit, zamiast konfigurować ustawienia globalnie.
  • Funkcja inicjowania Genkit znajduje się teraz w pakiecie genkit.
  • Logowanie i telemetria są nadal konfigurowane globalnie za pomocą własnych metod. Te konfiguracje są stosowane równomiernie we wszystkich wystąpieniach Genkit.

4. Definiowanie procesów i jawne uruchamianie serwera

Gdy masz już skonfigurowaną instancję Genkit, musisz zdefiniować przepływy danych. Wszystkie podstawowe metody interfejsu API przeznaczone dla deweloperów, takie jak defineFlow, defineToolonFlow, są teraz wywoływane przez tę instancję.

Wcześniej przepływy i narzędzia były rejestrowane globalnie.

Stara wersja:

import { defineFlow, defineTool, onFlow } from '@genkit-ai/core';

defineFlow(...);
defineTool(...);

onFlow(...);

Nowość:

// Define tools and flows
const sampleFlow = ai.defineFlow(...);
const sampleTool = ai.defineTool(...);

// onFlow now takes the Genkit instance as first argument
// This registers the flow as a callable firebase function
onFlow(ai, ...);  

const flows = [ sampleFlow, ... ];
// Start the flow server to make the registered flows callable over HTTP
ai.startFlowServer({flows});

Obecnie wszystkie przepływy, które chcesz udostępnić, muszą być wyraźnie zarejestrowane w tablicy flows.

5. Narzędzia i prompty muszą być zdefiniowane statycznie.

W wcześniejszych wersjach Genkit można było dynamicznie definiować narzędzia i prompty w czasie wykonywania kodu bezpośrednio w ramach przepływu.

W wersji Genkit 0.9 takie działanie jest niedozwolone. Zamiast tego musisz zdefiniować wszystkie działania i przepływy poza ich wykonywaniem (czyli statycznie).

Ta zmiana narzuca ściślejsze oddzielenie definicji działań od ich wykonania.

Jeśli jakikolwiek kod jest zdefiniowany dynamicznie, musisz go przerobić. W przeciwnym razie podczas wykonywania przepływu wystąpi błąd.

❌ NIE ROBIĆ:

const flow = defineFlow({...}, async (input) => {
  const tool = defineTool({...});
  await tool(...);
});

✅ DO:

const tool = ai.defineTool({...});

const flow = ai.defineFlow({...}, async (input) => {
  await tool(...);
});

6. Nowy interfejs API do strumieniowego przesyłania danych

W wersji Genkit 0.9 uprościliśmy składnię definiowania i wywoływania przepływu strumieniowego.

Po pierwsze, defineFlowdefineStreamingFlow zostały rozdzielone. Jeśli masz przepływ, który ma być przesyłany strumieniowo, musisz zaktualizować kod, aby zdefiniować go za pomocą funkcji defineStreamingFlow.

Po drugie, zamiast wywoływać osobne funkcje stream()response(), teraz wartości stream i response są zwracane bezpośrednio z przepływu. Ta zmiana upraszcza strumieniowe przesyłanie danych.

Stara wersja:

import { defineFlow, streamFlow } from '@genkit-ai/flow';

const myStreamingFlow = defineFlow(...);
const { stream, output } = await streamFlow(myStreamingFlow, ...);

for await (const chunk of stream()) {
  console.log(chunk);
}

console.log(await output());

Nowość:

const myStreamingFlow = ai.defineStreamingFlow(...);
const { stream, response } = await myStreamingFlow(...);

for await (const chunk of stream) {
  console.log(chunk);
}

console.log(await response);

7. Metody klasy GenerateResponse zostały zastąpione właściwościami gettera

Wcześniej dostęp do uporządkowanego wyjścia lub tekstu odpowiedzi uzyskiwano za pomocą metod klasy, takich jak output() lub text().

W Genkit 0.9 te metody zostały zastąpione przez właściwości gettera. Dzięki temu łatwiej będzie Ci pracować z odpowiedziami.

Stara wersja:

const response = await generate({ prompt: 'hi' });
console.log(response.text());

Nowość:

const response = await ai.generate('hi');
console.log(response.text);

To samo dotyczy output:

Stara wersja:

console.log(response.output());

Nowość:

console.log(response.output);

8. Wygenerowanie kandydatów zostało wyeliminowane

Wersja Genkit 0.9 upraszcza obsługę odpowiedzi przez usunięcie atrybutu candidates. Wcześniej odpowiedzi mogły zawierać wielu kandydatów, których trzeba było obsłużyć osobno. Teraz tylko pierwszy kandydat jest zwracany bezpośrednio w ramach odpowiedzi.

Żaden kod, który bezpośrednio uzyskuje dostęp do kandydatów, nie będzie już działać.

Stara wersja:

const response = await generate({
 messages: [ { role: 'user', content: ...} ]
});
console.log(response.candidates); // previously you could access candidates directly

Nowość:

const response = await ai.generate({
 messages: [ { role: 'user', content: ...} ]
});
console.log(response.message); // single candidate is returned directly in a flat response

9. Generowanie interfejsu API – ulepszenia dotyczące wielu tur

W przypadku rozmów wieloetapowych stara metoda toHistory() została zastąpiona metodą messages, co jeszcze bardziej upraszcza sposób obsługi historii rozmów.

Stara wersja:

const history = response.toHistory();

Nowość:

const response = await ai.generate({
 messages: [ { role: 'user', content: ...} ]
});
const history = response.messages;

10. Uproszczone Chat API

W Genkit 0.9 interfejs Chat API został przeprojektowany, aby ułatwić zarządzanie sesjami i interakcje. Oto, jak możesz go używać w przypadku czatu synchronicznego i strumieniowego:

import { genkit } from 'genkit';
import { gemini15Flash, googleAI } from '@genkit-ai/googleai';

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

const session = ai.createSession({ store: firestoreSessionStore() });
const chat = await session.chat({ system: 'talk like a pirate' });

let response = await chat.send('hi, my name is Pavel');
console.log(response.text()); // "hi Pavel, I'm llm"

// continue the conversation
response = await chat.send("what's my name");
console.log(response.text()); // "Pavel"

// can stream
const { response, stream } = await chat.sendStream('bye');
for await (const chunk of stream) {
 console.log(chunk.text());
}
console.log((await response).text());

// can load session from the store
const prevSession = await ai.loadSession(session.id, { store });
const prevChat = await prevSession.chat();
await prevChat.send('bye');