Écrire des plug-ins Genkit

Les fonctionnalités de Firebase Genkit sont conçues pour être étendues par des plug-ins. Les plug-ins Genkit sont des modules configurables pouvant fournir des modèles, des récupérateurs, des indexeurs, des magasins de traces, etc. Vous avez déjà vu des plug-ins en action simplement en utilisant Genkit:

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

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

Le plug-in Vertex AI effectue la configuration (telle que l'ID de projet Google Cloud de l'utilisateur) et enregistre divers nouveaux modèles, intégrateurs et plus encore dans le registre Genkit. Le Registre alimente l'UI locale de Genkit pour exécuter et inspecter des modèles, des invites, etc., et sert également de service de recherche pour les actions nommées au moment de l'exécution.

Créer un plug-in

Pour créer un plug-in, vous devez généralement créer un package NPM:

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

Définissez et exportez ensuite votre plug-in à partir de votre point d'entrée principal:

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

Conseils sur les options de plug-in

En général, votre plug-in doit accepter un seul argument options qui inclut toute configuration au niveau du plug-in nécessaire à son fonctionnement. Pour toute option de plug-in nécessitant une valeur secrète, telle que des clés API, vous devez proposer à la fois une option et une variable d'environnement par défaut pour la configurer:

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

Créer votre plug-in

Un seul plug-in peut activer de nombreuses nouvelles fonctionnalités dans Genkit. Par exemple, le plug-in Vertex AI active plusieurs nouveaux modèles ainsi qu'un outil d'intégration.

Plug-ins de modèle

Les plug-ins de modèle Genkit ajoutent un ou plusieurs modèles d'IA générative au registre Genkit. Un modèle représente tout modèle génératif capable de recevoir une requête en entrée et de générer du texte, des contenus multimédias ou des données en sortie. En règle générale, un plug-in de modèle effectue un ou plusieurs appels defineModel dans sa fonction d'initialisation.

Un modèle personnalisé se compose généralement de trois composants:

  1. Métadonnées définissant les fonctionnalités du modèle.
  2. Un schéma de configuration avec les paramètres spécifiques compatibles avec le modèle.
  3. Fonction implémentant le modèle acceptant GenerateRequest et renvoyant GenerateResponse.

Pour créer un plug-in de modèle, vous devez utiliser le package @genkit-ai/ai:

npm i --save @genkit-ai/ai

De manière générale, un plug-in de modèle peut se présenter comme suit:

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


Transformer les requêtes et les réponses

La tâche principale d'un plug-in de modèle Genkit consiste à transformer le GenerateRequest du format commun de Genkit en un format reconnu et compatible avec l'API de votre modèle, puis à transformer la réponse de votre modèle au format GenerateResponseData utilisé par Genkit.

Il peut parfois être nécessaire de modifier ou de manipuler les données pour contourner les limites du modèle. Par exemple, si votre modèle n'est pas compatible en mode natif avec un message system, vous devrez peut-être transformer le message système d'une invite en paire de messages utilisateur/modèle.

Références de modèles

Une fois qu'un modèle est enregistré à l'aide de defineModel, il est toujours disponible lorsqu'il est demandé par nom. Toutefois, pour améliorer la saisie et la saisie semi-automatique de l'IDE, vous pouvez exporter une référence de modèle à partir de votre package qui n'inclut que les métadonnées d'un modèle, mais pas son implémentation:

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

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

Lorsque vous appelez generate(), les références de modèle et les noms de modèle de chaîne peuvent être utilisés de manière interchangeable:

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

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

Publier un plug-in

Les plug-ins Genkit peuvent être publiés en tant que packages NPM normaux. Pour améliorer la visibilité et maximiser la cohérence, votre package doit être nommé genkitx-{name} pour indiquer qu'il s'agit d'un plug-in Genkit. Vous devez inclure autant de keywords suivants dans votre package.json que nécessaire pour votre plug-in:

  • genkit-plugin: incluez toujours ce mot clé dans votre package pour indiquer qu'il s'agit d'un plug-in Genkit.
  • genkit-model: incluez ce mot clé si votre package définit des modèles.
  • genkit-retriever: incluez ce mot clé si votre package définit des récupérateurs.
  • genkit-indexer: incluez ce mot clé si votre package définit des indexeurs.
  • genkit-embedder: incluez ce mot clé si votre package définit des indexeurs.
  • genkit-tracestore: incluez ce mot clé si votre package définit des magasins de traces.
  • genkit-statestore: incluez ce mot clé si votre package définit des magasins d'état.
  • genkit-telemetry: incluez ce mot clé si votre package définit un fournisseur de télémétrie.
  • genkit-deploy: incluez ce mot clé si votre package inclut des assistants permettant de déployer des applications Genkit auprès de fournisseurs cloud.
  • genkit-flow: incluez ce mot clé si votre package améliore les flux Genkit.

Un plug-in qui a fourni un extracteur, un outil d'intégration et un modèle peut avoir un package.json qui se présente comme suit:

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