Migração da versão 0.5

O Genkit 0.9 apresenta várias mudanças importantes e melhorias de recursos que melhoram a funcionalidade geral. Se você estiver desenvolvendo aplicativos com o Genkit 0.5, será necessário atualizar o código do aplicativo ao fazer upgrade para a versão mais recente. Este guia descreve as mudanças mais significativas e oferece etapas para migrar seus aplicativos atuais sem problemas.

Guia de início rápido

As etapas a seguir vão ajudar você a migrar rapidamente do Genkit 0.5 para o Genkit 0.9. Leia mais informações sobre essas mudanças no registro de mudanças detalhado abaixo.

1. Instalar a nova CLI

  • Desinstalar a CLI antiga

    npm uninstall -g genkit && npm uninstall genkit
    
  • Instalar a nova CLI

    npm i -D genkit-cli
    

2. Atualizar as dependências

  • Remover pacotes principais do Genkit individuais

    npm uninstall @genkit-ai/ai @genkit-ai/core @genkit-ai/dotprompt @genkit-ai/flow
    
  • Instalar o novo pacote consolidado de genkit

    npm i --save genkit
    
  • Faça upgrade de todas as versões do plug-in (exemplo abaixo)

    npm upgrade @genkit-ai/firebase
    

3. Mudar as importações

  • Remoção de importações para pacotes principais individuais do Genkit

    import { … } from '@genkit-ai/ai';
    import { … } from '@genkit-ai/core';
    import { … } from '@genkit-ai/flow';
    
  • Remover importações do zod

    import * as z from 'zod';
    
  • Importar genkit e zod de genkit

    import { z, genkit } from 'genkit';
    

4. Atualizar o código

Remover os blocos de configureGenkit

A configuração do Genkit agora é feita por instância. A telemetria e a geração de registros são configuradas globalmente e separadamente da instância do Genkit.

  • Substitua configureGenkit por blocos ai = genkit({...}). Mantenha apenas a configuração do plug-in.

    import { genkit } from 'genkit';
    
    const ai = genkit({ plugins: [...]});
    
  • Configurar a telemetria usando enableFirebaseTelemetry ou enableGoogleCloudTelemetry

    No Firebase:

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

    No Google Cloud:

    import { enableGoogleCloudTelemetry } from '@genkit-ai/google-cloud';
    
    enableGoogleCloudTelemetry({...});
    
  • Defina o nível de registro de forma independente ```js import { logger } from 'genkit/logging';

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

Consulte a documentação Monitoramento e geração de registros para mais detalhes sobre como configurar a telemetria e a geração de registros.

Consulte a documentação Primeiros passos para mais detalhes sobre como configurar uma instância do Genkit.

Migrar ações do Genkit para serem chamadas da instância genkit

As ações (fluxos, ferramentas, extratores, indexadores etc.) são definidas por instância. Leia o Registro de alterações para saber quais recursos você precisa mudar. Confira um exemplo de alguns comuns.

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. Executar

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

Registro de alterações

1. Mudanças na CLI

A interface de linha de comando (CLI) passou por atualizações significativas no Genkit 0.9. O comando para iniciar o Genkit mudou, e a CLI foi separada em um pacote independente, que agora precisa ser instalado separadamente.

Para instalar a CLI:

npm i -g genkit-cli

Algumas mudanças foram feitas no comando genkit start:

Inicia o código do aplicativo Genkit e a interface de desenvolvimento juntos:

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

O modo de exibição também é aceito:

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

Inicia SOMENTE o código do aplicativo no modo de desenvolvimento do Genkit:

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

Inicia SOMENTE a interface do desenvolvedor:

genkit start

Anteriormente, o comando genkit start iniciava a interface de desenvolvedor e o código do aplicativo juntos. Se você tiver pipelines de CI/CD que dependem desse comando, talvez seja necessário atualizá-los.

A interface do desenvolvedor interage diretamente com o servidor de fluxo para descobrir quais fluxos estão registrados e permite que você os invoque diretamente com entradas de exemplo.

2. Pacotes e importações simplificados

Antes, as bibliotecas do Genkit eram separadas em vários módulos, que precisavam ser instalados e importados individualmente. Agora esses módulos foram consolidados em uma única importação. Além disso, o módulo Zod agora é exportado novamente pelo Genkit.

Antigo:

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

Novo:

npm i genkit

Antigo:

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

Novo:

import { genkit, z } from 'genkit';

Os plug-ins do Genkit ainda precisam ser instalados e importados individualmente.

3. Como configurar o Genkit

Antes, a inicialização do Genkit era feita uma vez globalmente chamando a função configureGenkit. Os recursos do Genkit (fluxos, ferramentas, comandos, etc.) seriam conectados automaticamente a essa configuração global.

O Genkit 0.9 apresenta instâncias Genkit, cada uma delas encapsulando uma configuração. Veja os exemplos a seguir:

Antigo:

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

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

Novo:

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

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

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

Vamos explicar melhor:

  • configureGenkit() foi substituído por genkit() e retorna uma instância Genkit configurada em vez de configurar configurações globalmente.
  • A função de inicialização do Genkit agora está no pacote genkit.
  • O registro e a telemetria ainda são configurados globalmente usando os próprios métodos explícitos. Essas configurações são aplicadas de maneira uniforme em todas as instâncias de Genkit.

4. Como definir fluxos e iniciar o servidor de fluxo explicitamente

Agora que você tem uma instância Genkit configurada, é necessário definir seus fluxos. Todos os métodos principais de API voltados para desenvolvedores, como defineFlow, defineTool e onFlow, agora são invocados por essa instância.

Isso é diferente da maneira anterior, em que os fluxos e as ferramentas eram registrados globalmente.

Antigo:

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

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

onFlow(...);

Novo:

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

No momento, todos os fluxos que você quer disponibilizar precisam ser registrados explicitamente na matriz flows acima.

5. As ferramentas e os comandos precisam ser definidos de forma estática

Nas versões anteriores do Genkit, era possível definir ferramentas e comandos dinamicamente no momento da execução, diretamente em um fluxo.

No Genkit 0.9, esse comportamento não é mais permitido. Em vez disso, é necessário definir todas as ações e fluxos fora da execução do fluxo (ou seja, de forma estática).

Essa mudança reforça uma separação mais rígida das definições de ação da execução.

Se algum código for definido dinamicamente, ele precisará ser reestruturado. Caso contrário, um erro será gerado no ambiente de execução quando o fluxo for executado.

❌ O QUE NÃO FAZER:

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

✅ FAÇA:

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

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

6. Nova API para fluxos de streaming

No Genkit 0.9, simplificamos a sintaxe para definir e invocar um fluxo de streaming.

Primeiro, defineFlow e defineStreamingFlow foram separados. Se você tiver um fluxo que precisa ser transmitido, atualize o código para defini-lo usando defineStreamingFlow.

Em segundo lugar, em vez de chamar funções stream() e response() separadas, a transmissão e a resposta agora são valores retornados diretamente do fluxo. Essa mudança simplifica o streaming de fluxos.

Antigo:

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

Novo:

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

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

console.log(await response);

7. Os métodos da classe GenerateResponse foram substituídos por propriedades de getter

Antes, você acessava a saída estruturada ou o texto da resposta usando métodos de classe, como output() ou text().

No Genkit 0.9, esses métodos foram substituídos por propriedades getter. Isso simplifica o trabalho com respostas.

Antigo:

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

Novo:

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

O mesmo se aplica a output:

Antigo:

console.log(response.output());

Novo:

console.log(response.output);

8. Geração de candidatos eliminada

O Genkit 0.9 simplifica o processamento de respostas removendo o atributo candidates. Antes, as respostas podiam conter vários candidatos, que precisavam ser processados explicitamente. Agora, apenas o primeiro candidato é retornado diretamente em uma resposta plana.

Qualquer código que acesse os candidatos diretamente não vai mais funcionar.

Antigo:

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

Novo:

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: melhorias em várias etapas

Para conversas com vários turnos, o método toHistory() antigo foi substituído por messages, simplificando ainda mais o processamento do histórico de conversas.

Antigo:

const history = response.toHistory();

Novo:

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

10. API Streamlined Chat

No Genkit 0.9, a API Chat foi reformulada para facilitar o gerenciamento e a interação da sessão. Confira como aproveitar essa ferramenta para experiências de chat síncrono e de 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');