Como programar plug-ins do Genkit

Os recursos do Firebase Genkit foram projetados para serem ampliados por plug-ins. Os plug-ins do Genkit são módulos configuráveis que podem fornecer modelos, recuperadores, indexadores, armazenamentos de rastreamento e muito mais. Você já viu plug-ins em ação apenas usando o Genkit:

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

configureGenkit({
  plugins: [vertexAI({ projectId: 'my-project' })],
});

O plug-in Vertex AI recebe a configuração (como o ID do projeto do Google Cloud do usuário) e registra uma variedade de novos modelos, embedders e muito mais com o registro Genkit. O registro alimenta a IU local do Genkit para executar e inspecionar modelos, prompts e muito mais, além de funcionar como um serviço de pesquisa para ações nomeadas no momento da execução.

Como criar um plug-in

Para criar um plug-in, geralmente é necessário criar um novo pacote NPM:

mkdir genkitx-my-plugin
cd genkitx-my-plugin
npm init -y
npm i --save @genkit-ai/core
npm i --save-dev typescript
npx tsc --init

Em seguida, defina e exporte seu plug-in do ponto de entrada principal:

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

interface MyPluginOptions {
  // add any plugin configuration here
}

export const myPlugin = genkitPlugin(
  'my-plugin',
  async (options: MyPluginOptions) => {
    // initialize your plugin here...
  }
);

Orientação sobre as opções de plug-in

Em geral, o plug-in precisa ter um único argumento options que inclua qualquer configuração geral do plug-in necessária para funcionar. Para qualquer opção de plug-in que exija um valor secreto, como chaves de API, ofereça uma opção e uma variável de ambiente padrão para configurá-la:

import { genkitPlugin, GenkitError } from '@genkit-ai/core';

interface MyPluginOptions {
  apiKey?: string;
}

export const myPlugin = genkitPlugin(
  'my-plugin',
  async (options: MyPluginOptions) => {
    const apiKey = options.apiKey || process.env.MY_PLUGIN_API_KEY;
    if (!apiKey)
      throw new GenkitError({
        source: 'my-plugin',
        status: 'INVALID_ARGUMENT',
        message:
          'Must supply either `options.apiKey` or set `MY_PLUGIN_API_KEY` environment variable.',
      });
    // ... continue initialization
  }
);

Como criar seu plug-in

Um único plug-in pode ativar muitas coisas novas no Genkit. Por exemplo, o plug-in da Vertex AI ativa vários modelos novos, além de um incorporador.

Plug-ins de modelo

Os plug-ins de modelos do Genkit adicionam um ou mais modelos de IA generativa ao registro. Um modelo representa qualquer modelo generativo capaz de receber um comando como entrada e gerar texto, mídia ou dados como saída. Geralmente, um plug-in de modelo faz uma ou mais chamadas defineModel na função de inicialização.

Um modelo personalizado geralmente consiste em três componentes:

  1. Metadados que definem as capacidades do modelo.
  2. Um esquema de configuração com parâmetros específicos compatíveis com o modelo.
  3. Uma função que implementa o modelo aceitando GenerateRequest e retornando GenerateResponse.

Para criar um plug-in de modelo, você precisa usar o pacote @genkit-ai/ai:

npm i --save @genkit-ai/ai

De modo geral, um plug-in de modelo pode ter a seguinte aparência:

import { genkitPlugin, GenkitError } from '@genkit-ai/core';
import { defineModel, GenerationCommonConfigSchema } from '@genkit-ai/ai/model';
import { simulateSystemPrompt } from '@genkit-ai/ai/model/middleware';
import { z } from 'zod';

export const myPlugin = genkitPlugin('my-plugin', async (options: {apiKey?: string}) => {
  defineModel({
    // be sure to include your plugin as a provider prefix
    name: 'my-plugin/my-model',
    // label for your model as shown in Genkit Developer UI
    label: 'My Awesome Model',
    // optional list of supported versions of your model
    versions: ['my-model-001', 'my-model-001'],
    // model support attributes
    supports: {
      multiturn: true, // true if your model supports conversations
      media: true, // true if your model supports multimodal input
      tools: true, // true if your model supports tool/function calling
      systemRole: true, // true if your model supports the system role
      output: ['text', 'media', 'json'], // types of output your model supports
    },
    // Zod schema for your model's custom configuration
    configSchema: GenerationCommonConfigSchema.extend({
      safetySettings: z.object({...}),
    }),
    // list of middleware for your model to use
    use: [simulateSystemPrompt()]
  }, async request => {
    const myModelRequest = toMyModelRequest(request);
    const myModelResponse = await myModelApi(myModelRequest);
    return toGenerateResponse(myModelResponse);
  });
});

Como transformar solicitações e respostas

A principal tarefa de um plug-in de modelo do Genkit é transformar o GenerateRequest do formato comum do Genkit em um formato reconhecido e compatível com a API do modelo e, em seguida, transformar a resposta do modelo no formato GenerateResponseData usado pelo Genkit.

Às vezes, isso pode exigir massagens ou manipulação de dados para contornar as limitações do modelo. Por exemplo, se o modelo não tiver suporte nativo a uma mensagem system, talvez seja necessário transformar a mensagem do sistema de uma solicitação em um par de mensagens de usuário/modelo.

Referências de modelo

Depois que um modelo é registrado usando defineModel, ele está sempre disponível quando solicitado pelo nome. No entanto, para melhorar a digitação e o preenchimento automático do ambiente de desenvolvimento integrado, exporte uma referência de modelo do pacote que inclua apenas os metadados de um modelo, mas não a implementação dele:

import { modelRef } from "@genkit-ai/ai/model";

export myModelRef = modelRef({
  name: "my-plugin/my-model",
  configSchema: MyConfigSchema,
  info: {
    // ... model-specific info
  },
})

Ao chamar generate(), as referências de modelo e os nomes de modelo de string podem ser usados de forma intercambiável:

import { myModelRef } from 'genkitx-my-plugin';
import { generate } from '@genkit-ai/ai';

generate({ model: myModelRef });
// is equivalent to
generate({ model: 'my-plugin/my-model' });

Plug-ins de telemetria

Consulte Como criar um plug-in de telemetria do Genkit.

Publicar um plug-in

Os plug-ins do Genkit podem ser publicados como pacotes NPM normais. Para aumentar a capacidade de descoberta e maximizar a consistência, seu pacote precisa ser nomeado como genkitx-{name} para indicar que é um plug-in Genkit e incluir o máximo de keywords a seguir no package.json que seja relevante para o plug-in:

  • genkit-plugin: sempre inclua essa palavra-chave no pacote para indicar que é um plug-in do Genkit.
  • genkit-model: inclua essa palavra-chave se o pacote definir modelos.
  • genkit-retriever: inclua essa palavra-chave se o pacote definir algum recuperador.
  • genkit-indexer: inclua essa palavra-chave se o pacote definir algum indexador.
  • genkit-embedder: inclua essa palavra-chave se o pacote definir algum indexador.
  • genkit-tracestore: inclua essa palavra-chave se o pacote definir qualquer armazenamento de traces.
  • genkit-statestore: inclua essa palavra-chave se o pacote definir lojas de estado.
  • genkit-telemetry: inclua essa palavra-chave se o pacote definir um provedor de telemetria.
  • genkit-deploy: inclua essa palavra-chave se o pacote incluir auxiliares para implantar apps do Genkit em provedores de nuvem.
  • genkit-flow: inclua essa palavra-chave se o pacote melhorar os fluxos do Genkit.

Um plug-in que forneceu um recuperador, incorporador e modelo pode ter um package.json com esta aparência:

{
  "name": "genkitx-my-plugin",
  "keywords": ["genkit-plugin", "genkit-retriever", "genkit-embedder", "genkit-model"],
  // ... dependencies etc.
}