Scrivere plug-in Genkit

Le funzionalità di Firebase Genkit sono progettate per essere estese tramite plug-in. I plug-in Genkit sono moduli configurabili che possono fornire modelli, retriever, indicizzatori, repository di tracce e altro ancora. Hai già visto i plug-in in azione semplicemente utilizzando Genkit:

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

const ai = genkit({
  plugins: [vertexAI({ projectId: 'my-project' })],
});

Il plug-in Vertex AI acquisisce la configurazione (ad esempio l'ID progetto Google Cloud dell'utente) e registra una serie di nuovi modelli, embedder e altro ancora nel registry Genkit. Il registry supporta l'interfaccia utente locale di Genkit per l'esecuzione e l'ispezione di modelli, prompt e altro ancora, nonché come servizio di ricerca per le azioni denominate in fase di esecuzione.

Creazione di un plug-in

Per creare un plug-in, in genere è consigliabile creare un nuovo pacchetto NPM:

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

Quindi, definisci ed esporta il plug-in dal tuo entry point principale:

import { Genkit, z } from 'genkit';
import { GenkitPlugin, genkitPlugin } from 'genkit/plugin';

interface MyPluginOptions {
  // add any plugin configuration here
}

export function myPlugin(options?: MyPluginOptions) {
  return genkitPlugin('myPlugin', async (ai: Genkit) => {
    ai.defineModel(...);
    ai.defineEmbedder(...)
    // ....
  });
};

Indicazioni sulle opzioni dei plug-in

In generale, il plug-in deve accettare un singolo argomento options che includa qualsiasi configurazione a livello di plug-in necessaria per il funzionamento. Per qualsiasi opzione del plug-in che richiede un valore segreto, ad esempio le chiavi API, devi offrire sia un'opzione sia una variabile di ambiente predefinita per la configurazione:

import { Genkit, z } from 'genkit';
import { GenkitPlugin, genkitPlugin } from 'genkit/plugin';
import { GenkitError } from '@genkit-ai/core';

interface MyPluginOptions {
  apiKey?: string;
}

export function myPlugin(options?: MyPluginOptions) {
  return genkitPlugin('myPlugin', async (ai: Genkit) => {
    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.',
      });

    ai.defineModel(...);
    ai.defineEmbedder(...)
    
    // ....
  });
};

Creazione del plug-in

Un singolo plug-in può attivare molte nuove funzionalità in Genkit. Ad esempio, il plug-in Vertex AI attiva diversi nuovi modelli e un embedder.

Plugin del modello

I plug-in dei modelli Genkit aggiungono uno o più modelli di AI generativa al registry Genkit. Un modello rappresenta qualsiasi modello generativo in grado di ricevere un prompt come input e generare testo, contenuti multimediali o dati come output. In genere, un plug-in del modello esegue una o più chiamate a defineModel nella sua funzione di inizializzazione.

Un modello personalizzato è generalmente costituito da tre componenti:

  1. Metadati che definiscono le funzionalità del modello.
  2. Uno schema di configurazione con eventuali parametri specifici supportati dal modello.
  3. Una funzione che implementa il modello accettando GenerateRequest e restituisce GenerateResponse.

Per creare un plug-in del modello, devi utilizzare il pacchetto @genkit-ai/ai:

npm i --save @genkit-ai/ai

A livello generale, un plug-in del modello potrebbe avere il seguente aspetto:

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


export function myPlugin(options?: MyPluginOptions) {
  return genkitPlugin('my-plugin', async (ai: Genkit) => {
    ai.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);
    });
  });
};


Trasformazione di richieste e risposte

La funzione principale di un plug-in del modello Genkit è trasformare il GenerateRequest dal formato comune di Genkit in un formato riconosciuto e supportato dall'API del modello, quindi trasformare la risposta del modello nel formato GenerateResponseData utilizzato da Genkit.

A volte, per ovviare alle limitazioni del modello, potrebbe essere necessario modificare o manipolare i dati. Ad esempio, se il tuo modello non supporta nativamente un messaggio system, potrebbe essere necessario trasformare il messaggio di sistema di un prompt in una coppia di messaggi utente/modello.

Riferimenti ai modelli

Una volta registrato utilizzando defineModel, un modello è sempre disponibile quando viene richiesto per nome. Tuttavia, per migliorare la digitazione e la compilazione automatica dell'IDE, puoi esportare un riferimento a un modello dal tuo pacchetto che includa solo i metadati di un modello, ma non la relativa implementazione:

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

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

Quando chiami generate(), i riferimenti ai modelli e i nomi dei modelli di stringhe possono essere utilizzati in modo intercambiabile:

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

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

Pubblicazione di un plug-in

I plug-in Genkit possono essere pubblicati come normali pacchetti NPM. Per aumentare la rilevabilità e massimizzare la coerenza, il pacchetto deve essere denominato genkitx-{name} per indicare che si tratta di un plug-in Genkit e devi includere nel package.json quanti più keywords pertinenti per il plug-in.

  • genkit-plugin: includi sempre questa parola chiave nel pacchetto per indicare che si tratta di un plug-in Genkit.
  • genkit-model: includi questa parola chiave se il pacchetto definisce dei modelli.
  • genkit-retriever: includi questa parola chiave se il tuo pacchetto definisce dei retriever.
  • genkit-indexer: includi questa parola chiave se il pacchetto definisce indicizzatori.
  • genkit-embedder: includi questa parola chiave se il pacchetto definisce indicizzatori.
  • genkit-tracestore: includi questa parola chiave se il pacchetto definisce degli store traccia.
  • genkit-statestore: includi questa parola chiave se il pacchetto definisce degli stati.
  • genkit-telemetry: includi questa parola chiave se il pacchetto definisce un fornitore di telemetria.
  • genkit-deploy: includi questa parola chiave se il tuo pacchetto include helper per il deployment di app Genkit nei provider cloud.
  • genkit-flow: includi questa parola chiave se il tuo pacchetto migliora i flussi di Genkit.

Un plug-in che ha fornito un retriever, un embedder e un modello potrebbe avere un package.json simile al seguente:

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