Genkit 0.9 introduce una serie di modifiche che comportano interruzioni, oltre a miglioramenti delle funzionalità che migliorano la funzionalità complessiva. Se hai sviluppato applicazioni con Genkit 0.5, dovrai aggiornare il codice dell'applicazione quando esegui l'upgrade alla versione più recente. Questa guida illustra le modifiche più significative e offre i passaggi per eseguire la migrazione delle applicazioni esistenti senza problemi.
Guida rapida
I passaggi che seguono ti aiuteranno a eseguire rapidamente la migrazione da Genkit 0.5 a Genkit 0.9. Scopri di più su queste modifiche nel log delle modifiche dettagliato di seguito.
1. Installa la nuova interfaccia a riga di comando
Disinstalla la vecchia CLI
npm uninstall -g genkit && npm uninstall genkit
Installa la nuova interfaccia a riga di comando
npm i -D genkit-cli
2. Aggiorna le dipendenze
Rimuovere i singoli pacchetti di Genkit principali
npm uninstall @genkit-ai/ai @genkit-ai/core @genkit-ai/dotprompt @genkit-ai/flow
Installa il nuovo pacchetto consolidato
genkit
npm i --save genkit
Esegui l'upgrade di tutte le versioni dei plug-in (esempio di seguito)
npm upgrade @genkit-ai/firebase
3. Modificare le importazioni
Rimuovi le importazioni per i singoli pacchetti principali di Genkit
import { … } from '@genkit-ai/ai'; import { … } from '@genkit-ai/core'; import { … } from '@genkit-ai/flow';
Rimuovi le importazioni zod
import * as z from 'zod';
Importa
genkit
ezod
dagenkit
import { z, genkit } from 'genkit';
4. Aggiorna il codice
Rimuovi i blocchi configureGenkit
La configurazione di Genkit viene ora eseguita per istanza. La telemetria e la registrazione vengono configurate a livello globale e separatamente dall'istanza Genkit.
Sostituisci
configureGenkit
con blocchiai = genkit({...})
. Mantieni solo la configurazione del plug-in.import { genkit } from 'genkit'; const ai = genkit({ plugins: [...]});
Configura la telemetria utilizzando enableFirebaseTelemetry o enableGoogleCloudTelemetry
Per Firebase:
import { enableFirebaseTelemetry } from '@genkit-ai/firebase'; enableFirebaseTelemetry({...});
Per Google Cloud:
import { enableGoogleCloudTelemetry } from '@genkit-ai/google-cloud'; enableGoogleCloudTelemetry({...});
Imposta il livello di logging in modo indipendente ```js import { logger } from 'genkit/logging';
logger.setLogLevel('debug'); ```
Per ulteriori dettagli su come configurare la telemetria e il logging, consulta la documentazione relativa a Monitoraggio e logging.
Per maggiori dettagli su come configurare un'istanza Genkit, consulta la documentazione Guida introduttiva.
Esegui la migrazione delle azioni Genkit da chiamare dall'istanza genkit
Le azioni (flussi, strumenti, retriever, indicizzatori e così via) sono definite per istanza. Leggi il log delle modifiche per tutte le funzionalità che dovrai modificare, ma di seguito è riportato un esempio di alcune comuni.
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. Eseguilo
# run the DevUI and your js code genkit start -- <command to run node>
# run a defined flow genkit flow:run <flowName>
Log delle modifiche
1. Modifiche all'interfaccia a riga di comando
L'interfaccia a riga di comando (CLI) ha subito aggiornamenti significativi in Genkit 0.9. Il comando per avviare Genkit è cambiato e la CLI è stata separata in un proprio pacchetto autonomo, che ora devi installare separatamente.
Per installare l'interfaccia a riga di comando:
npm i -g genkit-cli
Sono state apportate alcune modifiche al comando genkit start
:
Avvia il codice dell'applicazione Genkit e l'interfaccia utente di sviluppo contemporaneamente:
genkit start -- [start command]
genkit start -- tsx src/index.ts
genkit start -- go run main.go
È supportata anche la modalità Orologio:
genkit start -- tsx --watch src/index.ts
Avvia SOLO il codice dell'applicazione in modalità di sviluppo Genkit:
genkit start --noui -- <start command>
genkit start --noui -- tsx src/index.ts
Avvia SOLO l'interfaccia utente di sviluppo:
genkit start
In precedenza, il comando genkit start
avviava contemporaneamente l'interfaccia utente di sviluppo e il codice dell'applicazione. Se hai pipeline CI/CD che si basano su questo comando, potresti doverle aggiornare.
L'interfaccia utente per sviluppatori interagisce direttamente con il server di flusso per capire quali flussi sono registrati e ti consente di invocarli direttamente con input di esempio.
2. Pacchetti e importazioni semplificati
In precedenza, le librerie Genkit erano suddivise in diversi moduli che dovevano essere installati e importati singolarmente. Questi moduli sono stati ora raggruppati in un'unica importazione. Inoltre, il modulo Zod viene ora esportato di nuovo da Genkit.
Precedente:
npm i @genkit-ai/core @genkit-ai/ai @genkit-ai/flow @genkit-ai/dotprompt
Novità:
npm i genkit
Precedente:
import { … } from '@genkit-ai/ai';
import { … } from '@genkit-ai/core';
import { … } from '@genkit-ai/flow';
import * as z from 'zod';
Novità:
import { genkit, z } from 'genkit';
I plug-in Genkit devono comunque essere installati e importati singolarmente.
3. Configurazione di Genkit
In precedenza, l'inizializzazione di Genkit veniva eseguita una volta a livello globale chiamando la funzione configureGenkit
. Le risorse di Genkit (flussi, strumenti, prompt e così via) verranno collegate automaticamente a questa configurazione globale.
Genkit 0.9 introduce le istanze Genkit
, ognuna delle quali incapsula una configurazione. Vedi i seguenti esempi:
Precedente:
import { configureGenkit } from '@genkit-ai/core';
configureGenkit({
telemetry: {
instrumentation: ...,
logger: ...
}
});
Novità:
import { genkit } from 'genkit';
import { logger } from 'genkit/logging';
import { enableFirebaseTelemetry } from '@genkit-ai/firebase';
logger.setLogLevel('debug');
enableFirebaseTelemetry({...});
const ai = genkit({ ... });
Analizziamo la questione nel dettaglio:
configureGenkit()
è stato sostituito congenkit()
e restituisce un'istanzaGenkit
configurata anziché configurare le configurazioni a livello globale.- La funzione di inizializzazione di Genkit ora si trova nel pacchetto
genkit
. - La registrazione e la telemetria vengono comunque configurate a livello globale utilizzando i relativi metodi espliciti. Queste configurazioni si applicano in modo uniforme a tutte le istanze di
Genkit
.
4. Definire i flussi e avviare il server di flusso in modo esplicito
Ora che hai configurato un'istanza Genkit
, devi definire i flussi. Tutti i metodi API principali rivolti agli sviluppatori, come defineFlow
, defineTool
e onFlow
, vengono ora invocati tramite questa istanza.
Questo approccio è diverso da quello precedente, in cui i flussi e gli strumenti venivano registrati a livello globale.
Precedente:
import { defineFlow, defineTool, onFlow } from '@genkit-ai/core';
defineFlow(...);
defineTool(...);
onFlow(...);
Novità:
// 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});
Al momento, tutti i flussi che vuoi rendere disponibili devono essere registrati esplicitamente nell'array flows
riportato sopra.
5. Gli strumenti e i prompt devono essere definiti in modo statico
Nelle versioni precedenti di Genkit, era possibile definire dinamicamente strumenti e prompt in fase di esecuzione, direttamente all'interno di un flusso.
In Genkit 0.9, questo comportamento non è più consentito. Devi invece definire tutte le azioni e i flussi al di fuori dell'esecuzione del flusso (ovvero in modo statico).
Questa modifica impone una separazione più rigida delle definizioni delle azioni dall'esecuzione.
Se parte del codice è definito in modo dinamico, deve essere sottoposto a refactoring. In caso contrario, verrà generato un errore durante l'esecuzione del flusso.
❌ NON:
const flow = defineFlow({...}, async (input) => {
const tool = defineTool({...});
await tool(...);
});
✅ DA FARE:
const tool = ai.defineTool({...});
const flow = ai.defineFlow({...}, async (input) => {
await tool(...);
});
6. Nuova API per i flussi di streaming
In Genkit 0.9 abbiamo semplificato la sintassi per definire e richiamare un flusso di streaming.
Innanzitutto, defineFlow
e defineStreamingFlow
sono stati separati. Se hai un flusso destinato a essere trasmesso in streaming, dovrai aggiornare il codice per definirlo tramite defineStreamingFlow
.
In secondo luogo, anziché chiamare funzioni stream()
e response()
separate, ora sia stream che response sono valori restituiti direttamente dal flusso. Questa modifica semplifica lo streaming in sequenza.
Precedente:
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());
Novità:
const myStreamingFlow = ai.defineStreamingFlow(...);
const { stream, response } = await myStreamingFlow(...);
for await (const chunk of stream) {
console.log(chunk);
}
console.log(await response);
7. I metodi della classe GenerateResponse sono stati sostituiti con proprietà getter
In precedenza, per accedere all'output strutturato o al testo della risposta utilizzavi i metodi di classe, come output()
o text()
.
In Genkit 0.9, questi metodi sono stati sostituiti dalle proprietà getter. In questo modo, la gestione delle risposte è più semplice.
Precedente:
const response = await generate({ prompt: 'hi' });
console.log(response.text());
Novità:
const response = await ai.generate('hi');
console.log(response.text);
Lo stesso vale per output
:
Precedente:
console.log(response.output());
Novità:
console.log(response.output);
8. Generazione di candidati eliminata
Genkit 0.9 semplifica la gestione delle risposte rimuovendo l'attributo candidates
. In precedenza, le risposte potevano contenere più candidati, che dovevano essere gestiti esplicitamente. Ora, solo il primo candidato viene restituito direttamente in una risposta piatta.
Qualsiasi codice che acceda direttamente ai candidati non funzionerà più.
Precedente:
const response = await generate({
messages: [ { role: 'user', content: ...} ]
});
console.log(response.candidates); // previously you could access candidates directly
Novità:
const response = await ai.generate({
messages: [ { role: 'user', content: ...} ]
});
console.log(response.message); // single candidate is returned directly in a flat response
9. API Generate - Miglioramenti per più passaggi
Per le conversazioni multi-turno, il vecchio metodo toHistory()
è stato sostituito da messages
, semplificando ulteriormente la gestione della cronologia delle conversazioni.
Precedente:
const history = response.toHistory();
Novità:
const response = await ai.generate({
messages: [ { role: 'user', content: ...} ]
});
const history = response.messages;
10. API Chat semplificata
In Genkit 0.9, l'API Chat è stata riprogettata per semplificare la gestione e l'interazione con le sessioni. Ecco come puoi utilizzarla per esperienze di chat sia sincrone che in streaming:
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');